]>
Commit | Line | Data |
---|---|---|
4ce5a728 | 1 | /* |
306563a7 AA |
2 | * Driver for the TWSI (i2c) controller found on the Marvell |
3 | * orion5x and kirkwood SoC families. | |
4ce5a728 | 4 | * |
57b4bce9 | 5 | * Author: Albert Aribaud <albert.u.boot@aribaud.net> |
306563a7 | 6 | * Copyright (c) 2010 Albert Aribaud. |
4ce5a728 | 7 | * |
1a459660 | 8 | * SPDX-License-Identifier: GPL-2.0+ |
4ce5a728 | 9 | */ |
306563a7 | 10 | |
4ce5a728 HS |
11 | #include <common.h> |
12 | #include <i2c.h> | |
4ce5a728 HS |
13 | #include <asm/errno.h> |
14 | #include <asm/io.h> | |
15 | ||
306563a7 | 16 | /* |
49c801bf | 17 | * Include a file that will provide CONFIG_I2C_MVTWSI_BASE*, and possibly other |
18 | * settings | |
306563a7 | 19 | */ |
4ce5a728 | 20 | |
306563a7 AA |
21 | #if defined(CONFIG_ORION5X) |
22 | #include <asm/arch/orion5x.h> | |
81e33f4b | 23 | #elif (defined(CONFIG_KIRKWOOD) || defined(CONFIG_ARCH_MVEBU)) |
3dc23f78 | 24 | #include <asm/arch/soc.h> |
6620377e HG |
25 | #elif defined(CONFIG_SUNXI) |
26 | #include <asm/arch/i2c.h> | |
306563a7 AA |
27 | #else |
28 | #error Driver mvtwsi not supported by SoC or board | |
4ce5a728 HS |
29 | #endif |
30 | ||
306563a7 AA |
31 | /* |
32 | * TWSI register structure | |
33 | */ | |
4ce5a728 | 34 | |
6620377e HG |
35 | #ifdef CONFIG_SUNXI |
36 | ||
37 | struct mvtwsi_registers { | |
38 | u32 slave_address; | |
39 | u32 xtnd_slave_addr; | |
40 | u32 data; | |
41 | u32 control; | |
42 | u32 status; | |
43 | u32 baudrate; | |
44 | u32 soft_reset; | |
45 | }; | |
46 | ||
47 | #else | |
48 | ||
306563a7 AA |
49 | struct mvtwsi_registers { |
50 | u32 slave_address; | |
51 | u32 data; | |
52 | u32 control; | |
53 | union { | |
49c801bf | 54 | u32 status; /* When reading */ |
55 | u32 baudrate; /* When writing */ | |
306563a7 AA |
56 | }; |
57 | u32 xtnd_slave_addr; | |
58 | u32 reserved[2]; | |
59 | u32 soft_reset; | |
4ce5a728 HS |
60 | }; |
61 | ||
6620377e HG |
62 | #endif |
63 | ||
306563a7 | 64 | /* |
dfc3958c | 65 | * enum mvtwsi_ctrl_register_fields - Bit masks for flags in the control |
66 | * register | |
306563a7 | 67 | */ |
dfc3958c | 68 | enum mvtwsi_ctrl_register_fields { |
69 | /* Acknowledge bit */ | |
70 | MVTWSI_CONTROL_ACK = 0x00000004, | |
71 | /* Interrupt flag */ | |
72 | MVTWSI_CONTROL_IFLG = 0x00000008, | |
73 | /* Stop bit */ | |
74 | MVTWSI_CONTROL_STOP = 0x00000010, | |
75 | /* Start bit */ | |
76 | MVTWSI_CONTROL_START = 0x00000020, | |
77 | /* I2C enable */ | |
78 | MVTWSI_CONTROL_TWSIEN = 0x00000040, | |
79 | /* Interrupt enable */ | |
80 | MVTWSI_CONTROL_INTEN = 0x00000080, | |
81 | }; | |
4ce5a728 | 82 | |
904dfbfd | 83 | /* |
49c801bf | 84 | * On sun6i and newer, IFLG is a write-clear bit, which is cleared by writing 1; |
85 | * on other platforms, it is a normal r/w bit, which is cleared by writing 0. | |
904dfbfd HG |
86 | */ |
87 | ||
88 | #ifdef CONFIG_SUNXI_GEN_SUN6I | |
89 | #define MVTWSI_CONTROL_CLEAR_IFLG 0x00000008 | |
90 | #else | |
91 | #define MVTWSI_CONTROL_CLEAR_IFLG 0x00000000 | |
92 | #endif | |
93 | ||
306563a7 | 94 | /* |
dfc3958c | 95 | * enum mvstwsi_status_values - Possible values of I2C controller's status |
96 | * register | |
97 | * | |
98 | * Only those statuses expected in normal master operation on | |
99 | * non-10-bit-address devices are specified. | |
100 | * | |
101 | * Every status that's unexpected during normal operation (bus errors, | |
102 | * arbitration losses, missing ACKs...) is passed back to the caller as an error | |
306563a7 AA |
103 | * code. |
104 | */ | |
dfc3958c | 105 | enum mvstwsi_status_values { |
106 | /* START condition transmitted */ | |
107 | MVTWSI_STATUS_START = 0x08, | |
108 | /* Repeated START condition transmitted */ | |
109 | MVTWSI_STATUS_REPEATED_START = 0x10, | |
110 | /* Address + write bit transmitted, ACK received */ | |
111 | MVTWSI_STATUS_ADDR_W_ACK = 0x18, | |
112 | /* Data transmitted, ACK received */ | |
113 | MVTWSI_STATUS_DATA_W_ACK = 0x28, | |
114 | /* Address + read bit transmitted, ACK received */ | |
115 | MVTWSI_STATUS_ADDR_R_ACK = 0x40, | |
116 | /* Address + read bit transmitted, ACK not received */ | |
117 | MVTWSI_STATUS_ADDR_R_NAK = 0x48, | |
118 | /* Data received, ACK transmitted */ | |
119 | MVTWSI_STATUS_DATA_R_ACK = 0x50, | |
120 | /* Data received, ACK not transmitted */ | |
121 | MVTWSI_STATUS_DATA_R_NAK = 0x58, | |
122 | /* No relevant status */ | |
123 | MVTWSI_STATUS_IDLE = 0xF8, | |
124 | }; | |
306563a7 | 125 | |
670514f5 | 126 | /* |
127 | * enum mvstwsi_ack_flags - Determine whether a read byte should be | |
128 | * acknowledged or not. | |
129 | */ | |
130 | enum mvtwsi_ack_flags { | |
131 | /* Send NAK after received byte */ | |
132 | MVTWSI_READ_NAK = 0, | |
133 | /* Send ACK after received byte */ | |
134 | MVTWSI_READ_ACK = 1, | |
135 | }; | |
136 | ||
306563a7 | 137 | /* |
dd82242b | 138 | * MVTWSI controller base |
306563a7 | 139 | */ |
4ce5a728 | 140 | |
dd82242b PK |
141 | static struct mvtwsi_registers *twsi_get_base(struct i2c_adapter *adap) |
142 | { | |
143 | switch (adap->hwadapnr) { | |
144 | #ifdef CONFIG_I2C_MVTWSI_BASE0 | |
145 | case 0: | |
9ec43b0c | 146 | return (struct mvtwsi_registers *)CONFIG_I2C_MVTWSI_BASE0; |
dd82242b PK |
147 | #endif |
148 | #ifdef CONFIG_I2C_MVTWSI_BASE1 | |
149 | case 1: | |
9ec43b0c | 150 | return (struct mvtwsi_registers *)CONFIG_I2C_MVTWSI_BASE1; |
dd82242b PK |
151 | #endif |
152 | #ifdef CONFIG_I2C_MVTWSI_BASE2 | |
153 | case 2: | |
9ec43b0c | 154 | return (struct mvtwsi_registers *)CONFIG_I2C_MVTWSI_BASE2; |
dd82242b PK |
155 | #endif |
156 | #ifdef CONFIG_I2C_MVTWSI_BASE3 | |
157 | case 3: | |
9ec43b0c | 158 | return (struct mvtwsi_registers *)CONFIG_I2C_MVTWSI_BASE3; |
dd82242b PK |
159 | #endif |
160 | #ifdef CONFIG_I2C_MVTWSI_BASE4 | |
161 | case 4: | |
9ec43b0c | 162 | return (struct mvtwsi_registers *)CONFIG_I2C_MVTWSI_BASE4; |
9d082687 JW |
163 | #endif |
164 | #ifdef CONFIG_I2C_MVTWSI_BASE5 | |
165 | case 5: | |
9ec43b0c | 166 | return (struct mvtwsi_registers *)CONFIG_I2C_MVTWSI_BASE5; |
dd82242b PK |
167 | #endif |
168 | default: | |
169 | printf("Missing mvtwsi controller %d base\n", adap->hwadapnr); | |
170 | break; | |
171 | } | |
172 | ||
173 | return NULL; | |
174 | } | |
4ce5a728 HS |
175 | |
176 | /* | |
dfc3958c | 177 | * enum mvtwsi_error_class - types of I2C errors |
4ce5a728 | 178 | */ |
dfc3958c | 179 | enum mvtwsi_error_class { |
180 | /* The controller returned a different status than expected */ | |
181 | MVTWSI_ERROR_WRONG_STATUS = 0x01, | |
182 | /* The controller timed out */ | |
183 | MVTWSI_ERROR_TIMEOUT = 0x02, | |
184 | }; | |
4ce5a728 | 185 | |
dfc3958c | 186 | /* |
187 | * mvtwsi_error() - Build I2C return code from error information | |
188 | * | |
189 | * For debugging purposes, this function packs some information of an occurred | |
190 | * error into a return code. These error codes are returned from I2C API | |
191 | * functions (i2c_{read,write}, dm_i2c_{read,write}, etc.). | |
192 | * | |
193 | * @ec: The error class of the error (enum mvtwsi_error_class). | |
194 | * @lc: The last value of the control register. | |
195 | * @ls: The last value of the status register. | |
196 | * @es: The expected value of the status register. | |
197 | * @return The generated error code. | |
198 | */ | |
199 | inline uint mvtwsi_error(uint ec, uint lc, uint ls, uint es) | |
200 | { | |
201 | return ((ec << 24) & 0xFF000000) | |
202 | | ((lc << 16) & 0x00FF0000) | |
203 | | ((ls << 8) & 0x0000FF00) | |
204 | | (es & 0xFF); | |
205 | } | |
4ce5a728 | 206 | |
306563a7 | 207 | /* |
49c801bf | 208 | * Wait for IFLG to raise, or return 'timeout.' Then, if the status is as |
209 | * expected, return 0 (ok) or 'wrong status' otherwise. | |
306563a7 | 210 | */ |
dd82242b | 211 | static int twsi_wait(struct i2c_adapter *adap, int expected_status) |
306563a7 | 212 | { |
dd82242b | 213 | struct mvtwsi_registers *twsi = twsi_get_base(adap); |
306563a7 AA |
214 | int control, status; |
215 | int timeout = 1000; | |
216 | ||
217 | do { | |
218 | control = readl(&twsi->control); | |
219 | if (control & MVTWSI_CONTROL_IFLG) { | |
220 | status = readl(&twsi->status); | |
221 | if (status == expected_status) | |
222 | return 0; | |
223 | else | |
dfc3958c | 224 | return mvtwsi_error( |
306563a7 AA |
225 | MVTWSI_ERROR_WRONG_STATUS, |
226 | control, status, expected_status); | |
4ce5a728 | 227 | } |
49c801bf | 228 | udelay(10); /* One clock cycle at 100 kHz */ |
306563a7 AA |
229 | } while (timeout--); |
230 | status = readl(&twsi->status); | |
dfc3958c | 231 | return mvtwsi_error(MVTWSI_ERROR_TIMEOUT, control, status, |
232 | expected_status); | |
4ce5a728 HS |
233 | } |
234 | ||
306563a7 AA |
235 | /* |
236 | * Assert the START condition, either in a single I2C transaction | |
237 | * or inside back-to-back ones (repeated starts). | |
238 | */ | |
670514f5 | 239 | static int twsi_start(struct i2c_adapter *adap, int expected_status) |
4ce5a728 | 240 | { |
dd82242b PK |
241 | struct mvtwsi_registers *twsi = twsi_get_base(adap); |
242 | ||
49c801bf | 243 | /* Assert START */ |
670514f5 | 244 | writel(MVTWSI_CONTROL_TWSIEN | MVTWSI_CONTROL_START | |
49c801bf | 245 | MVTWSI_CONTROL_CLEAR_IFLG, &twsi->control); |
246 | /* Wait for controller to process START */ | |
dd82242b | 247 | return twsi_wait(adap, expected_status); |
4ce5a728 HS |
248 | } |
249 | ||
306563a7 AA |
250 | /* |
251 | * Send a byte (i2c address or data). | |
252 | */ | |
670514f5 | 253 | static int twsi_send(struct i2c_adapter *adap, u8 byte, int expected_status) |
4ce5a728 | 254 | { |
dd82242b PK |
255 | struct mvtwsi_registers *twsi = twsi_get_base(adap); |
256 | ||
49c801bf | 257 | /* Write byte to data register for sending */ |
306563a7 | 258 | writel(byte, &twsi->data); |
49c801bf | 259 | /* Clear any pending interrupt -- that will cause sending */ |
670514f5 | 260 | writel(MVTWSI_CONTROL_TWSIEN | MVTWSI_CONTROL_CLEAR_IFLG, |
261 | &twsi->control); | |
49c801bf | 262 | /* Wait for controller to receive byte, and check ACK */ |
dd82242b | 263 | return twsi_wait(adap, expected_status); |
4ce5a728 HS |
264 | } |
265 | ||
306563a7 AA |
266 | /* |
267 | * Receive a byte. | |
306563a7 | 268 | */ |
670514f5 | 269 | static int twsi_recv(struct i2c_adapter *adap, u8 *byte, int ack_flag) |
4ce5a728 | 270 | { |
dd82242b | 271 | struct mvtwsi_registers *twsi = twsi_get_base(adap); |
670514f5 | 272 | int expected_status, status, control; |
306563a7 | 273 | |
670514f5 | 274 | /* Compute expected status based on passed ACK flag */ |
275 | expected_status = ack_flag ? MVTWSI_STATUS_DATA_R_ACK : | |
276 | MVTWSI_STATUS_DATA_R_NAK; | |
49c801bf | 277 | /* Acknowledge *previous state*, and launch receive */ |
670514f5 | 278 | control = MVTWSI_CONTROL_TWSIEN; |
279 | control |= ack_flag == MVTWSI_READ_ACK ? MVTWSI_CONTROL_ACK : 0; | |
280 | writel(control | MVTWSI_CONTROL_CLEAR_IFLG, &twsi->control); | |
49c801bf | 281 | /* Wait for controller to receive byte, and assert ACK or NAK */ |
dd82242b | 282 | status = twsi_wait(adap, expected_status); |
49c801bf | 283 | /* If we did receive the expected byte, store it */ |
306563a7 AA |
284 | if (status == 0) |
285 | *byte = readl(&twsi->data); | |
306563a7 | 286 | return status; |
4ce5a728 HS |
287 | } |
288 | ||
306563a7 AA |
289 | /* |
290 | * Assert the STOP condition. | |
49c801bf | 291 | * This is also used to force the bus back to idle (SDA = SCL = 1). |
306563a7 | 292 | */ |
dd82242b | 293 | static int twsi_stop(struct i2c_adapter *adap, int status) |
4ce5a728 | 294 | { |
dd82242b | 295 | struct mvtwsi_registers *twsi = twsi_get_base(adap); |
306563a7 AA |
296 | int control, stop_status; |
297 | int timeout = 1000; | |
298 | ||
49c801bf | 299 | /* Assert STOP */ |
306563a7 | 300 | control = MVTWSI_CONTROL_TWSIEN | MVTWSI_CONTROL_STOP; |
904dfbfd | 301 | writel(control | MVTWSI_CONTROL_CLEAR_IFLG, &twsi->control); |
49c801bf | 302 | /* Wait for IDLE; IFLG won't rise, so we can't use twsi_wait() */ |
306563a7 AA |
303 | do { |
304 | stop_status = readl(&twsi->status); | |
305 | if (stop_status == MVTWSI_STATUS_IDLE) | |
306 | break; | |
49c801bf | 307 | udelay(10); /* One clock cycle at 100 kHz */ |
306563a7 AA |
308 | } while (timeout--); |
309 | control = readl(&twsi->control); | |
310 | if (stop_status != MVTWSI_STATUS_IDLE) | |
311 | if (status == 0) | |
dfc3958c | 312 | status = mvtwsi_error( |
306563a7 AA |
313 | MVTWSI_ERROR_TIMEOUT, |
314 | control, status, MVTWSI_STATUS_IDLE); | |
315 | return status; | |
4ce5a728 HS |
316 | } |
317 | ||
f582a158 SR |
318 | static unsigned int twsi_calc_freq(const int n, const int m) |
319 | { | |
320 | #ifdef CONFIG_SUNXI | |
321 | return CONFIG_SYS_TCLK / (10 * (m + 1) * (1 << n)); | |
322 | #else | |
323 | return CONFIG_SYS_TCLK / (10 * (m + 1) * (2 << n)); | |
324 | #endif | |
325 | } | |
306563a7 | 326 | |
306563a7 AA |
327 | /* |
328 | * Reset controller. | |
306563a7 | 329 | * Controller reset also resets the baud rate and slave address, so |
0db2bbdc | 330 | * they must be re-established afterwards. |
306563a7 | 331 | */ |
0db2bbdc | 332 | static void twsi_reset(struct i2c_adapter *adap) |
306563a7 | 333 | { |
dd82242b | 334 | struct mvtwsi_registers *twsi = twsi_get_base(adap); |
d6b7757e | 335 | |
49c801bf | 336 | /* Reset controller */ |
306563a7 | 337 | writel(0, &twsi->soft_reset); |
49c801bf | 338 | /* Wait 2 ms -- this is what the Marvell LSP does */ |
306563a7 | 339 | udelay(20000); |
4ce5a728 HS |
340 | } |
341 | ||
306563a7 | 342 | /* |
49c801bf | 343 | * Sets baud to the highest possible value not exceeding the requested one. |
306563a7 | 344 | */ |
0db2bbdc HG |
345 | static unsigned int twsi_i2c_set_bus_speed(struct i2c_adapter *adap, |
346 | unsigned int requested_speed) | |
4ce5a728 | 347 | { |
dd82242b | 348 | struct mvtwsi_registers *twsi = twsi_get_base(adap); |
0db2bbdc | 349 | unsigned int tmp_speed, highest_speed, n, m; |
49c801bf | 350 | unsigned int baud = 0x44; /* Baud rate after controller reset */ |
306563a7 | 351 | |
306563a7 | 352 | highest_speed = 0; |
49c801bf | 353 | /* Successively try m, n combinations, and use the combination |
354 | * resulting in the largest speed that's not above the requested | |
355 | * speed */ | |
306563a7 AA |
356 | for (n = 0; n < 8; n++) { |
357 | for (m = 0; m < 16; m++) { | |
f582a158 | 358 | tmp_speed = twsi_calc_freq(n, m); |
9ec43b0c | 359 | if ((tmp_speed <= requested_speed) && |
360 | (tmp_speed > highest_speed)) { | |
306563a7 AA |
361 | highest_speed = tmp_speed; |
362 | baud = (m << 3) | n; | |
363 | } | |
364 | } | |
4ce5a728 | 365 | } |
0db2bbdc HG |
366 | writel(baud, &twsi->baudrate); |
367 | return 0; | |
368 | } | |
369 | ||
370 | static void twsi_i2c_init(struct i2c_adapter *adap, int speed, int slaveadd) | |
371 | { | |
dd82242b PK |
372 | struct mvtwsi_registers *twsi = twsi_get_base(adap); |
373 | ||
49c801bf | 374 | /* Reset controller */ |
0db2bbdc | 375 | twsi_reset(adap); |
49c801bf | 376 | /* Set speed */ |
0db2bbdc | 377 | twsi_i2c_set_bus_speed(adap, speed); |
49c801bf | 378 | /* Set slave address; even though we don't use it */ |
0db2bbdc HG |
379 | writel(slaveadd, &twsi->slave_address); |
380 | writel(0, &twsi->xtnd_slave_addr); | |
49c801bf | 381 | /* Assert STOP, but don't care for the result */ |
dd82242b | 382 | (void) twsi_stop(adap, 0); |
4ce5a728 HS |
383 | } |
384 | ||
306563a7 AA |
385 | /* |
386 | * Begin I2C transaction with expected start status, at given address. | |
306563a7 AA |
387 | * Expected address status will derive from direction bit (bit 0) in addr. |
388 | */ | |
dd82242b | 389 | static int i2c_begin(struct i2c_adapter *adap, int expected_start_status, |
670514f5 | 390 | u8 addr) |
4ce5a728 | 391 | { |
306563a7 AA |
392 | int status, expected_addr_status; |
393 | ||
49c801bf | 394 | /* Compute the expected address status from the direction bit in |
395 | * the address byte */ | |
396 | if (addr & 1) /* Reading */ | |
306563a7 | 397 | expected_addr_status = MVTWSI_STATUS_ADDR_R_ACK; |
49c801bf | 398 | else /* Writing */ |
306563a7 | 399 | expected_addr_status = MVTWSI_STATUS_ADDR_W_ACK; |
49c801bf | 400 | /* Assert START */ |
670514f5 | 401 | status = twsi_start(adap, expected_start_status); |
49c801bf | 402 | /* Send out the address if the start went well */ |
306563a7 | 403 | if (status == 0) |
670514f5 | 404 | status = twsi_send(adap, addr, expected_addr_status); |
49c801bf | 405 | /* Return 0, or the status of the first failure */ |
306563a7 | 406 | return status; |
4ce5a728 HS |
407 | } |
408 | ||
306563a7 | 409 | /* |
306563a7 AA |
410 | * Begin read, nak data byte, end. |
411 | */ | |
0db2bbdc | 412 | static int twsi_i2c_probe(struct i2c_adapter *adap, uchar chip) |
4ce5a728 | 413 | { |
306563a7 AA |
414 | u8 dummy_byte; |
415 | int status; | |
416 | ||
49c801bf | 417 | /* Begin i2c read */ |
670514f5 | 418 | status = i2c_begin(adap, MVTWSI_STATUS_START, (chip << 1) | 1); |
49c801bf | 419 | /* Dummy read was accepted: receive byte, but NAK it. */ |
306563a7 | 420 | if (status == 0) |
670514f5 | 421 | status = twsi_recv(adap, &dummy_byte, MVTWSI_READ_NAK); |
306563a7 | 422 | /* Stop transaction */ |
dd82242b | 423 | twsi_stop(adap, 0); |
49c801bf | 424 | /* Return 0, or the status of the first failure */ |
306563a7 | 425 | return status; |
4ce5a728 HS |
426 | } |
427 | ||
306563a7 | 428 | /* |
306563a7 AA |
429 | * Begin write, send address byte(s), begin read, receive data bytes, end. |
430 | * | |
49c801bf | 431 | * NOTE: Some devices want a stop right before the second start, while some |
432 | * will choke if it is there. Since deciding this is not yet supported in | |
433 | * higher level APIs, we need to make a decision here, and for the moment that | |
434 | * will be a repeated start without a preceding stop. | |
306563a7 | 435 | */ |
0db2bbdc HG |
436 | static int twsi_i2c_read(struct i2c_adapter *adap, uchar chip, uint addr, |
437 | int alen, uchar *data, int length) | |
4ce5a728 | 438 | { |
306563a7 AA |
439 | int status; |
440 | ||
49c801bf | 441 | /* Begin i2c write to send the address bytes */ |
670514f5 | 442 | status = i2c_begin(adap, MVTWSI_STATUS_START, (chip << 1)); |
49c801bf | 443 | /* Send address bytes */ |
306563a7 | 444 | while ((status == 0) && alen--) |
dd82242b | 445 | status = twsi_send(adap, addr >> (8*alen), |
670514f5 | 446 | MVTWSI_STATUS_DATA_W_ACK); |
49c801bf | 447 | /* Begin i2c read to receive data bytes */ |
306563a7 | 448 | if (status == 0) |
dd82242b | 449 | status = i2c_begin(adap, MVTWSI_STATUS_REPEATED_START, |
670514f5 | 450 | (chip << 1) | 1); |
451 | /* Receive actual data bytes; set NAK if we if we have nothing more to | |
452 | * read */ | |
453 | while ((status == 0) && length--) | |
454 | status = twsi_recv(adap, data++, | |
455 | length > 0 ? | |
456 | MVTWSI_READ_ACK : MVTWSI_READ_NAK); | |
306563a7 | 457 | /* Stop transaction */ |
dd82242b | 458 | status = twsi_stop(adap, status); |
49c801bf | 459 | /* Return 0, or the status of the first failure */ |
306563a7 | 460 | return status; |
4ce5a728 HS |
461 | } |
462 | ||
306563a7 | 463 | /* |
306563a7 AA |
464 | * Begin write, send address byte(s), send data bytes, end. |
465 | */ | |
0db2bbdc HG |
466 | static int twsi_i2c_write(struct i2c_adapter *adap, uchar chip, uint addr, |
467 | int alen, uchar *data, int length) | |
4ce5a728 | 468 | { |
306563a7 AA |
469 | int status; |
470 | ||
49c801bf | 471 | /* Begin i2c write to send first the address bytes, then the |
472 | * data bytes */ | |
670514f5 | 473 | status = i2c_begin(adap, MVTWSI_STATUS_START, (chip << 1)); |
49c801bf | 474 | /* Send address bytes */ |
306563a7 | 475 | while ((status == 0) && alen--) |
dd82242b | 476 | status = twsi_send(adap, addr >> (8*alen), |
670514f5 | 477 | MVTWSI_STATUS_DATA_W_ACK); |
49c801bf | 478 | /* Send data bytes */ |
306563a7 | 479 | while ((status == 0) && (length-- > 0)) |
670514f5 | 480 | status = twsi_send(adap, *(data++), MVTWSI_STATUS_DATA_W_ACK); |
306563a7 | 481 | /* Stop transaction */ |
dd82242b | 482 | status = twsi_stop(adap, status); |
49c801bf | 483 | /* Return 0, or the status of the first failure */ |
306563a7 | 484 | return status; |
4ce5a728 HS |
485 | } |
486 | ||
dd82242b | 487 | #ifdef CONFIG_I2C_MVTWSI_BASE0 |
0db2bbdc HG |
488 | U_BOOT_I2C_ADAP_COMPLETE(twsi0, twsi_i2c_init, twsi_i2c_probe, |
489 | twsi_i2c_read, twsi_i2c_write, | |
490 | twsi_i2c_set_bus_speed, | |
491 | CONFIG_SYS_I2C_SPEED, CONFIG_SYS_I2C_SLAVE, 0) | |
dd82242b PK |
492 | #endif |
493 | #ifdef CONFIG_I2C_MVTWSI_BASE1 | |
494 | U_BOOT_I2C_ADAP_COMPLETE(twsi1, twsi_i2c_init, twsi_i2c_probe, | |
495 | twsi_i2c_read, twsi_i2c_write, | |
496 | twsi_i2c_set_bus_speed, | |
497 | CONFIG_SYS_I2C_SPEED, CONFIG_SYS_I2C_SLAVE, 1) | |
498 | ||
499 | #endif | |
500 | #ifdef CONFIG_I2C_MVTWSI_BASE2 | |
501 | U_BOOT_I2C_ADAP_COMPLETE(twsi2, twsi_i2c_init, twsi_i2c_probe, | |
502 | twsi_i2c_read, twsi_i2c_write, | |
503 | twsi_i2c_set_bus_speed, | |
504 | CONFIG_SYS_I2C_SPEED, CONFIG_SYS_I2C_SLAVE, 2) | |
505 | ||
506 | #endif | |
507 | #ifdef CONFIG_I2C_MVTWSI_BASE3 | |
508 | U_BOOT_I2C_ADAP_COMPLETE(twsi3, twsi_i2c_init, twsi_i2c_probe, | |
509 | twsi_i2c_read, twsi_i2c_write, | |
510 | twsi_i2c_set_bus_speed, | |
511 | CONFIG_SYS_I2C_SPEED, CONFIG_SYS_I2C_SLAVE, 3) | |
512 | ||
513 | #endif | |
514 | #ifdef CONFIG_I2C_MVTWSI_BASE4 | |
515 | U_BOOT_I2C_ADAP_COMPLETE(twsi4, twsi_i2c_init, twsi_i2c_probe, | |
516 | twsi_i2c_read, twsi_i2c_write, | |
517 | twsi_i2c_set_bus_speed, | |
518 | CONFIG_SYS_I2C_SPEED, CONFIG_SYS_I2C_SLAVE, 4) | |
519 | ||
520 | #endif | |
9d082687 JW |
521 | #ifdef CONFIG_I2C_MVTWSI_BASE5 |
522 | U_BOOT_I2C_ADAP_COMPLETE(twsi5, twsi_i2c_init, twsi_i2c_probe, | |
523 | twsi_i2c_read, twsi_i2c_write, | |
524 | twsi_i2c_set_bus_speed, | |
525 | CONFIG_SYS_I2C_SPEED, CONFIG_SYS_I2C_SLAVE, 5) | |
526 | ||
527 | #endif |