修訂 | 5eefa9344b0a46f97c97fbbb35ac17bd9a4c6f2a (tree) |
---|---|
時間 | 2022-07-20 04:54:41 |
作者 | Tom Rini <trini@kons...> |
Commiter | Tom Rini |
Merge tag 'for-v2022.10' of https://source.denx.de/u-boot/custodians/u-boot-i2c
i2c changes for 2022.10
- new driver nuvoton, NPCM7xx from Jim Liu
Fixes:
- ast_i2c: Remove SCL direct drive mode
- avoid dynamic stack use in dm_i2c_write
@@ -447,6 +447,11 @@ config SYS_I2C_NEXELL | ||
447 | 447 | have several I2C ports and all are provided, controlled by the |
448 | 448 | device tree. |
449 | 449 | |
450 | +config SYS_I2C_NPCM | |
451 | + bool "Nuvoton NPCM I2C driver" | |
452 | + help | |
453 | + Support for Nuvoton I2C controller driver. | |
454 | + | |
450 | 455 | config SYS_I2C_OCORES |
451 | 456 | bool "ocores I2C driver" |
452 | 457 | depends on DM_I2C |
@@ -33,6 +33,7 @@ obj-$(CONFIG_SYS_I2C_MV) += mv_i2c.o | ||
33 | 33 | obj-$(CONFIG_SYS_I2C_MVTWSI) += mvtwsi.o |
34 | 34 | obj-$(CONFIG_SYS_I2C_MXC) += mxc_i2c.o |
35 | 35 | obj-$(CONFIG_SYS_I2C_NEXELL) += nx_i2c.o |
36 | +obj-$(CONFIG_SYS_I2C_NPCM) += npcm_i2c.o | |
36 | 37 | obj-$(CONFIG_SYS_I2C_OCORES) += ocores_i2c.o |
37 | 38 | obj-$(CONFIG_SYS_I2C_OCTEON) += octeon_i2c.o |
38 | 39 | obj-$(CONFIG_SYS_I2C_OMAP24XX) += omap24xx_i2c.o |
@@ -77,7 +77,7 @@ static void ast_i2c_init_bus(struct udevice *dev) | ||
77 | 77 | /* Enable Master Mode. Assuming single-master */ |
78 | 78 | writel(I2CD_MASTER_EN |
79 | 79 | | I2CD_M_SDA_LOCK_EN |
80 | - | I2CD_MULTI_MASTER_DIS | I2CD_M_SCL_DRIVE_EN, | |
80 | + | I2CD_MULTI_MASTER_DIS, | |
81 | 81 | &priv->regs->fcr); |
82 | 82 | /* Enable Interrupts */ |
83 | 83 | writel(I2CD_INTR_TX_ACK |
@@ -168,6 +168,9 @@ int dm_i2c_write(struct udevice *dev, uint offset, const uint8_t *buffer, | ||
168 | 168 | struct udevice *bus = dev_get_parent(dev); |
169 | 169 | struct dm_i2c_ops *ops = i2c_get_ops(bus); |
170 | 170 | struct i2c_msg msg[1]; |
171 | + uint8_t _buf[I2C_MAX_OFFSET_LEN + 64]; | |
172 | + uint8_t *buf = _buf; | |
173 | + int ret; | |
171 | 174 | |
172 | 175 | if (!ops->xfer) |
173 | 176 | return -ENOSYS; |
@@ -192,29 +195,20 @@ int dm_i2c_write(struct udevice *dev, uint offset, const uint8_t *buffer, | ||
192 | 195 | * need to allow space for the offset (up to 4 bytes) and the message |
193 | 196 | * itself. |
194 | 197 | */ |
195 | - if (len < 64) { | |
196 | - uint8_t buf[I2C_MAX_OFFSET_LEN + len]; | |
197 | - | |
198 | - i2c_setup_offset(chip, offset, buf, msg); | |
199 | - msg->len += len; | |
200 | - memcpy(buf + chip->offset_len, buffer, len); | |
201 | - | |
202 | - return ops->xfer(bus, msg, 1); | |
203 | - } else { | |
204 | - uint8_t *buf; | |
205 | - int ret; | |
206 | - | |
198 | + if (len > sizeof(_buf) - I2C_MAX_OFFSET_LEN) { | |
207 | 199 | buf = malloc(I2C_MAX_OFFSET_LEN + len); |
208 | 200 | if (!buf) |
209 | 201 | return -ENOMEM; |
210 | - i2c_setup_offset(chip, offset, buf, msg); | |
211 | - msg->len += len; | |
212 | - memcpy(buf + chip->offset_len, buffer, len); | |
202 | + } | |
213 | 203 | |
214 | - ret = ops->xfer(bus, msg, 1); | |
204 | + i2c_setup_offset(chip, offset, buf, msg); | |
205 | + msg->len += len; | |
206 | + memcpy(buf + chip->offset_len, buffer, len); | |
207 | + | |
208 | + ret = ops->xfer(bus, msg, 1); | |
209 | + if (buf != _buf) | |
215 | 210 | free(buf); |
216 | - return ret; | |
217 | - } | |
211 | + return ret; | |
218 | 212 | } |
219 | 213 | |
220 | 214 | int dm_i2c_xfer(struct udevice *dev, struct i2c_msg *msg, int nmsgs) |
@@ -0,0 +1,630 @@ | ||
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 | + | |
520 | + if (bus_freq > I2C_FREQ_100K) { | |
521 | + printf("Support standard mode only\n"); | |
522 | + return -EINVAL; | |
523 | + } | |
524 | + | |
525 | + /* SCLFRQ = T(SCL)/4/T(CLK) = FREQ(CLK)/4/FREQ(SCL) */ | |
526 | + sclfrq = freq / (bus_freq * 4); | |
527 | + if (sclfrq < SCLFRQ_MIN || sclfrq > SCLFRQ_MAX) | |
528 | + return -EINVAL; | |
529 | + | |
530 | + if (freq >= 40000000) | |
531 | + hldt = 17; | |
532 | + else if (freq >= 12500000) | |
533 | + hldt = 15; | |
534 | + else | |
535 | + hldt = 7; | |
536 | + | |
537 | + val = readb(®->ctl2) & 0x1; | |
538 | + val |= (sclfrq & 0x7F) << 1; | |
539 | + writeb(val, ®->ctl2); | |
540 | + | |
541 | + /* clear 400K_MODE bit */ | |
542 | + val = readb(®->ctl3) & 0xc; | |
543 | + val |= (sclfrq >> 7) & 0x3; | |
544 | + writeb(val, ®->ctl3); | |
545 | + | |
546 | + writeb(hldt, ®->bank0.ctl4); | |
547 | + | |
548 | + return 0; | |
549 | +} | |
550 | + | |
551 | +static int npcm_i2c_set_bus_speed(struct udevice *dev, | |
552 | + unsigned int speed) | |
553 | +{ | |
554 | + struct npcm_i2c_bus *bus = dev_get_priv(dev); | |
555 | + | |
556 | + return npcm_i2c_init_clk(bus, speed); | |
557 | +} | |
558 | + | |
559 | +static int npcm_i2c_probe(struct udevice *dev) | |
560 | +{ | |
561 | + struct npcm_i2c_bus *bus = dev_get_priv(dev); | |
562 | + struct npcm_gcr *gcr = (struct npcm_gcr *)NPCM_GCR_BA; | |
563 | + struct npcm_i2c_regs *reg; | |
564 | + u32 i2csegctl_val = dev_get_driver_data(dev); | |
565 | + struct clk clk; | |
566 | + int ret; | |
567 | + | |
568 | + ret = clk_get_by_index(dev, 0, &clk); | |
569 | + if (ret) { | |
570 | + printf("%s: ret %d\n", __func__, ret); | |
571 | + return ret; | |
572 | + } | |
573 | + bus->apb_clk = clk_get_rate(&clk); | |
574 | + if (bus->apb_clk <= 0) { | |
575 | + printf("%s: fail to get rate\n", __func__); | |
576 | + return -EINVAL; | |
577 | + } | |
578 | + clk_free(&clk); | |
579 | + | |
580 | + bus->num = dev->seq_; | |
581 | + bus->reg = dev_read_addr_ptr(dev); | |
582 | + bus->freq = dev_read_u32_default(dev, "clock-frequency", 100000); | |
583 | + bus->started = false; | |
584 | + reg = bus->reg; | |
585 | + | |
586 | + if (npcm_i2c_init_clk(bus, bus->freq)) { | |
587 | + printf("%s: init_clk failed\n", __func__); | |
588 | + return -EINVAL; | |
589 | + } | |
590 | + | |
591 | + /* set initial i2csegctl value */ | |
592 | + writel(i2csegctl_val, &gcr->i2csegctl); | |
593 | + | |
594 | + /* enable SMB module */ | |
595 | + setbits_8(®->ctl2, SMBCTL2_ENABLE); | |
596 | + | |
597 | + /* select register bank 0 */ | |
598 | + clrbits_8(®->ctl3, SMBCTL3_BNK_SEL); | |
599 | + | |
600 | + /* single byte mode */ | |
601 | + clrbits_8(®->bank0.fif_ctl, SMBFIF_CTL_FIFO_EN); | |
602 | + | |
603 | + /* set POLL mode */ | |
604 | + writeb(0, ®->ctl1); | |
605 | + | |
606 | + printf("I2C bus %d ready. speed=%d, base=0x%x, apb=%u\n", | |
607 | + bus->num, bus->freq, (u32)(uintptr_t)bus->reg, bus->apb_clk); | |
608 | + | |
609 | + return 0; | |
610 | +} | |
611 | + | |
612 | +static const struct dm_i2c_ops nuvoton_i2c_ops = { | |
613 | + .xfer = npcm_i2c_xfer, | |
614 | + .set_bus_speed = npcm_i2c_set_bus_speed, | |
615 | +}; | |
616 | + | |
617 | +static const struct udevice_id nuvoton_i2c_of_match[] = { | |
618 | + { .compatible = "nuvoton,npcm845-i2c", .data = NPCM8XX_I2CSEGCTL_INIT_VAL}, | |
619 | + { .compatible = "nuvoton,npcm750-i2c", .data = NPCM7XX_I2CSEGCTL_INIT_VAL}, | |
620 | + {} | |
621 | +}; | |
622 | + | |
623 | +U_BOOT_DRIVER(npcm_i2c_bus) = { | |
624 | + .name = "npcm-i2c", | |
625 | + .id = UCLASS_I2C, | |
626 | + .of_match = nuvoton_i2c_of_match, | |
627 | + .probe = npcm_i2c_probe, | |
628 | + .priv_auto = sizeof(struct npcm_i2c_bus), | |
629 | + .ops = &nuvoton_i2c_ops, | |
630 | +}; |