]>
Commit | Line | Data |
---|---|---|
8ed96046 WD |
1 | /* |
2 | * Basic I2C functions | |
3 | * | |
4 | * Copyright (c) 2004 Texas Instruments | |
5 | * | |
6 | * This package is free software; you can redistribute it and/or | |
7 | * modify it under the terms of the license found in the file | |
8 | * named COPYING that should have accompanied this file. | |
9 | * | |
10 | * THIS PACKAGE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR | |
11 | * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED | |
12 | * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. | |
13 | * | |
14 | * Author: Jian Zhang [email protected], Texas Instruments | |
15 | * | |
16 | * Copyright (c) 2003 Wolfgang Denk, [email protected] | |
17 | * Rewritten to fit into the current U-Boot framework | |
18 | * | |
19 | * Adapted for OMAP2420 I2C, [email protected] | |
20 | * | |
960187ff LP |
21 | * Copyright (c) 2013 Lubomir Popov <[email protected]>, MM Solutions |
22 | * New i2c_read, i2c_write and i2c_probe functions, tested on OMAP4 | |
23 | * (4430/60/70), OMAP5 (5430) and AM335X (3359); should work on older | |
24 | * OMAPs and derivatives as well. The only anticipated exception would | |
25 | * be the OMAP2420, which shall require driver modification. | |
26 | * - Rewritten i2c_read to operate correctly with all types of chips | |
27 | * (old function could not read consistent data from some I2C slaves). | |
28 | * - Optimized i2c_write. | |
29 | * - New i2c_probe, performs write access vs read. The old probe could | |
30 | * hang the system under certain conditions (e.g. unconfigured pads). | |
31 | * - The read/write/probe functions try to identify unconfigured bus. | |
32 | * - Status functions now read irqstatus_raw as per TRM guidelines | |
33 | * (except for OMAP243X and OMAP34XX). | |
34 | * - Driver now supports up to I2C5 (OMAP5). | |
d5243359 | 35 | * |
4c302b9a | 36 | * Copyright (c) 2014 Hannes Schmelzer <[email protected]>, B&R |
d5243359 HP |
37 | * - Added support for set_speed |
38 | * | |
8ed96046 WD |
39 | */ |
40 | ||
41 | #include <common.h> | |
daa69ffe | 42 | #include <dm.h> |
6789e84e | 43 | #include <i2c.h> |
f7ae49fc | 44 | #include <log.h> |
289f932c | 45 | |
8ed96046 | 46 | #include <asm/io.h> |
5f97ae68 | 47 | #include <asm/omap_i2c.h> |
8ed96046 | 48 | |
bca09ce4 V |
49 | /* |
50 | * Provide access to architecture-specific I2C header files for platforms | |
51 | * that are NOT yet solely relying on CONFIG_DM_I2C, CONFIG_OF_CONTROL, and | |
52 | * the defaults provided in 'omap24xx_i2c.h' for all U-Boot stages where I2C | |
53 | * access is desired. | |
54 | */ | |
55 | #ifndef CONFIG_ARCH_K3 | |
56 | #include <asm/arch/i2c.h> | |
57 | #endif | |
58 | ||
938717ce SS |
59 | #include "omap24xx_i2c.h" |
60 | ||
cec487a4 | 61 | #define I2C_TIMEOUT 1000 |
d708395d | 62 | |
960187ff LP |
63 | /* Absolutely safe for status update at 100 kHz I2C: */ |
64 | #define I2C_WAIT 200 | |
65 | ||
bca09ce4 V |
66 | enum { |
67 | OMAP_I2C_REV_REG = 0, /* Only on IP V1 (OMAP34XX) */ | |
68 | OMAP_I2C_IE_REG, /* Only on IP V1 (OMAP34XX) */ | |
69 | OMAP_I2C_STAT_REG, | |
70 | OMAP_I2C_WE_REG, | |
71 | OMAP_I2C_SYSS_REG, | |
72 | OMAP_I2C_BUF_REG, | |
73 | OMAP_I2C_CNT_REG, | |
74 | OMAP_I2C_DATA_REG, | |
75 | OMAP_I2C_SYSC_REG, | |
76 | OMAP_I2C_CON_REG, | |
77 | OMAP_I2C_OA_REG, | |
78 | OMAP_I2C_SA_REG, | |
79 | OMAP_I2C_PSC_REG, | |
80 | OMAP_I2C_SCLL_REG, | |
81 | OMAP_I2C_SCLH_REG, | |
82 | OMAP_I2C_SYSTEST_REG, | |
83 | OMAP_I2C_BUFSTAT_REG, | |
84 | /* Only on IP V2 (OMAP4430, etc.) */ | |
85 | OMAP_I2C_IP_V2_REVNB_LO, | |
86 | OMAP_I2C_IP_V2_REVNB_HI, | |
87 | OMAP_I2C_IP_V2_IRQSTATUS_RAW, | |
88 | OMAP_I2C_IP_V2_IRQENABLE_SET, | |
89 | OMAP_I2C_IP_V2_IRQENABLE_CLR, | |
90 | }; | |
91 | ||
92 | static const u8 __maybe_unused reg_map_ip_v1[] = { | |
93 | [OMAP_I2C_REV_REG] = 0x00, | |
94 | [OMAP_I2C_IE_REG] = 0x04, | |
95 | [OMAP_I2C_STAT_REG] = 0x08, | |
96 | [OMAP_I2C_WE_REG] = 0x0c, | |
97 | [OMAP_I2C_SYSS_REG] = 0x10, | |
98 | [OMAP_I2C_BUF_REG] = 0x14, | |
99 | [OMAP_I2C_CNT_REG] = 0x18, | |
100 | [OMAP_I2C_DATA_REG] = 0x1c, | |
101 | [OMAP_I2C_SYSC_REG] = 0x20, | |
102 | [OMAP_I2C_CON_REG] = 0x24, | |
103 | [OMAP_I2C_OA_REG] = 0x28, | |
104 | [OMAP_I2C_SA_REG] = 0x2c, | |
105 | [OMAP_I2C_PSC_REG] = 0x30, | |
106 | [OMAP_I2C_SCLL_REG] = 0x34, | |
107 | [OMAP_I2C_SCLH_REG] = 0x38, | |
108 | [OMAP_I2C_SYSTEST_REG] = 0x3c, | |
109 | [OMAP_I2C_BUFSTAT_REG] = 0x40, | |
110 | }; | |
111 | ||
112 | static const u8 __maybe_unused reg_map_ip_v2[] = { | |
113 | [OMAP_I2C_STAT_REG] = 0x28, | |
114 | [OMAP_I2C_WE_REG] = 0x34, | |
115 | [OMAP_I2C_SYSS_REG] = 0x90, | |
116 | [OMAP_I2C_BUF_REG] = 0x94, | |
117 | [OMAP_I2C_CNT_REG] = 0x98, | |
118 | [OMAP_I2C_DATA_REG] = 0x9c, | |
119 | [OMAP_I2C_SYSC_REG] = 0x10, | |
120 | [OMAP_I2C_CON_REG] = 0xa4, | |
121 | [OMAP_I2C_OA_REG] = 0xa8, | |
122 | [OMAP_I2C_SA_REG] = 0xac, | |
123 | [OMAP_I2C_PSC_REG] = 0xb0, | |
124 | [OMAP_I2C_SCLL_REG] = 0xb4, | |
125 | [OMAP_I2C_SCLH_REG] = 0xb8, | |
126 | [OMAP_I2C_SYSTEST_REG] = 0xbc, | |
127 | [OMAP_I2C_BUFSTAT_REG] = 0xc0, | |
128 | [OMAP_I2C_IP_V2_REVNB_LO] = 0x00, | |
129 | [OMAP_I2C_IP_V2_REVNB_HI] = 0x04, | |
130 | [OMAP_I2C_IP_V2_IRQSTATUS_RAW] = 0x24, | |
131 | [OMAP_I2C_IP_V2_IRQENABLE_SET] = 0x2c, | |
132 | [OMAP_I2C_IP_V2_IRQENABLE_CLR] = 0x30, | |
133 | }; | |
134 | ||
daa69ffe M |
135 | struct omap_i2c { |
136 | struct udevice *clk; | |
bca09ce4 | 137 | int ip_rev; |
daa69ffe M |
138 | struct i2c *regs; |
139 | unsigned int speed; | |
140 | int waitdelay; | |
141 | int clk_id; | |
142 | }; | |
143 | ||
bca09ce4 V |
144 | static inline const u8 *omap_i2c_get_ip_reg_map(int ip_rev) |
145 | { | |
146 | switch (ip_rev) { | |
147 | case OMAP_I2C_REV_V1: | |
148 | return reg_map_ip_v1; | |
149 | case OMAP_I2C_REV_V2: | |
150 | /* Fall through... */ | |
151 | default: | |
152 | return reg_map_ip_v2; | |
153 | } | |
154 | } | |
155 | ||
156 | static inline void omap_i2c_write_reg(void __iomem *base, int ip_rev, | |
157 | u16 val, int reg) | |
158 | { | |
159 | writew(val, base + omap_i2c_get_ip_reg_map(ip_rev)[reg]); | |
160 | } | |
161 | ||
162 | static inline u16 omap_i2c_read_reg(void __iomem *base, int ip_rev, int reg) | |
163 | { | |
164 | return readw(base + omap_i2c_get_ip_reg_map(ip_rev)[reg]); | |
165 | } | |
166 | ||
d5243359 | 167 | static int omap24_i2c_findpsc(u32 *pscl, u32 *psch, uint speed) |
8ed96046 | 168 | { |
b52a3fa0 LM |
169 | unsigned long internal_clk = 0, fclk; |
170 | unsigned int prescaler; | |
7f79dfb4 | 171 | |
d5243359 | 172 | /* |
b52a3fa0 LM |
173 | * This method is only called for Standard and Fast Mode speeds |
174 | * | |
175 | * For some TI SoCs it is explicitly written in TRM (e,g, SPRUHZ6G, | |
176 | * page 5685, Table 24-7) | |
177 | * that the internal I2C clock (after prescaler) should be between | |
178 | * 7-12 MHz (at least for Fast Mode (FS)). | |
179 | * | |
180 | * Such approach is used in v4.9 Linux kernel in: | |
181 | * ./drivers/i2c/busses/i2c-omap.c (omap_i2c_init function). | |
d5243359 | 182 | */ |
b52a3fa0 LM |
183 | |
184 | speed /= 1000; /* convert speed to kHz */ | |
185 | ||
186 | if (speed > 100) | |
187 | internal_clk = 9600; | |
188 | else | |
189 | internal_clk = 4000; | |
190 | ||
191 | fclk = I2C_IP_CLK / 1000; | |
192 | prescaler = fclk / internal_clk; | |
193 | prescaler = prescaler - 1; | |
194 | ||
195 | if (speed > 100) { | |
196 | unsigned long scl; | |
197 | ||
198 | /* Fast mode */ | |
199 | scl = internal_clk / speed; | |
200 | *pscl = scl - (scl / 3) - I2C_FASTSPEED_SCLL_TRIM; | |
201 | *psch = (scl / 3) - I2C_FASTSPEED_SCLH_TRIM; | |
202 | } else { | |
203 | /* Standard mode */ | |
204 | *pscl = internal_clk / (speed * 2) - I2C_FASTSPEED_SCLL_TRIM; | |
205 | *psch = internal_clk / (speed * 2) - I2C_FASTSPEED_SCLH_TRIM; | |
7f79dfb4 | 206 | } |
b52a3fa0 LM |
207 | |
208 | debug("%s: speed [kHz]: %d psc: 0x%x sscl: 0x%x ssch: 0x%x\n", | |
209 | __func__, speed, prescaler, *pscl, *psch); | |
210 | ||
211 | if (*pscl <= 0 || *psch <= 0 || prescaler <= 0) | |
212 | return -EINVAL; | |
213 | ||
214 | return prescaler; | |
d5243359 | 215 | } |
be243e41 M |
216 | |
217 | /* | |
218 | * Wait for the bus to be free by checking the Bus Busy (BB) | |
219 | * bit to become clear | |
220 | */ | |
bca09ce4 | 221 | static int wait_for_bb(void __iomem *i2c_base, int ip_rev, int waitdelay) |
be243e41 M |
222 | { |
223 | int timeout = I2C_TIMEOUT; | |
bca09ce4 | 224 | int irq_stat_reg; |
be243e41 M |
225 | u16 stat; |
226 | ||
bca09ce4 V |
227 | irq_stat_reg = (ip_rev == OMAP_I2C_REV_V1) ? |
228 | OMAP_I2C_STAT_REG : OMAP_I2C_IP_V2_IRQSTATUS_RAW; | |
229 | ||
230 | /* clear current interrupts */ | |
231 | omap_i2c_write_reg(i2c_base, ip_rev, 0xFFFF, OMAP_I2C_STAT_REG); | |
232 | ||
233 | while ((stat = omap_i2c_read_reg(i2c_base, ip_rev, irq_stat_reg) & | |
be243e41 | 234 | I2C_STAT_BB) && timeout--) { |
bca09ce4 | 235 | omap_i2c_write_reg(i2c_base, ip_rev, stat, OMAP_I2C_STAT_REG); |
be243e41 M |
236 | udelay(waitdelay); |
237 | } | |
238 | ||
239 | if (timeout <= 0) { | |
bca09ce4 | 240 | printf("Timed out in %s: status=%04x\n", __func__, stat); |
be243e41 M |
241 | return 1; |
242 | } | |
bca09ce4 V |
243 | |
244 | /* clear delayed stuff */ | |
245 | omap_i2c_write_reg(i2c_base, ip_rev, 0xFFFF, OMAP_I2C_STAT_REG); | |
be243e41 M |
246 | return 0; |
247 | } | |
248 | ||
249 | /* | |
250 | * Wait for the I2C controller to complete current action | |
251 | * and update status | |
252 | */ | |
bca09ce4 | 253 | static u16 wait_for_event(void __iomem *i2c_base, int ip_rev, int waitdelay) |
be243e41 M |
254 | { |
255 | u16 status; | |
256 | int timeout = I2C_TIMEOUT; | |
bca09ce4 | 257 | int irq_stat_reg; |
be243e41 | 258 | |
bca09ce4 V |
259 | irq_stat_reg = (ip_rev == OMAP_I2C_REV_V1) ? |
260 | OMAP_I2C_STAT_REG : OMAP_I2C_IP_V2_IRQSTATUS_RAW; | |
be243e41 M |
261 | do { |
262 | udelay(waitdelay); | |
bca09ce4 | 263 | status = omap_i2c_read_reg(i2c_base, ip_rev, irq_stat_reg); |
be243e41 M |
264 | } while (!(status & |
265 | (I2C_STAT_ROVR | I2C_STAT_XUDF | I2C_STAT_XRDY | | |
266 | I2C_STAT_RRDY | I2C_STAT_ARDY | I2C_STAT_NACK | | |
267 | I2C_STAT_AL)) && timeout--); | |
268 | ||
269 | if (timeout <= 0) { | |
bca09ce4 | 270 | printf("Timed out in %s: status=%04x\n", __func__, status); |
be243e41 M |
271 | /* |
272 | * If status is still 0 here, probably the bus pads have | |
273 | * not been configured for I2C, and/or pull-ups are missing. | |
274 | */ | |
275 | printf("Check if pads/pull-ups of bus are properly configured\n"); | |
bca09ce4 | 276 | omap_i2c_write_reg(i2c_base, ip_rev, 0xFFFF, OMAP_I2C_STAT_REG); |
be243e41 M |
277 | status = 0; |
278 | } | |
279 | ||
280 | return status; | |
281 | } | |
282 | ||
bca09ce4 | 283 | static void flush_fifo(void __iomem *i2c_base, int ip_rev) |
be243e41 M |
284 | { |
285 | u16 stat; | |
286 | ||
287 | /* | |
288 | * note: if you try and read data when its not there or ready | |
289 | * you get a bus error | |
290 | */ | |
291 | while (1) { | |
bca09ce4 | 292 | stat = omap_i2c_read_reg(i2c_base, ip_rev, OMAP_I2C_STAT_REG); |
be243e41 | 293 | if (stat == I2C_STAT_RRDY) { |
bca09ce4 V |
294 | omap_i2c_read_reg(i2c_base, ip_rev, OMAP_I2C_DATA_REG); |
295 | omap_i2c_write_reg(i2c_base, ip_rev, | |
296 | I2C_STAT_RRDY, OMAP_I2C_STAT_REG); | |
be243e41 M |
297 | udelay(1000); |
298 | } else | |
299 | break; | |
300 | } | |
301 | } | |
302 | ||
bca09ce4 | 303 | static int __omap24_i2c_setspeed(void __iomem *i2c_base, int ip_rev, uint speed, |
be243e41 | 304 | int *waitdelay) |
d5243359 | 305 | { |
d5243359 HP |
306 | int psc, fsscll = 0, fssclh = 0; |
307 | int hsscll = 0, hssclh = 0; | |
308 | u32 scll = 0, sclh = 0; | |
7f79dfb4 | 309 | |
4bef5368 | 310 | if (speed >= I2C_SPEED_HIGH_RATE) { |
7f79dfb4 | 311 | /* High speed */ |
d5243359 HP |
312 | psc = I2C_IP_CLK / I2C_INTERNAL_SAMPLING_CLK; |
313 | psc -= 1; | |
314 | if (psc < I2C_PSC_MIN) { | |
315 | printf("Error : I2C unsupported prescaler %d\n", psc); | |
316 | return -1; | |
317 | } | |
7f79dfb4 TR |
318 | |
319 | /* For first phase of HS mode */ | |
d5243359 HP |
320 | fsscll = I2C_INTERNAL_SAMPLING_CLK / (2 * speed); |
321 | ||
322 | fssclh = fsscll; | |
7f79dfb4 TR |
323 | |
324 | fsscll -= I2C_HIGHSPEED_PHASE_ONE_SCLL_TRIM; | |
325 | fssclh -= I2C_HIGHSPEED_PHASE_ONE_SCLH_TRIM; | |
326 | if (((fsscll < 0) || (fssclh < 0)) || | |
327 | ((fsscll > 255) || (fssclh > 255))) { | |
49e9b4bd | 328 | puts("Error : I2C initializing first phase clock\n"); |
d5243359 | 329 | return -1; |
7f79dfb4 TR |
330 | } |
331 | ||
332 | /* For second phase of HS mode */ | |
333 | hsscll = hssclh = I2C_INTERNAL_SAMPLING_CLK / (2 * speed); | |
334 | ||
335 | hsscll -= I2C_HIGHSPEED_PHASE_TWO_SCLL_TRIM; | |
336 | hssclh -= I2C_HIGHSPEED_PHASE_TWO_SCLH_TRIM; | |
337 | if (((fsscll < 0) || (fssclh < 0)) || | |
338 | ((fsscll > 255) || (fssclh > 255))) { | |
49e9b4bd | 339 | puts("Error : I2C initializing second phase clock\n"); |
d5243359 | 340 | return -1; |
7f79dfb4 TR |
341 | } |
342 | ||
343 | scll = (unsigned int)hsscll << 8 | (unsigned int)fsscll; | |
344 | sclh = (unsigned int)hssclh << 8 | (unsigned int)fssclh; | |
345 | ||
346 | } else { | |
347 | /* Standard and fast speed */ | |
d5243359 HP |
348 | psc = omap24_i2c_findpsc(&scll, &sclh, speed); |
349 | if (0 > psc) { | |
49e9b4bd | 350 | puts("Error : I2C initializing clock\n"); |
d5243359 | 351 | return -1; |
7f79dfb4 | 352 | } |
7f79dfb4 | 353 | } |
8ed96046 | 354 | |
bca09ce4 V |
355 | /* wait for 20 clkperiods */ |
356 | *waitdelay = (10000000 / speed) * 2; | |
357 | ||
358 | omap_i2c_write_reg(i2c_base, ip_rev, 0, OMAP_I2C_CON_REG); | |
359 | omap_i2c_write_reg(i2c_base, ip_rev, psc, OMAP_I2C_PSC_REG); | |
360 | omap_i2c_write_reg(i2c_base, ip_rev, scll, OMAP_I2C_SCLL_REG); | |
361 | omap_i2c_write_reg(i2c_base, ip_rev, sclh, OMAP_I2C_SCLH_REG); | |
362 | omap_i2c_write_reg(i2c_base, ip_rev, I2C_CON_EN, OMAP_I2C_CON_REG); | |
363 | ||
364 | /* clear all pending status */ | |
365 | omap_i2c_write_reg(i2c_base, ip_rev, 0xFFFF, OMAP_I2C_STAT_REG); | |
d5243359 HP |
366 | |
367 | return 0; | |
368 | } | |
f7c10535 | 369 | |
bca09ce4 | 370 | static void omap24_i2c_deblock(void __iomem *i2c_base, int ip_rev) |
f7c10535 | 371 | { |
f7c10535 HS |
372 | int i; |
373 | u16 systest; | |
374 | u16 orgsystest; | |
375 | ||
376 | /* set test mode ST_EN = 1 */ | |
bca09ce4 | 377 | orgsystest = omap_i2c_read_reg(i2c_base, ip_rev, OMAP_I2C_SYSTEST_REG); |
f7c10535 | 378 | systest = orgsystest; |
bca09ce4 | 379 | |
f7c10535 HS |
380 | /* enable testmode */ |
381 | systest |= I2C_SYSTEST_ST_EN; | |
bca09ce4 | 382 | omap_i2c_write_reg(i2c_base, ip_rev, systest, OMAP_I2C_SYSTEST_REG); |
f7c10535 HS |
383 | systest &= ~I2C_SYSTEST_TMODE_MASK; |
384 | systest |= 3 << I2C_SYSTEST_TMODE_SHIFT; | |
bca09ce4 | 385 | omap_i2c_write_reg(i2c_base, ip_rev, systest, OMAP_I2C_SYSTEST_REG); |
f7c10535 HS |
386 | |
387 | /* set SCL, SDA = 1 */ | |
388 | systest |= I2C_SYSTEST_SCL_O | I2C_SYSTEST_SDA_O; | |
bca09ce4 | 389 | omap_i2c_write_reg(i2c_base, ip_rev, systest, OMAP_I2C_SYSTEST_REG); |
f7c10535 HS |
390 | udelay(10); |
391 | ||
392 | /* toggle scl 9 clocks */ | |
393 | for (i = 0; i < 9; i++) { | |
394 | /* SCL = 0 */ | |
395 | systest &= ~I2C_SYSTEST_SCL_O; | |
bca09ce4 V |
396 | omap_i2c_write_reg(i2c_base, ip_rev, |
397 | systest, OMAP_I2C_SYSTEST_REG); | |
f7c10535 HS |
398 | udelay(10); |
399 | /* SCL = 1 */ | |
400 | systest |= I2C_SYSTEST_SCL_O; | |
bca09ce4 V |
401 | omap_i2c_write_reg(i2c_base, ip_rev, |
402 | systest, OMAP_I2C_SYSTEST_REG); | |
f7c10535 HS |
403 | udelay(10); |
404 | } | |
405 | ||
406 | /* send stop */ | |
407 | systest &= ~I2C_SYSTEST_SDA_O; | |
bca09ce4 | 408 | omap_i2c_write_reg(i2c_base, ip_rev, systest, OMAP_I2C_SYSTEST_REG); |
f7c10535 HS |
409 | udelay(10); |
410 | systest |= I2C_SYSTEST_SCL_O | I2C_SYSTEST_SDA_O; | |
bca09ce4 | 411 | omap_i2c_write_reg(i2c_base, ip_rev, systest, OMAP_I2C_SYSTEST_REG); |
f7c10535 HS |
412 | udelay(10); |
413 | ||
414 | /* restore original mode */ | |
bca09ce4 | 415 | omap_i2c_write_reg(i2c_base, ip_rev, orgsystest, OMAP_I2C_SYSTEST_REG); |
f7c10535 HS |
416 | } |
417 | ||
bca09ce4 V |
418 | static void __omap24_i2c_init(void __iomem *i2c_base, int ip_rev, int speed, |
419 | int slaveadd, int *waitdelay) | |
d5243359 | 420 | { |
d5243359 | 421 | int timeout = I2C_TIMEOUT; |
f7c10535 | 422 | int deblock = 1; |
d5243359 | 423 | |
f7c10535 | 424 | retry: |
bca09ce4 V |
425 | if (omap_i2c_read_reg(i2c_base, ip_rev, OMAP_I2C_CON_REG) & |
426 | I2C_CON_EN) { | |
427 | omap_i2c_write_reg(i2c_base, ip_rev, 0, OMAP_I2C_CON_REG); | |
89677b27 | 428 | udelay(50000); |
8ed96046 WD |
429 | } |
430 | ||
bca09ce4 V |
431 | /* for ES2 after soft reset */ |
432 | omap_i2c_write_reg(i2c_base, ip_rev, 0x2, OMAP_I2C_SYSC_REG); | |
cec487a4 TR |
433 | udelay(1000); |
434 | ||
bca09ce4 V |
435 | omap_i2c_write_reg(i2c_base, ip_rev, I2C_CON_EN, OMAP_I2C_CON_REG); |
436 | while (!(omap_i2c_read_reg(i2c_base, ip_rev, OMAP_I2C_SYSS_REG) & | |
437 | I2C_SYSS_RDONE) && timeout--) { | |
cec487a4 TR |
438 | if (timeout <= 0) { |
439 | puts("ERROR: Timeout in soft-reset\n"); | |
440 | return; | |
441 | } | |
442 | udelay(1000); | |
443 | } | |
444 | ||
bca09ce4 | 445 | if (__omap24_i2c_setspeed(i2c_base, ip_rev, speed, waitdelay)) { |
d5243359 HP |
446 | printf("ERROR: failed to setup I2C bus-speed!\n"); |
447 | return; | |
448 | } | |
7f79dfb4 | 449 | |
8ed96046 | 450 | /* own address */ |
bca09ce4 V |
451 | omap_i2c_write_reg(i2c_base, ip_rev, slaveadd, OMAP_I2C_OA_REG); |
452 | ||
453 | if (ip_rev == OMAP_I2C_REV_V1) { | |
454 | /* | |
455 | * Have to enable interrupts for OMAP2/3, these IPs don't have | |
456 | * an 'irqstatus_raw' register and we shall have to poll 'stat' | |
457 | */ | |
458 | omap_i2c_write_reg(i2c_base, ip_rev, I2C_IE_XRDY_IE | | |
459 | I2C_IE_RRDY_IE | I2C_IE_ARDY_IE | | |
460 | I2C_IE_NACK_IE | I2C_IE_AL_IE, | |
461 | OMAP_I2C_IE_REG); | |
462 | } | |
d5243359 | 463 | |
89677b27 | 464 | udelay(1000); |
bca09ce4 V |
465 | flush_fifo(i2c_base, ip_rev); |
466 | omap_i2c_write_reg(i2c_base, ip_rev, 0xFFFF, OMAP_I2C_STAT_REG); | |
f7c10535 HS |
467 | |
468 | /* Handle possible failed I2C state */ | |
bca09ce4 | 469 | if (wait_for_bb(i2c_base, ip_rev, *waitdelay)) |
f7c10535 | 470 | if (deblock == 1) { |
bca09ce4 | 471 | omap24_i2c_deblock(i2c_base, ip_rev); |
f7c10535 HS |
472 | deblock = 0; |
473 | goto retry; | |
474 | } | |
cec487a4 TR |
475 | } |
476 | ||
960187ff LP |
477 | /* |
478 | * i2c_probe: Use write access. Allows to identify addresses that are | |
479 | * write-only (like the config register of dual-port EEPROMs) | |
480 | */ | |
bca09ce4 V |
481 | static int __omap24_i2c_probe(void __iomem *i2c_base, int ip_rev, int waitdelay, |
482 | uchar chip) | |
8ed96046 | 483 | { |
cec487a4 | 484 | u16 status; |
8ed96046 WD |
485 | int res = 1; /* default = fail */ |
486 | ||
bca09ce4 | 487 | if (chip == omap_i2c_read_reg(i2c_base, ip_rev, OMAP_I2C_OA_REG)) |
8ed96046 | 488 | return res; |
8ed96046 | 489 | |
960187ff | 490 | /* Wait until bus is free */ |
bca09ce4 | 491 | if (wait_for_bb(i2c_base, ip_rev, waitdelay)) |
febc4cd4 | 492 | return res; |
8ed96046 | 493 | |
960187ff | 494 | /* No data transfer, slave addr only */ |
bca09ce4 V |
495 | omap_i2c_write_reg(i2c_base, ip_rev, chip, OMAP_I2C_SA_REG); |
496 | ||
960187ff | 497 | /* Stop bit needed here */ |
bca09ce4 V |
498 | omap_i2c_write_reg(i2c_base, ip_rev, I2C_CON_EN | I2C_CON_MST | |
499 | I2C_CON_STT | I2C_CON_TRX | I2C_CON_STP, | |
500 | OMAP_I2C_CON_REG); | |
960187ff | 501 | |
bca09ce4 | 502 | status = wait_for_event(i2c_base, ip_rev, waitdelay); |
960187ff LP |
503 | |
504 | if ((status & ~I2C_STAT_XRDY) == 0 || (status & I2C_STAT_AL)) { | |
505 | /* | |
506 | * With current high-level command implementation, notifying | |
507 | * the user shall flood the console with 127 messages. If | |
508 | * silent exit is desired upon unconfigured bus, remove the | |
509 | * following 'if' section: | |
510 | */ | |
511 | if (status == I2C_STAT_XRDY) | |
be243e41 M |
512 | printf("i2c_probe: pads on bus probably not configured (status=0x%x)\n", |
513 | status); | |
960187ff LP |
514 | |
515 | goto pr_exit; | |
168a5acb | 516 | } |
cec487a4 | 517 | |
960187ff LP |
518 | /* Check for ACK (!NAK) */ |
519 | if (!(status & I2C_STAT_NACK)) { | |
d5243359 | 520 | res = 0; /* Device found */ |
be243e41 | 521 | udelay(waitdelay);/* Required by AM335X in SPL */ |
960187ff | 522 | /* Abort transfer (force idle state) */ |
bca09ce4 V |
523 | omap_i2c_write_reg(i2c_base, ip_rev, I2C_CON_MST | I2C_CON_TRX, |
524 | OMAP_I2C_CON_REG); /* Reset */ | |
960187ff | 525 | udelay(1000); |
bca09ce4 V |
526 | omap_i2c_write_reg(i2c_base, ip_rev, I2C_CON_EN | I2C_CON_MST | |
527 | I2C_CON_TRX | I2C_CON_STP, | |
528 | OMAP_I2C_CON_REG); /* STP */ | |
960187ff | 529 | } |
bca09ce4 | 530 | |
960187ff | 531 | pr_exit: |
bca09ce4 V |
532 | flush_fifo(i2c_base, ip_rev); |
533 | omap_i2c_write_reg(i2c_base, ip_rev, 0xFFFF, OMAP_I2C_STAT_REG); | |
8ed96046 WD |
534 | return res; |
535 | } | |
536 | ||
960187ff LP |
537 | /* |
538 | * i2c_read: Function now uses a single I2C read transaction with bulk transfer | |
539 | * of the requested number of bytes (note that the 'i2c md' command | |
540 | * limits this to 16 bytes anyway). If CONFIG_I2C_REPEATED_START is | |
541 | * defined in the board config header, this transaction shall be with | |
542 | * Repeated Start (Sr) between the address and data phases; otherwise | |
543 | * Stop-Start (P-S) shall be used (some I2C chips do require a P-S). | |
544 | * The address (reg offset) may be 0, 1 or 2 bytes long. | |
545 | * Function now reads correctly from chips that return more than one | |
546 | * byte of data per addressed register (like TI temperature sensors), | |
547 | * or that do not need a register address at all (such as some clock | |
548 | * distributors). | |
549 | */ | |
bca09ce4 V |
550 | static int __omap24_i2c_read(void __iomem *i2c_base, int ip_rev, int waitdelay, |
551 | uchar chip, uint addr, int alen, uchar *buffer, | |
552 | int len) | |
8ed96046 | 553 | { |
960187ff LP |
554 | int i2c_error = 0; |
555 | u16 status; | |
556 | ||
557 | if (alen < 0) { | |
558 | puts("I2C read: addr len < 0\n"); | |
559 | return 1; | |
560 | } | |
bca09ce4 | 561 | |
960187ff LP |
562 | if (len < 0) { |
563 | puts("I2C read: data len < 0\n"); | |
564 | return 1; | |
565 | } | |
bca09ce4 | 566 | |
960187ff LP |
567 | if (buffer == NULL) { |
568 | puts("I2C read: NULL pointer passed\n"); | |
569 | return 1; | |
570 | } | |
8ed96046 | 571 | |
55faa589 | 572 | if (alen > 2) { |
cec487a4 | 573 | printf("I2C read: addr len %d not supported\n", alen); |
8ed96046 WD |
574 | return 1; |
575 | } | |
576 | ||
55faa589 | 577 | if (addr + len > (1 << 16)) { |
cec487a4 | 578 | puts("I2C read: address out of range\n"); |
8ed96046 WD |
579 | return 1; |
580 | } | |
581 | ||
32b9b556 GT |
582 | #ifdef CONFIG_SYS_I2C_EEPROM_ADDR_OVERFLOW |
583 | /* | |
584 | * EEPROM chips that implement "address overflow" are ones | |
585 | * like Catalyst 24WC04/08/16 which has 9/10/11 bits of | |
586 | * address and the extra bits end up in the "chip address" | |
587 | * bit slots. This makes a 24WC08 (1Kbyte) chip look like | |
588 | * four 256 byte chips. | |
589 | * | |
590 | * Note that we consider the length of the address field to | |
591 | * still be one byte because the extra address bits are | |
592 | * hidden in the chip address. | |
593 | */ | |
594 | if (alen > 0) | |
595 | chip |= ((addr >> (alen * 8)) & | |
596 | CONFIG_SYS_I2C_EEPROM_ADDR_OVERFLOW); | |
597 | #endif | |
598 | ||
960187ff | 599 | /* Wait until bus not busy */ |
bca09ce4 | 600 | if (wait_for_bb(i2c_base, ip_rev, waitdelay)) |
960187ff LP |
601 | return 1; |
602 | ||
603 | /* Zero, one or two bytes reg address (offset) */ | |
bca09ce4 | 604 | omap_i2c_write_reg(i2c_base, ip_rev, alen, OMAP_I2C_CNT_REG); |
960187ff | 605 | /* Set slave address */ |
bca09ce4 | 606 | omap_i2c_write_reg(i2c_base, ip_rev, chip, OMAP_I2C_SA_REG); |
960187ff LP |
607 | |
608 | if (alen) { | |
609 | /* Must write reg offset first */ | |
610 | #ifdef CONFIG_I2C_REPEATED_START | |
611 | /* No stop bit, use Repeated Start (Sr) */ | |
bca09ce4 V |
612 | omap_i2c_write_reg(i2c_base, ip_rev, I2C_CON_EN | I2C_CON_MST | |
613 | I2C_CON_STT | I2C_CON_TRX, OMAP_I2C_CON_REG); | |
960187ff LP |
614 | #else |
615 | /* Stop - Start (P-S) */ | |
bca09ce4 V |
616 | omap_i2c_write_reg(i2c_base, ip_rev, I2C_CON_EN | I2C_CON_MST | |
617 | I2C_CON_STT | I2C_CON_STP | I2C_CON_TRX, | |
618 | OMAP_I2C_CON_REG); | |
960187ff LP |
619 | #endif |
620 | /* Send register offset */ | |
621 | while (1) { | |
bca09ce4 | 622 | status = wait_for_event(i2c_base, ip_rev, waitdelay); |
960187ff LP |
623 | /* Try to identify bus that is not padconf'd for I2C */ |
624 | if (status == I2C_STAT_XRDY) { | |
625 | i2c_error = 2; | |
be243e41 M |
626 | printf("i2c_read (addr phase): pads on bus probably not configured (status=0x%x)\n", |
627 | status); | |
960187ff LP |
628 | goto rd_exit; |
629 | } | |
d5243359 | 630 | if (status == 0 || (status & I2C_STAT_NACK)) { |
960187ff LP |
631 | i2c_error = 1; |
632 | printf("i2c_read: error waiting for addr ACK (status=0x%x)\n", | |
633 | status); | |
634 | goto rd_exit; | |
635 | } | |
636 | if (alen) { | |
637 | if (status & I2C_STAT_XRDY) { | |
bca09ce4 | 638 | u8 addr_byte; |
960187ff | 639 | alen--; |
bca09ce4 V |
640 | addr_byte = (addr >> (8 * alen)) & 0xff; |
641 | omap_i2c_write_reg(i2c_base, ip_rev, | |
642 | addr_byte, | |
643 | OMAP_I2C_DATA_REG); | |
644 | omap_i2c_write_reg(i2c_base, ip_rev, | |
645 | I2C_STAT_XRDY, | |
646 | OMAP_I2C_STAT_REG); | |
960187ff LP |
647 | } |
648 | } | |
649 | if (status & I2C_STAT_ARDY) { | |
bca09ce4 V |
650 | omap_i2c_write_reg(i2c_base, ip_rev, |
651 | I2C_STAT_ARDY, | |
652 | OMAP_I2C_STAT_REG); | |
960187ff LP |
653 | break; |
654 | } | |
8ed96046 WD |
655 | } |
656 | } | |
bca09ce4 | 657 | |
960187ff | 658 | /* Set slave address */ |
bca09ce4 | 659 | omap_i2c_write_reg(i2c_base, ip_rev, chip, OMAP_I2C_SA_REG); |
960187ff | 660 | /* Read len bytes from slave */ |
bca09ce4 | 661 | omap_i2c_write_reg(i2c_base, ip_rev, len, OMAP_I2C_CNT_REG); |
960187ff | 662 | /* Need stop bit here */ |
bca09ce4 V |
663 | omap_i2c_write_reg(i2c_base, ip_rev, I2C_CON_EN | I2C_CON_MST | |
664 | I2C_CON_STT | I2C_CON_STP, OMAP_I2C_CON_REG); | |
8ed96046 | 665 | |
960187ff LP |
666 | /* Receive data */ |
667 | while (1) { | |
bca09ce4 | 668 | status = wait_for_event(i2c_base, ip_rev, waitdelay); |
960187ff LP |
669 | /* |
670 | * Try to identify bus that is not padconf'd for I2C. This | |
671 | * state could be left over from previous transactions if | |
672 | * the address phase is skipped due to alen=0. | |
673 | */ | |
674 | if (status == I2C_STAT_XRDY) { | |
675 | i2c_error = 2; | |
be243e41 M |
676 | printf("i2c_read (data phase): pads on bus probably not configured (status=0x%x)\n", |
677 | status); | |
960187ff LP |
678 | goto rd_exit; |
679 | } | |
d5243359 | 680 | if (status == 0 || (status & I2C_STAT_NACK)) { |
960187ff LP |
681 | i2c_error = 1; |
682 | goto rd_exit; | |
683 | } | |
684 | if (status & I2C_STAT_RRDY) { | |
bca09ce4 V |
685 | *buffer++ = omap_i2c_read_reg(i2c_base, ip_rev, |
686 | OMAP_I2C_DATA_REG); | |
687 | omap_i2c_write_reg(i2c_base, ip_rev, | |
688 | I2C_STAT_RRDY, OMAP_I2C_STAT_REG); | |
960187ff LP |
689 | } |
690 | if (status & I2C_STAT_ARDY) { | |
bca09ce4 V |
691 | omap_i2c_write_reg(i2c_base, ip_rev, |
692 | I2C_STAT_ARDY, OMAP_I2C_STAT_REG); | |
960187ff LP |
693 | break; |
694 | } | |
695 | } | |
696 | ||
697 | rd_exit: | |
bca09ce4 V |
698 | flush_fifo(i2c_base, ip_rev); |
699 | omap_i2c_write_reg(i2c_base, ip_rev, 0xFFFF, OMAP_I2C_STAT_REG); | |
960187ff | 700 | return i2c_error; |
8ed96046 WD |
701 | } |
702 | ||
960187ff | 703 | /* i2c_write: Address (reg offset) may be 0, 1 or 2 bytes long. */ |
bca09ce4 V |
704 | static int __omap24_i2c_write(void __iomem *i2c_base, int ip_rev, int waitdelay, |
705 | uchar chip, uint addr, int alen, uchar *buffer, | |
706 | int len) | |
8ed96046 | 707 | { |
cec487a4 TR |
708 | int i; |
709 | u16 status; | |
710 | int i2c_error = 0; | |
d5243359 | 711 | int timeout = I2C_TIMEOUT; |
960187ff LP |
712 | |
713 | if (alen < 0) { | |
714 | puts("I2C write: addr len < 0\n"); | |
715 | return 1; | |
716 | } | |
717 | ||
718 | if (len < 0) { | |
719 | puts("I2C write: data len < 0\n"); | |
720 | return 1; | |
721 | } | |
722 | ||
723 | if (buffer == NULL) { | |
724 | puts("I2C write: NULL pointer passed\n"); | |
725 | return 1; | |
726 | } | |
8ed96046 | 727 | |
55faa589 | 728 | if (alen > 2) { |
cec487a4 | 729 | printf("I2C write: addr len %d not supported\n", alen); |
8ed96046 | 730 | return 1; |
cec487a4 | 731 | } |
8ed96046 | 732 | |
55faa589 | 733 | if (addr + len > (1 << 16)) { |
cec487a4 | 734 | printf("I2C write: address 0x%x + 0x%x out of range\n", |
960187ff | 735 | addr, len); |
8ed96046 WD |
736 | return 1; |
737 | } | |
738 | ||
32b9b556 GT |
739 | #ifdef CONFIG_SYS_I2C_EEPROM_ADDR_OVERFLOW |
740 | /* | |
741 | * EEPROM chips that implement "address overflow" are ones | |
742 | * like Catalyst 24WC04/08/16 which has 9/10/11 bits of | |
743 | * address and the extra bits end up in the "chip address" | |
744 | * bit slots. This makes a 24WC08 (1Kbyte) chip look like | |
745 | * four 256 byte chips. | |
746 | * | |
747 | * Note that we consider the length of the address field to | |
748 | * still be one byte because the extra address bits are | |
749 | * hidden in the chip address. | |
750 | */ | |
751 | if (alen > 0) | |
752 | chip |= ((addr >> (alen * 8)) & | |
753 | CONFIG_SYS_I2C_EEPROM_ADDR_OVERFLOW); | |
754 | #endif | |
755 | ||
960187ff | 756 | /* Wait until bus not busy */ |
bca09ce4 | 757 | if (wait_for_bb(i2c_base, ip_rev, waitdelay)) |
febc4cd4 | 758 | return 1; |
0607e2b9 | 759 | |
960187ff | 760 | /* Start address phase - will write regoffset + len bytes data */ |
bca09ce4 | 761 | omap_i2c_write_reg(i2c_base, ip_rev, alen + len, OMAP_I2C_CNT_REG); |
960187ff | 762 | /* Set slave address */ |
bca09ce4 | 763 | omap_i2c_write_reg(i2c_base, ip_rev, chip, OMAP_I2C_SA_REG); |
960187ff | 764 | /* Stop bit needed here */ |
bca09ce4 V |
765 | omap_i2c_write_reg(i2c_base, ip_rev, I2C_CON_EN | I2C_CON_MST | |
766 | I2C_CON_STT | I2C_CON_TRX | I2C_CON_STP, | |
767 | OMAP_I2C_CON_REG); | |
960187ff LP |
768 | |
769 | while (alen) { | |
770 | /* Must write reg offset (one or two bytes) */ | |
bca09ce4 | 771 | status = wait_for_event(i2c_base, ip_rev, waitdelay); |
960187ff LP |
772 | /* Try to identify bus that is not padconf'd for I2C */ |
773 | if (status == I2C_STAT_XRDY) { | |
774 | i2c_error = 2; | |
be243e41 M |
775 | printf("i2c_write: pads on bus probably not configured (status=0x%x)\n", |
776 | status); | |
960187ff LP |
777 | goto wr_exit; |
778 | } | |
d5243359 | 779 | if (status == 0 || (status & I2C_STAT_NACK)) { |
cec487a4 | 780 | i2c_error = 1; |
960187ff LP |
781 | printf("i2c_write: error waiting for addr ACK (status=0x%x)\n", |
782 | status); | |
783 | goto wr_exit; | |
cec487a4 | 784 | } |
cec487a4 | 785 | if (status & I2C_STAT_XRDY) { |
960187ff | 786 | alen--; |
bca09ce4 V |
787 | omap_i2c_write_reg(i2c_base, ip_rev, |
788 | (addr >> (8 * alen)) & 0xff, | |
789 | OMAP_I2C_DATA_REG); | |
790 | omap_i2c_write_reg(i2c_base, ip_rev, | |
791 | I2C_STAT_XRDY, OMAP_I2C_STAT_REG); | |
960187ff LP |
792 | } else { |
793 | i2c_error = 1; | |
794 | printf("i2c_write: bus not ready for addr Tx (status=0x%x)\n", | |
795 | status); | |
796 | goto wr_exit; | |
797 | } | |
798 | } | |
bca09ce4 | 799 | |
960187ff LP |
800 | /* Address phase is over, now write data */ |
801 | for (i = 0; i < len; i++) { | |
bca09ce4 | 802 | status = wait_for_event(i2c_base, ip_rev, waitdelay); |
d5243359 | 803 | if (status == 0 || (status & I2C_STAT_NACK)) { |
960187ff LP |
804 | i2c_error = 1; |
805 | printf("i2c_write: error waiting for data ACK (status=0x%x)\n", | |
806 | status); | |
807 | goto wr_exit; | |
808 | } | |
809 | if (status & I2C_STAT_XRDY) { | |
bca09ce4 V |
810 | omap_i2c_write_reg(i2c_base, ip_rev, |
811 | buffer[i], OMAP_I2C_DATA_REG); | |
812 | omap_i2c_write_reg(i2c_base, ip_rev, | |
813 | I2C_STAT_XRDY, OMAP_I2C_STAT_REG); | |
cec487a4 TR |
814 | } else { |
815 | i2c_error = 1; | |
960187ff LP |
816 | printf("i2c_write: bus not ready for data Tx (i=%d)\n", |
817 | i); | |
818 | goto wr_exit; | |
8ed96046 WD |
819 | } |
820 | } | |
bca09ce4 | 821 | |
d5243359 HP |
822 | /* |
823 | * poll ARDY bit for making sure that last byte really has been | |
824 | * transferred on the bus. | |
825 | */ | |
826 | do { | |
bca09ce4 | 827 | status = wait_for_event(i2c_base, ip_rev, waitdelay); |
d5243359 HP |
828 | } while (!(status & I2C_STAT_ARDY) && timeout--); |
829 | if (timeout <= 0) | |
830 | printf("i2c_write: timed out writig last byte!\n"); | |
8ed96046 | 831 | |
960187ff | 832 | wr_exit: |
bca09ce4 V |
833 | flush_fifo(i2c_base, ip_rev); |
834 | omap_i2c_write_reg(i2c_base, ip_rev, 0xFFFF, OMAP_I2C_STAT_REG); | |
cec487a4 | 835 | return i2c_error; |
8ed96046 WD |
836 | } |
837 | ||
daa69ffe | 838 | #ifndef CONFIG_DM_I2C |
960187ff | 839 | /* |
be243e41 M |
840 | * The legacy I2C functions. These need to get removed once |
841 | * all users of this driver are converted to DM. | |
960187ff | 842 | */ |
bca09ce4 | 843 | static void __iomem *omap24_get_base(struct i2c_adapter *adap) |
1d2e96de | 844 | { |
6789e84e | 845 | switch (adap->hwadapnr) { |
960187ff | 846 | case 0: |
bca09ce4 | 847 | return (void __iomem *)I2C_BASE1; |
960187ff LP |
848 | break; |
849 | case 1: | |
bca09ce4 | 850 | return (void __iomem *)I2C_BASE2; |
960187ff | 851 | break; |
ac1d8ac8 | 852 | #if (CONFIG_SYS_I2C_BUS_MAX > 2) |
960187ff | 853 | case 2: |
bca09ce4 | 854 | return (void __iomem *)I2C_BASE3; |
960187ff | 855 | break; |
ac1d8ac8 | 856 | #if (CONFIG_SYS_I2C_BUS_MAX > 3) |
960187ff | 857 | case 3: |
bca09ce4 | 858 | return (void __iomem *)I2C_BASE4; |
960187ff | 859 | break; |
ac1d8ac8 | 860 | #if (CONFIG_SYS_I2C_BUS_MAX > 4) |
960187ff | 861 | case 4: |
bca09ce4 | 862 | return (void __iomem *)I2C_BASE5; |
960187ff | 863 | break; |
a5322780 | 864 | #endif |
1d2e96de | 865 | #endif |
960187ff | 866 | #endif |
6789e84e HS |
867 | default: |
868 | printf("wrong hwadapnr: %d\n", adap->hwadapnr); | |
869 | break; | |
960187ff | 870 | } |
bca09ce4 | 871 | |
6789e84e HS |
872 | return NULL; |
873 | } | |
1d2e96de | 874 | |
bca09ce4 V |
875 | static int omap24_get_ip_rev(void) |
876 | { | |
877 | #ifdef CONFIG_OMAP34XX | |
878 | return OMAP_I2C_REV_V1; | |
879 | #else | |
880 | return OMAP_I2C_REV_V2; | |
881 | #endif | |
882 | } | |
be243e41 M |
883 | |
884 | static int omap24_i2c_read(struct i2c_adapter *adap, uchar chip, uint addr, | |
885 | int alen, uchar *buffer, int len) | |
886 | { | |
bca09ce4 V |
887 | void __iomem *i2c_base = omap24_get_base(adap); |
888 | int ip_rev = omap24_get_ip_rev(); | |
be243e41 | 889 | |
bca09ce4 | 890 | return __omap24_i2c_read(i2c_base, ip_rev, adap->waitdelay, chip, addr, |
be243e41 M |
891 | alen, buffer, len); |
892 | } | |
893 | ||
be243e41 M |
894 | static int omap24_i2c_write(struct i2c_adapter *adap, uchar chip, uint addr, |
895 | int alen, uchar *buffer, int len) | |
896 | { | |
bca09ce4 V |
897 | void __iomem *i2c_base = omap24_get_base(adap); |
898 | int ip_rev = omap24_get_ip_rev(); | |
be243e41 | 899 | |
bca09ce4 | 900 | return __omap24_i2c_write(i2c_base, ip_rev, adap->waitdelay, chip, addr, |
be243e41 M |
901 | alen, buffer, len); |
902 | } | |
903 | ||
904 | static uint omap24_i2c_setspeed(struct i2c_adapter *adap, uint speed) | |
905 | { | |
bca09ce4 V |
906 | void __iomem *i2c_base = omap24_get_base(adap); |
907 | int ip_rev = omap24_get_ip_rev(); | |
be243e41 M |
908 | int ret; |
909 | ||
bca09ce4 | 910 | ret = __omap24_i2c_setspeed(i2c_base, ip_rev, speed, &adap->waitdelay); |
be243e41 | 911 | if (ret) { |
9b643e31 | 912 | pr_err("%s: set i2c speed failed\n", __func__); |
be243e41 M |
913 | return ret; |
914 | } | |
915 | ||
916 | adap->speed = speed; | |
917 | ||
918 | return 0; | |
919 | } | |
920 | ||
921 | static void omap24_i2c_init(struct i2c_adapter *adap, int speed, int slaveadd) | |
922 | { | |
bca09ce4 V |
923 | void __iomem *i2c_base = omap24_get_base(adap); |
924 | int ip_rev = omap24_get_ip_rev(); | |
be243e41 | 925 | |
bca09ce4 V |
926 | return __omap24_i2c_init(i2c_base, ip_rev, speed, slaveadd, |
927 | &adap->waitdelay); | |
be243e41 M |
928 | } |
929 | ||
930 | static int omap24_i2c_probe(struct i2c_adapter *adap, uchar chip) | |
931 | { | |
bca09ce4 V |
932 | void __iomem *i2c_base = omap24_get_base(adap); |
933 | int ip_rev = omap24_get_ip_rev(); | |
be243e41 | 934 | |
bca09ce4 | 935 | return __omap24_i2c_probe(i2c_base, ip_rev, adap->waitdelay, chip); |
be243e41 M |
936 | } |
937 | ||
6789e84e HS |
938 | #if !defined(CONFIG_SYS_OMAP24_I2C_SPEED1) |
939 | #define CONFIG_SYS_OMAP24_I2C_SPEED1 CONFIG_SYS_OMAP24_I2C_SPEED | |
940 | #endif | |
941 | #if !defined(CONFIG_SYS_OMAP24_I2C_SLAVE1) | |
942 | #define CONFIG_SYS_OMAP24_I2C_SLAVE1 CONFIG_SYS_OMAP24_I2C_SLAVE | |
943 | #endif | |
1d2e96de | 944 | |
6789e84e | 945 | U_BOOT_I2C_ADAP_COMPLETE(omap24_0, omap24_i2c_init, omap24_i2c_probe, |
d5243359 | 946 | omap24_i2c_read, omap24_i2c_write, omap24_i2c_setspeed, |
6789e84e HS |
947 | CONFIG_SYS_OMAP24_I2C_SPEED, |
948 | CONFIG_SYS_OMAP24_I2C_SLAVE, | |
949 | 0) | |
950 | U_BOOT_I2C_ADAP_COMPLETE(omap24_1, omap24_i2c_init, omap24_i2c_probe, | |
d5243359 | 951 | omap24_i2c_read, omap24_i2c_write, omap24_i2c_setspeed, |
6789e84e HS |
952 | CONFIG_SYS_OMAP24_I2C_SPEED1, |
953 | CONFIG_SYS_OMAP24_I2C_SLAVE1, | |
954 | 1) | |
bca09ce4 | 955 | |
ac1d8ac8 | 956 | #if (CONFIG_SYS_I2C_BUS_MAX > 2) |
6789e84e HS |
957 | #if !defined(CONFIG_SYS_OMAP24_I2C_SPEED2) |
958 | #define CONFIG_SYS_OMAP24_I2C_SPEED2 CONFIG_SYS_OMAP24_I2C_SPEED | |
959 | #endif | |
960 | #if !defined(CONFIG_SYS_OMAP24_I2C_SLAVE2) | |
961 | #define CONFIG_SYS_OMAP24_I2C_SLAVE2 CONFIG_SYS_OMAP24_I2C_SLAVE | |
962 | #endif | |
1d2e96de | 963 | |
6789e84e HS |
964 | U_BOOT_I2C_ADAP_COMPLETE(omap24_2, omap24_i2c_init, omap24_i2c_probe, |
965 | omap24_i2c_read, omap24_i2c_write, NULL, | |
966 | CONFIG_SYS_OMAP24_I2C_SPEED2, | |
967 | CONFIG_SYS_OMAP24_I2C_SLAVE2, | |
968 | 2) | |
ac1d8ac8 | 969 | #if (CONFIG_SYS_I2C_BUS_MAX > 3) |
6789e84e HS |
970 | #if !defined(CONFIG_SYS_OMAP24_I2C_SPEED3) |
971 | #define CONFIG_SYS_OMAP24_I2C_SPEED3 CONFIG_SYS_OMAP24_I2C_SPEED | |
972 | #endif | |
973 | #if !defined(CONFIG_SYS_OMAP24_I2C_SLAVE3) | |
974 | #define CONFIG_SYS_OMAP24_I2C_SLAVE3 CONFIG_SYS_OMAP24_I2C_SLAVE | |
975 | #endif | |
938717ce | 976 | |
6789e84e HS |
977 | U_BOOT_I2C_ADAP_COMPLETE(omap24_3, omap24_i2c_init, omap24_i2c_probe, |
978 | omap24_i2c_read, omap24_i2c_write, NULL, | |
979 | CONFIG_SYS_OMAP24_I2C_SPEED3, | |
980 | CONFIG_SYS_OMAP24_I2C_SLAVE3, | |
981 | 3) | |
ac1d8ac8 | 982 | #if (CONFIG_SYS_I2C_BUS_MAX > 4) |
6789e84e HS |
983 | #if !defined(CONFIG_SYS_OMAP24_I2C_SPEED4) |
984 | #define CONFIG_SYS_OMAP24_I2C_SPEED4 CONFIG_SYS_OMAP24_I2C_SPEED | |
985 | #endif | |
986 | #if !defined(CONFIG_SYS_OMAP24_I2C_SLAVE4) | |
987 | #define CONFIG_SYS_OMAP24_I2C_SLAVE4 CONFIG_SYS_OMAP24_I2C_SLAVE | |
988 | #endif | |
989 | ||
990 | U_BOOT_I2C_ADAP_COMPLETE(omap24_4, omap24_i2c_init, omap24_i2c_probe, | |
991 | omap24_i2c_read, omap24_i2c_write, NULL, | |
992 | CONFIG_SYS_OMAP24_I2C_SPEED4, | |
993 | CONFIG_SYS_OMAP24_I2C_SLAVE4, | |
994 | 4) | |
995 | #endif | |
996 | #endif | |
997 | #endif | |
daa69ffe M |
998 | |
999 | #else /* CONFIG_DM_I2C */ | |
1000 | ||
1001 | static int omap_i2c_xfer(struct udevice *bus, struct i2c_msg *msg, int nmsgs) | |
1002 | { | |
1003 | struct omap_i2c *priv = dev_get_priv(bus); | |
1004 | int ret; | |
1005 | ||
1006 | debug("i2c_xfer: %d messages\n", nmsgs); | |
1007 | for (; nmsgs > 0; nmsgs--, msg++) { | |
1008 | debug("i2c_xfer: chip=0x%x, len=0x%x\n", msg->addr, msg->len); | |
1009 | if (msg->flags & I2C_M_RD) { | |
bca09ce4 V |
1010 | ret = __omap24_i2c_read(priv->regs, priv->ip_rev, |
1011 | priv->waitdelay, | |
daa69ffe M |
1012 | msg->addr, 0, 0, msg->buf, |
1013 | msg->len); | |
1014 | } else { | |
bca09ce4 V |
1015 | ret = __omap24_i2c_write(priv->regs, priv->ip_rev, |
1016 | priv->waitdelay, | |
daa69ffe M |
1017 | msg->addr, 0, 0, msg->buf, |
1018 | msg->len); | |
1019 | } | |
1020 | if (ret) { | |
1021 | debug("i2c_write: error sending\n"); | |
1022 | return -EREMOTEIO; | |
1023 | } | |
1024 | } | |
1025 | ||
1026 | return 0; | |
1027 | } | |
1028 | ||
1029 | static int omap_i2c_set_bus_speed(struct udevice *bus, unsigned int speed) | |
1030 | { | |
1031 | struct omap_i2c *priv = dev_get_priv(bus); | |
1032 | ||
1033 | priv->speed = speed; | |
1034 | ||
bca09ce4 V |
1035 | return __omap24_i2c_setspeed(priv->regs, priv->ip_rev, speed, |
1036 | &priv->waitdelay); | |
daa69ffe M |
1037 | } |
1038 | ||
1039 | static int omap_i2c_probe_chip(struct udevice *bus, uint chip_addr, | |
1040 | uint chip_flags) | |
1041 | { | |
1042 | struct omap_i2c *priv = dev_get_priv(bus); | |
1043 | ||
bca09ce4 V |
1044 | return __omap24_i2c_probe(priv->regs, priv->ip_rev, priv->waitdelay, |
1045 | chip_addr); | |
daa69ffe M |
1046 | } |
1047 | ||
1048 | static int omap_i2c_probe(struct udevice *bus) | |
1049 | { | |
1050 | struct omap_i2c *priv = dev_get_priv(bus); | |
5f97ae68 | 1051 | struct omap_i2c_platdata *plat = dev_get_platdata(bus); |
daa69ffe | 1052 | |
5f97ae68 JJH |
1053 | priv->speed = plat->speed; |
1054 | priv->regs = map_physmem(plat->base, sizeof(void *), | |
1055 | MAP_NOCACHE); | |
1056 | priv->ip_rev = plat->ip_rev; | |
bca09ce4 V |
1057 | |
1058 | __omap24_i2c_init(priv->regs, priv->ip_rev, priv->speed, 0, | |
1059 | &priv->waitdelay); | |
daa69ffe M |
1060 | |
1061 | return 0; | |
1062 | } | |
1063 | ||
410c505c | 1064 | #if CONFIG_IS_ENABLED(OF_CONTROL) && !CONFIG_IS_ENABLED(OF_PLATDATA) |
daa69ffe M |
1065 | static int omap_i2c_ofdata_to_platdata(struct udevice *bus) |
1066 | { | |
5f97ae68 | 1067 | struct omap_i2c_platdata *plat = dev_get_platdata(bus); |
daa69ffe | 1068 | |
5f97ae68 | 1069 | plat->base = devfdt_get_addr(bus); |
f3d46152 SG |
1070 | plat->speed = dev_read_u32_default(bus, "clock-frequency", |
1071 | I2C_SPEED_STANDARD_RATE); | |
5f97ae68 | 1072 | plat->ip_rev = dev_get_driver_data(bus); |
daa69ffe M |
1073 | |
1074 | return 0; | |
1075 | } | |
1076 | ||
daa69ffe | 1077 | static const struct udevice_id omap_i2c_ids[] = { |
bca09ce4 V |
1078 | { .compatible = "ti,omap3-i2c", .data = OMAP_I2C_REV_V1 }, |
1079 | { .compatible = "ti,omap4-i2c", .data = OMAP_I2C_REV_V2 }, | |
daa69ffe M |
1080 | { } |
1081 | }; | |
410c505c AF |
1082 | #endif |
1083 | ||
1084 | static const struct dm_i2c_ops omap_i2c_ops = { | |
1085 | .xfer = omap_i2c_xfer, | |
1086 | .probe_chip = omap_i2c_probe_chip, | |
1087 | .set_bus_speed = omap_i2c_set_bus_speed, | |
1088 | }; | |
daa69ffe M |
1089 | |
1090 | U_BOOT_DRIVER(i2c_omap) = { | |
1091 | .name = "i2c_omap", | |
1092 | .id = UCLASS_I2C, | |
410c505c | 1093 | #if CONFIG_IS_ENABLED(OF_CONTROL) && !CONFIG_IS_ENABLED(OF_PLATDATA) |
daa69ffe M |
1094 | .of_match = omap_i2c_ids, |
1095 | .ofdata_to_platdata = omap_i2c_ofdata_to_platdata, | |
5f97ae68 | 1096 | .platdata_auto_alloc_size = sizeof(struct omap_i2c_platdata), |
410c505c | 1097 | #endif |
daa69ffe M |
1098 | .probe = omap_i2c_probe, |
1099 | .priv_auto_alloc_size = sizeof(struct omap_i2c), | |
1100 | .ops = &omap_i2c_ops, | |
e0cfc209 | 1101 | #if !CONFIG_IS_ENABLED(OF_CONTROL) |
daa69ffe | 1102 | .flags = DM_FLAG_PRE_RELOC, |
e0cfc209 | 1103 | #endif |
daa69ffe M |
1104 | }; |
1105 | ||
1106 | #endif /* CONFIG_DM_I2C */ |