]>
Commit | Line | Data |
---|---|---|
c74b2108 SK |
1 | /* |
2 | * TI DaVinci (TMS320DM644x) I2C driver. | |
3 | * | |
e8459dcc VA |
4 | * (C) Copyright 2012-2014 |
5 | * Texas Instruments Incorporated, <www.ti.com> | |
6 | * (C) Copyright 2007 Sergey Kubushyn <ksi@koi8.net> | |
c74b2108 SK |
7 | * -------------------------------------------------------- |
8 | * | |
1a459660 | 9 | * SPDX-License-Identifier: GPL-2.0+ |
c74b2108 SK |
10 | */ |
11 | ||
12 | #include <common.h> | |
c74b2108 SK |
13 | #include <i2c.h> |
14 | #include <asm/arch/hardware.h> | |
15 | #include <asm/arch/i2c_defs.h> | |
e8459dcc | 16 | #include <asm/io.h> |
356d15eb | 17 | #include "davinci_i2c.h" |
c74b2108 SK |
18 | |
19 | #define CHECK_NACK() \ | |
20 | do {\ | |
21 | if (tmp & (I2C_TIMEOUT | I2C_STAT_NACK)) {\ | |
e8459dcc VA |
22 | REG(&(i2c_base->i2c_con)) = 0;\ |
23 | return 1;\ | |
24 | } \ | |
c74b2108 SK |
25 | } while (0) |
26 | ||
e8459dcc | 27 | static struct i2c_regs *davinci_get_base(struct i2c_adapter *adap); |
c74b2108 | 28 | |
e8459dcc | 29 | static int wait_for_bus(struct i2c_adapter *adap) |
c74b2108 | 30 | { |
e8459dcc | 31 | struct i2c_regs *i2c_base = davinci_get_base(adap); |
c74b2108 SK |
32 | int stat, timeout; |
33 | ||
e8459dcc | 34 | REG(&(i2c_base->i2c_stat)) = 0xffff; |
c74b2108 SK |
35 | |
36 | for (timeout = 0; timeout < 10; timeout++) { | |
e8459dcc VA |
37 | stat = REG(&(i2c_base->i2c_stat)); |
38 | if (!((stat) & I2C_STAT_BB)) { | |
39 | REG(&(i2c_base->i2c_stat)) = 0xffff; | |
40 | return 0; | |
c74b2108 SK |
41 | } |
42 | ||
e8459dcc | 43 | REG(&(i2c_base->i2c_stat)) = stat; |
c74b2108 SK |
44 | udelay(50000); |
45 | } | |
46 | ||
e8459dcc VA |
47 | REG(&(i2c_base->i2c_stat)) = 0xffff; |
48 | return 1; | |
c74b2108 SK |
49 | } |
50 | ||
51 | ||
e8459dcc | 52 | static int poll_i2c_irq(struct i2c_adapter *adap, int mask) |
c74b2108 | 53 | { |
e8459dcc | 54 | struct i2c_regs *i2c_base = davinci_get_base(adap); |
c74b2108 SK |
55 | int stat, timeout; |
56 | ||
57 | for (timeout = 0; timeout < 10; timeout++) { | |
58 | udelay(1000); | |
e8459dcc VA |
59 | stat = REG(&(i2c_base->i2c_stat)); |
60 | if (stat & mask) | |
61 | return stat; | |
c74b2108 SK |
62 | } |
63 | ||
e8459dcc VA |
64 | REG(&(i2c_base->i2c_stat)) = 0xffff; |
65 | return stat | I2C_TIMEOUT; | |
c74b2108 SK |
66 | } |
67 | ||
e8459dcc | 68 | static void flush_rx(struct i2c_adapter *adap) |
c74b2108 | 69 | { |
e8459dcc VA |
70 | struct i2c_regs *i2c_base = davinci_get_base(adap); |
71 | ||
c74b2108 | 72 | while (1) { |
e8459dcc | 73 | if (!(REG(&(i2c_base->i2c_stat)) & I2C_STAT_RRDY)) |
c74b2108 SK |
74 | break; |
75 | ||
e8459dcc VA |
76 | REG(&(i2c_base->i2c_drr)); |
77 | REG(&(i2c_base->i2c_stat)) = I2C_STAT_RRDY; | |
c74b2108 SK |
78 | udelay(1000); |
79 | } | |
80 | } | |
81 | ||
e8459dcc VA |
82 | static uint davinci_i2c_setspeed(struct i2c_adapter *adap, uint speed) |
83 | { | |
84 | struct i2c_regs *i2c_base = davinci_get_base(adap); | |
85 | uint32_t div, psc; | |
86 | ||
87 | psc = 2; | |
88 | /* SCLL + SCLH */ | |
89 | div = (CONFIG_SYS_HZ_CLOCK / ((psc + 1) * speed)) - 10; | |
90 | REG(&(i2c_base->i2c_psc)) = psc; /* 27MHz / (2 + 1) = 9MHz */ | |
91 | REG(&(i2c_base->i2c_scll)) = (div * 50) / 100; /* 50% Duty */ | |
92 | REG(&(i2c_base->i2c_sclh)) = div - REG(&(i2c_base->i2c_scll)); | |
93 | ||
94 | adap->speed = speed; | |
95 | return 0; | |
96 | } | |
c74b2108 | 97 | |
e8459dcc | 98 | static void davinci_i2c_init(struct i2c_adapter *adap, int speed, int slaveadd) |
c74b2108 | 99 | { |
e8459dcc | 100 | struct i2c_regs *i2c_base = davinci_get_base(adap); |
c74b2108 | 101 | |
e8459dcc VA |
102 | if (REG(&(i2c_base->i2c_con)) & I2C_CON_EN) { |
103 | REG(&(i2c_base->i2c_con)) = 0; | |
104 | udelay(50000); | |
c74b2108 SK |
105 | } |
106 | ||
e8459dcc | 107 | davinci_i2c_setspeed(adap, speed); |
c74b2108 | 108 | |
e8459dcc VA |
109 | REG(&(i2c_base->i2c_oa)) = slaveadd; |
110 | REG(&(i2c_base->i2c_cnt)) = 0; | |
c74b2108 SK |
111 | |
112 | /* Interrupts must be enabled or I2C module won't work */ | |
e8459dcc | 113 | REG(&(i2c_base->i2c_ie)) = I2C_IE_SCD_IE | I2C_IE_XRDY_IE | |
c74b2108 SK |
114 | I2C_IE_RRDY_IE | I2C_IE_ARDY_IE | I2C_IE_NACK_IE; |
115 | ||
116 | /* Now enable I2C controller (get it out of reset) */ | |
e8459dcc | 117 | REG(&(i2c_base->i2c_con)) = I2C_CON_EN; |
c74b2108 SK |
118 | |
119 | udelay(1000); | |
120 | } | |
121 | ||
e8459dcc | 122 | static int davinci_i2c_probe(struct i2c_adapter *adap, uint8_t chip) |
c74b2108 | 123 | { |
e8459dcc | 124 | struct i2c_regs *i2c_base = davinci_get_base(adap); |
c74b2108 SK |
125 | int rc = 1; |
126 | ||
e8459dcc VA |
127 | if (chip == REG(&(i2c_base->i2c_oa))) |
128 | return rc; | |
c74b2108 | 129 | |
e8459dcc VA |
130 | REG(&(i2c_base->i2c_con)) = 0; |
131 | if (wait_for_bus(adap)) | |
132 | return 1; | |
c74b2108 SK |
133 | |
134 | /* try to read one byte from current (or only) address */ | |
e8459dcc VA |
135 | REG(&(i2c_base->i2c_cnt)) = 1; |
136 | REG(&(i2c_base->i2c_sa)) = chip; | |
137 | REG(&(i2c_base->i2c_con)) = (I2C_CON_EN | I2C_CON_MST | I2C_CON_STT | | |
138 | I2C_CON_STP); | |
139 | udelay(50000); | |
c74b2108 | 140 | |
e8459dcc | 141 | if (!(REG(&(i2c_base->i2c_stat)) & I2C_STAT_NACK)) { |
c74b2108 | 142 | rc = 0; |
e8459dcc VA |
143 | flush_rx(adap); |
144 | REG(&(i2c_base->i2c_stat)) = 0xffff; | |
c74b2108 | 145 | } else { |
e8459dcc VA |
146 | REG(&(i2c_base->i2c_stat)) = 0xffff; |
147 | REG(&(i2c_base->i2c_con)) |= I2C_CON_STP; | |
c74b2108 | 148 | udelay(20000); |
e8459dcc VA |
149 | if (wait_for_bus(adap)) |
150 | return 1; | |
c74b2108 SK |
151 | } |
152 | ||
e8459dcc VA |
153 | flush_rx(adap); |
154 | REG(&(i2c_base->i2c_stat)) = 0xffff; | |
155 | REG(&(i2c_base->i2c_cnt)) = 0; | |
156 | return rc; | |
c74b2108 SK |
157 | } |
158 | ||
e8459dcc VA |
159 | static int davinci_i2c_read(struct i2c_adapter *adap, uint8_t chip, |
160 | uint32_t addr, int alen, uint8_t *buf, int len) | |
c74b2108 | 161 | { |
e8459dcc VA |
162 | struct i2c_regs *i2c_base = davinci_get_base(adap); |
163 | uint32_t tmp; | |
c74b2108 SK |
164 | int i; |
165 | ||
166 | if ((alen < 0) || (alen > 2)) { | |
e8459dcc VA |
167 | printf("%s(): bogus address length %x\n", __func__, alen); |
168 | return 1; | |
c74b2108 SK |
169 | } |
170 | ||
e8459dcc VA |
171 | if (wait_for_bus(adap)) |
172 | return 1; | |
c74b2108 SK |
173 | |
174 | if (alen != 0) { | |
175 | /* Start address phase */ | |
176 | tmp = I2C_CON_EN | I2C_CON_MST | I2C_CON_STT | I2C_CON_TRX; | |
e8459dcc VA |
177 | REG(&(i2c_base->i2c_cnt)) = alen; |
178 | REG(&(i2c_base->i2c_sa)) = chip; | |
179 | REG(&(i2c_base->i2c_con)) = tmp; | |
c74b2108 | 180 | |
e8459dcc | 181 | tmp = poll_i2c_irq(adap, I2C_STAT_XRDY | I2C_STAT_NACK); |
c74b2108 SK |
182 | |
183 | CHECK_NACK(); | |
184 | ||
185 | switch (alen) { | |
e8459dcc VA |
186 | case 2: |
187 | /* Send address MSByte */ | |
188 | if (tmp & I2C_STAT_XRDY) { | |
189 | REG(&(i2c_base->i2c_dxr)) = (addr >> 8) & 0xff; | |
190 | } else { | |
191 | REG(&(i2c_base->i2c_con)) = 0; | |
192 | return 1; | |
193 | } | |
194 | ||
195 | tmp = poll_i2c_irq(adap, I2C_STAT_XRDY | I2C_STAT_NACK); | |
196 | ||
197 | CHECK_NACK(); | |
198 | /* No break, fall through */ | |
199 | case 1: | |
200 | /* Send address LSByte */ | |
201 | if (tmp & I2C_STAT_XRDY) { | |
202 | REG(&(i2c_base->i2c_dxr)) = addr & 0xff; | |
203 | } else { | |
204 | REG(&(i2c_base->i2c_con)) = 0; | |
205 | return 1; | |
206 | } | |
207 | ||
208 | tmp = poll_i2c_irq(adap, I2C_STAT_XRDY | | |
209 | I2C_STAT_NACK | I2C_STAT_ARDY); | |
210 | ||
211 | CHECK_NACK(); | |
212 | ||
213 | if (!(tmp & I2C_STAT_ARDY)) { | |
214 | REG(&(i2c_base->i2c_con)) = 0; | |
215 | return 1; | |
216 | } | |
c74b2108 SK |
217 | } |
218 | } | |
219 | ||
220 | /* Address phase is over, now read 'len' bytes and stop */ | |
221 | tmp = I2C_CON_EN | I2C_CON_MST | I2C_CON_STT | I2C_CON_STP; | |
e8459dcc VA |
222 | REG(&(i2c_base->i2c_cnt)) = len & 0xffff; |
223 | REG(&(i2c_base->i2c_sa)) = chip; | |
224 | REG(&(i2c_base->i2c_con)) = tmp; | |
c74b2108 SK |
225 | |
226 | for (i = 0; i < len; i++) { | |
e8459dcc VA |
227 | tmp = poll_i2c_irq(adap, I2C_STAT_RRDY | I2C_STAT_NACK | |
228 | I2C_STAT_ROVR); | |
c74b2108 SK |
229 | |
230 | CHECK_NACK(); | |
231 | ||
232 | if (tmp & I2C_STAT_RRDY) { | |
e8459dcc | 233 | buf[i] = REG(&(i2c_base->i2c_drr)); |
c74b2108 | 234 | } else { |
e8459dcc VA |
235 | REG(&(i2c_base->i2c_con)) = 0; |
236 | return 1; | |
c74b2108 SK |
237 | } |
238 | } | |
239 | ||
e8459dcc | 240 | tmp = poll_i2c_irq(adap, I2C_STAT_SCD | I2C_STAT_NACK); |
c74b2108 SK |
241 | |
242 | CHECK_NACK(); | |
243 | ||
244 | if (!(tmp & I2C_STAT_SCD)) { | |
e8459dcc VA |
245 | REG(&(i2c_base->i2c_con)) = 0; |
246 | return 1; | |
c74b2108 SK |
247 | } |
248 | ||
e8459dcc VA |
249 | flush_rx(adap); |
250 | REG(&(i2c_base->i2c_stat)) = 0xffff; | |
251 | REG(&(i2c_base->i2c_cnt)) = 0; | |
252 | REG(&(i2c_base->i2c_con)) = 0; | |
c74b2108 | 253 | |
e8459dcc | 254 | return 0; |
c74b2108 SK |
255 | } |
256 | ||
e8459dcc VA |
257 | static int davinci_i2c_write(struct i2c_adapter *adap, uint8_t chip, |
258 | uint32_t addr, int alen, uint8_t *buf, int len) | |
c74b2108 | 259 | { |
e8459dcc VA |
260 | struct i2c_regs *i2c_base = davinci_get_base(adap); |
261 | uint32_t tmp; | |
c74b2108 SK |
262 | int i; |
263 | ||
264 | if ((alen < 0) || (alen > 2)) { | |
e8459dcc VA |
265 | printf("%s(): bogus address length %x\n", __func__, alen); |
266 | return 1; | |
c74b2108 SK |
267 | } |
268 | if (len < 0) { | |
e8459dcc VA |
269 | printf("%s(): bogus length %x\n", __func__, len); |
270 | return 1; | |
c74b2108 SK |
271 | } |
272 | ||
e8459dcc VA |
273 | if (wait_for_bus(adap)) |
274 | return 1; | |
c74b2108 SK |
275 | |
276 | /* Start address phase */ | |
e8459dcc VA |
277 | tmp = I2C_CON_EN | I2C_CON_MST | I2C_CON_STT | |
278 | I2C_CON_TRX | I2C_CON_STP; | |
279 | REG(&(i2c_base->i2c_cnt)) = (alen == 0) ? | |
280 | len & 0xffff : (len & 0xffff) + alen; | |
281 | REG(&(i2c_base->i2c_sa)) = chip; | |
282 | REG(&(i2c_base->i2c_con)) = tmp; | |
c74b2108 SK |
283 | |
284 | switch (alen) { | |
e8459dcc VA |
285 | case 2: |
286 | /* Send address MSByte */ | |
287 | tmp = poll_i2c_irq(adap, I2C_STAT_XRDY | I2C_STAT_NACK); | |
c74b2108 | 288 | |
e8459dcc | 289 | CHECK_NACK(); |
c74b2108 | 290 | |
e8459dcc VA |
291 | if (tmp & I2C_STAT_XRDY) { |
292 | REG(&(i2c_base->i2c_dxr)) = (addr >> 8) & 0xff; | |
293 | } else { | |
294 | REG(&(i2c_base->i2c_con)) = 0; | |
295 | return 1; | |
296 | } | |
297 | /* No break, fall through */ | |
298 | case 1: | |
299 | /* Send address LSByte */ | |
300 | tmp = poll_i2c_irq(adap, I2C_STAT_XRDY | I2C_STAT_NACK); | |
c74b2108 | 301 | |
e8459dcc | 302 | CHECK_NACK(); |
c74b2108 | 303 | |
e8459dcc VA |
304 | if (tmp & I2C_STAT_XRDY) { |
305 | REG(&(i2c_base->i2c_dxr)) = addr & 0xff; | |
306 | } else { | |
307 | REG(&(i2c_base->i2c_con)) = 0; | |
308 | return 1; | |
309 | } | |
c74b2108 SK |
310 | } |
311 | ||
312 | for (i = 0; i < len; i++) { | |
e8459dcc | 313 | tmp = poll_i2c_irq(adap, I2C_STAT_XRDY | I2C_STAT_NACK); |
c74b2108 SK |
314 | |
315 | CHECK_NACK(); | |
316 | ||
e8459dcc VA |
317 | if (tmp & I2C_STAT_XRDY) |
318 | REG(&(i2c_base->i2c_dxr)) = buf[i]; | |
319 | else | |
320 | return 1; | |
c74b2108 SK |
321 | } |
322 | ||
e8459dcc | 323 | tmp = poll_i2c_irq(adap, I2C_STAT_SCD | I2C_STAT_NACK); |
c74b2108 SK |
324 | |
325 | CHECK_NACK(); | |
326 | ||
327 | if (!(tmp & I2C_STAT_SCD)) { | |
e8459dcc VA |
328 | REG(&(i2c_base->i2c_con)) = 0; |
329 | return 1; | |
c74b2108 SK |
330 | } |
331 | ||
e8459dcc VA |
332 | flush_rx(adap); |
333 | REG(&(i2c_base->i2c_stat)) = 0xffff; | |
334 | REG(&(i2c_base->i2c_cnt)) = 0; | |
335 | REG(&(i2c_base->i2c_con)) = 0; | |
336 | ||
337 | return 0; | |
338 | } | |
339 | ||
340 | static struct i2c_regs *davinci_get_base(struct i2c_adapter *adap) | |
341 | { | |
342 | switch (adap->hwadapnr) { | |
343 | #if I2C_BUS_MAX >= 3 | |
344 | case 2: | |
345 | return (struct i2c_regs *)I2C2_BASE; | |
346 | #endif | |
347 | #if I2C_BUS_MAX >= 2 | |
348 | case 1: | |
349 | return (struct i2c_regs *)I2C1_BASE; | |
350 | #endif | |
351 | case 0: | |
352 | return (struct i2c_regs *)I2C_BASE; | |
353 | ||
354 | default: | |
355 | printf("wrong hwadapnr: %d\n", adap->hwadapnr); | |
356 | } | |
c74b2108 | 357 | |
e8459dcc | 358 | return NULL; |
c74b2108 | 359 | } |
e8459dcc VA |
360 | |
361 | U_BOOT_I2C_ADAP_COMPLETE(davinci_0, davinci_i2c_init, davinci_i2c_probe, | |
362 | davinci_i2c_read, davinci_i2c_write, | |
363 | davinci_i2c_setspeed, | |
364 | CONFIG_SYS_DAVINCI_I2C_SPEED, | |
365 | CONFIG_SYS_DAVINCI_I2C_SLAVE, | |
366 | 0) | |
367 | ||
368 | #if I2C_BUS_MAX >= 2 | |
369 | U_BOOT_I2C_ADAP_COMPLETE(davinci_1, davinci_i2c_init, davinci_i2c_probe, | |
370 | davinci_i2c_read, davinci_i2c_write, | |
371 | davinci_i2c_setspeed, | |
372 | CONFIG_SYS_DAVINCI_I2C_SPEED1, | |
373 | CONFIG_SYS_DAVINCI_I2C_SLAVE1, | |
374 | 1) | |
375 | #endif | |
376 | ||
377 | #if I2C_BUS_MAX >= 3 | |
378 | U_BOOT_I2C_ADAP_COMPLETE(davinci_2, davinci_i2c_init, davinci_i2c_probe, | |
379 | davinci_i2c_read, davinci_i2c_write, | |
380 | davinci_i2c_setspeed, | |
381 | CONFIG_SYS_DAVINCI_I2C_SPEED2, | |
382 | CONFIG_SYS_DAVINCI_I2C_SLAVE2, | |
383 | 2) | |
384 | #endif |