]> git.kernelconcepts.de Git - karo-tx-uboot.git/blob - drivers/s3c24x0_i2c.c
bf435c9839ad60891ce179917f41ebf8d20ccbcb
[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 IIC_WRITE       0
43 #define IIC_READ        1
44
45 #define IIC_OK          0
46 #define IIC_NOK         1
47 #define IIC_NACK        2
48 #define IIC_NOK_LA      3               /* Lost arbitration */
49 #define IIC_NOK_TOUT    4               /* time out */
50
51 #define IICSTAT_BSY     0x20            /* Busy bit */
52 #define IICSTAT_NACK    0x01            /* Nack bit */
53 #define IICCON_IRPND    0x10            /* Interrupt pending bit */
54 #define IIC_MODE_MT     0xC0            /* Master Transmit Mode */
55 #define IIC_MODE_MR     0x80            /* Master Receive Mode */
56 #define IIC_START_STOP  0x20            /* START / STOP */
57 #define IIC_TXRX_ENA    0x10            /* I2C Tx/Rx enable */
58
59 #define IIC_TIMEOUT 1                   /* 1 seconde */
60
61
62 static int GetIICSDA(void)
63 {
64         return (rGPEDAT & 0x8000) >> 15;
65 }
66
67 static void SetIICSDA(int x)
68 {
69         rGPEDAT = (rGPEDAT & ~0x8000) | (x&1) << 15;
70 }
71
72 static void SetIICSCL(int x)
73 {
74         rGPEDAT = (rGPEDAT & ~0x4000) | (x&1) << 14;
75 }
76
77
78 static int WaitForXfer(void)
79 {
80     int i, status;
81
82     i = IIC_TIMEOUT * 1000;
83     status = rIICCON;
84     while ((i > 0) && !(status & IICCON_IRPND)) {
85         udelay(1000);
86         status = rIICCON;
87         i--;
88     }
89
90     return(status & IICCON_IRPND) ? IIC_OK : IIC_NOK_TOUT;
91 }
92
93 static int IsACK(void)
94 {
95     return(!(rIICSTAT & IICSTAT_NACK));
96 }
97
98 static void ReadWriteByte(void)
99 {
100     rIICCON &= ~IICCON_IRPND;
101 }
102
103 void i2c_init (int speed, int slaveadd)
104 {
105     ulong freq, pres = 16, div;
106     int i, status;
107
108     /* wait for some time to give previous transfer a chance to finish */
109
110     i = IIC_TIMEOUT * 1000;
111     status = rIICSTAT;
112     while ((i > 0) && (status & IICSTAT_BSY)) {
113         udelay(1000);
114         status = rIICSTAT;
115         i--;
116     }
117
118     if ((status & IICSTAT_BSY) || GetIICSDA() == 0) {
119         ulong old_gpecon = rGPECON;
120         /* bus still busy probably by (most) previously interrupted transfer */
121
122         /* set IICSDA and IICSCL (GPE15, GPE14) to GPIO */
123         rGPECON = (rGPECON & ~0xF0000000) | 0x10000000;
124
125         /* toggle IICSCL until bus idle */
126         SetIICSCL(0); udelay(1000);
127         i = 10;
128         while ((i > 0) && (GetIICSDA() != 1)) {
129                 SetIICSCL(1); udelay(1000);
130                 SetIICSCL(0); udelay(1000);
131                 i--;
132         }
133         SetIICSCL(1); udelay(1000);
134
135         /* restore pin functions */
136         rGPECON = old_gpecon;
137     }
138
139     /* calculate prescaler and divisor values */
140     freq = get_PCLK();
141     if ((freq / pres / (16+1)) > speed)
142         /* set prescaler to 512 */
143         pres = 512;
144
145     div = 0;
146     while ((freq / pres / (div+1)) > speed)
147         div++;
148
149     /* set prescaler, divisor according to freq, also set
150        ACKGEN, IRQ */
151     rIICCON = (div & 0x0F) | 0xA0 | ((pres == 512) ? 0x40 : 0);
152
153     /* init to SLAVE REVEIVE and set slaveaddr */
154     rIICSTAT = 0;
155     rIICADD = slaveadd;
156     /* program Master Transmit (and implicit STOP) */
157     rIICSTAT = IIC_MODE_MT | IIC_TXRX_ENA;
158
159 }
160
161 /*
162   cmd_type is 0 for write 1 for read.
163
164   addr_len can take any value from 0-255, it is only limited
165   by the char, we could make it larger if needed. If it is
166   0 we skip the address write cycle.
167
168 */
169 static
170 int i2c_transfer(unsigned char cmd_type,
171                  unsigned char chip,
172                  unsigned char addr[],
173                  unsigned char addr_len,
174                  unsigned char data[],
175                  unsigned short data_len)
176 {
177     int i, status, result;
178
179     if (data == 0 || data_len == 0) {
180         /*Don't support data transfer of no length or to address 0*/
181         printf( "i2c_transfer: bad call\n" );
182         return IIC_NOK;
183     }
184
185     //CheckDelay();
186
187     /* Check I2C bus idle */
188     i = IIC_TIMEOUT * 1000;
189     status = rIICSTAT;
190     while ((i > 0) && (status & IICSTAT_BSY)) {
191         udelay(1000);
192         status = rIICSTAT;
193         i--;
194     }
195
196
197     if (status & IICSTAT_BSY) {
198         result = IIC_NOK_TOUT;
199         return(result);
200     }
201
202     rIICCON |= 0x80;
203
204     result = IIC_OK;
205
206     switch (cmd_type) {
207         case IIC_WRITE:
208             if (addr && addr_len) {
209                 rIICDS = chip;
210                 /* send START */
211                 rIICSTAT = IIC_MODE_MT | IIC_TXRX_ENA | IIC_START_STOP;
212                 i = 0;
213                 while ((i < addr_len) && (result == IIC_OK)) {
214                     result = WaitForXfer();
215                     rIICDS = addr[i];
216                     ReadWriteByte();
217                     i++;
218                 }
219                 i = 0;
220                 while ((i < data_len) && (result == IIC_OK)) {
221                     result = WaitForXfer();
222                     rIICDS = data[i];
223                     ReadWriteByte();
224                     i++;
225                 }
226             } else {
227                 rIICDS = chip;
228                 /* send START */
229                 rIICSTAT = IIC_MODE_MT | IIC_TXRX_ENA | IIC_START_STOP;
230                 i = 0;
231                 while ((i < data_len) && (result = IIC_OK)) {
232                     result = WaitForXfer();
233                     rIICDS = data[i];
234                     ReadWriteByte();
235                     i++;
236                 }
237             }
238
239             if (result == IIC_OK)
240                 result = WaitForXfer();
241
242             /* send STOP */
243             rIICSTAT = IIC_MODE_MR | IIC_TXRX_ENA;
244             ReadWriteByte();
245             break;
246
247         case IIC_READ:
248             if (addr && addr_len) {
249                 rIICSTAT = IIC_MODE_MT | IIC_TXRX_ENA;
250                 rIICDS = chip;
251                 /* send START */
252                 rIICSTAT |= IIC_START_STOP;
253                 result = WaitForXfer();
254                 if (IsACK()) {
255                     i = 0;
256                     while ((i < addr_len) && (result == IIC_OK)) {
257                         rIICDS = addr[i];
258                         ReadWriteByte();
259                         result = WaitForXfer();
260                         i++;
261                     }
262
263                     rIICDS = chip;
264                     /* resend START */
265                     rIICSTAT = IIC_MODE_MR | IIC_TXRX_ENA | IIC_START_STOP;
266                     ReadWriteByte();
267                     result = WaitForXfer();
268                     i = 0;
269                     while ((i < data_len) && (result == IIC_OK)) {
270                         /* disable ACK for final READ */
271                         if (i == data_len - 1)
272                             rIICCON &= ~0x80;
273                         ReadWriteByte();
274                         result = WaitForXfer();
275                         data[i] = rIICDS;
276                         i++;
277                     }
278                 } else {
279                     result = IIC_NACK;
280                 }
281
282             } else {
283                 rIICSTAT = IIC_MODE_MR | IIC_TXRX_ENA;
284                 rIICDS = chip;
285                 /* send START */
286                 rIICSTAT |= IIC_START_STOP;
287                 result = WaitForXfer();
288
289                 if (IsACK()) {
290                     i = 0;
291                     while ((i < data_len) && (result == IIC_OK)) {
292                         /* disable ACK for final READ */
293                         if (i == data_len - 1)
294                             rIICCON &= ~0x80;
295                         ReadWriteByte();
296                         result = WaitForXfer();
297                         data[i] = rIICDS;
298                         i++;
299                     }
300                 } else {
301                     result = IIC_NACK;
302                 }
303             }
304
305             /* send STOP */
306             rIICSTAT = IIC_MODE_MR | IIC_TXRX_ENA;
307             ReadWriteByte();
308             break;
309
310         default:
311             printf( "i2c_transfer: bad call\n" );
312             result = IIC_NOK;
313             break;
314     }
315
316     return (result);
317 }
318
319 int i2c_probe (uchar chip)
320 {
321     uchar buf[1];
322
323     buf[0] = 0;
324
325     /*
326      * What is needed is to send the chip address and verify that the
327      * address was <ACK>ed (i.e. there was a chip at that address which
328      * drove the data line low).
329      */
330     return(i2c_transfer (IIC_READ, chip << 1, 0, 0, buf, 1) != IIC_OK);
331 }
332
333 int i2c_read (uchar chip, uint addr, int alen, uchar * buffer, int len)
334 {
335     uchar xaddr[4];
336     int ret;
337
338     if ( alen > 4 ) {
339         printf ("I2C read: addr len %d not supported\n", alen);
340         return 1;
341     }
342
343     if ( alen > 0 ) {
344         xaddr[0] = (addr >> 24) & 0xFF;
345         xaddr[1] = (addr >> 16) & 0xFF;
346         xaddr[2] = (addr >> 8) & 0xFF;
347         xaddr[3] = addr & 0xFF;
348     }
349
350
351 #ifdef CFG_I2C_EEPROM_ADDR_OVERFLOW
352     /*
353      * EEPROM chips that implement "address overflow" are ones
354      * like Catalyst 24WC04/08/16 which has 9/10/11 bits of
355      * address and the extra bits end up in the "chip address"
356      * bit slots. This makes a 24WC08 (1Kbyte) chip look like
357      * four 256 byte chips.
358      *
359      * Note that we consider the length of the address field to
360      * still be one byte because the extra address bits are
361      * hidden in the chip address.
362      */
363     if( alen > 0 )
364         chip |= ((addr >> (alen * 8)) & CFG_I2C_EEPROM_ADDR_OVERFLOW);
365 #endif
366     if( (ret = i2c_transfer(IIC_READ, chip<<1, &xaddr[4-alen], alen, buffer, len )) != 0) {
367         printf( "I2c read: failed %d\n", ret);
368         return 1;
369     }
370     return 0;
371 }
372
373 int i2c_write (uchar chip, uint addr, int alen, uchar * buffer, int len)
374 {
375     uchar xaddr[4];
376
377     if ( alen > 4 ) {
378         printf ("I2C write: addr len %d not supported\n", alen);
379         return 1;
380     }
381
382     if ( alen > 0 ) {
383         xaddr[0] = (addr >> 24) & 0xFF;
384         xaddr[1] = (addr >> 16) & 0xFF;
385         xaddr[2] = (addr >> 8) & 0xFF;
386         xaddr[3] = addr & 0xFF;
387     }
388
389 #ifdef CFG_I2C_EEPROM_ADDR_OVERFLOW
390     /*
391      * EEPROM chips that implement "address overflow" are ones
392      * like Catalyst 24WC04/08/16 which has 9/10/11 bits of
393      * address and the extra bits end up in the "chip address"
394      * bit slots. This makes a 24WC08 (1Kbyte) chip look like
395      * four 256 byte chips.
396      *
397      * Note that we consider the length of the address field to
398      * still be one byte because the extra address bits are
399      * hidden in the chip address.
400      */
401     if( alen > 0 )
402         chip |= ((addr >> (alen * 8)) & CFG_I2C_EEPROM_ADDR_OVERFLOW);
403 #endif
404     return (i2c_transfer(IIC_WRITE, chip<<1, &xaddr[4-alen], alen, buffer, len ) != 0);
405 }
406
407 #endif  /* CONFIG_HARD_I2C */
408
409 #endif /* CONFIG_DRIVER_S3C24X0_I2C */