]>
Commit | Line | Data |
---|---|---|
83d290c5 | 1 | // SPDX-License-Identifier: GPL-2.0+ |
43d9616c WD |
2 | /* |
3 | * (C) Copyright 2000 | |
4 | * Paolo Scaffardi, AIRVENT SAM s.p.a - RIMINI(ITALY), [email protected] | |
5 | * | |
6 | * (C) Copyright 2000 Sysgo Real-Time Solutions, GmbH <www.elinos.com> | |
7 | * Marius Groeger <[email protected]> | |
8 | * | |
9 | * (C) Copyright 2003 Pengutronix e.K. | |
10 | * Robert Schwebel <[email protected]> | |
11 | * | |
3df619ec LW |
12 | * (C) Copyright 2011 Marvell Inc. |
13 | * Lei Wen <[email protected]> | |
14 | * | |
43d9616c WD |
15 | * Back ported to the 8xx platform (from the 8260 platform) by |
16 | * [email protected], 27-Jan-01. | |
17 | */ | |
18 | ||
0c0f719a | 19 | #include <dm.h> |
43d9616c | 20 | #include <i2c.h> |
f7ae49fc | 21 | #include <log.h> |
7b46ee52 | 22 | #include <asm/io.h> |
c05ed00a | 23 | #include <linux/delay.h> |
3df619ec | 24 | #include "mv_i2c.h" |
43d9616c | 25 | |
43d9616c | 26 | /* All transfers are described by this data structure */ |
fffff726 | 27 | struct mv_i2c_msg { |
43d9616c | 28 | u8 condition; |
8bde7f77 WD |
29 | u8 acknack; |
30 | u8 direction; | |
43d9616c WD |
31 | u8 data; |
32 | }; | |
33 | ||
0c0f719a SR |
34 | #ifdef CONFIG_ARMADA_3700 |
35 | /* Armada 3700 has no padding between the registers */ | |
36 | struct mv_i2c { | |
37 | u32 ibmr; | |
38 | u32 idbr; | |
39 | u32 icr; | |
40 | u32 isr; | |
41 | u32 isar; | |
42 | }; | |
43 | #else | |
3df619ec LW |
44 | struct mv_i2c { |
45 | u32 ibmr; | |
46 | u32 pad0; | |
47 | u32 idbr; | |
48 | u32 pad1; | |
49 | u32 icr; | |
50 | u32 pad2; | |
51 | u32 isr; | |
52 | u32 pad3; | |
53 | u32 isar; | |
54 | }; | |
0c0f719a SR |
55 | #endif |
56 | ||
57 | /* | |
58 | * Dummy implementation that can be overwritten by a board | |
59 | * specific function | |
60 | */ | |
61 | __weak void i2c_clk_enable(void) | |
62 | { | |
63 | } | |
3df619ec | 64 | |
68432c27 | 65 | /* |
3df619ec | 66 | * i2c_reset: - reset the host controller |
43d9616c WD |
67 | * |
68 | */ | |
7b46ee52 | 69 | static void i2c_reset(struct mv_i2c *base) |
43d9616c | 70 | { |
9ad5a007 SR |
71 | u32 icr_mode; |
72 | ||
73 | /* Save bus mode (standard or fast speed) for later use */ | |
74 | icr_mode = readl(&base->icr) & ICR_MODE_MASK; | |
3df619ec LW |
75 | writel(readl(&base->icr) & ~ICR_IUE, &base->icr); /* disable unit */ |
76 | writel(readl(&base->icr) | ICR_UR, &base->icr); /* reset the unit */ | |
8bde7f77 | 77 | udelay(100); |
3df619ec LW |
78 | writel(readl(&base->icr) & ~ICR_IUE, &base->icr); /* disable unit */ |
79 | ||
80 | i2c_clk_enable(); | |
81 | ||
a5752f8a | 82 | writel(0x0, &base->isar); /* set our slave address */ |
9ad5a007 SR |
83 | /* set control reg values */ |
84 | writel(I2C_ICR_INIT | icr_mode, &base->icr); | |
3df619ec LW |
85 | writel(I2C_ISR_INIT, &base->isr); /* set clear interrupt bits */ |
86 | writel(readl(&base->icr) | ICR_IUE, &base->icr); /* enable unit */ | |
8bde7f77 | 87 | udelay(100); |
43d9616c WD |
88 | } |
89 | ||
68432c27 | 90 | /* |
8bde7f77 | 91 | * i2c_isr_set_cleared: - wait until certain bits of the I2C status register |
43d9616c WD |
92 | * are set and cleared |
93 | * | |
ba70d6a4 | 94 | * @return: 1 in case of success, 0 means timeout (no match within 10 ms). |
43d9616c | 95 | */ |
7b46ee52 | 96 | static int i2c_isr_set_cleared(struct mv_i2c *base, unsigned long set_mask, |
68432c27 | 97 | unsigned long cleared_mask) |
43d9616c | 98 | { |
3df619ec | 99 | int timeout = 1000, isr; |
43d9616c | 100 | |
3df619ec LW |
101 | do { |
102 | isr = readl(&base->isr); | |
68432c27 LW |
103 | udelay(10); |
104 | if (timeout-- < 0) | |
105 | return 0; | |
3df619ec LW |
106 | } while (((isr & set_mask) != set_mask) |
107 | || ((isr & cleared_mask) != 0)); | |
43d9616c | 108 | |
8bde7f77 | 109 | return 1; |
43d9616c WD |
110 | } |
111 | ||
68432c27 | 112 | /* |
43d9616c WD |
113 | * i2c_transfer: - Transfer one byte over the i2c bus |
114 | * | |
8bde7f77 WD |
115 | * This function can tranfer a byte over the i2c bus in both directions. |
116 | * It is used by the public API functions. | |
43d9616c WD |
117 | * |
118 | * @return: 0: transfer successful | |
119 | * -1: message is empty | |
120 | * -2: transmit timeout | |
121 | * -3: ACK missing | |
122 | * -4: receive timeout | |
123 | * -5: illegal parameters | |
124 | * -6: bus is busy and couldn't be aquired | |
8bde7f77 | 125 | */ |
7b46ee52 | 126 | static int i2c_transfer(struct mv_i2c *base, struct mv_i2c_msg *msg) |
43d9616c WD |
127 | { |
128 | int ret; | |
129 | ||
8bde7f77 | 130 | if (!msg) |
43d9616c WD |
131 | goto transfer_error_msg_empty; |
132 | ||
68432c27 | 133 | switch (msg->direction) { |
43d9616c | 134 | case I2C_WRITE: |
43d9616c | 135 | /* check if bus is not busy */ |
7b46ee52 | 136 | if (!i2c_isr_set_cleared(base, 0, ISR_IBB)) |
43d9616c WD |
137 | goto transfer_error_bus_busy; |
138 | ||
139 | /* start transmission */ | |
3df619ec LW |
140 | writel(readl(&base->icr) & ~ICR_START, &base->icr); |
141 | writel(readl(&base->icr) & ~ICR_STOP, &base->icr); | |
142 | writel(msg->data, &base->idbr); | |
3ba8bf7c | 143 | if (msg->condition == I2C_COND_START) |
3df619ec | 144 | writel(readl(&base->icr) | ICR_START, &base->icr); |
3ba8bf7c | 145 | if (msg->condition == I2C_COND_STOP) |
3df619ec | 146 | writel(readl(&base->icr) | ICR_STOP, &base->icr); |
3ba8bf7c | 147 | if (msg->acknack == I2C_ACKNAK_SENDNAK) |
3df619ec | 148 | writel(readl(&base->icr) | ICR_ACKNAK, &base->icr); |
3ba8bf7c | 149 | if (msg->acknack == I2C_ACKNAK_SENDACK) |
3df619ec LW |
150 | writel(readl(&base->icr) & ~ICR_ACKNAK, &base->icr); |
151 | writel(readl(&base->icr) & ~ICR_ALDIE, &base->icr); | |
152 | writel(readl(&base->icr) | ICR_TB, &base->icr); | |
43d9616c WD |
153 | |
154 | /* transmit register empty? */ | |
7b46ee52 | 155 | if (!i2c_isr_set_cleared(base, ISR_ITE, 0)) |
43d9616c WD |
156 | goto transfer_error_transmit_timeout; |
157 | ||
158 | /* clear 'transmit empty' state */ | |
3df619ec | 159 | writel(readl(&base->isr) | ISR_ITE, &base->isr); |
43d9616c WD |
160 | |
161 | /* wait for ACK from slave */ | |
162 | if (msg->acknack == I2C_ACKNAK_WAITACK) | |
7b46ee52 | 163 | if (!i2c_isr_set_cleared(base, 0, ISR_ACKNAK)) |
43d9616c WD |
164 | goto transfer_error_ack_missing; |
165 | break; | |
166 | ||
167 | case I2C_READ: | |
168 | ||
169 | /* check if bus is not busy */ | |
7b46ee52 | 170 | if (!i2c_isr_set_cleared(base, 0, ISR_IBB)) |
43d9616c WD |
171 | goto transfer_error_bus_busy; |
172 | ||
173 | /* start receive */ | |
3df619ec LW |
174 | writel(readl(&base->icr) & ~ICR_START, &base->icr); |
175 | writel(readl(&base->icr) & ~ICR_STOP, &base->icr); | |
3ba8bf7c | 176 | if (msg->condition == I2C_COND_START) |
3df619ec | 177 | writel(readl(&base->icr) | ICR_START, &base->icr); |
3ba8bf7c | 178 | if (msg->condition == I2C_COND_STOP) |
3df619ec | 179 | writel(readl(&base->icr) | ICR_STOP, &base->icr); |
3ba8bf7c | 180 | if (msg->acknack == I2C_ACKNAK_SENDNAK) |
3df619ec | 181 | writel(readl(&base->icr) | ICR_ACKNAK, &base->icr); |
3ba8bf7c | 182 | if (msg->acknack == I2C_ACKNAK_SENDACK) |
3df619ec LW |
183 | writel(readl(&base->icr) & ~ICR_ACKNAK, &base->icr); |
184 | writel(readl(&base->icr) & ~ICR_ALDIE, &base->icr); | |
185 | writel(readl(&base->icr) | ICR_TB, &base->icr); | |
43d9616c WD |
186 | |
187 | /* receive register full? */ | |
7b46ee52 | 188 | if (!i2c_isr_set_cleared(base, ISR_IRF, 0)) |
8bde7f77 | 189 | goto transfer_error_receive_timeout; |
43d9616c | 190 | |
3df619ec | 191 | msg->data = readl(&base->idbr); |
43d9616c WD |
192 | |
193 | /* clear 'receive empty' state */ | |
3df619ec | 194 | writel(readl(&base->isr) | ISR_IRF, &base->isr); |
43d9616c | 195 | break; |
43d9616c | 196 | default: |
43d9616c | 197 | goto transfer_error_illegal_param; |
43d9616c WD |
198 | } |
199 | ||
8bde7f77 | 200 | return 0; |
43d9616c | 201 | |
8bde7f77 | 202 | transfer_error_msg_empty: |
8eff909a SR |
203 | debug("i2c_transfer: error: 'msg' is empty\n"); |
204 | ret = -1; | |
205 | goto i2c_transfer_finish; | |
43d9616c WD |
206 | |
207 | transfer_error_transmit_timeout: | |
8eff909a SR |
208 | debug("i2c_transfer: error: transmit timeout\n"); |
209 | ret = -2; | |
210 | goto i2c_transfer_finish; | |
43d9616c WD |
211 | |
212 | transfer_error_ack_missing: | |
8eff909a SR |
213 | debug("i2c_transfer: error: ACK missing\n"); |
214 | ret = -3; | |
215 | goto i2c_transfer_finish; | |
43d9616c WD |
216 | |
217 | transfer_error_receive_timeout: | |
8eff909a SR |
218 | debug("i2c_transfer: error: receive timeout\n"); |
219 | ret = -4; | |
220 | goto i2c_transfer_finish; | |
43d9616c WD |
221 | |
222 | transfer_error_illegal_param: | |
8eff909a SR |
223 | debug("i2c_transfer: error: illegal parameters\n"); |
224 | ret = -5; | |
225 | goto i2c_transfer_finish; | |
43d9616c WD |
226 | |
227 | transfer_error_bus_busy: | |
8eff909a SR |
228 | debug("i2c_transfer: error: bus is busy\n"); |
229 | ret = -6; | |
230 | goto i2c_transfer_finish; | |
43d9616c WD |
231 | |
232 | i2c_transfer_finish: | |
8eff909a | 233 | debug("i2c_transfer: ISR: 0x%04x\n", readl(&base->isr)); |
7b46ee52 | 234 | i2c_reset(base); |
8eff909a | 235 | return ret; |
43d9616c WD |
236 | } |
237 | ||
0c0f719a | 238 | static int __i2c_read(struct mv_i2c *base, uchar chip, u8 *addr, int alen, |
7b46ee52 | 239 | uchar *buffer, int len) |
43d9616c | 240 | { |
fffff726 | 241 | struct mv_i2c_msg msg; |
43d9616c | 242 | |
8eff909a | 243 | debug("i2c_read(chip=0x%02x, addr=0x%02x, alen=0x%02x, " |
0c0f719a | 244 | "len=0x%02x)\n", chip, *addr, alen, len); |
43d9616c | 245 | |
85f03f0e | 246 | if (len == 0) { |
247 | printf("reading zero byte is invalid\n"); | |
248 | return -EINVAL; | |
249 | } | |
250 | ||
7b46ee52 | 251 | i2c_reset(base); |
43d9616c WD |
252 | |
253 | /* dummy chip address write */ | |
8eff909a | 254 | debug("i2c_read: dummy chip address write\n"); |
43d9616c WD |
255 | msg.condition = I2C_COND_START; |
256 | msg.acknack = I2C_ACKNAK_WAITACK; | |
257 | msg.direction = I2C_WRITE; | |
68432c27 LW |
258 | msg.data = (chip << 1); |
259 | msg.data &= 0xFE; | |
7b46ee52 | 260 | if (i2c_transfer(base, &msg)) |
68432c27 | 261 | return -1; |
8bde7f77 | 262 | |
43d9616c | 263 | /* |
8bde7f77 WD |
264 | * send memory address bytes; |
265 | * alen defines how much bytes we have to send. | |
43d9616c | 266 | */ |
43d9616c | 267 | while (--alen >= 0) { |
0c0f719a SR |
268 | debug("i2c_read: send address byte %02x (alen=%d)\n", |
269 | *addr, alen); | |
43d9616c WD |
270 | msg.condition = I2C_COND_NORMAL; |
271 | msg.acknack = I2C_ACKNAK_WAITACK; | |
272 | msg.direction = I2C_WRITE; | |
77466267 | 273 | msg.data = addr[alen]; |
7b46ee52 | 274 | if (i2c_transfer(base, &msg)) |
68432c27 | 275 | return -1; |
43d9616c | 276 | } |
8bde7f77 | 277 | |
43d9616c | 278 | /* start read sequence */ |
8eff909a | 279 | debug("i2c_read: start read sequence\n"); |
43d9616c WD |
280 | msg.condition = I2C_COND_START; |
281 | msg.acknack = I2C_ACKNAK_WAITACK; | |
282 | msg.direction = I2C_WRITE; | |
283 | msg.data = (chip << 1); | |
284 | msg.data |= 0x01; | |
7b46ee52 | 285 | if (i2c_transfer(base, &msg)) |
68432c27 | 286 | return -1; |
43d9616c WD |
287 | |
288 | /* read bytes; send NACK at last byte */ | |
289 | while (len--) { | |
68432c27 | 290 | if (len == 0) { |
43d9616c WD |
291 | msg.condition = I2C_COND_STOP; |
292 | msg.acknack = I2C_ACKNAK_SENDNAK; | |
293 | } else { | |
294 | msg.condition = I2C_COND_NORMAL; | |
295 | msg.acknack = I2C_ACKNAK_SENDACK; | |
296 | } | |
297 | ||
298 | msg.direction = I2C_READ; | |
299 | msg.data = 0x00; | |
7b46ee52 | 300 | if (i2c_transfer(base, &msg)) |
68432c27 | 301 | return -1; |
43d9616c | 302 | |
ba70d6a4 | 303 | *buffer = msg.data; |
0c0f719a SR |
304 | debug("i2c_read: reading byte (%p)=0x%02x\n", |
305 | buffer, *buffer); | |
ba70d6a4 | 306 | buffer++; |
43d9616c WD |
307 | } |
308 | ||
7b46ee52 | 309 | i2c_reset(base); |
43d9616c WD |
310 | |
311 | return 0; | |
312 | } | |
313 | ||
0c0f719a | 314 | static int __i2c_write(struct mv_i2c *base, uchar chip, u8 *addr, int alen, |
7b46ee52 | 315 | uchar *buffer, int len) |
43d9616c | 316 | { |
fffff726 | 317 | struct mv_i2c_msg msg; |
43d9616c | 318 | |
8eff909a | 319 | debug("i2c_write(chip=0x%02x, addr=0x%02x, alen=0x%02x, " |
0c0f719a | 320 | "len=0x%02x)\n", chip, *addr, alen, len); |
43d9616c | 321 | |
7b46ee52 | 322 | i2c_reset(base); |
43d9616c WD |
323 | |
324 | /* chip address write */ | |
8eff909a | 325 | debug("i2c_write: chip address write\n"); |
43d9616c WD |
326 | msg.condition = I2C_COND_START; |
327 | msg.acknack = I2C_ACKNAK_WAITACK; | |
328 | msg.direction = I2C_WRITE; | |
68432c27 LW |
329 | msg.data = (chip << 1); |
330 | msg.data &= 0xFE; | |
7b46ee52 | 331 | if (i2c_transfer(base, &msg)) |
68432c27 | 332 | return -1; |
8bde7f77 | 333 | |
43d9616c | 334 | /* |
8bde7f77 WD |
335 | * send memory address bytes; |
336 | * alen defines how much bytes we have to send. | |
43d9616c | 337 | */ |
43d9616c | 338 | while (--alen >= 0) { |
0c0f719a SR |
339 | debug("i2c_read: send address byte %02x (alen=%d)\n", |
340 | *addr, alen); | |
43d9616c WD |
341 | msg.condition = I2C_COND_NORMAL; |
342 | msg.acknack = I2C_ACKNAK_WAITACK; | |
343 | msg.direction = I2C_WRITE; | |
77466267 | 344 | msg.data = addr[alen]; |
7b46ee52 | 345 | if (i2c_transfer(base, &msg)) |
68432c27 | 346 | return -1; |
43d9616c | 347 | } |
8bde7f77 | 348 | |
43d9616c WD |
349 | /* write bytes; send NACK at last byte */ |
350 | while (len--) { | |
0c0f719a SR |
351 | debug("i2c_write: writing byte (%p)=0x%02x\n", |
352 | buffer, *buffer); | |
43d9616c | 353 | |
68432c27 | 354 | if (len == 0) |
43d9616c WD |
355 | msg.condition = I2C_COND_STOP; |
356 | else | |
357 | msg.condition = I2C_COND_NORMAL; | |
358 | ||
359 | msg.acknack = I2C_ACKNAK_WAITACK; | |
360 | msg.direction = I2C_WRITE; | |
361 | msg.data = *(buffer++); | |
8bde7f77 | 362 | |
7b46ee52 | 363 | if (i2c_transfer(base, &msg)) |
68432c27 | 364 | return -1; |
43d9616c WD |
365 | } |
366 | ||
7b46ee52 | 367 | i2c_reset(base); |
43d9616c WD |
368 | |
369 | return 0; | |
43d9616c | 370 | } |
7b46ee52 | 371 | |
2147a169 | 372 | #if !CONFIG_IS_ENABLED(DM_I2C) |
0c0f719a | 373 | |
7b46ee52 SR |
374 | static struct mv_i2c *base_glob; |
375 | ||
7b46ee52 SR |
376 | /* API Functions */ |
377 | void i2c_init(int speed, int slaveaddr) | |
378 | { | |
9ad5a007 SR |
379 | u32 val; |
380 | ||
7b46ee52 | 381 | base_glob = (struct mv_i2c *)CONFIG_MV_I2C_REG; |
7b46ee52 | 382 | |
f3d46152 | 383 | if (speed > I2C_SPEED_STANDARD_RATE) |
9ad5a007 SR |
384 | val = ICR_FM; |
385 | else | |
386 | val = ICR_SM; | |
387 | clrsetbits_le32(&base_glob->icr, ICR_MODE_MASK, val); | |
7b46ee52 SR |
388 | } |
389 | ||
0c0f719a SR |
390 | static int __i2c_probe_chip(struct mv_i2c *base, uchar chip) |
391 | { | |
392 | struct mv_i2c_msg msg; | |
393 | ||
394 | i2c_reset(base); | |
395 | ||
396 | msg.condition = I2C_COND_START; | |
397 | msg.acknack = I2C_ACKNAK_WAITACK; | |
398 | msg.direction = I2C_WRITE; | |
399 | msg.data = (chip << 1) + 1; | |
400 | if (i2c_transfer(base, &msg)) | |
401 | return -1; | |
402 | ||
403 | msg.condition = I2C_COND_STOP; | |
404 | msg.acknack = I2C_ACKNAK_SENDNAK; | |
405 | msg.direction = I2C_READ; | |
406 | msg.data = 0x00; | |
407 | if (i2c_transfer(base, &msg)) | |
408 | return -1; | |
409 | ||
410 | return 0; | |
411 | } | |
412 | ||
7b46ee52 SR |
413 | /* |
414 | * i2c_probe: - Test if a chip answers for a given i2c address | |
415 | * | |
416 | * @chip: address of the chip which is searched for | |
417 | * @return: 0 if a chip was found, -1 otherwhise | |
418 | */ | |
419 | int i2c_probe(uchar chip) | |
420 | { | |
421 | return __i2c_probe_chip(base_glob, chip); | |
422 | } | |
423 | ||
424 | /* | |
425 | * i2c_read: - Read multiple bytes from an i2c device | |
426 | * | |
427 | * The higher level routines take into account that this function is only | |
428 | * called with len < page length of the device (see configuration file) | |
429 | * | |
430 | * @chip: address of the chip which is to be read | |
431 | * @addr: i2c data address within the chip | |
432 | * @alen: length of the i2c data address (1..2 bytes) | |
433 | * @buffer: where to write the data | |
434 | * @len: how much byte do we want to read | |
435 | * @return: 0 in case of success | |
436 | */ | |
437 | int i2c_read(uchar chip, uint addr, int alen, uchar *buffer, int len) | |
438 | { | |
0c0f719a SR |
439 | u8 addr_bytes[4]; |
440 | ||
441 | addr_bytes[0] = (addr >> 0) & 0xFF; | |
442 | addr_bytes[1] = (addr >> 8) & 0xFF; | |
443 | addr_bytes[2] = (addr >> 16) & 0xFF; | |
444 | addr_bytes[3] = (addr >> 24) & 0xFF; | |
445 | ||
446 | return __i2c_read(base_glob, chip, addr_bytes, alen, buffer, len); | |
7b46ee52 SR |
447 | } |
448 | ||
449 | /* | |
450 | * i2c_write: - Write multiple bytes to an i2c device | |
451 | * | |
452 | * The higher level routines take into account that this function is only | |
453 | * called with len < page length of the device (see configuration file) | |
454 | * | |
455 | * @chip: address of the chip which is to be written | |
456 | * @addr: i2c data address within the chip | |
457 | * @alen: length of the i2c data address (1..2 bytes) | |
458 | * @buffer: where to find the data to be written | |
459 | * @len: how much byte do we want to read | |
460 | * @return: 0 in case of success | |
461 | */ | |
462 | int i2c_write(uchar chip, uint addr, int alen, uchar *buffer, int len) | |
463 | { | |
0c0f719a SR |
464 | u8 addr_bytes[4]; |
465 | ||
466 | addr_bytes[0] = (addr >> 0) & 0xFF; | |
467 | addr_bytes[1] = (addr >> 8) & 0xFF; | |
468 | addr_bytes[2] = (addr >> 16) & 0xFF; | |
469 | addr_bytes[3] = (addr >> 24) & 0xFF; | |
470 | ||
471 | return __i2c_write(base_glob, chip, addr_bytes, alen, buffer, len); | |
472 | } | |
473 | ||
474 | #else /* CONFIG_DM_I2C */ | |
475 | ||
476 | struct mv_i2c_priv { | |
477 | struct mv_i2c *base; | |
478 | }; | |
479 | ||
480 | static int mv_i2c_xfer(struct udevice *bus, struct i2c_msg *msg, int nmsgs) | |
481 | { | |
482 | struct mv_i2c_priv *i2c = dev_get_priv(bus); | |
483 | struct i2c_msg *dmsg, *omsg, dummy; | |
484 | ||
485 | memset(&dummy, 0, sizeof(struct i2c_msg)); | |
486 | ||
487 | /* | |
488 | * We expect either two messages (one with an offset and one with the | |
489 | * actual data) or one message (just data or offset/data combined) | |
490 | */ | |
491 | if (nmsgs > 2 || nmsgs == 0) { | |
492 | debug("%s: Only one or two messages are supported.", __func__); | |
493 | return -1; | |
494 | } | |
495 | ||
496 | omsg = nmsgs == 1 ? &dummy : msg; | |
497 | dmsg = nmsgs == 1 ? msg : msg + 1; | |
498 | ||
499 | if (dmsg->flags & I2C_M_RD) | |
500 | return __i2c_read(i2c->base, dmsg->addr, omsg->buf, | |
501 | omsg->len, dmsg->buf, dmsg->len); | |
502 | else | |
503 | return __i2c_write(i2c->base, dmsg->addr, omsg->buf, | |
504 | omsg->len, dmsg->buf, dmsg->len); | |
7b46ee52 | 505 | } |
0c0f719a | 506 | |
9ad5a007 SR |
507 | static int mv_i2c_set_bus_speed(struct udevice *bus, unsigned int speed) |
508 | { | |
509 | struct mv_i2c_priv *priv = dev_get_priv(bus); | |
510 | u32 val; | |
511 | ||
f3d46152 | 512 | if (speed > I2C_SPEED_STANDARD_RATE) |
9ad5a007 SR |
513 | val = ICR_FM; |
514 | else | |
515 | val = ICR_SM; | |
516 | clrsetbits_le32(&priv->base->icr, ICR_MODE_MASK, val); | |
517 | ||
518 | return 0; | |
519 | } | |
520 | ||
0c0f719a SR |
521 | static int mv_i2c_probe(struct udevice *bus) |
522 | { | |
523 | struct mv_i2c_priv *priv = dev_get_priv(bus); | |
524 | ||
702e57e1 | 525 | priv->base = dev_read_addr_ptr(bus); |
0c0f719a SR |
526 | |
527 | return 0; | |
528 | } | |
529 | ||
530 | static const struct dm_i2c_ops mv_i2c_ops = { | |
531 | .xfer = mv_i2c_xfer, | |
9ad5a007 | 532 | .set_bus_speed = mv_i2c_set_bus_speed, |
0c0f719a SR |
533 | }; |
534 | ||
535 | static const struct udevice_id mv_i2c_ids[] = { | |
536 | { .compatible = "marvell,armada-3700-i2c" }, | |
537 | { } | |
538 | }; | |
539 | ||
540 | U_BOOT_DRIVER(i2c_mv) = { | |
541 | .name = "i2c_mv", | |
542 | .id = UCLASS_I2C, | |
543 | .of_match = mv_i2c_ids, | |
544 | .probe = mv_i2c_probe, | |
41575d8e | 545 | .priv_auto = sizeof(struct mv_i2c_priv), |
0c0f719a SR |
546 | .ops = &mv_i2c_ops, |
547 | }; | |
548 | #endif /* CONFIG_DM_I2C */ |