]>
Commit | Line | Data |
---|---|---|
1 | /* | |
2 | * TI DaVinci (TMS320DM644x) I2C driver. | |
3 | * | |
4 | * Copyright (C) 2007 Sergey Kubushyn <ksi@koi8.net> | |
5 | * | |
6 | * -------------------------------------------------------- | |
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 | ||
29 | #ifdef CONFIG_DRIVER_DAVINCI_I2C | |
30 | ||
31 | #include <i2c.h> | |
32 | #include <asm/arch/hardware.h> | |
33 | #include <asm/arch/i2c_defs.h> | |
34 | ||
35 | #define CHECK_NACK() \ | |
36 | do {\ | |
37 | if (tmp & (I2C_TIMEOUT | I2C_STAT_NACK)) {\ | |
38 | REG(I2C_CON) = 0;\ | |
39 | return(1);\ | |
40 | }\ | |
41 | } while (0) | |
42 | ||
43 | ||
44 | static int wait_for_bus(void) | |
45 | { | |
46 | int stat, timeout; | |
47 | ||
48 | REG(I2C_STAT) = 0xffff; | |
49 | ||
50 | for (timeout = 0; timeout < 10; timeout++) { | |
51 | if (!((stat = REG(I2C_STAT)) & I2C_STAT_BB)) { | |
52 | REG(I2C_STAT) = 0xffff; | |
53 | return(0); | |
54 | } | |
55 | ||
56 | REG(I2C_STAT) = stat; | |
57 | udelay(50000); | |
58 | } | |
59 | ||
60 | REG(I2C_STAT) = 0xffff; | |
61 | return(1); | |
62 | } | |
63 | ||
64 | ||
65 | static int poll_i2c_irq(int mask) | |
66 | { | |
67 | int stat, timeout; | |
68 | ||
69 | for (timeout = 0; timeout < 10; timeout++) { | |
70 | udelay(1000); | |
71 | stat = REG(I2C_STAT); | |
72 | if (stat & mask) { | |
73 | return(stat); | |
74 | } | |
75 | } | |
76 | ||
77 | REG(I2C_STAT) = 0xffff; | |
78 | return(stat | I2C_TIMEOUT); | |
79 | } | |
80 | ||
81 | ||
82 | void flush_rx(void) | |
83 | { | |
84 | int dummy; | |
85 | ||
86 | while (1) { | |
87 | if (!(REG(I2C_STAT) & I2C_STAT_RRDY)) | |
88 | break; | |
89 | ||
90 | dummy = REG(I2C_DRR); | |
91 | REG(I2C_STAT) = I2C_STAT_RRDY; | |
92 | udelay(1000); | |
93 | } | |
94 | } | |
95 | ||
96 | ||
97 | void i2c_init(int speed, int slaveadd) | |
98 | { | |
99 | u_int32_t div, psc; | |
100 | ||
101 | if (REG(I2C_CON) & I2C_CON_EN) { | |
102 | REG(I2C_CON) = 0; | |
103 | udelay (50000); | |
104 | } | |
105 | ||
106 | psc = 2; | |
107 | div = (CONFIG_SYS_HZ_CLOCK / ((psc + 1) * speed)) - 10; /* SCLL + SCLH */ | |
108 | REG(I2C_PSC) = psc; /* 27MHz / (2 + 1) = 9MHz */ | |
109 | REG(I2C_SCLL) = (div * 50) / 100; /* 50% Duty */ | |
110 | REG(I2C_SCLH) = div - REG(I2C_SCLL); | |
111 | ||
112 | REG(I2C_OA) = slaveadd; | |
113 | REG(I2C_CNT) = 0; | |
114 | ||
115 | /* Interrupts must be enabled or I2C module won't work */ | |
116 | REG(I2C_IE) = I2C_IE_SCD_IE | I2C_IE_XRDY_IE | | |
117 | I2C_IE_RRDY_IE | I2C_IE_ARDY_IE | I2C_IE_NACK_IE; | |
118 | ||
119 | /* Now enable I2C controller (get it out of reset) */ | |
120 | REG(I2C_CON) = I2C_CON_EN; | |
121 | ||
122 | udelay(1000); | |
123 | } | |
124 | ||
125 | ||
126 | int i2c_probe(u_int8_t chip) | |
127 | { | |
128 | int rc = 1; | |
129 | ||
130 | if (chip == REG(I2C_OA)) { | |
131 | return(rc); | |
132 | } | |
133 | ||
134 | REG(I2C_CON) = 0; | |
135 | if (wait_for_bus()) {return(1);} | |
136 | ||
137 | /* try to read one byte from current (or only) address */ | |
138 | REG(I2C_CNT) = 1; | |
139 | REG(I2C_SA) = chip; | |
140 | REG(I2C_CON) = (I2C_CON_EN | I2C_CON_MST | I2C_CON_STT | I2C_CON_STP); | |
141 | udelay (50000); | |
142 | ||
143 | if (!(REG(I2C_STAT) & I2C_STAT_NACK)) { | |
144 | rc = 0; | |
145 | flush_rx(); | |
146 | REG(I2C_STAT) = 0xffff; | |
147 | } else { | |
148 | REG(I2C_STAT) = 0xffff; | |
149 | REG(I2C_CON) |= I2C_CON_STP; | |
150 | udelay(20000); | |
151 | if (wait_for_bus()) {return(1);} | |
152 | } | |
153 | ||
154 | flush_rx(); | |
155 | REG(I2C_STAT) = 0xffff; | |
156 | REG(I2C_CNT) = 0; | |
157 | return(rc); | |
158 | } | |
159 | ||
160 | ||
161 | int i2c_read(u_int8_t chip, u_int32_t addr, int alen, u_int8_t *buf, int len) | |
162 | { | |
163 | u_int32_t tmp; | |
164 | int i; | |
165 | ||
166 | if ((alen < 0) || (alen > 2)) { | |
167 | printf("%s(): bogus address length %x\n", __FUNCTION__, alen); | |
168 | return(1); | |
169 | } | |
170 | ||
171 | if (wait_for_bus()) {return(1);} | |
172 | ||
173 | if (alen != 0) { | |
174 | /* Start address phase */ | |
175 | tmp = I2C_CON_EN | I2C_CON_MST | I2C_CON_STT | I2C_CON_TRX; | |
176 | REG(I2C_CNT) = alen; | |
177 | REG(I2C_SA) = chip; | |
178 | REG(I2C_CON) = tmp; | |
179 | ||
180 | tmp = poll_i2c_irq(I2C_STAT_XRDY | I2C_STAT_NACK); | |
181 | ||
182 | CHECK_NACK(); | |
183 | ||
184 | switch (alen) { | |
185 | case 2: | |
186 | /* Send address MSByte */ | |
187 | if (tmp & I2C_STAT_XRDY) { | |
188 | REG(I2C_DXR) = (addr >> 8) & 0xff; | |
189 | } else { | |
190 | REG(I2C_CON) = 0; | |
191 | return(1); | |
192 | } | |
193 | ||
194 | tmp = poll_i2c_irq(I2C_STAT_XRDY | I2C_STAT_NACK); | |
195 | ||
196 | CHECK_NACK(); | |
197 | /* No break, fall through */ | |
198 | case 1: | |
199 | /* Send address LSByte */ | |
200 | if (tmp & I2C_STAT_XRDY) { | |
201 | REG(I2C_DXR) = addr & 0xff; | |
202 | } else { | |
203 | REG(I2C_CON) = 0; | |
204 | return(1); | |
205 | } | |
206 | ||
207 | tmp = poll_i2c_irq(I2C_STAT_XRDY | I2C_STAT_NACK | I2C_STAT_ARDY); | |
208 | ||
209 | CHECK_NACK(); | |
210 | ||
211 | if (!(tmp & I2C_STAT_ARDY)) { | |
212 | REG(I2C_CON) = 0; | |
213 | return(1); | |
214 | } | |
215 | } | |
216 | } | |
217 | ||
218 | /* Address phase is over, now read 'len' bytes and stop */ | |
219 | tmp = I2C_CON_EN | I2C_CON_MST | I2C_CON_STT | I2C_CON_STP; | |
220 | REG(I2C_CNT) = len & 0xffff; | |
221 | REG(I2C_SA) = chip; | |
222 | REG(I2C_CON) = tmp; | |
223 | ||
224 | for (i = 0; i < len; i++) { | |
225 | tmp = poll_i2c_irq(I2C_STAT_RRDY | I2C_STAT_NACK | I2C_STAT_ROVR); | |
226 | ||
227 | CHECK_NACK(); | |
228 | ||
229 | if (tmp & I2C_STAT_RRDY) { | |
230 | buf[i] = REG(I2C_DRR); | |
231 | } else { | |
232 | REG(I2C_CON) = 0; | |
233 | return(1); | |
234 | } | |
235 | } | |
236 | ||
237 | tmp = poll_i2c_irq(I2C_STAT_SCD | I2C_STAT_NACK); | |
238 | ||
239 | CHECK_NACK(); | |
240 | ||
241 | if (!(tmp & I2C_STAT_SCD)) { | |
242 | REG(I2C_CON) = 0; | |
243 | return(1); | |
244 | } | |
245 | ||
246 | flush_rx(); | |
247 | REG(I2C_STAT) = 0xffff; | |
248 | REG(I2C_CNT) = 0; | |
249 | REG(I2C_CON) = 0; | |
250 | ||
251 | return(0); | |
252 | } | |
253 | ||
254 | ||
255 | int i2c_write(u_int8_t chip, u_int32_t addr, int alen, u_int8_t *buf, int len) | |
256 | { | |
257 | u_int32_t tmp; | |
258 | int i; | |
259 | ||
260 | if ((alen < 0) || (alen > 2)) { | |
261 | printf("%s(): bogus address length %x\n", __FUNCTION__, alen); | |
262 | return(1); | |
263 | } | |
264 | if (len < 0) { | |
265 | printf("%s(): bogus length %x\n", __FUNCTION__, len); | |
266 | return(1); | |
267 | } | |
268 | ||
269 | if (wait_for_bus()) {return(1);} | |
270 | ||
271 | /* Start address phase */ | |
272 | tmp = I2C_CON_EN | I2C_CON_MST | I2C_CON_STT | I2C_CON_TRX | I2C_CON_STP; | |
273 | REG(I2C_CNT) = (alen == 0) ? len & 0xffff : (len & 0xffff) + alen; | |
274 | REG(I2C_SA) = chip; | |
275 | REG(I2C_CON) = tmp; | |
276 | ||
277 | switch (alen) { | |
278 | case 2: | |
279 | /* Send address MSByte */ | |
280 | tmp = poll_i2c_irq(I2C_STAT_XRDY | I2C_STAT_NACK); | |
281 | ||
282 | CHECK_NACK(); | |
283 | ||
284 | if (tmp & I2C_STAT_XRDY) { | |
285 | REG(I2C_DXR) = (addr >> 8) & 0xff; | |
286 | } else { | |
287 | REG(I2C_CON) = 0; | |
288 | return(1); | |
289 | } | |
290 | /* No break, fall through */ | |
291 | case 1: | |
292 | /* Send address LSByte */ | |
293 | tmp = poll_i2c_irq(I2C_STAT_XRDY | I2C_STAT_NACK); | |
294 | ||
295 | CHECK_NACK(); | |
296 | ||
297 | if (tmp & I2C_STAT_XRDY) { | |
298 | REG(I2C_DXR) = addr & 0xff; | |
299 | } else { | |
300 | REG(I2C_CON) = 0; | |
301 | return(1); | |
302 | } | |
303 | } | |
304 | ||
305 | for (i = 0; i < len; i++) { | |
306 | tmp = poll_i2c_irq(I2C_STAT_XRDY | I2C_STAT_NACK); | |
307 | ||
308 | CHECK_NACK(); | |
309 | ||
310 | if (tmp & I2C_STAT_XRDY) { | |
311 | REG(I2C_DXR) = buf[i]; | |
312 | } else { | |
313 | return(1); | |
314 | } | |
315 | } | |
316 | ||
317 | tmp = poll_i2c_irq(I2C_STAT_SCD | I2C_STAT_NACK); | |
318 | ||
319 | CHECK_NACK(); | |
320 | ||
321 | if (!(tmp & I2C_STAT_SCD)) { | |
322 | REG(I2C_CON) = 0; | |
323 | return(1); | |
324 | } | |
325 | ||
326 | flush_rx(); | |
327 | REG(I2C_STAT) = 0xffff; | |
328 | REG(I2C_CNT) = 0; | |
329 | REG(I2C_CON) = 0; | |
330 | ||
331 | return(0); | |
332 | } | |
333 | ||
334 | ||
335 | u_int8_t i2c_reg_read(u_int8_t chip, u_int8_t reg) | |
336 | { | |
337 | u_int8_t tmp; | |
338 | ||
339 | i2c_read(chip, reg, 1, &tmp, 1); | |
340 | return(tmp); | |
341 | } | |
342 | ||
343 | ||
344 | void i2c_reg_write(u_int8_t chip, u_int8_t reg, u_int8_t val) | |
345 | { | |
346 | u_int8_t tmp; | |
347 | ||
348 | i2c_write(chip, reg, 1, &tmp, 1); | |
349 | } | |
350 | ||
351 | #endif /* CONFIG_DRIVER_DAVINCI_I2C */ |