blob: b4d904b2eb4ae385a1450b8548180dca58a5028d [file] [log] [blame]
Jean-Christophe PLAGNIOL-VILLARD50f601c2009-03-29 23:01:40 +02001/*
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 * See file CREDITS for list of people who contributed to this
9 * project.
10 *
11 * This program is free software; you can redistribute it and/or
12 * modify it under the terms of the GNU General Public License as
13 * published by the Free Software Foundation; either version 2 of
14 * the License, or (at your option) any later version.
15 *
16 * This program is distributed in the hope that it will be useful,
17 * but WITHOUT ANY WARRANTY; without even the implied warranty of
18 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19 * GNU General Public License for more details.
20 *
21 * You should have received a copy of the GNU General Public License
22 * along with this program; if not, write to the Free Software
23 * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
24 * MA 02111-1307 USA
25 */
26
27#include <common.h>
28#include <command.h>
29#include <asm/hardware.h>
30
31/*
32 * Initialization, must be called once on start up, may be called
33 * repeatedly to change the speed and slave addresses.
34 */
35void i2c_init(int speed, int slaveaddr)
36{
37 /*
38 setting up I2C support
39 */
40 unsigned int save_F,save_PF,rIICCON,rPCONA,rPDATA,rPCONF,rPUPF;
41
42 save_F = PCONF;
43 save_PF = PUPF;
44
45 rPCONF = ((save_F & ~(0xF))| 0xa);
46 rPUPF = (save_PF | 0x3);
47 PCONF = rPCONF; /*PF0:IICSCL, PF1:IICSDA*/
48 PUPF = rPUPF; /* Disable pull-up */
49
50 /* Configuring pin for WC pin of EEprom */
51 rPCONA = PCONA;
52 rPCONA &= ~(1<<9);
53 PCONA = rPCONA;
54
55 rPDATA = PDATA;
56 rPDATA &= ~(1<<9);
57 PDATA = rPDATA;
58
59 /*
60 Enable ACK, IICCLK=MCLK/16, enable interrupt
61 75MHz/16/(12+1) = 390625 Hz
62 */
63 rIICCON=(1<<7)|(0<<6)|(1<<5)|(0xC);
64 IICCON = rIICCON;
65
66 IICADD = slaveaddr;
67}
68
69/*
70 * Probe the given I2C chip address. Returns 0 if a chip responded,
71 * not 0 on failure.
72 */
73int i2c_probe(uchar chip)
74{
75 /*
76 not implemented
77 */
78
79 printf("i2c_probe chip %d\n", (int) chip);
80 return -1;
81}
82
83/*
84 * Read/Write interface:
85 * chip: I2C chip address, range 0..127
86 * addr: Memory (register) address within the chip
87 * alen: Number of bytes to use for addr (typically 1, 2 for larger
88 * memories, 0 for register type devices with only one
89 * register)
90 * buffer: Where to read/write the data
91 * len: How many bytes to read/write
92 *
93 * Returns: 0 on success, not 0 on failure
94 */
95
96#define S3C44B0X_rIIC_INTPEND (1<<4)
97#define S3C44B0X_rIIC_LAST_RECEIV_BIT (1<<0)
98#define S3C44B0X_rIIC_INTERRUPT_ENABLE (1<<5)
99#define S3C44B0_IIC_TIMEOUT 100
100
101int i2c_read(uchar chip, uint addr, int alen, uchar *buffer, int len)
102{
103
104 int k, j, temp;
105 u32 rIICSTAT;
106
107 /*
108 send the device offset
109 */
110
111 rIICSTAT = 0xD0;
112 IICSTAT = rIICSTAT;
113
114 IICDS = chip; /* this is a write operation... */
115
116 rIICSTAT |= (1<<5);
117 IICSTAT = rIICSTAT;
118
119 for(k=0; k<S3C44B0_IIC_TIMEOUT; k++) {
120 temp = IICCON;
121 if( (temp & S3C44B0X_rIIC_INTPEND) == S3C44B0X_rIIC_INTPEND)
122 break;
123 udelay(2000);
124 }
125 if (k==S3C44B0_IIC_TIMEOUT)
126 return -1;
127
128 /* wait and check ACK */
129 temp = IICSTAT;
130 if ((temp & S3C44B0X_rIIC_LAST_RECEIV_BIT) == S3C44B0X_rIIC_LAST_RECEIV_BIT )
131 return -1;
132
133 IICDS = addr;
134 IICCON = IICCON & ~(S3C44B0X_rIIC_INTPEND);
135
136 /* wait and check ACK */
137 for(k=0; k<S3C44B0_IIC_TIMEOUT; k++) {
138 temp = IICCON;
139 if( (temp & S3C44B0X_rIIC_INTPEND) == S3C44B0X_rIIC_INTPEND)
140 break;
141 udelay(2000);
142 }
143 if (k==S3C44B0_IIC_TIMEOUT)
144 return -1;
145
146 temp = IICSTAT;
147 if ((temp & S3C44B0X_rIIC_LAST_RECEIV_BIT) == S3C44B0X_rIIC_LAST_RECEIV_BIT )
148 return -1;
149
150 /*
151 now we can start with the read operation...
152 */
153
154 IICDS = chip | 0x01; /* this is a read operation... */
155
156 rIICSTAT = 0x90; /*master recv*/
157 rIICSTAT |= (1<<5);
158 IICSTAT = rIICSTAT;
159
160 IICCON = IICCON & ~(S3C44B0X_rIIC_INTPEND);
161
162 /* wait and check ACK */
163 for(k=0; k<S3C44B0_IIC_TIMEOUT; k++) {
164 temp = IICCON;
165 if( (temp & S3C44B0X_rIIC_INTPEND) == S3C44B0X_rIIC_INTPEND)
166 break;
167 udelay(2000);
168 }
169 if (k==S3C44B0_IIC_TIMEOUT)
170 return -1;
171
172 temp = IICSTAT;
173 if ((temp & S3C44B0X_rIIC_LAST_RECEIV_BIT) == S3C44B0X_rIIC_LAST_RECEIV_BIT )
174 return -1;
175
176 for (j=0; j<len-1; j++) {
177
178 /*clear pending bit to resume */
179
180 temp = IICCON & ~(S3C44B0X_rIIC_INTPEND);
181 IICCON = temp;
182
183 /* wait and check ACK */
184 for(k=0; k<S3C44B0_IIC_TIMEOUT; k++) {
185 temp = IICCON;
186 if( (temp & S3C44B0X_rIIC_INTPEND) == S3C44B0X_rIIC_INTPEND)
187 break;
188 udelay(2000);
189 }
190 if (k==S3C44B0_IIC_TIMEOUT)
191 return -1;
192
193
194 buffer[j] = IICDS; /*save readed data*/
195
196 } /*end for(j)*/
197
198 /*
199 reading the last data
200 unset ACK generation
201 */
202 temp = IICCON & ~(S3C44B0X_rIIC_INTPEND | (1<<7));
203 IICCON = temp;
204
205 /* wait but NOT check ACK */
206 for(k=0; k<S3C44B0_IIC_TIMEOUT; k++) {
207 temp = IICCON;
208 if( (temp & S3C44B0X_rIIC_INTPEND) == S3C44B0X_rIIC_INTPEND)
209 break;
210 udelay(2000);
211 }
212 if (k==S3C44B0_IIC_TIMEOUT)
213 return -1;
214
215 buffer[j] = IICDS; /*save readed data*/
216
217 rIICSTAT = 0x90; /*master recv*/
218
219 /* Write operation Terminate sending STOP */
220 IICSTAT = rIICSTAT;
221 /*Clear Int Pending Bit to RESUME*/
222 temp = IICCON;
223 IICCON = temp & (~S3C44B0X_rIIC_INTPEND);
224
225 IICCON = IICCON | (1<<7); /*restore ACK generation*/
226
227 return 0;
228}
229
230int i2c_write(uchar chip, uint addr, int alen, uchar *buffer, int len)
231{
232 int j, k;
233 u32 rIICSTAT, temp;
234
235
236 /*
237 send the device offset
238 */
239
240 rIICSTAT = 0xD0;
241 IICSTAT = rIICSTAT;
242
243 IICDS = chip; /* this is a write operation... */
244
245 rIICSTAT |= (1<<5);
246 IICSTAT = rIICSTAT;
247
248 IICCON = IICCON & ~(S3C44B0X_rIIC_INTPEND);
249
250 /* wait and check ACK */
251 for(k=0; k<S3C44B0_IIC_TIMEOUT; k++) {
252 temp = IICCON;
253 if( (temp & S3C44B0X_rIIC_INTPEND) == S3C44B0X_rIIC_INTPEND)
254 break;
255 udelay(2000);
256 }
257 if (k==S3C44B0_IIC_TIMEOUT)
258 return -1;
259
260 temp = IICSTAT;
261 if ((temp & S3C44B0X_rIIC_LAST_RECEIV_BIT) == S3C44B0X_rIIC_LAST_RECEIV_BIT )
262 return -1;
263
264 IICDS = addr;
265 IICCON = IICCON & ~(S3C44B0X_rIIC_INTPEND);
266
267 /* wait and check ACK */
268 for(k=0; k<S3C44B0_IIC_TIMEOUT; k++) {
269 temp = IICCON;
270 if( (temp & S3C44B0X_rIIC_INTPEND) == S3C44B0X_rIIC_INTPEND)
271 break;
272 udelay(2000);
273 }
274 if (k==S3C44B0_IIC_TIMEOUT)
275 return -1;
276
277 temp = IICSTAT;
278 if ((temp & S3C44B0X_rIIC_LAST_RECEIV_BIT) == S3C44B0X_rIIC_LAST_RECEIV_BIT )
279 return -1;
280
281 /*
282 now we can start with the read write operation
283 */
284 for (j=0; j<len; j++) {
285
286 IICDS = buffer[j]; /*prerare data to write*/
287
288 /*clear pending bit to resume*/
289
290 temp = IICCON & ~(S3C44B0X_rIIC_INTPEND);
291 IICCON = temp;
292
293 /* wait but NOT check ACK */
294 for(k=0; k<S3C44B0_IIC_TIMEOUT; k++) {
295 temp = IICCON;
296 if( (temp & S3C44B0X_rIIC_INTPEND) == S3C44B0X_rIIC_INTPEND)
297 break;
298
299 udelay(2000);
300 }
301
302 if (k==S3C44B0_IIC_TIMEOUT)
303 return -1;
304
305 } /* end for(j) */
306
307 /* sending stop to terminate */
308 rIICSTAT = 0xD0; /*master send*/
309 IICSTAT = rIICSTAT;
310 /*Clear Int Pending Bit to RESUME*/
311 temp = IICCON;
312 IICCON = temp & (~S3C44B0X_rIIC_INTPEND);
313
314 return 0;
315}