blob: fc89fb1e259e935fde52b85ebd5aa7e630c2177d [file] [log] [blame]
Eran Libertyf046ccd2005-07-28 10:08:46 -05001/*
Dave Liuf6eda7f2006-10-25 14:41:21 -05002 * (C) Copyright 2006 Freescale Semiconductor, Inc.
3 *
Eran Libertyf046ccd2005-07-28 10:08:46 -05004 * (C) Copyright 2003,Motorola Inc.
5 * Xianghua Xiao <x.xiao@motorola.com>
6 * Adapted for Motorola 85xx chip.
7 *
8 * (C) Copyright 2003
9 * Gleb Natapov <gnatapov@mrv.com>
10 * Some bits are taken from linux driver writen by adrian@humboldt.co.uk
11 *
12 * Hardware I2C driver for MPC107 PCI bridge.
13 *
14 * See file CREDITS for list of people who contributed to this
15 * project.
16 *
17 * This program is free software; you can redistribute it and/or
18 * modify it under the terms of the GNU General Public License as
19 * published by the Free Software Foundation; either version 2 of
20 * the License, or (at your option) any later version.
21 *
22 * This program is distributed in the hope that it will be useful,
23 * but WITHOUT ANY WARRANTY; without even the implied warranty of
24 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
25 * GNU General Public License for more details.
26 *
27 * You should have received a copy of the GNU General Public License
28 * along with this program; if not, write to the Free Software
29 * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
30 * MA 02111-1307 USA
31 *
32 * Change log:
33 *
34 * 20050101: Eran Liberty (liberty@freescale.com)
35 * Initial file creating (porting from 85XX & 8260)
Dave Liuf6eda7f2006-10-25 14:41:21 -050036 * 20060601: Dave Liu (daveliu@freescale.com)
37 * Unified variable names for mpc83xx
Eran Libertyf046ccd2005-07-28 10:08:46 -050038 */
39
40#include <common.h>
41#include <command.h>
42#include <asm/io.h>
43
44#ifdef CONFIG_HARD_I2C
45#include <i2c.h>
46#include <asm/i2c.h>
47
Ben Warrenb24f1192006-09-07 16:51:04 -040048DECLARE_GLOBAL_DATA_PTR;
49
50/* Three I2C bus speeds are supported here (50kHz, 100kHz
51 * and 400kHz). It should be easy to add more. Note that
52 * the maximum bus speed for I2C bus 1 is CSB/3, while I2C
53 * bus 2 can go as high as CSB.
54 * Typical values for CSB are 266MHz and 200MHz. */
55
56 /* 50kH 100kHz 400kHz */
57static const uchar speed_map_266[][3] =
58 {{0x2e, 0x2a, 0x20}, /* base 88MHz */
59 {0x34, 0x30, 0x28}}; /* base 266 MHz */
60
61static const uchar speed_map_200[][3] =
62 {{0x2c, 0x28, 0x20}, /* base 66 MHz */
63 {0x33, 0x2f, 0x26}}; /* base 200 MHz */
64
65/* Initialize the bus pointer to whatever one the SPD EEPROM is on.
66 * Default is bus 1. This is necessary because the DDR initialization
67 * runs from ROM, and we can't switch buses because we can't modify
68 * the i2c_dev variable. Everything gets straightened out once i2c_init
69 * is called from RAM. */
70
71#if defined CFG_SPD_BUS_NUM
72static i2c_t *i2c_dev = CFG_SPD_BUS_NUM;
73#else
74static i2c_t *i2c_dev = I2C_1;
Eran Libertyf046ccd2005-07-28 10:08:46 -050075#endif
76
Ben Warrenb24f1192006-09-07 16:51:04 -040077static uchar busNum = I2C_BUS_1 ;
78static int bus_speed[2] = {0, 0};
79
80static int set_speed(int speed)
81{
82 uchar value;
83 const uchar *spdPtr;
84
85 /* Global data contains maximum I2C bus 1 speed, which is CSB/3 */
86 if(gd->i2c_clk == 88000000)
87 {
88 spdPtr = speed_map_266[busNum];
89 }
90 else if(gd->i2c_clk == 66000000)
91 {
92 spdPtr = speed_map_200[busNum];
93 }
94 else
95 {
96 printf("Max I2C bus speed %d not supported\n", gd->i2c_clk);
97 return -1;
98 }
99
100 switch(speed)
101 {
102 case 50000:
103 value = *(spdPtr + 0);
104 break;
105 case 100000:
106 value = *(spdPtr + 1);
107 break;
108 case 400000:
109 value = *(spdPtr + 2);
110 break;
111 default:
112 printf("I2C bus speed %d not supported\n", speed);
113 return -2;
114 }
115 /* set clock */
116 writeb(value, &i2c_dev->fdr);
117 bus_speed[busNum] = speed;
118 return 0;
119}
120
121
122static void _i2c_init(int speed, int slaveadd)
Eran Libertyf046ccd2005-07-28 10:08:46 -0500123{
124 /* stop I2C controller */
Ben Warrenb24f1192006-09-07 16:51:04 -0400125 writeb(0x00 , &i2c_dev->cr);
Eran Libertyf046ccd2005-07-28 10:08:46 -0500126
127 /* set clock */
Ben Warrenb24f1192006-09-07 16:51:04 -0400128 writeb(speed, &i2c_dev->fdr);
Eran Libertyf046ccd2005-07-28 10:08:46 -0500129
130 /* set default filter */
Ben Warrenb24f1192006-09-07 16:51:04 -0400131 writeb(0x10,&i2c_dev->dfsrr);
Eran Libertyf046ccd2005-07-28 10:08:46 -0500132
133 /* write slave address */
Ben Warrenb24f1192006-09-07 16:51:04 -0400134 writeb(slaveadd, &i2c_dev->adr);
Eran Libertyf046ccd2005-07-28 10:08:46 -0500135
136 /* clear status register */
Ben Warrenb24f1192006-09-07 16:51:04 -0400137 writeb(0x00, &i2c_dev->sr);
Eran Libertyf046ccd2005-07-28 10:08:46 -0500138
139 /* start I2C controller */
Ben Warrenb24f1192006-09-07 16:51:04 -0400140 writeb(I2C_CR_MEN, &i2c_dev->cr);
141}
142
143void i2c_init(int speed, int slaveadd)
144{
145 /* Set both interfaces to the same speed and slave address */
146 /* Note: This function gets called twice - before and after
147 * relocation to RAM. The first time it's called, we are unable
148 * to change buses, so whichever one 'i2c_dev' was initialized to
149 * gets set twice. When run from RAM both buses get set properly */
150
151 i2c_set_bus_num(I2C_BUS_1);
152 _i2c_init(speed, slaveadd);
153#ifdef CFG_I2C2_OFFSET
154 i2c_set_bus_num(I2C_BUS_2);
155 _i2c_init(speed, slaveadd);
156 i2c_set_bus_num(I2C_BUS_1);
157#endif /* CFG_I2C2_OFFSET */
Eran Libertyf046ccd2005-07-28 10:08:46 -0500158}
159
160static __inline__ int
161i2c_wait4bus (void)
162{
163 ulong timeval = get_timer (0);
Ben Warrenb24f1192006-09-07 16:51:04 -0400164 while (readb(&i2c_dev->sr) & I2C_SR_MBB) {
Eran Libertyf046ccd2005-07-28 10:08:46 -0500165 if (get_timer (timeval) > I2C_TIMEOUT) {
166 return -1;
167 }
168 }
169 return 0;
170}
171
172static __inline__ int
173i2c_wait (int write)
174{
175 u32 csr;
176 ulong timeval = get_timer(0);
177 do {
Ben Warrenb24f1192006-09-07 16:51:04 -0400178 csr = readb(&i2c_dev->sr);
Eran Libertyf046ccd2005-07-28 10:08:46 -0500179
180 if (!(csr & I2C_SR_MIF))
181 continue;
182
Ben Warrenb24f1192006-09-07 16:51:04 -0400183 writeb(0x0, &i2c_dev->sr);
Eran Libertyf046ccd2005-07-28 10:08:46 -0500184
185 if (csr & I2C_SR_MAL) {
186 debug("i2c_wait: MAL\n");
187 return -1;
188 }
189
190 if (!(csr & I2C_SR_MCF)) {
191 debug("i2c_wait: unfinished\n");
192 return -1;
193 }
194
195 if (write == I2C_WRITE && (csr & I2C_SR_RXAK)) {
196 debug("i2c_wait: No RXACK\n");
197 return -1;
198 }
199
200 return 0;
201 } while (get_timer (timeval) < I2C_TIMEOUT);
Marian Balakowicze6f2e902005-10-11 19:09:42 +0200202
Eran Libertyf046ccd2005-07-28 10:08:46 -0500203 debug("i2c_wait: timed out\n");
Wolfgang Denk77ddac92005-10-13 16:45:02 +0200204 return -1;
Eran Libertyf046ccd2005-07-28 10:08:46 -0500205}
206
207static __inline__ int
208i2c_write_addr (u8 dev, u8 dir, int rsta)
209{
210 writeb(I2C_CR_MEN | I2C_CR_MSTA | I2C_CR_MTX |
211 (rsta?I2C_CR_RSTA:0),
Ben Warrenb24f1192006-09-07 16:51:04 -0400212 &i2c_dev->cr);
Eran Libertyf046ccd2005-07-28 10:08:46 -0500213
Ben Warrenb24f1192006-09-07 16:51:04 -0400214 writeb((dev << 1) | dir, &i2c_dev->dr);
Eran Libertyf046ccd2005-07-28 10:08:46 -0500215
216 if (i2c_wait (I2C_WRITE) < 0)
217 return 0;
218 return 1;
219}
220
221static __inline__ int
222__i2c_write (u8 *data, int length)
223{
224 int i;
225
226 writeb(I2C_CR_MEN | I2C_CR_MSTA | I2C_CR_MTX,
Ben Warrenb24f1192006-09-07 16:51:04 -0400227 &i2c_dev->cr);
Eran Libertyf046ccd2005-07-28 10:08:46 -0500228
229 for (i=0; i < length; i++) {
Ben Warrenb24f1192006-09-07 16:51:04 -0400230 writeb(data[i], &i2c_dev->dr);
Eran Libertyf046ccd2005-07-28 10:08:46 -0500231
232 if (i2c_wait (I2C_WRITE) < 0)
233 break;
234 }
235 return i;
236}
237
238static __inline__ int
239__i2c_read (u8 *data, int length)
240{
241 int i;
242
243 writeb(I2C_CR_MEN | I2C_CR_MSTA |
244 ((length == 1) ? I2C_CR_TXAK : 0),
Ben Warrenb24f1192006-09-07 16:51:04 -0400245 &i2c_dev->cr);
Eran Libertyf046ccd2005-07-28 10:08:46 -0500246
247 /* dummy read */
Ben Warrenb24f1192006-09-07 16:51:04 -0400248 readb(&i2c_dev->dr);
Eran Libertyf046ccd2005-07-28 10:08:46 -0500249
250 for (i=0; i < length; i++) {
251 if (i2c_wait (I2C_READ) < 0)
252 break;
253
254 /* Generate ack on last next to last byte */
255 if (i == length - 2)
256 writeb(I2C_CR_MEN | I2C_CR_MSTA |
257 I2C_CR_TXAK,
Ben Warrenb24f1192006-09-07 16:51:04 -0400258 &i2c_dev->cr);
Eran Libertyf046ccd2005-07-28 10:08:46 -0500259
260 /* Generate stop on last byte */
261 if (i == length - 1)
Ben Warrenb24f1192006-09-07 16:51:04 -0400262 writeb(I2C_CR_MEN | I2C_CR_TXAK, &i2c_dev->cr);
Eran Libertyf046ccd2005-07-28 10:08:46 -0500263
Ben Warrenb24f1192006-09-07 16:51:04 -0400264 data[i] = readb(&i2c_dev->dr);
Eran Libertyf046ccd2005-07-28 10:08:46 -0500265 }
266 return i;
267}
268
269int
270i2c_read (u8 dev, uint addr, int alen, u8 *data, int length)
271{
272 int i = 0;
273 u8 *a = (u8*)&addr;
274
275 if (i2c_wait4bus () < 0)
276 goto exit;
277
278 if (i2c_write_addr (dev, I2C_WRITE, 0) == 0)
279 goto exit;
280
281 if (__i2c_write (&a[4 - alen], alen) != alen)
282 goto exit;
283
284 if (i2c_write_addr (dev, I2C_READ, 1) == 0)
285 goto exit;
286
287 i = __i2c_read (data, length);
288
289 exit:
Ben Warrenb24f1192006-09-07 16:51:04 -0400290 writeb(I2C_CR_MEN, &i2c_dev->cr);
Eran Libertyf046ccd2005-07-28 10:08:46 -0500291 return !(i == length);
292}
293
294int
295i2c_write (u8 dev, uint addr, int alen, u8 *data, int length)
296{
297 int i = 0;
298 u8 *a = (u8*)&addr;
299
300 if (i2c_wait4bus () < 0)
301 goto exit;
302
303 if (i2c_write_addr (dev, I2C_WRITE, 0) == 0)
304 goto exit;
305
306 if (__i2c_write (&a[4 - alen], alen) != alen)
307 goto exit;
308
309 i = __i2c_write (data, length);
310
311 exit:
Ben Warrenb24f1192006-09-07 16:51:04 -0400312 writeb(I2C_CR_MEN, &i2c_dev->cr);
Eran Libertyf046ccd2005-07-28 10:08:46 -0500313 return !(i == length);
314}
315
316int i2c_probe (uchar chip)
317{
318 int tmp;
319
320 /*
321 * Try to read the first location of the chip. The underlying
322 * driver doesn't appear to support sending just the chip address
323 * and looking for an <ACK> back.
324 */
325 udelay(10000);
Wolfgang Denk77ddac92005-10-13 16:45:02 +0200326 return i2c_read (chip, 0, 1, (uchar *)&tmp, 1);
Eran Libertyf046ccd2005-07-28 10:08:46 -0500327}
328
329uchar i2c_reg_read (uchar i2c_addr, uchar reg)
330{
Wolfgang Denk77ddac92005-10-13 16:45:02 +0200331 uchar buf[1];
Eran Libertyf046ccd2005-07-28 10:08:46 -0500332
333 i2c_read (i2c_addr, reg, 1, buf, 1);
334
335 return (buf[0]);
336}
337
338void i2c_reg_write (uchar i2c_addr, uchar reg, uchar val)
339{
340 i2c_write (i2c_addr, reg, 1, &val, 1);
341}
342
Ben Warrenb24f1192006-09-07 16:51:04 -0400343int i2c_set_bus_num(uchar bus)
344{
345 if(bus == I2C_BUS_1)
346 {
347 i2c_dev = I2C_1;
348 }
349#ifdef CFG_I2C2_OFFSET
350 else if(bus == I2C_BUS_2)
351 {
352 i2c_dev = I2C_2;
353 }
354#endif /* CFG_I2C2_OFFSET */
355 else
356 {
357 return -1;
358 }
359 busNum = bus;
360 return 0;
361}
362
363int i2c_set_bus_speed(int speed)
364{
365 return set_speed(speed);
366}
367
368uchar i2c_get_bus_num(void)
369{
370 return busNum;
371}
372
373int i2c_get_bus_speed(void)
374{
375 return bus_speed[busNum];
376}
Eran Libertyf046ccd2005-07-28 10:08:46 -0500377#endif /* CONFIG_HARD_I2C */