]> git.sur5r.net Git - u-boot/blob - drivers/fsl_i2c.c
mpc83xx: Update 83xx to use fsl_i2c.c
[u-boot] / drivers / fsl_i2c.c
1 /*
2  * Copyright 2006 Freescale Semiconductor, Inc.
3  *
4  * This program is free software; you can redistribute it and/or
5  * modify it under the terms of the GNU General Public License
6  * Version 2 as published by the Free Software Foundation.
7  *
8  * This program is distributed in the hope that it will be useful,
9  * but WITHOUT ANY WARRANTY; without even the implied warranty of
10  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
11  * GNU General Public License for more details.
12  *
13  * You should have received a copy of the GNU General Public License
14  * along with this program; if not, write to the Free Software
15  * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
16  * MA 02111-1307 USA
17  */
18
19 #include <common.h>
20
21 #ifdef CONFIG_FSL_I2C
22 #ifdef CONFIG_HARD_I2C
23
24 #include <command.h>
25 #include <i2c.h>                /* Functional interface */
26
27 #include <asm/io.h>
28 #include <asm/fsl_i2c.h>        /* HW definitions */
29
30 #define I2C_TIMEOUT     (CFG_HZ / 4)
31
32 /* Initialize the bus pointer to whatever one the SPD EEPROM is on.
33  * Default is bus 0.  This is necessary because the DDR initialization
34  * runs from ROM, and we can't switch buses because we can't modify
35  * the global variables.
36  */
37 #ifdef CFG_SPD_BUS_NUM
38 static unsigned int i2c_bus_num __attribute__ ((section ("data"))) = CFG_SPD_BUS_NUM;
39 #else
40 static unsigned int i2c_bus_num __attribute__ ((section ("data"))) = 0;
41 #endif
42
43 static volatile struct fsl_i2c *i2c_dev[2] = {
44         (struct fsl_i2c *) (CFG_IMMR + CFG_I2C_OFFSET),
45 #ifdef CFG_I2C2_OFFSET
46         (struct fsl_i2c *) (CFG_IMMR + CFG_I2C2_OFFSET)
47 #endif
48 };
49
50 void
51 i2c_init(int speed, int slaveadd)
52 {
53         volatile struct fsl_i2c *dev;
54
55         dev = (struct fsl_i2c *) (CFG_IMMR + CFG_I2C_OFFSET);
56
57         writeb(0, &dev->cr);                    /* stop I2C controller */
58         writeb(0x3F, &dev->fdr);                /* set bus speed */
59         writeb(0x3F, &dev->dfsrr);              /* set default filter */
60         writeb(slaveadd, &dev->adr);            /* write slave address */
61         writeb(0x0, &dev->sr);                  /* clear status register */
62         writeb(I2C_CR_MEN, &dev->cr);           /* start I2C controller */
63
64 #ifdef  CFG_I2C2_OFFSET
65         dev = (struct fsl_i2c *) (CFG_IMMR + CFG_I2C2_OFFSET);
66
67         writeb(0, &dev->cr);                    /* stop I2C controller */
68         writeb(0x3F, &dev->fdr);                /* set bus speed */
69         writeb(0x3F, &dev->dfsrr);              /* set default filter */
70         writeb(slaveadd, &dev->adr);            /* write slave address */
71         writeb(0x0, &dev->sr);                  /* clear status register */
72         writeb(I2C_CR_MEN, &dev->cr);           /* start I2C controller */
73 #endif  /* CFG_I2C2_OFFSET */
74 }
75
76 static __inline__ int
77 i2c_wait4bus(void)
78 {
79         ulong timeval = get_timer(0);
80
81         while (readb(&i2c_dev[i2c_bus_num]->sr) & I2C_SR_MBB) {
82                 if (get_timer(timeval) > I2C_TIMEOUT) {
83                         return -1;
84                 }
85         }
86
87         return 0;
88 }
89
90 static __inline__ int
91 i2c_wait(int write)
92 {
93         u32 csr;
94         ulong timeval = get_timer(0);
95
96         do {
97                 csr = readb(&i2c_dev[i2c_bus_num]->sr);
98                 if (!(csr & I2C_SR_MIF))
99                         continue;
100
101                 writeb(0x0, &i2c_dev[i2c_bus_num]->sr);
102
103                 if (csr & I2C_SR_MAL) {
104                         debug("i2c_wait: MAL\n");
105                         return -1;
106                 }
107
108                 if (!(csr & I2C_SR_MCF))        {
109                         debug("i2c_wait: unfinished\n");
110                         return -1;
111                 }
112
113                 if (write == I2C_WRITE && (csr & I2C_SR_RXAK)) {
114                         debug("i2c_wait: No RXACK\n");
115                         return -1;
116                 }
117
118                 return 0;
119         } while (get_timer (timeval) < I2C_TIMEOUT);
120
121         debug("i2c_wait: timed out\n");
122         return -1;
123 }
124
125 static __inline__ int
126 i2c_write_addr (u8 dev, u8 dir, int rsta)
127 {
128         writeb(I2C_CR_MEN | I2C_CR_MSTA | I2C_CR_MTX
129                | (rsta ? I2C_CR_RSTA : 0),
130                &i2c_dev[i2c_bus_num]->cr);
131
132         writeb((dev << 1) | dir, &i2c_dev[i2c_bus_num]->dr);
133
134         if (i2c_wait(I2C_WRITE) < 0)
135                 return 0;
136
137         return 1;
138 }
139
140 static __inline__ int
141 __i2c_write(u8 *data, int length)
142 {
143         int i;
144
145         writeb(I2C_CR_MEN | I2C_CR_MSTA | I2C_CR_MTX,
146                &i2c_dev[i2c_bus_num]->cr);
147
148         for (i = 0; i < length; i++) {
149                 writeb(data[i], &i2c_dev[i2c_bus_num]->dr);
150
151                 if (i2c_wait(I2C_WRITE) < 0)
152                         break;
153         }
154
155         return i;
156 }
157
158 static __inline__ int
159 __i2c_read(u8 *data, int length)
160 {
161         int i;
162
163         writeb(I2C_CR_MEN | I2C_CR_MSTA | ((length == 1) ? I2C_CR_TXAK : 0),
164                &i2c_dev[i2c_bus_num]->cr);
165
166         /* dummy read */
167         readb(&i2c_dev[i2c_bus_num]->dr);
168
169         for (i = 0; i < length; i++) {
170                 if (i2c_wait(I2C_READ) < 0)
171                         break;
172
173                 /* Generate ack on last next to last byte */
174                 if (i == length - 2)
175                         writeb(I2C_CR_MEN | I2C_CR_MSTA | I2C_CR_TXAK,
176                                &i2c_dev[i2c_bus_num]->cr);
177
178                 /* Generate stop on last byte */
179                 if (i == length - 1)
180                         writeb(I2C_CR_MEN | I2C_CR_TXAK, &i2c_dev[i2c_bus_num]->cr);
181
182                 data[i] = readb(&i2c_dev[i2c_bus_num]->dr);
183         }
184
185         return i;
186 }
187
188 int
189 i2c_read(u8 dev, uint addr, int alen, u8 *data, int length)
190 {
191         int i = 0;
192         u8 *a = (u8*)&addr;
193
194         if (i2c_wait4bus() >= 0
195             && i2c_write_addr(dev, I2C_WRITE, 0) != 0
196             && __i2c_write(&a[4 - alen], alen) == alen
197             && i2c_write_addr(dev, I2C_READ, 1) != 0) {
198                 i = __i2c_read(data, length);
199         }
200
201         writeb(I2C_CR_MEN, &i2c_dev[i2c_bus_num]->cr);
202
203         if (i == length)
204             return 0;
205
206         return -1;
207 }
208
209 int
210 i2c_write(u8 dev, uint addr, int alen, u8 *data, int length)
211 {
212         int i = 0;
213         u8 *a = (u8*)&addr;
214
215         if (i2c_wait4bus() >= 0
216             && i2c_write_addr(dev, I2C_WRITE, 0) != 0
217             && __i2c_write(&a[4 - alen], alen) == alen) {
218                 i = __i2c_write(data, length);
219         }
220
221         writeb(I2C_CR_MEN, &i2c_dev[i2c_bus_num]->cr);
222
223         if (i == length)
224             return 0;
225
226         return -1;
227 }
228
229 int
230 i2c_probe(uchar chip)
231 {
232         int tmp;
233
234         /*
235          * Try to read the first location of the chip.  The underlying
236          * driver doesn't appear to support sending just the chip address
237          * and looking for an <ACK> back.
238          */
239         udelay(10000);
240
241         return i2c_read(chip, 0, 1, (uchar *)&tmp, 1);
242 }
243
244 uchar
245 i2c_reg_read(uchar i2c_addr, uchar reg)
246 {
247         uchar buf[1];
248
249         i2c_read(i2c_addr, reg, 1, buf, 1);
250
251         return buf[0];
252 }
253
254 void
255 i2c_reg_write(uchar i2c_addr, uchar reg, uchar val)
256 {
257         i2c_write(i2c_addr, reg, 1, &val, 1);
258 }
259
260 int i2c_set_bus_num(unsigned int bus)
261 {
262 #ifdef CFG_I2C2_OFFSET
263         if (bus > 1) {
264 #else
265         if (bus > 0) {
266 #endif
267                 return -1;
268         }
269
270         i2c_bus_num = bus;
271
272         return 0;
273 }
274
275 int i2c_set_bus_speed(unsigned int speed)
276 {
277         return -1;
278 }
279
280 unsigned int i2c_get_bus_num(void)
281 {
282         return i2c_bus_num;
283 }
284
285 unsigned int i2c_get_bus_speed(void)
286 {
287         return 0;
288 }
289 #endif /* CONFIG_HARD_I2C */
290 #endif /* CONFIG_FSL_I2C */