]> git.kernelconcepts.de Git - karo-tx-uboot.git/blob - cpu/mpc5xxx/i2c.c
* Patch by David Müller, 13 Sep 2003:
[karo-tx-uboot.git] / cpu / mpc5xxx / i2c.c
1 /*
2  * (C) Copyright 2003
3  * Wolfgang Denk, DENX Software Engineering, wd@denx.de.
4  *
5  * See file CREDITS for list of people who contributed to this
6  * project.
7  *
8  * This program is free software; you can redistribute it and/or
9  * modify it under the terms of the GNU General Public License as
10  * published by the Free Software Foundation; either version 2 of
11  * the License, or (at your option) any later version.
12  *
13  * This program is distributed in the hope that it will be useful,
14  * but WITHOUT ANY WARRANTY; without even the implied warranty of
15  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16  * GNU General Public License for more details.
17  *
18  * You should have received a copy of the GNU General Public License
19  * along with this program; if not, write to the Free Software
20  * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
21  * MA 02111-1307 USA
22  */
23
24 #include <common.h>
25
26 #ifdef CONFIG_HARD_I2C
27
28 #include <mpc5xxx.h>
29 #include <i2c.h>
30
31 #ifdef CFG_I2C_MODULE
32 #define I2C_BASE        MPC5XXX_I2C2
33 #else
34 #define I2C_BASE        MPC5XXX_I2C1
35 #endif
36
37 #define I2C_TIMEOUT     100
38 #define I2C_RETRIES     3
39
40 static int  mpc_reg_in    (volatile u32 *reg);
41 static void mpc_reg_out   (volatile u32 *reg, int val, int mask);
42 static int  wait_for_bb   (void);
43 static int  wait_for_pin  (int *status);
44 static int  do_address    (uchar chip, char rdwr_flag);
45 static int  send_bytes    (uchar chip, char *buf, int len);
46 static int  receive_bytes (uchar chip, char *buf, int len);
47
48 static int mpc_reg_in(volatile u32 *reg)
49 {
50         return *reg >> 24;
51         __asm__ __volatile__ ("eieio");
52 }
53
54 static void mpc_reg_out(volatile u32 *reg, int val, int mask)
55 {
56         int tmp;
57
58         if (!mask) {
59                 *reg = val << 24;
60         } else {
61                 tmp = mpc_reg_in(reg);
62                 *reg = ((tmp & ~mask) | (val & mask)) << 24;
63         }
64         __asm__ __volatile__ ("eieio");
65
66         return;
67 }
68
69 static int wait_for_bb(void)
70 {
71         struct mpc5xxx_i2c *regs    = (struct mpc5xxx_i2c *)I2C_BASE;
72         int                 timeout = I2C_TIMEOUT;
73         int                 status;
74
75         status = mpc_reg_in(&regs->msr);
76
77         while (timeout-- && (status & I2C_BB)) {
78 #if 1
79                 volatile int temp;
80                 mpc_reg_out(&regs->mcr, I2C_STA, I2C_STA);
81                 temp = mpc_reg_in(&regs->mdr);
82                 mpc_reg_out(&regs->mcr, 0, I2C_STA);
83                 mpc_reg_out(&regs->mcr, 0, 0);
84                 mpc_reg_out(&regs->mcr, I2C_EN, 0);
85 #endif
86                 udelay(1000);
87                 status = mpc_reg_in(&regs->msr);
88         }
89
90         return (status & I2C_BB);
91 }
92
93 static int wait_for_pin(int *status)
94 {
95         struct mpc5xxx_i2c *regs    = (struct mpc5xxx_i2c *)I2C_BASE;
96         int                 timeout = I2C_TIMEOUT;
97
98         *status = mpc_reg_in(&regs->msr);
99
100         while (timeout-- && !(*status & I2C_IF)) {
101                 udelay(1000);
102                 *status = mpc_reg_in(&regs->msr);
103         }
104
105         if (!(*status & I2C_IF)) {
106                 return -1;
107         }
108
109         mpc_reg_out(&regs->msr, 0, I2C_IF);
110
111         return 0;
112 }
113
114 static int do_address(uchar chip, char rdwr_flag)
115 {
116         struct mpc5xxx_i2c *regs = (struct mpc5xxx_i2c *)I2C_BASE;
117         int                 status;
118
119         chip <<= 1;
120
121         if (rdwr_flag) {
122                 chip |= 1;
123         }
124
125         mpc_reg_out(&regs->mcr, I2C_TX, I2C_TX);
126         mpc_reg_out(&regs->mdr, chip, 0);
127
128         if (wait_for_pin(&status)) {
129                 return -2;
130         }
131
132         if (status & I2C_RXAK) {
133                 return -3;
134         }
135
136         return 0;
137 }
138
139 static int send_bytes(uchar chip, char *buf, int len)
140 {
141         struct mpc5xxx_i2c *regs = (struct mpc5xxx_i2c *)I2C_BASE;
142         int                 wrcount;
143         int                 status;
144
145         for (wrcount = 0; wrcount < len; ++wrcount) {
146
147                 mpc_reg_out(&regs->mdr, buf[wrcount], 0);
148
149                 if (wait_for_pin(&status)) {
150                         break;
151                 }
152
153                 if (status & I2C_RXAK) {
154                         break;
155                 }
156
157         }
158
159         return !(wrcount == len);
160 }
161
162 static int receive_bytes(uchar chip, char *buf, int len)
163 {
164         struct mpc5xxx_i2c *regs    = (struct mpc5xxx_i2c *)I2C_BASE;
165         int                 dummy   = 1;
166         int                 rdcount = 0;
167         int                 status;
168         int                 i;
169
170         mpc_reg_out(&regs->mcr, 0, I2C_TX);
171
172         for (i = 0; i < len; ++i) {
173                 buf[rdcount] = mpc_reg_in(&regs->mdr);
174
175                 if (dummy) {
176                         dummy = 0;
177                 } else {
178                         rdcount++;
179                 }
180
181
182                 if (wait_for_pin(&status)) {
183                         return -4;
184                 }
185         }
186
187         mpc_reg_out(&regs->mcr, I2C_TXAK, I2C_TXAK);
188         buf[rdcount++] = mpc_reg_in(&regs->mdr);
189
190         if (wait_for_pin(&status)) {
191                 return -5;
192         }
193
194         mpc_reg_out(&regs->mcr, 0, I2C_TXAK);
195
196         return 0;
197 }
198
199 /**************** I2C API ****************/
200
201 void i2c_init(int speed, int saddr)
202 {
203         struct mpc5xxx_i2c *regs = (struct mpc5xxx_i2c *)I2C_BASE;
204
205         mpc_reg_out(&regs->mcr, 0, 0);
206         mpc_reg_out(&regs->madr, saddr << 1, 0);
207
208         /* Set clock
209          */
210         mpc_reg_out(&regs->mfdr, speed, 0);
211
212         /* Enable module
213          */
214         mpc_reg_out(&regs->mcr, I2C_EN, I2C_INIT_MASK);
215         mpc_reg_out(&regs->msr, 0, I2C_IF);
216
217         return;
218 }
219
220 int i2c_probe(uchar chip)
221 {
222         struct mpc5xxx_i2c *regs = (struct mpc5xxx_i2c *)I2C_BASE;
223         int                 i;
224
225         for (i = 0; i < I2C_RETRIES; i++) {
226                 mpc_reg_out(&regs->mcr, I2C_STA, I2C_STA);
227
228                 if (! do_address(chip, 0)) {
229                         mpc_reg_out(&regs->mcr, 0, I2C_STA);
230                         break;
231                 }
232
233                 mpc_reg_out(&regs->mcr, 0, I2C_STA);
234                 udelay(500);
235         }
236
237         return (i == I2C_RETRIES);
238 }
239
240 int i2c_read(uchar chip, uint addr, int alen, uchar *buf, int len)
241 {
242         uchar                xaddr[4];
243         struct mpc5xxx_i2c * regs        = (struct mpc5xxx_i2c *)I2C_BASE;
244         int                  ret         = -1;
245
246         xaddr[0] = (addr >> 24) & 0xFF;
247         xaddr[1] = (addr >> 16) & 0xFF;
248         xaddr[2] = (addr >>  8) & 0xFF;
249         xaddr[3] =  addr        & 0xFF;
250
251         if (wait_for_bb()) {
252                 printf("i2c_read: bus is busy\n");
253                 goto Done;
254         }
255
256         mpc_reg_out(&regs->mcr, I2C_STA, I2C_STA);
257         if (do_address(chip, 0)) {
258                 printf("i2c_read: failed to address chip\n");
259                 goto Done;
260         }
261
262         if (send_bytes(chip, &xaddr[4-alen], alen)) {
263                 printf("i2c_read: send_bytes failed\n");
264                 goto Done;
265         }
266
267         mpc_reg_out(&regs->mcr, I2C_RSTA, I2C_RSTA);
268         if (do_address(chip, 1)) {
269                 printf("i2c_read: failed to address chip\n");
270                 goto Done;
271         }
272
273         if (receive_bytes(chip, buf, len)) {
274                 printf("i2c_read: receive_bytes failed\n");
275                 goto Done;
276         }
277
278         ret = 0;
279 Done:
280         mpc_reg_out(&regs->mcr, 0, I2C_STA);
281         return ret;
282 }
283
284 int i2c_write(uchar chip, uint addr, int alen, uchar *buf, int len)
285 {
286         uchar               xaddr[4];
287         struct mpc5xxx_i2c *regs        = (struct mpc5xxx_i2c *)I2C_BASE;
288         int                 ret         = -1;
289
290         xaddr[0] = (addr >> 24) & 0xFF;
291         xaddr[1] = (addr >> 16) & 0xFF;
292         xaddr[2] = (addr >>  8) & 0xFF;
293         xaddr[3] =  addr        & 0xFF;
294
295         if (wait_for_bb()) {
296                 printf("i2c_write: bus is busy\n");
297                 goto Done;
298         }
299
300         mpc_reg_out(&regs->mcr, I2C_STA, I2C_STA);
301         if (do_address(chip, 0)) {
302                 printf("i2c_write: failed to address chip\n");
303                 goto Done;
304         }
305
306         if (send_bytes(chip, &xaddr[4-alen], alen)) {
307                 printf("i2c_write: send_bytes failed\n");
308                 goto Done;
309         }
310
311         if (send_bytes(chip, buf, len)) {
312                 printf("i2c_write: send_bytes failed\n");
313                 goto Done;
314         }
315
316         ret = 0;
317 Done:
318         mpc_reg_out(&regs->mcr, 0, I2C_STA);
319         return ret;
320 }
321
322 uchar i2c_reg_read(uchar chip, uchar reg)
323 {
324         char buf;
325
326         i2c_read(chip, reg, 1, &buf, 1);
327
328         return buf;
329 }
330
331 void i2c_reg_write(uchar chip, uchar reg, uchar val)
332 {
333         i2c_write(chip, reg, 1, &val, 1);
334
335         return;
336 }
337
338 #endif  /* CONFIG_HARD_I2C */