]>
Commit | Line | Data |
---|---|---|
2b77eea7 JL |
1 | // SPDX-License-Identifier: GPL-2.0+ |
2 | /* | |
3 | * Copyright (c) 2021 Nuvoton Technology Corp. | |
4 | */ | |
5 | ||
6 | #include <clk.h> | |
7 | #include <dm.h> | |
8 | #include <i2c.h> | |
9 | #include <asm/io.h> | |
10 | #include <linux/iopoll.h> | |
11 | #include <asm/arch/gcr.h> | |
12 | ||
13 | #define I2C_FREQ_100K 100000 | |
14 | #define NPCM_I2C_TIMEOUT_MS 10 | |
15 | #define NPCM7XX_I2CSEGCTL_INIT_VAL 0x0333F000 | |
16 | #define NPCM8XX_I2CSEGCTL_INIT_VAL 0x9333F000 | |
17 | ||
18 | /* SCLFRQ min/max field values */ | |
19 | #define SCLFRQ_MIN 10 | |
20 | #define SCLFRQ_MAX 511 | |
21 | ||
22 | /* SMBCTL1 */ | |
23 | #define SMBCTL1_START BIT(0) | |
24 | #define SMBCTL1_STOP BIT(1) | |
25 | #define SMBCTL1_INTEN BIT(2) | |
26 | #define SMBCTL1_ACK BIT(4) | |
27 | #define SMBCTL1_STASTRE BIT(7) | |
28 | ||
29 | /* SMBCTL2 */ | |
30 | #define SMBCTL2_ENABLE BIT(0) | |
31 | ||
32 | /* SMBCTL3 */ | |
33 | #define SMBCTL3_SCL_LVL BIT(7) | |
34 | #define SMBCTL3_SDA_LVL BIT(6) | |
35 | ||
36 | /* SMBCST */ | |
37 | #define SMBCST_BB BIT(1) | |
38 | #define SMBCST_TGSCL BIT(5) | |
39 | ||
40 | /* SMBST */ | |
41 | #define SMBST_XMIT BIT(0) | |
42 | #define SMBST_MASTER BIT(1) | |
43 | #define SMBST_STASTR BIT(3) | |
44 | #define SMBST_NEGACK BIT(4) | |
45 | #define SMBST_BER BIT(5) | |
46 | #define SMBST_SDAST BIT(6) | |
47 | ||
48 | /* SMBCST3 in bank0 */ | |
49 | #define SMBCST3_EO_BUSY BIT(7) | |
50 | ||
51 | /* SMBFIF_CTS in bank1 */ | |
52 | #define SMBFIF_CTS_CLR_FIFO BIT(6) | |
53 | ||
54 | #define SMBFIF_CTL_FIFO_EN BIT(4) | |
55 | #define SMBCTL3_BNK_SEL BIT(5) | |
56 | ||
57 | enum { | |
58 | I2C_ERR_NACK = 1, | |
59 | I2C_ERR_BER, | |
60 | I2C_ERR_TIMEOUT, | |
61 | }; | |
62 | ||
63 | struct smb_bank0_regs { | |
64 | u8 addr3; | |
65 | u8 addr7; | |
66 | u8 addr4; | |
67 | u8 addr8; | |
68 | u16 addr5; | |
69 | u16 addr6; | |
70 | u8 cst2; | |
71 | u8 cst3; | |
72 | u8 ctl4; | |
73 | u8 ctl5; | |
74 | u8 scllt; | |
75 | u8 fif_ctl; | |
76 | u8 sclht; | |
77 | }; | |
78 | ||
79 | struct smb_bank1_regs { | |
80 | u8 fif_cts; | |
81 | u8 fair_per; | |
82 | u16 txf_ctl; | |
83 | u32 t_out; | |
84 | u8 cst2; | |
85 | u8 cst3; | |
86 | u16 txf_sts; | |
87 | u16 rxf_sts; | |
88 | u8 rxf_ctl; | |
89 | }; | |
90 | ||
91 | struct npcm_i2c_regs { | |
92 | u16 sda; | |
93 | u16 st; | |
94 | u16 cst; | |
95 | u16 ctl1; | |
96 | u16 addr; | |
97 | u16 ctl2; | |
98 | u16 addr2; | |
99 | u16 ctl3; | |
100 | union { | |
101 | struct smb_bank0_regs bank0; | |
102 | struct smb_bank1_regs bank1; | |
103 | }; | |
104 | ||
105 | }; | |
106 | ||
107 | struct npcm_i2c_bus { | |
108 | struct npcm_i2c_regs *reg; | |
109 | int num; | |
110 | u32 apb_clk; | |
111 | u32 freq; | |
112 | bool started; | |
113 | }; | |
114 | ||
115 | static void npcm_dump_regs(struct npcm_i2c_bus *bus) | |
116 | { | |
117 | struct npcm_i2c_regs *reg = bus->reg; | |
118 | ||
119 | printf("\n"); | |
120 | printf("SMBST=0x%x\n", readb(®->st)); | |
121 | printf("SMBCST=0x%x\n", readb(®->cst)); | |
122 | printf("SMBCTL1=0x%x\n", readb(®->ctl1)); | |
123 | printf("\n"); | |
124 | } | |
125 | ||
126 | static int npcm_i2c_check_sda(struct npcm_i2c_bus *bus) | |
127 | { | |
128 | struct npcm_i2c_regs *reg = bus->reg; | |
129 | ulong start_time; | |
130 | int err = I2C_ERR_TIMEOUT; | |
131 | u8 val; | |
132 | ||
133 | start_time = get_timer(0); | |
134 | /* wait SDAST to be 1 */ | |
135 | while (get_timer(start_time) < NPCM_I2C_TIMEOUT_MS) { | |
136 | val = readb(®->st); | |
137 | if (val & SMBST_NEGACK) { | |
138 | err = I2C_ERR_NACK; | |
139 | break; | |
140 | } | |
141 | if (val & SMBST_BER) { | |
142 | err = I2C_ERR_BER; | |
143 | break; | |
144 | } | |
145 | if (val & SMBST_SDAST) { | |
146 | err = 0; | |
147 | break; | |
148 | } | |
149 | } | |
150 | ||
151 | if (err) | |
152 | printf("%s: err %d\n", __func__, err); | |
153 | ||
154 | return err; | |
155 | } | |
156 | ||
157 | static int npcm_i2c_send_start(struct npcm_i2c_bus *bus) | |
158 | { | |
159 | struct npcm_i2c_regs *reg = bus->reg; | |
160 | ulong start_time; | |
161 | int err = I2C_ERR_TIMEOUT; | |
162 | ||
163 | /* Generate START condition */ | |
164 | setbits_8(®->ctl1, SMBCTL1_START); | |
165 | ||
166 | start_time = get_timer(0); | |
167 | while (get_timer(start_time) < NPCM_I2C_TIMEOUT_MS) { | |
168 | if (readb(®->st) & SMBST_BER) | |
169 | return I2C_ERR_BER; | |
170 | if (readb(®->st) & SMBST_MASTER) { | |
171 | err = 0; | |
172 | break; | |
173 | } | |
174 | } | |
175 | bus->started = true; | |
176 | ||
177 | return err; | |
178 | } | |
179 | ||
180 | static int npcm_i2c_send_stop(struct npcm_i2c_bus *bus, bool wait) | |
181 | { | |
182 | struct npcm_i2c_regs *reg = bus->reg; | |
183 | ulong start_time; | |
184 | int err = I2C_ERR_TIMEOUT; | |
185 | ||
186 | setbits_8(®->ctl1, SMBCTL1_STOP); | |
187 | ||
188 | /* Clear NEGACK, STASTR and BER bits */ | |
189 | writeb(SMBST_STASTR | SMBST_NEGACK | SMBST_BER, ®->st); | |
190 | ||
191 | bus->started = false; | |
192 | ||
193 | if (!wait) | |
194 | return 0; | |
195 | ||
196 | start_time = get_timer(0); | |
197 | while (get_timer(start_time) < NPCM_I2C_TIMEOUT_MS) { | |
198 | if ((readb(®->ctl1) & SMBCTL1_STOP) == 0) { | |
199 | err = 0; | |
200 | break; | |
201 | } | |
202 | } | |
203 | if (err) { | |
204 | printf("%s: err %d\n", __func__, err); | |
205 | npcm_dump_regs(bus); | |
206 | } | |
207 | ||
208 | return err; | |
209 | } | |
210 | ||
211 | static void npcm_i2c_reset(struct npcm_i2c_bus *bus) | |
212 | { | |
213 | struct npcm_i2c_regs *reg = bus->reg; | |
214 | ||
215 | debug("%s: module %d\n", __func__, bus->num); | |
216 | /* disable & enable SMB moudle */ | |
217 | clrbits_8(®->ctl2, SMBCTL2_ENABLE); | |
218 | setbits_8(®->ctl2, SMBCTL2_ENABLE); | |
219 | ||
220 | /* clear BB and status */ | |
221 | writeb(SMBCST_BB, ®->cst); | |
222 | writeb(0xff, ®->st); | |
223 | ||
224 | /* select bank 1 */ | |
225 | setbits_8(®->ctl3, SMBCTL3_BNK_SEL); | |
226 | /* Clear all fifo bits */ | |
227 | writeb(SMBFIF_CTS_CLR_FIFO, ®->bank1.fif_cts); | |
228 | ||
229 | /* select bank 0 */ | |
230 | clrbits_8(®->ctl3, SMBCTL3_BNK_SEL); | |
231 | /* clear EOB bit */ | |
232 | writeb(SMBCST3_EO_BUSY, ®->bank0.cst3); | |
233 | /* single byte mode */ | |
234 | clrbits_8(®->bank0.fif_ctl, SMBFIF_CTL_FIFO_EN); | |
235 | ||
236 | /* set POLL mode */ | |
237 | writeb(0, ®->ctl1); | |
238 | } | |
239 | ||
240 | static void npcm_i2c_recovery(struct npcm_i2c_bus *bus, u32 addr) | |
241 | { | |
242 | u8 val; | |
243 | int iter = 27; | |
244 | struct npcm_i2c_regs *reg = bus->reg; | |
245 | int err; | |
246 | ||
247 | val = readb(®->ctl3); | |
248 | /* Skip recovery, bus not stucked */ | |
249 | if ((val & SMBCTL3_SCL_LVL) && (val & SMBCTL3_SDA_LVL)) | |
250 | return; | |
251 | ||
252 | printf("Performing I2C bus %d recovery...\n", bus->num); | |
253 | /* SCL/SDA are not releaed, perform recovery */ | |
254 | while (1) { | |
255 | /* toggle SCL line */ | |
256 | writeb(SMBCST_TGSCL, ®->cst); | |
257 | ||
258 | udelay(20); | |
259 | val = readb(®->ctl3); | |
260 | if (val & SMBCTL3_SDA_LVL) | |
261 | break; | |
262 | if (iter-- == 0) | |
263 | break; | |
264 | } | |
265 | ||
266 | if (val & SMBCTL3_SDA_LVL) { | |
267 | writeb((u8)((addr << 1) & 0xff), ®->sda); | |
268 | err = npcm_i2c_send_start(bus); | |
269 | if (!err) { | |
270 | udelay(20); | |
271 | npcm_i2c_send_stop(bus, false); | |
272 | udelay(200); | |
273 | printf("I2C bus %d recovery completed\n", | |
274 | bus->num); | |
275 | } else { | |
276 | printf("%s: send START err %d\n", __func__, err); | |
277 | } | |
278 | } else { | |
279 | printf("Fail to recover I2C bus %d\n", bus->num); | |
280 | } | |
281 | npcm_i2c_reset(bus); | |
282 | } | |
283 | ||
284 | static int npcm_i2c_send_address(struct npcm_i2c_bus *bus, u8 addr, | |
285 | bool stall) | |
286 | { | |
287 | struct npcm_i2c_regs *reg = bus->reg; | |
288 | ulong start_time; | |
289 | u8 val; | |
290 | ||
291 | /* Stall After Start Enable */ | |
292 | if (stall) | |
293 | setbits_8(®->ctl1, SMBCTL1_STASTRE); | |
294 | ||
295 | writeb(addr, ®->sda); | |
296 | if (stall) { | |
297 | start_time = get_timer(0); | |
298 | while (get_timer(start_time) < NPCM_I2C_TIMEOUT_MS) { | |
299 | if (readb(®->st) & SMBST_STASTR) | |
300 | break; | |
301 | ||
302 | if (readb(®->st) & SMBST_BER) { | |
303 | clrbits_8(®->ctl1, SMBCTL1_STASTRE); | |
304 | return I2C_ERR_BER; | |
305 | } | |
306 | } | |
307 | } | |
308 | ||
309 | /* check ACK */ | |
310 | val = readb(®->st); | |
311 | if (val & SMBST_NEGACK) { | |
312 | debug("NACK on addr 0x%x\n", addr >> 1); | |
313 | /* After a Stop condition, writing 1 to NEGACK clears it */ | |
314 | return I2C_ERR_NACK; | |
315 | } | |
316 | if (val & SMBST_BER) | |
317 | return I2C_ERR_BER; | |
318 | ||
319 | return 0; | |
320 | } | |
321 | ||
322 | static int npcm_i2c_read_bytes(struct npcm_i2c_bus *bus, u8 *data, int len) | |
323 | { | |
324 | struct npcm_i2c_regs *reg = bus->reg; | |
325 | u8 val; | |
326 | int i; | |
327 | int err = 0; | |
328 | ||
329 | if (len == 1) { | |
330 | /* bus should be stalled before receiving last byte */ | |
331 | setbits_8(®->ctl1, SMBCTL1_ACK); | |
332 | ||
333 | /* clear STASTRE if it is set */ | |
334 | if (readb(®->ctl1) & SMBCTL1_STASTRE) { | |
335 | writeb(SMBST_STASTR, ®->st); | |
336 | clrbits_8(®->ctl1, SMBCTL1_STASTRE); | |
337 | } | |
338 | npcm_i2c_check_sda(bus); | |
339 | npcm_i2c_send_stop(bus, false); | |
340 | *data = readb(®->sda); | |
341 | /* this must be done to generate STOP condition */ | |
342 | writeb(SMBST_NEGACK, ®->st); | |
343 | } else { | |
344 | for (i = 0; i < len; i++) { | |
345 | /* | |
346 | * When NEGACK bit is set to 1 after the transmission of a byte, | |
347 | * SDAST is not set to 1. | |
348 | */ | |
349 | if (i != (len - 1)) { | |
350 | err = npcm_i2c_check_sda(bus); | |
351 | } else { | |
352 | err = readb_poll_timeout(®->ctl1, val, | |
353 | !(val & SMBCTL1_ACK), 100000); | |
354 | if (err) { | |
355 | printf("wait nack timeout\n"); | |
356 | err = I2C_ERR_TIMEOUT; | |
357 | npcm_dump_regs(bus); | |
358 | } | |
359 | } | |
360 | if (err && err != I2C_ERR_TIMEOUT) | |
361 | break; | |
362 | if (i == (len - 2)) { | |
363 | /* set NACK before last byte */ | |
364 | setbits_8(®->ctl1, SMBCTL1_ACK); | |
365 | } | |
366 | if (i == (len - 1)) { | |
367 | /* last byte, send STOP condition */ | |
368 | npcm_i2c_send_stop(bus, false); | |
369 | *data = readb(®->sda); | |
370 | writeb(SMBST_NEGACK, ®->st); | |
371 | break; | |
372 | } | |
373 | *data = readb(®->sda); | |
374 | data++; | |
375 | } | |
376 | } | |
377 | ||
378 | return err; | |
379 | } | |
380 | ||
381 | static int npcm_i2c_send_bytes(struct npcm_i2c_bus *bus, u8 *data, int len) | |
382 | { | |
383 | struct npcm_i2c_regs *reg = bus->reg; | |
384 | u8 val; | |
385 | int i; | |
386 | int err = 0; | |
387 | ||
388 | val = readb(®->st); | |
389 | if (val & SMBST_NEGACK) | |
390 | return I2C_ERR_NACK; | |
391 | else if (val & SMBST_BER) | |
392 | return I2C_ERR_BER; | |
393 | ||
394 | /* clear STASTRE if it is set */ | |
395 | if (readb(®->ctl1) & SMBCTL1_STASTRE) | |
396 | clrbits_8(®->ctl1, SMBCTL1_STASTRE); | |
397 | ||
398 | for (i = 0; i < len; i++) { | |
399 | err = npcm_i2c_check_sda(bus); | |
400 | if (err) | |
401 | break; | |
402 | writeb(*data, ®->sda); | |
403 | data++; | |
404 | } | |
405 | npcm_i2c_check_sda(bus); | |
406 | ||
407 | return err; | |
408 | } | |
409 | ||
410 | static int npcm_i2c_read(struct npcm_i2c_bus *bus, u32 addr, u8 *data, | |
411 | u32 len) | |
412 | { | |
413 | struct npcm_i2c_regs *reg = bus->reg; | |
414 | int err; | |
415 | bool stall; | |
416 | ||
417 | if (len <= 0) | |
418 | return -EINVAL; | |
419 | ||
420 | /* send START condition */ | |
421 | err = npcm_i2c_send_start(bus); | |
422 | if (err) { | |
423 | debug("%s: send START err %d\n", __func__, err); | |
424 | return err; | |
425 | } | |
426 | ||
427 | stall = (len == 1) ? true : false; | |
428 | /* send address byte */ | |
429 | err = npcm_i2c_send_address(bus, (u8)(addr << 1) | 0x1, stall); | |
430 | ||
431 | if (!err && len) | |
432 | npcm_i2c_read_bytes(bus, data, len); | |
433 | ||
434 | if (err == I2C_ERR_NACK) { | |
435 | /* clear NACK */ | |
436 | writeb(SMBST_NEGACK, ®->st); | |
437 | } | |
438 | ||
439 | if (err) | |
440 | debug("%s: err %d\n", __func__, err); | |
441 | ||
442 | return err; | |
443 | } | |
444 | ||
445 | static int npcm_i2c_write(struct npcm_i2c_bus *bus, u32 addr, u8 *data, | |
446 | u32 len) | |
447 | { | |
448 | struct npcm_i2c_regs *reg = bus->reg; | |
449 | int err; | |
450 | bool stall; | |
451 | ||
452 | /* send START condition */ | |
453 | err = npcm_i2c_send_start(bus); | |
454 | if (err) { | |
455 | debug("%s: send START err %d\n", __func__, err); | |
456 | return err; | |
457 | } | |
458 | ||
459 | stall = (len == 0) ? true : false; | |
460 | /* send address byte */ | |
461 | err = npcm_i2c_send_address(bus, (u8)(addr << 1), stall); | |
462 | ||
463 | if (!err && len) | |
464 | err = npcm_i2c_send_bytes(bus, data, len); | |
465 | ||
466 | /* clear STASTRE if it is set */ | |
467 | if (stall) | |
468 | clrbits_8(®->ctl1, SMBCTL1_STASTRE); | |
469 | ||
470 | if (err) | |
471 | debug("%s: err %d\n", __func__, err); | |
472 | ||
473 | return err; | |
474 | } | |
475 | ||
476 | static int npcm_i2c_xfer(struct udevice *dev, | |
477 | struct i2c_msg *msg, int nmsgs) | |
478 | { | |
479 | struct npcm_i2c_bus *bus = dev_get_priv(dev); | |
480 | struct npcm_i2c_regs *reg = bus->reg; | |
481 | int ret = 0, err = 0; | |
482 | ||
483 | if (nmsgs < 1 || nmsgs > 2) { | |
484 | printf("%s: commands not support\n", __func__); | |
485 | return -EREMOTEIO; | |
486 | } | |
487 | /* clear ST register */ | |
488 | writeb(0xFF, ®->st); | |
489 | ||
490 | for ( ; nmsgs > 0; nmsgs--, msg++) { | |
491 | if (msg->flags & I2C_M_RD) | |
492 | err = npcm_i2c_read(bus, msg->addr, msg->buf, | |
493 | msg->len); | |
494 | else | |
495 | err = npcm_i2c_write(bus, msg->addr, msg->buf, | |
496 | msg->len); | |
497 | if (err) { | |
498 | debug("i2c_xfer: error %d\n", err); | |
499 | ret = -EREMOTEIO; | |
500 | break; | |
501 | } | |
502 | } | |
503 | ||
504 | if (bus->started) | |
505 | npcm_i2c_send_stop(bus, true); | |
506 | ||
507 | if (err) | |
508 | npcm_i2c_recovery(bus, msg->addr); | |
509 | ||
510 | return ret; | |
511 | } | |
512 | ||
513 | static int npcm_i2c_init_clk(struct npcm_i2c_bus *bus, u32 bus_freq) | |
514 | { | |
515 | struct npcm_i2c_regs *reg = bus->reg; | |
516 | u32 freq = bus->apb_clk; | |
517 | u32 sclfrq; | |
518 | u8 hldt, val; | |
519 | ||
2b77eea7 JL |
520 | /* SCLFRQ = T(SCL)/4/T(CLK) = FREQ(CLK)/4/FREQ(SCL) */ |
521 | sclfrq = freq / (bus_freq * 4); | |
522 | if (sclfrq < SCLFRQ_MIN || sclfrq > SCLFRQ_MAX) | |
523 | return -EINVAL; | |
524 | ||
525 | if (freq >= 40000000) | |
526 | hldt = 17; | |
527 | else if (freq >= 12500000) | |
528 | hldt = 15; | |
529 | else | |
530 | hldt = 7; | |
531 | ||
532 | val = readb(®->ctl2) & 0x1; | |
533 | val |= (sclfrq & 0x7F) << 1; | |
534 | writeb(val, ®->ctl2); | |
535 | ||
536 | /* clear 400K_MODE bit */ | |
537 | val = readb(®->ctl3) & 0xc; | |
538 | val |= (sclfrq >> 7) & 0x3; | |
539 | writeb(val, ®->ctl3); | |
540 | ||
541 | writeb(hldt, ®->bank0.ctl4); | |
542 | ||
543 | return 0; | |
544 | } | |
545 | ||
546 | static int npcm_i2c_set_bus_speed(struct udevice *dev, | |
547 | unsigned int speed) | |
548 | { | |
549 | struct npcm_i2c_bus *bus = dev_get_priv(dev); | |
550 | ||
551 | return npcm_i2c_init_clk(bus, speed); | |
552 | } | |
553 | ||
554 | static int npcm_i2c_probe(struct udevice *dev) | |
555 | { | |
556 | struct npcm_i2c_bus *bus = dev_get_priv(dev); | |
557 | struct npcm_gcr *gcr = (struct npcm_gcr *)NPCM_GCR_BA; | |
558 | struct npcm_i2c_regs *reg; | |
559 | u32 i2csegctl_val = dev_get_driver_data(dev); | |
560 | struct clk clk; | |
561 | int ret; | |
562 | ||
563 | ret = clk_get_by_index(dev, 0, &clk); | |
564 | if (ret) { | |
565 | printf("%s: ret %d\n", __func__, ret); | |
566 | return ret; | |
567 | } | |
568 | bus->apb_clk = clk_get_rate(&clk); | |
569 | if (bus->apb_clk <= 0) { | |
570 | printf("%s: fail to get rate\n", __func__); | |
571 | return -EINVAL; | |
572 | } | |
2b77eea7 JL |
573 | |
574 | bus->num = dev->seq_; | |
575 | bus->reg = dev_read_addr_ptr(dev); | |
576 | bus->freq = dev_read_u32_default(dev, "clock-frequency", 100000); | |
577 | bus->started = false; | |
578 | reg = bus->reg; | |
579 | ||
580 | if (npcm_i2c_init_clk(bus, bus->freq)) { | |
581 | printf("%s: init_clk failed\n", __func__); | |
582 | return -EINVAL; | |
583 | } | |
584 | ||
585 | /* set initial i2csegctl value */ | |
586 | writel(i2csegctl_val, &gcr->i2csegctl); | |
587 | ||
588 | /* enable SMB module */ | |
589 | setbits_8(®->ctl2, SMBCTL2_ENABLE); | |
590 | ||
591 | /* select register bank 0 */ | |
592 | clrbits_8(®->ctl3, SMBCTL3_BNK_SEL); | |
593 | ||
594 | /* single byte mode */ | |
595 | clrbits_8(®->bank0.fif_ctl, SMBFIF_CTL_FIFO_EN); | |
596 | ||
597 | /* set POLL mode */ | |
598 | writeb(0, ®->ctl1); | |
599 | ||
600 | printf("I2C bus %d ready. speed=%d, base=0x%x, apb=%u\n", | |
601 | bus->num, bus->freq, (u32)(uintptr_t)bus->reg, bus->apb_clk); | |
602 | ||
603 | return 0; | |
604 | } | |
605 | ||
606 | static const struct dm_i2c_ops nuvoton_i2c_ops = { | |
607 | .xfer = npcm_i2c_xfer, | |
608 | .set_bus_speed = npcm_i2c_set_bus_speed, | |
609 | }; | |
610 | ||
611 | static const struct udevice_id nuvoton_i2c_of_match[] = { | |
612 | { .compatible = "nuvoton,npcm845-i2c", .data = NPCM8XX_I2CSEGCTL_INIT_VAL}, | |
613 | { .compatible = "nuvoton,npcm750-i2c", .data = NPCM7XX_I2CSEGCTL_INIT_VAL}, | |
614 | {} | |
615 | }; | |
616 | ||
617 | U_BOOT_DRIVER(npcm_i2c_bus) = { | |
618 | .name = "npcm-i2c", | |
619 | .id = UCLASS_I2C, | |
620 | .of_match = nuvoton_i2c_of_match, | |
621 | .probe = npcm_i2c_probe, | |
622 | .priv_auto = sizeof(struct npcm_i2c_bus), | |
623 | .ops = &nuvoton_i2c_ops, | |
624 | }; |