]>
Commit | Line | Data |
---|---|---|
c25e9e04 SB |
1 | #include <common.h> |
2 | #include <errno.h> | |
3 | #include <dm.h> | |
4 | #include <i2c.h> | |
5 | #include <log.h> | |
6 | #include <asm/arch/nexell.h> | |
7 | #include <asm/arch/reset.h> | |
8 | #include <asm/arch/clk.h> | |
9 | #include <asm/arch/nx_gpio.h> | |
10 | #include <linux/delay.h> | |
11 | ||
12 | #define I2C_WRITE 0 | |
13 | #define I2C_READ 1 | |
14 | ||
15 | #define I2CSTAT_MTM 0xC0 /* Master Transmit Mode */ | |
16 | #define I2CSTAT_MRM 0x80 /* Master Receive Mode */ | |
17 | #define I2CSTAT_BSY 0x20 /* Read: Bus Busy */ | |
18 | #define I2CSTAT_SS 0x20 /* Write: START (1) / STOP (0) */ | |
19 | #define I2CSTAT_RXTXEN 0x10 /* Rx/Tx enable */ | |
20 | #define I2CSTAT_ABT 0x08 /* Arbitration bit */ | |
21 | #define I2CSTAT_NACK 0x01 /* Nack bit */ | |
22 | #define I2CCON_IRCLR 0x100 /* Interrupt Clear bit */ | |
23 | #define I2CCON_ACKGEN 0x80 /* Acknowledge generation */ | |
24 | #define I2CCON_TCP256 0x40 /* Tx-clock prescaler: 16 (0) / 256 (1) */ | |
25 | #define I2CCON_IRENB 0x20 /* Interrupt Enable bit */ | |
26 | #define I2CCON_IRPND 0x10 /* Interrupt pending bit */ | |
27 | #define I2CCON_TCDMSK 0x0F /* I2C-bus transmit clock divider bit mask */ | |
28 | ||
29 | #ifdef CONFIG_ARCH_S5P6818 | |
30 | #define SDADLY_CLKSTEP 5 /* SDA delay: Reg. val. is multiple of 5 clks */ | |
31 | #define SDADLY_MAX 3 /* SDA delay: Max. reg. value is 3 */ | |
32 | #define I2CLC_FILTER 0x04 /* SDA filter on */ | |
33 | #else | |
34 | #define STOPCON_CLR 0x01 /* Clock Line Release */ | |
35 | #define STOPCON_DLR 0x02 /* Data Line Release */ | |
36 | #define STOPCON_NAG 0x04 /* not-ackn. generation and data shift cont. */ | |
37 | #endif | |
38 | ||
39 | #define I2C_TIMEOUT_MS 10 /* 10 ms */ | |
40 | ||
41 | #define I2C_M_NOSTOP 0x100 | |
42 | ||
43 | #define MAX_I2C_NUM 3 | |
44 | ||
45 | #define DEFAULT_SPEED 100000 /* default I2C speed [Hz] */ | |
46 | ||
47 | DECLARE_GLOBAL_DATA_PTR; | |
48 | ||
49 | struct nx_i2c_regs { | |
50 | uint iiccon; | |
51 | uint iicstat; | |
52 | uint iicadd; | |
53 | uint iicds; | |
54 | #ifdef CONFIG_ARCH_S5P6818 | |
55 | /* S5P6818: Offset 0x10 is Line Control Register (SDA-delay, Filter) */ | |
56 | uint iiclc; | |
57 | #else | |
58 | /* S5P4418: Offset 0x10 is Stop Control Register */ | |
59 | uint iicstopcon; | |
60 | #endif | |
61 | }; | |
62 | ||
63 | struct nx_i2c_bus { | |
64 | uint bus_num; | |
65 | struct nx_i2c_regs *regs; | |
66 | uint speed; | |
67 | uint target_speed; | |
68 | #ifdef CONFIG_ARCH_S5P6818 | |
69 | uint sda_delay; | |
70 | #else | |
71 | /* setup time for Stop condition [us] */ | |
72 | uint tsu_stop; | |
73 | #endif | |
74 | }; | |
75 | ||
76 | /* s5pxx18 i2c must be reset before enabled */ | |
77 | static void i2c_reset(int ch) | |
78 | { | |
79 | int rst_id = RESET_ID_I2C0 + ch; | |
80 | ||
81 | nx_rstcon_setrst(rst_id, 0); | |
82 | nx_rstcon_setrst(rst_id, 1); | |
83 | } | |
84 | ||
85 | static uint i2c_get_clkrate(struct nx_i2c_bus *bus) | |
86 | { | |
87 | struct clk *clk; | |
88 | int index = bus->bus_num; | |
89 | char name[50] = {0, }; | |
90 | ||
91 | sprintf(name, "%s.%d", DEV_NAME_I2C, index); | |
92 | clk = clk_get((const char *)name); | |
93 | if (!clk) | |
94 | return -1; | |
95 | ||
96 | return clk_get_rate(clk); | |
97 | } | |
98 | ||
99 | static uint i2c_set_clk(struct nx_i2c_bus *bus, uint enb) | |
100 | { | |
101 | struct clk *clk; | |
102 | char name[50]; | |
103 | ||
104 | sprintf(name, "%s.%d", DEV_NAME_I2C, bus->bus_num); | |
105 | clk = clk_get((const char *)name); | |
106 | if (!clk) { | |
107 | debug("%s(): clk_get(%s) error!\n", | |
108 | __func__, (const char *)name); | |
109 | return -EINVAL; | |
110 | } | |
111 | ||
112 | clk_disable(clk); | |
113 | if (enb) | |
114 | clk_enable(clk); | |
115 | ||
116 | return 0; | |
117 | } | |
118 | ||
119 | #ifdef CONFIG_ARCH_S5P6818 | |
120 | /* Set SDA line delay, not available at S5P4418 */ | |
121 | static int nx_i2c_set_sda_delay(struct nx_i2c_bus *bus) | |
122 | { | |
123 | struct nx_i2c_regs *i2c = bus->regs; | |
124 | uint pclk = 0; | |
125 | uint t_pclk = 0; | |
126 | uint delay = 0; | |
127 | ||
128 | /* get input clock of the I2C-controller */ | |
129 | pclk = i2c_get_clkrate(bus); | |
130 | ||
131 | if (bus->sda_delay) { | |
132 | /* t_pclk = period time of one pclk [ns] */ | |
133 | t_pclk = DIV_ROUND_UP(1000, pclk / 1000000); | |
134 | /* delay = number of pclks required for sda_delay [ns] */ | |
135 | delay = DIV_ROUND_UP(bus->sda_delay, t_pclk); | |
136 | /* delay = register value (step of 5 clocks) */ | |
137 | delay = DIV_ROUND_UP(delay, SDADLY_CLKSTEP); | |
138 | /* max. possible register value = 3 */ | |
139 | if (delay > SDADLY_MAX) { | |
140 | delay = SDADLY_MAX; | |
141 | debug("%s(): sda-delay des.: %dns, sat. to max.: %dns (granularity: %dns)\n", | |
142 | __func__, bus->sda_delay, t_pclk * delay * SDADLY_CLKSTEP, | |
143 | t_pclk * SDADLY_CLKSTEP); | |
144 | } else { | |
145 | debug("%s(): sda-delay des.: %dns, act.: %dns (granularity: %dns)\n", | |
146 | __func__, bus->sda_delay, t_pclk * delay * SDADLY_CLKSTEP, | |
147 | t_pclk * SDADLY_CLKSTEP); | |
148 | } | |
149 | ||
150 | delay |= I2CLC_FILTER; | |
151 | } else { | |
152 | delay = 0; | |
153 | debug("%s(): sda-delay = 0\n", __func__); | |
154 | } | |
155 | ||
156 | delay &= 0x7; | |
157 | writel(delay, &i2c->iiclc); | |
158 | ||
159 | return 0; | |
160 | } | |
161 | #endif | |
162 | ||
163 | static int nx_i2c_set_bus_speed(struct udevice *dev, uint speed) | |
164 | { | |
165 | struct nx_i2c_bus *bus = dev_get_priv(dev); | |
166 | struct nx_i2c_regs *i2c = bus->regs; | |
167 | unsigned long pclk, pres = 16, div; | |
168 | ||
169 | if (i2c_set_clk(bus, 1)) | |
170 | return -EINVAL; | |
171 | ||
172 | /* get input clock of the I2C-controller */ | |
173 | pclk = i2c_get_clkrate(bus); | |
174 | ||
175 | /* calculate prescaler and divisor values */ | |
176 | if ((pclk / pres / (16 + 1)) > speed) | |
177 | /* prescaler value 16 is too less --> set to 256 */ | |
178 | pres = 256; | |
179 | ||
180 | div = 0; | |
181 | /* actual divider = div + 1 */ | |
182 | while ((pclk / pres / (div + 1)) > speed) | |
183 | div++; | |
184 | ||
185 | if (div > 0xF) { | |
186 | debug("%s(): pres==%ld, div==0x%lx is saturated to 0xF !)\n", | |
187 | __func__, pres, div); | |
188 | div = 0xF; | |
189 | } else { | |
190 | debug("%s(): pres==%ld, div==0x%lx)\n", __func__, pres, div); | |
191 | } | |
192 | ||
193 | /* set Tx-clock divisor and prescaler values */ | |
194 | writel((div & I2CCON_TCDMSK) | ((pres == 256) ? I2CCON_TCP256 : 0), | |
195 | &i2c->iiccon); | |
196 | ||
197 | /* init to SLAVE REVEIVE and set slaveaddr */ | |
198 | writel(0, &i2c->iicstat); | |
199 | writel(0x00, &i2c->iicadd); | |
200 | ||
201 | /* program Master Transmit (and implicit STOP) */ | |
202 | writel(I2CSTAT_MTM | I2CSTAT_RXTXEN, &i2c->iicstat); | |
203 | ||
204 | /* calculate actual I2C speed [Hz] */ | |
205 | bus->speed = pclk / ((div + 1) * pres); | |
206 | debug("%s(): speed des.: %dHz, act.: %dHz\n", | |
207 | __func__, speed, bus->speed); | |
208 | ||
209 | #ifdef CONFIG_ARCH_S5P6818 | |
210 | nx_i2c_set_sda_delay(bus); | |
211 | #else | |
212 | /* setup time for Stop condition [us], min. 4us @ 100kHz I2C-clock */ | |
213 | bus->tsu_stop = DIV_ROUND_UP(400, bus->speed / 1000); | |
214 | #endif | |
215 | ||
216 | if (i2c_set_clk(bus, 0)) | |
217 | return -EINVAL; | |
218 | return 0; | |
219 | } | |
220 | ||
221 | static void i2c_process_node(struct udevice *dev) | |
222 | { | |
223 | struct nx_i2c_bus *bus = dev_get_priv(dev); | |
224 | ||
225 | bus->target_speed = dev_read_s32_default(dev, "clock-frequency", | |
226 | DEFAULT_SPEED); | |
227 | #ifdef CONFIG_ARCH_S5P6818 | |
228 | bus->sda_delay = dev_read_s32_default(dev, "i2c-sda-delay-ns", 0); | |
229 | #endif | |
230 | } | |
231 | ||
232 | static int nx_i2c_probe(struct udevice *dev) | |
233 | { | |
234 | struct nx_i2c_bus *bus = dev_get_priv(dev); | |
235 | fdt_addr_t addr; | |
236 | ||
237 | /* get regs = i2c base address */ | |
238 | addr = devfdt_get_addr(dev); | |
239 | if (addr == FDT_ADDR_T_NONE) | |
240 | return -EINVAL; | |
241 | bus->regs = (struct nx_i2c_regs *)addr; | |
242 | ||
243 | bus->bus_num = dev->seq; | |
244 | ||
245 | /* i2c node parsing */ | |
246 | i2c_process_node(dev); | |
247 | if (!bus->target_speed) | |
248 | return -ENODEV; | |
249 | ||
250 | /* reset */ | |
251 | i2c_reset(bus->bus_num); | |
252 | ||
253 | return 0; | |
254 | } | |
255 | ||
256 | /* i2c bus busy check */ | |
257 | static int i2c_is_busy(struct nx_i2c_regs *i2c) | |
258 | { | |
259 | ulong start_time; | |
260 | ||
261 | start_time = get_timer(0); | |
262 | while (readl(&i2c->iicstat) & I2CSTAT_BSY) { | |
263 | if (get_timer(start_time) > I2C_TIMEOUT_MS) { | |
264 | debug("Timeout\n"); | |
265 | return -EBUSY; | |
266 | } | |
267 | } | |
268 | return 0; | |
269 | } | |
270 | ||
271 | /* irq enable/disable functions */ | |
272 | static void i2c_enable_irq(struct nx_i2c_regs *i2c) | |
273 | { | |
274 | unsigned int reg; | |
275 | ||
276 | reg = readl(&i2c->iiccon); | |
277 | reg |= I2CCON_IRENB; | |
278 | writel(reg, &i2c->iiccon); | |
279 | } | |
280 | ||
281 | /* irq clear function */ | |
282 | static void i2c_clear_irq(struct nx_i2c_regs *i2c) | |
283 | { | |
284 | unsigned int reg; | |
285 | ||
286 | reg = readl(&i2c->iiccon); | |
287 | /* reset interrupt pending flag */ | |
288 | reg &= ~(I2CCON_IRPND); | |
289 | /* | |
290 | * Interrupt must also be cleared! | |
291 | * Otherwise linux boot may hang after: | |
292 | * [ 0.436000] NetLabel: unlabeled traffic allowed by default | |
293 | * Next would be: | |
294 | * [ 0.442000] clocksource: Switched to clocksource source timer | |
295 | */ | |
296 | reg |= I2CCON_IRCLR; | |
297 | writel(reg, &i2c->iiccon); | |
298 | } | |
299 | ||
300 | /* ack enable functions */ | |
301 | static void i2c_enable_ack(struct nx_i2c_regs *i2c) | |
302 | { | |
303 | unsigned int reg; | |
304 | ||
305 | reg = readl(&i2c->iiccon); | |
306 | reg |= I2CCON_ACKGEN; | |
307 | writel(reg, &i2c->iiccon); | |
308 | } | |
309 | ||
310 | static void i2c_send_stop(struct nx_i2c_bus *bus) | |
311 | { | |
312 | struct nx_i2c_regs *i2c = bus->regs; | |
313 | ||
314 | if (IS_ENABLED(CONFIG_ARCH_S5P6818)) { | |
315 | unsigned int reg; | |
316 | ||
317 | reg = readl(&i2c->iicstat); | |
318 | reg |= I2CSTAT_MRM | I2CSTAT_RXTXEN; | |
319 | reg &= (~I2CSTAT_SS); | |
320 | ||
321 | writel(reg, &i2c->iicstat); | |
322 | i2c_clear_irq(i2c); | |
323 | } else { /* S5P4418 */ | |
324 | writel(STOPCON_NAG, &i2c->iicstopcon); | |
325 | ||
326 | i2c_clear_irq(i2c); | |
327 | ||
328 | /* | |
329 | * Clock Line Release --> SDC changes from Low to High and | |
330 | * SDA from High to Low | |
331 | */ | |
332 | writel(STOPCON_CLR, &i2c->iicstopcon); | |
333 | ||
334 | /* Hold SDA Low (Setup Time for Stop condition) */ | |
335 | udelay(bus->tsu_stop); | |
336 | ||
337 | i2c_clear_irq(i2c); | |
338 | ||
339 | /* Master Receive Mode Stop --> SDA becomes High */ | |
340 | writel(I2CSTAT_MRM, &i2c->iicstat); | |
341 | } | |
342 | } | |
343 | ||
344 | static int wait_for_xfer(struct nx_i2c_regs *i2c) | |
345 | { | |
346 | unsigned long start_time = get_timer(0); | |
347 | ||
348 | do { | |
349 | if (readl(&i2c->iiccon) & I2CCON_IRPND) | |
350 | /* return -EREMOTEIO if not Acknowledged, otherwise 0 */ | |
351 | return (readl(&i2c->iicstat) & I2CSTAT_NACK) ? | |
352 | -EREMOTEIO : 0; | |
353 | } while (get_timer(start_time) < I2C_TIMEOUT_MS); | |
354 | ||
355 | return -ETIMEDOUT; | |
356 | } | |
357 | ||
358 | static int i2c_transfer(struct nx_i2c_regs *i2c, | |
359 | uchar cmd_type, | |
360 | uchar chip_addr, | |
361 | uchar addr[], | |
362 | uchar addr_len, | |
363 | uchar data[], | |
364 | unsigned short data_len, | |
365 | uint seq) | |
366 | { | |
367 | uint status; | |
368 | int i = 0, result; | |
369 | ||
370 | /* Note: data_len = 0 is supported for "probe_chip" */ | |
371 | ||
372 | i2c_enable_irq(i2c); | |
373 | i2c_enable_ack(i2c); | |
374 | ||
375 | /* Get the slave chip address going */ | |
376 | /* Enable Rx/Tx */ | |
377 | writel(I2CSTAT_RXTXEN, &i2c->iicstat); | |
378 | ||
379 | writel(chip_addr, &i2c->iicds); | |
380 | status = I2CSTAT_RXTXEN | I2CSTAT_SS; | |
381 | if (cmd_type == I2C_WRITE || (addr && addr_len)) | |
382 | status |= I2CSTAT_MTM; | |
383 | else | |
384 | status |= I2CSTAT_MRM; | |
385 | ||
386 | writel(status, &i2c->iicstat); | |
387 | if (seq) | |
388 | i2c_clear_irq(i2c); | |
389 | ||
390 | /* Wait for chip address to transmit. */ | |
391 | result = wait_for_xfer(i2c); | |
392 | if (result) { | |
393 | debug("%s: transmitting chip address failed\n", __func__); | |
394 | goto bailout; | |
395 | } | |
396 | ||
397 | /* If register address needs to be transmitted - do it now. */ | |
398 | if (addr && addr_len) { /* register addr */ | |
399 | while ((i < addr_len) && !result) { | |
400 | writel(addr[i++], &i2c->iicds); | |
401 | i2c_clear_irq(i2c); | |
402 | result = wait_for_xfer(i2c); | |
403 | } | |
404 | ||
405 | i = 0; | |
406 | if (result) { | |
407 | debug("%s: transmitting register address failed\n", | |
408 | __func__); | |
409 | goto bailout; | |
410 | } | |
411 | } | |
412 | ||
413 | switch (cmd_type) { | |
414 | case I2C_WRITE: | |
415 | while ((i < data_len) && !result) { | |
416 | writel(data[i++], &i2c->iicds); | |
417 | i2c_clear_irq(i2c); | |
418 | result = wait_for_xfer(i2c); | |
419 | } | |
420 | break; | |
421 | case I2C_READ: | |
422 | if (addr && addr_len) { | |
423 | /* | |
424 | * Register address has been sent, now send slave chip | |
425 | * address again to start the actual read transaction. | |
426 | */ | |
427 | writel(chip_addr, &i2c->iicds); | |
428 | ||
429 | /* Generate a re-START. */ | |
430 | writel(I2CSTAT_MRM | I2CSTAT_RXTXEN | | |
431 | I2CSTAT_SS, &i2c->iicstat); | |
432 | i2c_clear_irq(i2c); | |
433 | result = wait_for_xfer(i2c); | |
434 | if (result) { | |
435 | debug("%s: I2C_READ: sending chip addr. failed\n", | |
436 | __func__); | |
437 | goto bailout; | |
438 | } | |
439 | } | |
440 | ||
441 | while ((i < data_len) && !result) { | |
442 | /* disable ACK for final READ */ | |
443 | if (i == data_len - 1) | |
444 | clrbits_le32(&i2c->iiccon, I2CCON_ACKGEN); | |
445 | ||
446 | i2c_clear_irq(i2c); | |
447 | result = wait_for_xfer(i2c); | |
448 | data[i++] = readb(&i2c->iicds); | |
449 | } | |
450 | ||
451 | if (result == -EREMOTEIO) | |
452 | /* Not Acknowledged --> normal terminated read. */ | |
453 | result = 0; | |
454 | else if (result == -ETIMEDOUT) | |
455 | debug("%s: I2C_READ: time out\n", __func__); | |
456 | else | |
457 | debug("%s: I2C_READ: read not terminated with NACK\n", | |
458 | __func__); | |
459 | break; | |
460 | ||
461 | default: | |
462 | debug("%s: bad call\n", __func__); | |
463 | result = -EINVAL; | |
464 | break; | |
465 | } | |
466 | ||
467 | bailout: | |
468 | return result; | |
469 | } | |
470 | ||
471 | static int nx_i2c_read(struct udevice *dev, uchar chip_addr, uint addr, | |
472 | uint alen, uchar *buffer, uint len, uint seq) | |
473 | { | |
474 | struct nx_i2c_bus *i2c; | |
475 | uchar xaddr[4]; | |
476 | int ret; | |
477 | ||
478 | i2c = dev_get_priv(dev); | |
479 | if (!i2c) | |
480 | return -EFAULT; | |
481 | ||
482 | if (alen > 4) { | |
483 | debug("I2C read: addr len %d not supported\n", alen); | |
484 | return -EADDRNOTAVAIL; | |
485 | } | |
486 | ||
487 | if (alen > 0) | |
488 | xaddr[0] = (addr >> 24) & 0xFF; | |
489 | ||
490 | if (alen > 0) { | |
491 | xaddr[0] = (addr >> 24) & 0xFF; | |
492 | xaddr[1] = (addr >> 16) & 0xFF; | |
493 | xaddr[2] = (addr >> 8) & 0xFF; | |
494 | xaddr[3] = addr & 0xFF; | |
495 | } | |
496 | ||
497 | ret = i2c_transfer(i2c->regs, I2C_READ, chip_addr << 1, | |
498 | &xaddr[4 - alen], alen, buffer, len, seq); | |
499 | ||
500 | if (ret) { | |
501 | debug("I2C read failed %d\n", ret); | |
502 | return -EIO; | |
503 | } | |
504 | ||
505 | return 0; | |
506 | } | |
507 | ||
508 | static int nx_i2c_write(struct udevice *dev, uchar chip_addr, uint addr, | |
509 | uint alen, uchar *buffer, uint len, uint seq) | |
510 | { | |
511 | struct nx_i2c_bus *i2c; | |
512 | uchar xaddr[4]; | |
513 | int ret; | |
514 | ||
515 | i2c = dev_get_priv(dev); | |
516 | if (!i2c) | |
517 | return -EFAULT; | |
518 | ||
519 | if (alen > 4) { | |
520 | debug("I2C write: addr len %d not supported\n", alen); | |
521 | return -EINVAL; | |
522 | } | |
523 | ||
524 | if (alen > 0) { | |
525 | xaddr[0] = (addr >> 24) & 0xFF; | |
526 | xaddr[1] = (addr >> 16) & 0xFF; | |
527 | xaddr[2] = (addr >> 8) & 0xFF; | |
528 | xaddr[3] = addr & 0xFF; | |
529 | } | |
530 | ||
531 | ret = i2c_transfer(i2c->regs, I2C_WRITE, chip_addr << 1, | |
532 | &xaddr[4 - alen], alen, buffer, len, seq); | |
533 | if (ret) { | |
534 | debug("I2C write failed %d\n", ret); | |
535 | return -EIO; | |
536 | } | |
537 | ||
538 | return 0; | |
539 | } | |
540 | ||
541 | static int nx_i2c_xfer(struct udevice *dev, struct i2c_msg *msg, int nmsgs) | |
542 | { | |
543 | struct nx_i2c_bus *bus = dev_get_priv(dev); | |
544 | struct nx_i2c_regs *i2c = bus->regs; | |
545 | int ret; | |
546 | int i; | |
547 | ||
548 | /* The power loss by the clock, only during on/off. */ | |
549 | ret = i2c_set_clk(bus, 1); | |
550 | ||
551 | if (!ret) | |
552 | /* Bus State(Busy) check */ | |
553 | ret = i2c_is_busy(i2c); | |
554 | if (!ret) { | |
555 | for (i = 0; i < nmsgs; msg++, i++) { | |
556 | if (msg->flags & I2C_M_RD) { | |
557 | ret = nx_i2c_read(dev, msg->addr, 0, 0, | |
558 | msg->buf, msg->len, i); | |
559 | } else { | |
560 | ret = nx_i2c_write(dev, msg->addr, 0, 0, | |
561 | msg->buf, msg->len, i); | |
562 | } | |
563 | ||
564 | if (ret) { | |
565 | debug("i2c_xfer: error sending\n"); | |
566 | ret = -EREMOTEIO; | |
567 | } | |
568 | } | |
569 | ||
570 | i2c_send_stop(bus); | |
571 | if (i2c_set_clk(bus, 0)) | |
572 | ret = -EINVAL; | |
573 | } | |
574 | ||
575 | return ret; | |
576 | }; | |
577 | ||
578 | static int nx_i2c_probe_chip(struct udevice *dev, u32 chip_addr, | |
579 | u32 chip_flags) | |
580 | { | |
581 | int ret; | |
582 | struct nx_i2c_bus *bus = dev_get_priv(dev); | |
583 | ||
584 | ret = i2c_set_clk(bus, 1); | |
585 | ||
586 | if (!ret) { | |
587 | /* | |
588 | * Send Chip Address only | |
589 | * --> I2C transfer with data length and address length = 0. | |
590 | * If there is a Slave, i2c_transfer() returns 0 (acknowledge | |
591 | * transfer). | |
592 | * I2C_WRITE must be used in order Master Transmit Mode is | |
593 | * selected. Otherwise (in Master Receive Mode, I2C_READ) | |
594 | * sending the stop condition below is not working (SDA does | |
595 | * not transit to High). | |
596 | */ | |
597 | ret = i2c_transfer(bus->regs, I2C_WRITE, (uchar)chip_addr << 1, | |
598 | NULL, 0, NULL, 0, 0); | |
599 | ||
600 | i2c_send_stop(bus); | |
601 | if (i2c_set_clk(bus, 0)) | |
602 | ret = -EINVAL; | |
603 | } | |
604 | ||
605 | return ret; | |
606 | } | |
607 | ||
608 | static const struct dm_i2c_ops nx_i2c_ops = { | |
609 | .xfer = nx_i2c_xfer, | |
610 | .probe_chip = nx_i2c_probe_chip, | |
611 | .set_bus_speed = nx_i2c_set_bus_speed, | |
612 | }; | |
613 | ||
614 | static const struct udevice_id nx_i2c_ids[] = { | |
615 | { .compatible = "nexell,s5pxx18-i2c" }, | |
616 | { } | |
617 | }; | |
618 | ||
619 | U_BOOT_DRIVER(i2c_nexell) = { | |
620 | .name = "i2c_nexell", | |
621 | .id = UCLASS_I2C, | |
622 | .of_match = nx_i2c_ids, | |
623 | .probe = nx_i2c_probe, | |
41575d8e | 624 | .priv_auto = sizeof(struct nx_i2c_bus), |
c25e9e04 SB |
625 | .ops = &nx_i2c_ops, |
626 | }; |