]> git.kernelconcepts.de Git - karo-tx-uboot.git/blob - drivers/i2c/s3c44b0_i2c.c
i.MX6DQ/DLS: Add pad MX6_PAD_GPIO_1__USB_OTG_ID
[karo-tx-uboot.git] / drivers / i2c / s3c44b0_i2c.c
1 /*
2  * (C) Copyright 2004
3  * DAVE Srl
4  * http://www.dave-tech.it
5  * http://www.wawnet.biz
6  * mailto:info@wawnet.biz
7  *
8  * SPDX-License-Identifier:     GPL-2.0+
9  */
10
11 #include <common.h>
12 #include <command.h>
13 #include <asm/hardware.h>
14
15 /*
16  * Initialization, must be called once on start up, may be called
17  * repeatedly to change the speed and slave addresses.
18  */
19 void i2c_init(int speed, int slaveaddr)
20 {
21         /*
22                 setting up I2C support
23         */
24         unsigned int save_F,save_PF,rIICCON,rPCONA,rPDATA,rPCONF,rPUPF;
25
26         save_F = PCONF;
27         save_PF = PUPF;
28
29         rPCONF = ((save_F & ~(0xF))| 0xa);
30         rPUPF = (save_PF | 0x3);
31         PCONF = rPCONF; /*PF0:IICSCL, PF1:IICSDA*/
32         PUPF = rPUPF; /* Disable pull-up */
33
34         /* Configuring pin for WC pin of EEprom */
35         rPCONA = PCONA;
36         rPCONA &= ~(1<<9);
37         PCONA = rPCONA;
38
39         rPDATA = PDATA;
40         rPDATA &= ~(1<<9);
41         PDATA = rPDATA;
42
43         /*
44                 Enable ACK, IICCLK=MCLK/16, enable interrupt
45                 75MHz/16/(12+1) = 390625 Hz
46         */
47         rIICCON=(1<<7)|(0<<6)|(1<<5)|(0xC);
48         IICCON = rIICCON;
49
50         IICADD = slaveaddr;
51 }
52
53 /*
54  * Probe the given I2C chip address.  Returns 0 if a chip responded,
55  * not 0 on failure.
56  */
57 int i2c_probe(uchar chip)
58 {
59         /*
60                 not implemented
61         */
62
63         printf("i2c_probe chip %d\n", (int) chip);
64         return -1;
65 }
66
67 /*
68  * Read/Write interface:
69  *   chip:    I2C chip address, range 0..127
70  *   addr:    Memory (register) address within the chip
71  *   alen:    Number of bytes to use for addr (typically 1, 2 for larger
72  *              memories, 0 for register type devices with only one
73  *              register)
74  *   buffer:  Where to read/write the data
75  *   len:     How many bytes to read/write
76  *
77  *   Returns: 0 on success, not 0 on failure
78  */
79
80 #define S3C44B0X_rIIC_INTPEND               (1<<4)
81 #define S3C44B0X_rIIC_LAST_RECEIV_BIT       (1<<0)
82 #define S3C44B0X_rIIC_INTERRUPT_ENABLE      (1<<5)
83 #define S3C44B0_IIC_TIMEOUT 100
84
85 int i2c_read(uchar chip, uint addr, int alen, uchar *buffer, int len)
86 {
87
88         int k, j, temp;
89         u32 rIICSTAT;
90
91         /*
92                 send the device offset
93         */
94
95         rIICSTAT = 0xD0;
96         IICSTAT = rIICSTAT;
97
98         IICDS = chip;   /* this is a write operation... */
99
100         rIICSTAT |= (1<<5);
101         IICSTAT = rIICSTAT;
102
103         for(k=0; k<S3C44B0_IIC_TIMEOUT; k++) {
104                 temp = IICCON;
105                 if( (temp & S3C44B0X_rIIC_INTPEND) == S3C44B0X_rIIC_INTPEND)
106                 break;
107                 udelay(2000);
108         }
109         if (k==S3C44B0_IIC_TIMEOUT)
110                 return -1;
111
112         /* wait and check ACK */
113         temp = IICSTAT;
114         if ((temp & S3C44B0X_rIIC_LAST_RECEIV_BIT) == S3C44B0X_rIIC_LAST_RECEIV_BIT )
115                 return -1;
116
117         IICDS = addr;
118         IICCON = IICCON & ~(S3C44B0X_rIIC_INTPEND);
119
120         /* wait and check ACK */
121         for(k=0; k<S3C44B0_IIC_TIMEOUT; k++) {
122                 temp = IICCON;
123                 if( (temp & S3C44B0X_rIIC_INTPEND) == S3C44B0X_rIIC_INTPEND)
124                 break;
125                 udelay(2000);
126         }
127         if (k==S3C44B0_IIC_TIMEOUT)
128                 return -1;
129
130         temp = IICSTAT;
131         if ((temp & S3C44B0X_rIIC_LAST_RECEIV_BIT) == S3C44B0X_rIIC_LAST_RECEIV_BIT )
132                 return -1;
133
134         /*
135                 now we can start with the read operation...
136         */
137
138         IICDS = chip | 0x01;    /* this is a read operation... */
139
140         rIICSTAT = 0x90; /*master recv*/
141         rIICSTAT |= (1<<5);
142         IICSTAT = rIICSTAT;
143
144         IICCON = IICCON & ~(S3C44B0X_rIIC_INTPEND);
145
146         /* wait and check ACK */
147         for(k=0; k<S3C44B0_IIC_TIMEOUT; k++) {
148                 temp = IICCON;
149                 if( (temp & S3C44B0X_rIIC_INTPEND) == S3C44B0X_rIIC_INTPEND)
150                 break;
151                 udelay(2000);
152         }
153         if (k==S3C44B0_IIC_TIMEOUT)
154                 return -1;
155
156         temp = IICSTAT;
157         if ((temp & S3C44B0X_rIIC_LAST_RECEIV_BIT) == S3C44B0X_rIIC_LAST_RECEIV_BIT )
158                 return -1;
159
160         for (j=0; j<len-1; j++) {
161
162         /*clear pending bit to resume */
163
164         temp = IICCON & ~(S3C44B0X_rIIC_INTPEND);
165         IICCON = temp;
166
167         /* wait and check ACK */
168         for(k=0; k<S3C44B0_IIC_TIMEOUT; k++) {
169                 temp = IICCON;
170                 if( (temp & S3C44B0X_rIIC_INTPEND) == S3C44B0X_rIIC_INTPEND)
171                 break;
172                 udelay(2000);
173         }
174         if (k==S3C44B0_IIC_TIMEOUT)
175                 return -1;
176
177
178                 buffer[j] = IICDS; /*save readed data*/
179
180     } /*end for(j)*/
181
182         /*
183                 reading the last data
184                 unset ACK generation
185         */
186         temp = IICCON & ~(S3C44B0X_rIIC_INTPEND | (1<<7));
187         IICCON = temp;
188
189         /* wait but NOT check ACK */
190         for(k=0; k<S3C44B0_IIC_TIMEOUT; k++) {
191                 temp = IICCON;
192                 if( (temp & S3C44B0X_rIIC_INTPEND) == S3C44B0X_rIIC_INTPEND)
193                 break;
194                 udelay(2000);
195         }
196         if (k==S3C44B0_IIC_TIMEOUT)
197                 return -1;
198
199         buffer[j] = IICDS; /*save readed data*/
200
201         rIICSTAT = 0x90; /*master recv*/
202
203         /* Write operation Terminate sending STOP */
204         IICSTAT = rIICSTAT;
205         /*Clear Int Pending Bit to RESUME*/
206         temp = IICCON;
207         IICCON = temp & (~S3C44B0X_rIIC_INTPEND);
208
209         IICCON = IICCON | (1<<7);       /*restore ACK generation*/
210
211         return 0;
212 }
213
214 int i2c_write(uchar chip, uint addr, int alen, uchar *buffer, int len)
215 {
216         int j, k;
217         u32 rIICSTAT, temp;
218
219
220         /*
221                 send the device offset
222         */
223
224         rIICSTAT = 0xD0;
225         IICSTAT = rIICSTAT;
226
227         IICDS = chip;   /* this is a write operation... */
228
229         rIICSTAT |= (1<<5);
230         IICSTAT = rIICSTAT;
231
232         IICCON = IICCON & ~(S3C44B0X_rIIC_INTPEND);
233
234         /* wait and check ACK */
235         for(k=0; k<S3C44B0_IIC_TIMEOUT; k++) {
236                 temp = IICCON;
237                 if( (temp & S3C44B0X_rIIC_INTPEND) == S3C44B0X_rIIC_INTPEND)
238                 break;
239                 udelay(2000);
240         }
241         if (k==S3C44B0_IIC_TIMEOUT)
242                 return -1;
243
244         temp = IICSTAT;
245         if ((temp & S3C44B0X_rIIC_LAST_RECEIV_BIT) == S3C44B0X_rIIC_LAST_RECEIV_BIT )
246                 return -1;
247
248         IICDS = addr;
249         IICCON = IICCON & ~(S3C44B0X_rIIC_INTPEND);
250
251         /* wait and check ACK */
252         for(k=0; k<S3C44B0_IIC_TIMEOUT; k++) {
253                 temp = IICCON;
254                 if( (temp & S3C44B0X_rIIC_INTPEND) == S3C44B0X_rIIC_INTPEND)
255                 break;
256                 udelay(2000);
257         }
258         if (k==S3C44B0_IIC_TIMEOUT)
259           return -1;
260
261         temp = IICSTAT;
262         if ((temp & S3C44B0X_rIIC_LAST_RECEIV_BIT) == S3C44B0X_rIIC_LAST_RECEIV_BIT )
263                 return -1;
264
265         /*
266                 now we can start with the read write operation
267         */
268         for (j=0; j<len; j++) {
269
270                 IICDS = buffer[j]; /*prerare data to write*/
271
272                 /*clear pending bit to resume*/
273
274                 temp = IICCON & ~(S3C44B0X_rIIC_INTPEND);
275                 IICCON = temp;
276
277                 /* wait but NOT check ACK */
278                 for(k=0; k<S3C44B0_IIC_TIMEOUT; k++) {
279                         temp = IICCON;
280                         if( (temp & S3C44B0X_rIIC_INTPEND) == S3C44B0X_rIIC_INTPEND)
281                         break;
282
283                         udelay(2000);
284                 }
285
286                 if (k==S3C44B0_IIC_TIMEOUT)
287                         return -1;
288
289         } /* end for(j) */
290
291         /* sending stop to terminate */
292         rIICSTAT = 0xD0;  /*master send*/
293         IICSTAT = rIICSTAT;
294         /*Clear Int Pending Bit to RESUME*/
295         temp = IICCON;
296         IICCON = temp & (~S3C44B0X_rIIC_INTPEND);
297
298         return 0;
299 }