]> git.kernelconcepts.de Git - karo-tx-uboot.git/blob - drivers/s3c24x0_i2c.c
4158b148cf8c55fba81777d20d95d6d749d6cb8d
[karo-tx-uboot.git] / drivers / s3c24x0_i2c.c
1 /*
2  * (C) Copyright 2002
3  * David Mueller, ELSOFT AG, d.mueller@elsoft.ch
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 /* This code should work for both the S3C2400 and the S3C2410
25  * as they seem to have the same I2C controller inside.
26  * The different address mapping is handled by the s3c24xx.h files below.
27  */
28
29 #include <common.h>
30
31 #ifdef CONFIG_DRIVER_S3C24X0_I2C
32
33 #if defined(CONFIG_S3C2400)
34 #include <s3c2400.h>
35 #elif defined(CONFIG_S3C2410)
36 #include <s3c2410.h>
37 #endif
38 #include <i2c.h>
39
40 #ifdef CONFIG_HARD_I2C
41
42 #define I2C_WRITE       0
43 #define I2C_READ        1
44
45 #define I2C_OK          0
46 #define I2C_NOK         1
47 #define I2C_NACK        2
48 #define I2C_NOK_LA      3               /* Lost arbitration */
49 #define I2C_NOK_TOUT    4               /* time out */
50
51 #define I2CSTAT_BSY     0x20            /* Busy bit */
52 #define I2CSTAT_NACK    0x01            /* Nack bit */
53 #define I2CCON_IRPND    0x10            /* Interrupt pending bit */
54 #define I2C_MODE_MT     0xC0            /* Master Transmit Mode */
55 #define I2C_MODE_MR     0x80            /* Master Receive Mode */
56 #define I2C_START_STOP  0x20            /* START / STOP */
57 #define I2C_TXRX_ENA    0x10            /* I2C Tx/Rx enable */
58
59 #define I2C_TIMEOUT 1                   /* 1 seconde */
60
61
62 static int GetI2CSDA(void)
63 {
64         S3C24X0_GPIO * const gpio = S3C24X0_GetBase_GPIO();
65
66 #ifdef CONFIG_S3C2410
67         return (gpio->GPEDAT & 0x8000) >> 15;
68 #endif
69 #ifdef CONFIG_S3C2400
70         return (gpio->PGDAT & 0x0020) >> 5;
71 #endif
72 }
73
74 #if 0
75 static void SetI2CSDA(int x)
76 {
77         rGPEDAT = (rGPEDAT & ~0x8000) | (x&1) << 15;
78 }
79 #endif
80
81 static void SetI2CSCL(int x)
82 {
83         S3C24X0_GPIO * const gpio = S3C24X0_GetBase_GPIO();
84
85 #ifdef CONFIG_S3C2410
86         gpio->GPEDAT = (gpio->GPEDAT & ~0x4000) | (x&1) << 14;
87 #endif
88 #ifdef CONFIG_S3C2400
89         gpio->PGDAT = (gpio->PGDAT & ~0x0040) | (x&1) << 6;
90 #endif
91 }
92
93
94 static int WaitForXfer(void)
95 {
96     S3C24X0_I2C * const i2c = S3C24X0_GetBase_I2C();
97     int i, status;
98
99     i = I2C_TIMEOUT * 1000;
100     status = i2c->IICCON;
101     while ((i > 0) && !(status & I2CCON_IRPND)) {
102         udelay(1000);
103         status = i2c->IICCON;
104         i--;
105     }
106
107     return(status & I2CCON_IRPND) ? I2C_OK : I2C_NOK_TOUT;
108 }
109
110 static int IsACK(void)
111 {
112     S3C24X0_I2C * const i2c = S3C24X0_GetBase_I2C();
113
114     return(!(i2c->IICSTAT & I2CSTAT_NACK));
115 }
116
117 static void ReadWriteByte(void)
118 {
119     S3C24X0_I2C * const i2c = S3C24X0_GetBase_I2C();
120
121     i2c->IICCON &= ~I2CCON_IRPND;
122 }
123
124 void i2c_init (int speed, int slaveadd)
125 {
126     S3C24X0_I2C * const i2c = S3C24X0_GetBase_I2C();
127     S3C24X0_GPIO * const gpio = S3C24X0_GetBase_GPIO();
128     ulong freq, pres = 16, div;
129     int i, status;
130
131     /* wait for some time to give previous transfer a chance to finish */
132
133     i = I2C_TIMEOUT * 1000;
134     status = i2c->IICSTAT;
135     while ((i > 0) && (status & I2CSTAT_BSY)) {
136         udelay(1000);
137         status = i2c->IICSTAT;
138         i--;
139     }
140
141     if ((status & I2CSTAT_BSY) || GetI2CSDA() == 0) {
142 #ifdef CONFIG_S3C2410
143         ulong old_gpecon = gpio->GPECON;
144 #endif
145 #ifdef CONFIG_S3C2400
146         ulong old_gpecon = gpio->PGCON;
147 #endif
148         /* bus still busy probably by (most) previously interrupted transfer */
149
150 #ifdef CONFIG_S3C2410
151         /* set I2CSDA and I2CSCL (GPE15, GPE14) to GPIO */
152         gpio->GPECON = (gpio->GPECON & ~0xF0000000) | 0x10000000;
153 #endif
154 #ifdef CONFIG_S3C2400
155         /* set I2CSDA and I2CSCL (PG5, PG6) to GPIO */
156         gpio->PGCON = (gpio->PGCON & ~0x00003c00) | 0x00000c00;
157 #endif
158
159         /* toggle I2CSCL until bus idle */
160         SetI2CSCL(0); udelay(1000);
161         i = 10;
162         while ((i > 0) && (GetI2CSDA() != 1)) {
163                 SetI2CSCL(1); udelay(1000);
164                 SetI2CSCL(0); udelay(1000);
165                 i--;
166         }
167         SetI2CSCL(1); udelay(1000);
168
169         /* restore pin functions */
170 #ifdef CONFIG_S3C2410
171         gpio->GPECON = old_gpecon;
172 #endif
173 #ifdef CONFIG_S3C2400
174         gpio->PGCON = old_gpecon;
175 #endif
176     }
177
178     /* calculate prescaler and divisor values */
179     freq = get_PCLK();
180     if ((freq / pres / (16+1)) > speed)
181         /* set prescaler to 512 */
182         pres = 512;
183
184     div = 0;
185     while ((freq / pres / (div+1)) > speed)
186         div++;
187
188     /* set prescaler, divisor according to freq, also set
189        ACKGEN, IRQ */
190     i2c->IICCON = (div & 0x0F) | 0xA0 | ((pres == 512) ? 0x40 : 0);
191
192     /* init to SLAVE REVEIVE and set slaveaddr */
193     i2c->IICSTAT = 0;
194     i2c->IICADD = slaveadd;
195     /* program Master Transmit (and implicit STOP) */
196     i2c->IICSTAT = I2C_MODE_MT | I2C_TXRX_ENA;
197
198 }
199
200 /*
201   cmd_type is 0 for write 1 for read.
202
203   addr_len can take any value from 0-255, it is only limited
204   by the char, we could make it larger if needed. If it is
205   0 we skip the address write cycle.
206
207 */
208 static
209 int i2c_transfer(unsigned char cmd_type,
210                  unsigned char chip,
211                  unsigned char addr[],
212                  unsigned char addr_len,
213                  unsigned char data[],
214                  unsigned short data_len)
215 {
216     S3C24X0_I2C * const i2c = S3C24X0_GetBase_I2C();
217     int i, status, result;
218
219     if (data == 0 || data_len == 0) {
220         /*Don't support data transfer of no length or to address 0*/
221         printf( "i2c_transfer: bad call\n" );
222         return I2C_NOK;
223     }
224
225     /*CheckDelay(); */
226
227     /* Check I2C bus idle */
228     i = I2C_TIMEOUT * 1000;
229     status = i2c->IICSTAT;
230     while ((i > 0) && (status & I2CSTAT_BSY)) {
231         udelay(1000);
232         status = i2c->IICSTAT;
233         i--;
234     }
235
236
237     if (status & I2CSTAT_BSY) {
238         result = I2C_NOK_TOUT;
239         return(result);
240     }
241
242     i2c->IICCON |= 0x80;
243
244     result = I2C_OK;
245
246     switch (cmd_type) {
247         case I2C_WRITE:
248             if (addr && addr_len) {
249                 i2c->IICDS = chip;
250                 /* send START */
251                 i2c->IICSTAT = I2C_MODE_MT | I2C_TXRX_ENA | I2C_START_STOP;
252                 i = 0;
253                 while ((i < addr_len) && (result == I2C_OK)) {
254                     result = WaitForXfer();
255                     i2c->IICDS = addr[i];
256                     ReadWriteByte();
257                     i++;
258                 }
259                 i = 0;
260                 while ((i < data_len) && (result == I2C_OK)) {
261                     result = WaitForXfer();
262                     i2c->IICDS = data[i];
263                     ReadWriteByte();
264                     i++;
265                 }
266             } else {
267                 i2c->IICDS = chip;
268                 /* send START */
269                 i2c->IICSTAT = I2C_MODE_MT | I2C_TXRX_ENA | I2C_START_STOP;
270                 i = 0;
271                 while ((i < data_len) && (result = I2C_OK)) {
272                     result = WaitForXfer();
273                     i2c->IICDS = data[i];
274                     ReadWriteByte();
275                     i++;
276                 }
277             }
278
279             if (result == I2C_OK)
280                 result = WaitForXfer();
281
282             /* send STOP */
283             i2c->IICSTAT = I2C_MODE_MR | I2C_TXRX_ENA;
284             ReadWriteByte();
285             break;
286
287         case I2C_READ:
288             if (addr && addr_len) {
289                 i2c->IICSTAT = I2C_MODE_MT | I2C_TXRX_ENA;
290                 i2c->IICDS = chip;
291                 /* send START */
292                 i2c->IICSTAT |= I2C_START_STOP;
293                 result = WaitForXfer();
294                 if (IsACK()) {
295                     i = 0;
296                     while ((i < addr_len) && (result == I2C_OK)) {
297                         i2c->IICDS = addr[i];
298                         ReadWriteByte();
299                         result = WaitForXfer();
300                         i++;
301                     }
302
303                     i2c->IICDS = chip;
304                     /* resend START */
305                     i2c->IICSTAT = I2C_MODE_MR | I2C_TXRX_ENA | I2C_START_STOP;
306                     ReadWriteByte();
307                     result = WaitForXfer();
308                     i = 0;
309                     while ((i < data_len) && (result == I2C_OK)) {
310                         /* disable ACK for final READ */
311                         if (i == data_len - 1)
312                             i2c->IICCON &= ~0x80;
313                         ReadWriteByte();
314                         result = WaitForXfer();
315                         data[i] = i2c->IICDS;
316                         i++;
317                     }
318                 } else {
319                     result = I2C_NACK;
320                 }
321
322             } else {
323                 i2c->IICSTAT = I2C_MODE_MR | I2C_TXRX_ENA;
324                 i2c->IICDS = chip;
325                 /* send START */
326                 i2c->IICSTAT |= I2C_START_STOP;
327                 result = WaitForXfer();
328
329                 if (IsACK()) {
330                     i = 0;
331                     while ((i < data_len) && (result == I2C_OK)) {
332                         /* disable ACK for final READ */
333                         if (i == data_len - 1)
334                             i2c->IICCON &= ~0x80;
335                         ReadWriteByte();
336                         result = WaitForXfer();
337                         data[i] = i2c->IICDS;
338                         i++;
339                     }
340                 } else {
341                     result = I2C_NACK;
342                 }
343             }
344
345             /* send STOP */
346             i2c->IICSTAT = I2C_MODE_MR | I2C_TXRX_ENA;
347             ReadWriteByte();
348             break;
349
350         default:
351             printf( "i2c_transfer: bad call\n" );
352             result = I2C_NOK;
353             break;
354     }
355
356     return (result);
357 }
358
359 int i2c_probe (uchar chip)
360 {
361     uchar buf[1];
362
363     buf[0] = 0;
364
365     /*
366      * What is needed is to send the chip address and verify that the
367      * address was <ACK>ed (i.e. there was a chip at that address which
368      * drove the data line low).
369      */
370     return(i2c_transfer (I2C_READ, chip << 1, 0, 0, buf, 1) != I2C_OK);
371 }
372
373 int i2c_read (uchar chip, uint addr, int alen, uchar * buffer, int len)
374 {
375     uchar xaddr[4];
376     int ret;
377
378     if ( alen > 4 ) {
379         printf ("I2C read: addr len %d not supported\n", alen);
380         return 1;
381     }
382
383     if ( alen > 0 ) {
384         xaddr[0] = (addr >> 24) & 0xFF;
385         xaddr[1] = (addr >> 16) & 0xFF;
386         xaddr[2] = (addr >> 8) & 0xFF;
387         xaddr[3] = addr & 0xFF;
388     }
389
390
391 #ifdef CFG_I2C_EEPROM_ADDR_OVERFLOW
392     /*
393      * EEPROM chips that implement "address overflow" are ones
394      * like Catalyst 24WC04/08/16 which has 9/10/11 bits of
395      * address and the extra bits end up in the "chip address"
396      * bit slots. This makes a 24WC08 (1Kbyte) chip look like
397      * four 256 byte chips.
398      *
399      * Note that we consider the length of the address field to
400      * still be one byte because the extra address bits are
401      * hidden in the chip address.
402      */
403     if( alen > 0 )
404         chip |= ((addr >> (alen * 8)) & CFG_I2C_EEPROM_ADDR_OVERFLOW);
405 #endif
406     if( (ret = i2c_transfer(I2C_READ, chip<<1, &xaddr[4-alen], alen, buffer, len )) != 0) {
407         printf( "I2c read: failed %d\n", ret);
408         return 1;
409     }
410     return 0;
411 }
412
413 int i2c_write (uchar chip, uint addr, int alen, uchar * buffer, int len)
414 {
415     uchar xaddr[4];
416
417     if ( alen > 4 ) {
418         printf ("I2C write: addr len %d not supported\n", alen);
419         return 1;
420     }
421
422     if ( alen > 0 ) {
423         xaddr[0] = (addr >> 24) & 0xFF;
424         xaddr[1] = (addr >> 16) & 0xFF;
425         xaddr[2] = (addr >> 8) & 0xFF;
426         xaddr[3] = addr & 0xFF;
427     }
428
429 #ifdef CFG_I2C_EEPROM_ADDR_OVERFLOW
430     /*
431      * EEPROM chips that implement "address overflow" are ones
432      * like Catalyst 24WC04/08/16 which has 9/10/11 bits of
433      * address and the extra bits end up in the "chip address"
434      * bit slots. This makes a 24WC08 (1Kbyte) chip look like
435      * four 256 byte chips.
436      *
437      * Note that we consider the length of the address field to
438      * still be one byte because the extra address bits are
439      * hidden in the chip address.
440      */
441     if( alen > 0 )
442         chip |= ((addr >> (alen * 8)) & CFG_I2C_EEPROM_ADDR_OVERFLOW);
443 #endif
444     return (i2c_transfer(I2C_WRITE, chip<<1, &xaddr[4-alen], alen, buffer, len ) != 0);
445 }
446
447 #endif  /* CONFIG_HARD_I2C */
448
449 #endif /* CONFIG_DRIVER_S3C24X0_I2C */