blob: a4409be115d54d435b6bbd19d22957b773900103 [file] [log] [blame]
Heiko Schocher4ce5a722009-07-20 09:59:37 +02001/*
2 * Driver for the i2c controller on the Marvell line of host bridges
3 * (e.g, gt642[46]0, mv643[46]0, mv644[46]0, Orion SoC family),
4 * and Kirkwood family.
5 *
6 * Based on:
7 * Author: Mark A. Greer <mgreer@mvista.com>
Prafulla Wadaskarbeca04d2009-12-24 02:55:23 +05308 * 2005 (c) MontaVista, Software, Inc.
Heiko Schocher4ce5a722009-07-20 09:59:37 +02009 *
Prafulla Wadaskarbeca04d2009-12-24 02:55:23 +053010 * See file CREDITS for list of people who contributed to this
11 * project.
12 *
13 * This program is free software; you can redistribute it and/or
14 * modify it under the terms of the GNU General Public License as
15 * published by the Free Software Foundation; either version 2 of
16 * the License, or (at your option) any later version.
17 *
18 * This program is distributed in the hope that it will be useful,
19 * but WITHOUT ANY WARRANTY; without even the implied warranty of
20 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21 * GNU General Public License for more details.
22 *
23 * You should have received a copy of the GNU General Public License
24 * along with this program; if not, write to the Free Software
25 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
26 * MA 02110-1301 USA
Heiko Schocher4ce5a722009-07-20 09:59:37 +020027 *
28 * ported from Linux to u-boot
29 * (C) Copyright 2009
30 * Heiko Schocher, DENX Software Engineering, hs@denx.de.
Heiko Schocher4ce5a722009-07-20 09:59:37 +020031 */
32#include <common.h>
33#include <i2c.h>
34#include <asm/arch/kirkwood.h>
35#include <asm/errno.h>
36#include <asm/io.h>
37
38DECLARE_GLOBAL_DATA_PTR;
39
40static unsigned int i2c_bus_num __attribute__ ((section (".data"))) = 0;
41#if defined(CONFIG_I2C_MUX)
42static unsigned int i2c_bus_num_mux __attribute__ ((section ("data"))) = 0;
43#endif
44
45/* Register defines */
46#define KW_I2C_REG_SLAVE_ADDR 0x00
47#define KW_I2C_REG_DATA 0x04
48#define KW_I2C_REG_CONTROL 0x08
49#define KW_I2C_REG_STATUS 0x0c
50#define KW_I2C_REG_BAUD 0x0c
51#define KW_I2C_REG_EXT_SLAVE_ADDR 0x10
52#define KW_I2C_REG_SOFT_RESET 0x1c
53
54#define KW_I2C_REG_CONTROL_ACK 0x00000004
55#define KW_I2C_REG_CONTROL_IFLG 0x00000008
56#define KW_I2C_REG_CONTROL_STOP 0x00000010
57#define KW_I2C_REG_CONTROL_START 0x00000020
58#define KW_I2C_REG_CONTROL_TWSIEN 0x00000040
59#define KW_I2C_REG_CONTROL_INTEN 0x00000080
60
61/* Ctlr status values */
62#define KW_I2C_STATUS_BUS_ERR 0x00
63#define KW_I2C_STATUS_MAST_START 0x08
64#define KW_I2C_STATUS_MAST_REPEAT_START 0x10
65#define KW_I2C_STATUS_MAST_WR_ADDR_ACK 0x18
66#define KW_I2C_STATUS_MAST_WR_ADDR_NO_ACK 0x20
67#define KW_I2C_STATUS_MAST_WR_ACK 0x28
68#define KW_I2C_STATUS_MAST_WR_NO_ACK 0x30
69#define KW_I2C_STATUS_MAST_LOST_ARB 0x38
70#define KW_I2C_STATUS_MAST_RD_ADDR_ACK 0x40
71#define KW_I2C_STATUS_MAST_RD_ADDR_NO_ACK 0x48
72#define KW_I2C_STATUS_MAST_RD_DATA_ACK 0x50
73#define KW_I2C_STATUS_MAST_RD_DATA_NO_ACK 0x58
74#define KW_I2C_STATUS_MAST_WR_ADDR_2_ACK 0xd0
75#define KW_I2C_STATUS_MAST_WR_ADDR_2_NO_ACK 0xd8
76#define KW_I2C_STATUS_MAST_RD_ADDR_2_ACK 0xe0
77#define KW_I2C_STATUS_MAST_RD_ADDR_2_NO_ACK 0xe8
78#define KW_I2C_STATUS_NO_STATUS 0xf8
79
80/* Driver states */
81enum {
82 KW_I2C_STATE_INVALID,
83 KW_I2C_STATE_IDLE,
84 KW_I2C_STATE_WAITING_FOR_START_COND,
85 KW_I2C_STATE_WAITING_FOR_ADDR_1_ACK,
86 KW_I2C_STATE_WAITING_FOR_ADDR_2_ACK,
87 KW_I2C_STATE_WAITING_FOR_SLAVE_ACK,
88 KW_I2C_STATE_WAITING_FOR_SLAVE_DATA,
89};
90
91/* Driver actions */
92enum {
93 KW_I2C_ACTION_INVALID,
94 KW_I2C_ACTION_CONTINUE,
95 KW_I2C_ACTION_SEND_START,
96 KW_I2C_ACTION_SEND_ADDR_1,
97 KW_I2C_ACTION_SEND_ADDR_2,
98 KW_I2C_ACTION_SEND_DATA,
99 KW_I2C_ACTION_RCV_DATA,
100 KW_I2C_ACTION_RCV_DATA_STOP,
101 KW_I2C_ACTION_SEND_STOP,
102};
103
104/* defines to get compatible with Linux driver */
105#define IRQ_NONE 0x0
106#define IRQ_HANDLED 0x01
107
108#define I2C_M_TEN 0x01
109#define I2C_M_RD 0x02
110#define I2C_M_REV_DIR_ADDR 0x04;
111
112struct i2c_msg {
113 u32 addr;
114 u32 flags;
115 u8 *buf;
116 u32 len;
117};
118
119struct kirkwood_i2c_data {
120 int irq;
121 u32 state;
122 u32 action;
123 u32 aborting;
124 u32 cntl_bits;
125 void *reg_base;
126 u32 reg_base_p;
127 u32 reg_size;
128 u32 addr1;
129 u32 addr2;
130 u32 bytes_left;
131 u32 byte_posn;
132 u32 block;
133 int rc;
134 u32 freq_m;
135 u32 freq_n;
136 struct i2c_msg *msg;
137};
138
139static struct kirkwood_i2c_data __drv_data __attribute__ ((section (".data")));
140static struct kirkwood_i2c_data *drv_data = &__drv_data;
141static struct i2c_msg __i2c_msg __attribute__ ((section (".data")));
142static struct i2c_msg *kirkwood_i2c_msg = &__i2c_msg;
143
144/*
145 *****************************************************************************
146 *
147 * Finite State Machine & Interrupt Routines
148 *
149 *****************************************************************************
150 */
151
152static inline int abs(int n)
153{
154 if(n >= 0)
155 return n;
156 else
157 return n * -1;
158}
159
160static void kirkwood_calculate_speed(int speed)
161{
162 int calcspeed;
163 int diff;
164 int best_diff = CONFIG_SYS_TCLK;
165 int best_speed = 0;
166 int m, n;
167 int tmp[8] = {2, 4, 8, 16, 32, 64, 128, 256};
168
169 for (n = 0; n < 8; n++) {
170 for (m = 0; m < 16; m++) {
171 calcspeed = CONFIG_SYS_TCLK / (10 * (m + 1) * tmp[n]);
172 diff = abs((speed - calcspeed));
173 if ( diff < best_diff) {
174 best_diff = diff;
175 best_speed = calcspeed;
176 drv_data->freq_m = m;
177 drv_data->freq_n = n;
178 }
179 }
180 }
181}
182
183/* Reset hardware and initialize FSM */
184static void
185kirkwood_i2c_hw_init(int speed, int slaveadd)
186{
187 drv_data->state = KW_I2C_STATE_IDLE;
188
189 kirkwood_calculate_speed(speed);
190 writel(0, CONFIG_I2C_KW_REG_BASE + KW_I2C_REG_SOFT_RESET);
191 writel((((drv_data->freq_m & 0xf) << 3) | (drv_data->freq_n & 0x7)),
192 CONFIG_I2C_KW_REG_BASE + KW_I2C_REG_BAUD);
193 writel(slaveadd, CONFIG_I2C_KW_REG_BASE + KW_I2C_REG_SLAVE_ADDR);
194 writel(0, CONFIG_I2C_KW_REG_BASE + KW_I2C_REG_EXT_SLAVE_ADDR);
195 writel(KW_I2C_REG_CONTROL_TWSIEN | KW_I2C_REG_CONTROL_STOP,
196 CONFIG_I2C_KW_REG_BASE + KW_I2C_REG_CONTROL);
197}
198
199static void
200kirkwood_i2c_fsm(u32 status)
201{
202 /*
203 * If state is idle, then this is likely the remnants of an old
204 * operation that driver has given up on or the user has killed.
205 * If so, issue the stop condition and go to idle.
206 */
207 if (drv_data->state == KW_I2C_STATE_IDLE) {
208 drv_data->action = KW_I2C_ACTION_SEND_STOP;
209 return;
210 }
211
212 /* The status from the ctlr [mostly] tells us what to do next */
213 switch (status) {
214 /* Start condition interrupt */
215 case KW_I2C_STATUS_MAST_START: /* 0x08 */
216 case KW_I2C_STATUS_MAST_REPEAT_START: /* 0x10 */
217 drv_data->action = KW_I2C_ACTION_SEND_ADDR_1;
218 drv_data->state = KW_I2C_STATE_WAITING_FOR_ADDR_1_ACK;
219 break;
220
221 /* Performing a write */
222 case KW_I2C_STATUS_MAST_WR_ADDR_ACK: /* 0x18 */
223 if (drv_data->msg->flags & I2C_M_TEN) {
224 drv_data->action = KW_I2C_ACTION_SEND_ADDR_2;
225 drv_data->state =
226 KW_I2C_STATE_WAITING_FOR_ADDR_2_ACK;
227 break;
228 }
229 /* FALLTHRU */
230 case KW_I2C_STATUS_MAST_WR_ADDR_2_ACK: /* 0xd0 */
231 case KW_I2C_STATUS_MAST_WR_ACK: /* 0x28 */
232 if ((drv_data->bytes_left == 0)
233 || (drv_data->aborting
234 && (drv_data->byte_posn != 0))) {
235 drv_data->action = KW_I2C_ACTION_SEND_STOP;
236 drv_data->state = KW_I2C_STATE_IDLE;
237 } else {
238 drv_data->action = KW_I2C_ACTION_SEND_DATA;
239 drv_data->state =
240 KW_I2C_STATE_WAITING_FOR_SLAVE_ACK;
241 drv_data->bytes_left--;
242 }
243 break;
244
245 /* Performing a read */
246 case KW_I2C_STATUS_MAST_RD_ADDR_ACK: /* 40 */
247 if (drv_data->msg->flags & I2C_M_TEN) {
248 drv_data->action = KW_I2C_ACTION_SEND_ADDR_2;
249 drv_data->state =
250 KW_I2C_STATE_WAITING_FOR_ADDR_2_ACK;
251 break;
252 }
253 /* FALLTHRU */
254 case KW_I2C_STATUS_MAST_RD_ADDR_2_ACK: /* 0xe0 */
255 if (drv_data->bytes_left == 0) {
256 drv_data->action = KW_I2C_ACTION_SEND_STOP;
257 drv_data->state = KW_I2C_STATE_IDLE;
258 break;
259 }
260 /* FALLTHRU */
261 case KW_I2C_STATUS_MAST_RD_DATA_ACK: /* 0x50 */
262 if (status != KW_I2C_STATUS_MAST_RD_DATA_ACK)
263 drv_data->action = KW_I2C_ACTION_CONTINUE;
264 else {
265 drv_data->action = KW_I2C_ACTION_RCV_DATA;
266 drv_data->bytes_left--;
267 }
268 drv_data->state = KW_I2C_STATE_WAITING_FOR_SLAVE_DATA;
269
270 if ((drv_data->bytes_left == 1) || drv_data->aborting)
271 drv_data->cntl_bits &= ~KW_I2C_REG_CONTROL_ACK;
272 break;
273
274 case KW_I2C_STATUS_MAST_RD_DATA_NO_ACK: /* 0x58 */
275 drv_data->action = KW_I2C_ACTION_RCV_DATA_STOP;
276 drv_data->state = KW_I2C_STATE_IDLE;
277 break;
278
279 case KW_I2C_STATUS_MAST_WR_ADDR_NO_ACK: /* 0x20 */
280 case KW_I2C_STATUS_MAST_WR_NO_ACK: /* 30 */
281 case KW_I2C_STATUS_MAST_RD_ADDR_NO_ACK: /* 48 */
282 /* Doesn't seem to be a device at other end */
283 drv_data->action = KW_I2C_ACTION_SEND_STOP;
284 drv_data->state = KW_I2C_STATE_IDLE;
285 drv_data->rc = -ENODEV;
286 break;
287
288 default:
289 printf("kirkwood_i2c_fsm: Ctlr Error -- state: 0x%x, "
290 "status: 0x%x, addr: 0x%x, flags: 0x%x\n",
291 drv_data->state, status, drv_data->msg->addr,
292 drv_data->msg->flags);
293 drv_data->action = KW_I2C_ACTION_SEND_STOP;
294 kirkwood_i2c_hw_init(CONFIG_SYS_I2C_SPEED, CONFIG_SYS_I2C_SLAVE);
295 drv_data->rc = -EIO;
296 }
297}
298
299static void
300kirkwood_i2c_do_action(void)
301{
302 switch(drv_data->action) {
303 case KW_I2C_ACTION_CONTINUE:
304 writel(drv_data->cntl_bits,
305 CONFIG_I2C_KW_REG_BASE + KW_I2C_REG_CONTROL);
306 break;
307
308 case KW_I2C_ACTION_SEND_START:
309 writel(drv_data->cntl_bits | KW_I2C_REG_CONTROL_START,
310 CONFIG_I2C_KW_REG_BASE + KW_I2C_REG_CONTROL);
311 break;
312
313 case KW_I2C_ACTION_SEND_ADDR_1:
314 writel(drv_data->addr1,
315 CONFIG_I2C_KW_REG_BASE + KW_I2C_REG_DATA);
316 writel(drv_data->cntl_bits,
317 CONFIG_I2C_KW_REG_BASE + KW_I2C_REG_CONTROL);
318 break;
319
320 case KW_I2C_ACTION_SEND_ADDR_2:
321 writel(drv_data->addr2,
322 CONFIG_I2C_KW_REG_BASE + KW_I2C_REG_DATA);
323 writel(drv_data->cntl_bits,
324 CONFIG_I2C_KW_REG_BASE + KW_I2C_REG_CONTROL);
325 break;
326
327 case KW_I2C_ACTION_SEND_DATA:
328 writel(drv_data->msg->buf[drv_data->byte_posn++],
329 CONFIG_I2C_KW_REG_BASE + KW_I2C_REG_DATA);
330 writel(drv_data->cntl_bits,
331 CONFIG_I2C_KW_REG_BASE + KW_I2C_REG_CONTROL);
332 break;
333
334 case KW_I2C_ACTION_RCV_DATA:
335 drv_data->msg->buf[drv_data->byte_posn++] =
336 readl(CONFIG_I2C_KW_REG_BASE + KW_I2C_REG_DATA);
337 writel(drv_data->cntl_bits,
338 CONFIG_I2C_KW_REG_BASE + KW_I2C_REG_CONTROL);
339 break;
340
341 case KW_I2C_ACTION_RCV_DATA_STOP:
342 drv_data->msg->buf[drv_data->byte_posn++] =
343 readl(CONFIG_I2C_KW_REG_BASE + KW_I2C_REG_DATA);
344 drv_data->cntl_bits &= ~KW_I2C_REG_CONTROL_INTEN;
345 writel(drv_data->cntl_bits | KW_I2C_REG_CONTROL_STOP,
346 CONFIG_I2C_KW_REG_BASE + KW_I2C_REG_CONTROL);
347 drv_data->block = 0;
348 break;
349
350 case KW_I2C_ACTION_INVALID:
351 default:
352 printf("kirkwood_i2c_do_action: Invalid action: %d\n",
353 drv_data->action);
354 drv_data->rc = -EIO;
355 /* FALLTHRU */
356 case KW_I2C_ACTION_SEND_STOP:
357 drv_data->cntl_bits &= ~KW_I2C_REG_CONTROL_INTEN;
358 writel(drv_data->cntl_bits | KW_I2C_REG_CONTROL_STOP,
359 CONFIG_I2C_KW_REG_BASE + KW_I2C_REG_CONTROL);
360 drv_data->block = 0;
361 break;
362 }
363}
364
365static int
366kirkwood_i2c_intr(void)
367{
368 u32 status;
369 u32 ctrl;
370 int rc = IRQ_NONE;
371
372 ctrl = readl(CONFIG_I2C_KW_REG_BASE + KW_I2C_REG_CONTROL);
373 while ((ctrl & KW_I2C_REG_CONTROL_IFLG) &&
374 (drv_data->rc == 0)) {
375 status = readl(CONFIG_I2C_KW_REG_BASE + KW_I2C_REG_STATUS);
376 kirkwood_i2c_fsm(status);
377 kirkwood_i2c_do_action();
378 rc = IRQ_HANDLED;
379 ctrl = readl(CONFIG_I2C_KW_REG_BASE + KW_I2C_REG_CONTROL);
380 udelay(1000);
381 }
382 return rc;
383}
384
385static void
386kirkwood_i2c_doio(struct i2c_msg *msg)
387{
388 int ret;
389
390 while ((drv_data->rc == 0) && (drv_data->state != KW_I2C_STATE_IDLE)) {
391 /* poll Status register */
392 ret = kirkwood_i2c_intr();
393 if (ret == IRQ_NONE)
394 udelay(10);
395 }
396}
397
398static void
399kirkwood_i2c_prepare_for_io(struct i2c_msg *msg)
400{
401 u32 dir = 0;
402
403 drv_data->msg = msg;
404 drv_data->byte_posn = 0;
405 drv_data->bytes_left = msg->len;
406 drv_data->aborting = 0;
407 drv_data->rc = 0;
408 /* in u-boot we use no IRQs */
409 drv_data->cntl_bits = KW_I2C_REG_CONTROL_ACK | KW_I2C_REG_CONTROL_TWSIEN;
410
411 if (msg->flags & I2C_M_RD)
412 dir = 1;
413 if (msg->flags & I2C_M_TEN) {
414 drv_data->addr1 = 0xf0 | (((u32)msg->addr & 0x300) >> 7) | dir;
415 drv_data->addr2 = (u32)msg->addr & 0xff;
416 } else {
417 drv_data->addr1 = ((u32)msg->addr & 0x7f) << 1 | dir;
418 drv_data->addr2 = 0;
419 }
420 /* OK, no start it (from kirkwood_i2c_execute_msg())*/
421 drv_data->action = KW_I2C_ACTION_SEND_START;
422 drv_data->state = KW_I2C_STATE_WAITING_FOR_START_COND;
423 drv_data->block = 1;
424 kirkwood_i2c_do_action();
425}
426
427void
428i2c_init(int speed, int slaveadd)
429{
430 kirkwood_i2c_hw_init(speed, slaveadd);
431}
432
433int
434i2c_read(u8 dev, uint addr, int alen, u8 *data, int length)
435{
436 kirkwood_i2c_msg->buf = data;
437 kirkwood_i2c_msg->len = length;
438 kirkwood_i2c_msg->addr = dev;
439 kirkwood_i2c_msg->flags = I2C_M_RD;
440
441 kirkwood_i2c_prepare_for_io(kirkwood_i2c_msg);
442 kirkwood_i2c_doio(kirkwood_i2c_msg);
443 return drv_data->rc;
444}
445
446int
447i2c_write(u8 dev, uint addr, int alen, u8 *data, int length)
448{
449 kirkwood_i2c_msg->buf = data;
450 kirkwood_i2c_msg->len = length;
451 kirkwood_i2c_msg->addr = dev;
452 kirkwood_i2c_msg->flags = 0;
453
454 kirkwood_i2c_prepare_for_io(kirkwood_i2c_msg);
455 kirkwood_i2c_doio(kirkwood_i2c_msg);
456 return drv_data->rc;
457}
458
459int
460i2c_probe(uchar chip)
461{
462 return i2c_read(chip, 0, 0, NULL, 0);
463}
464
465int i2c_set_bus_num(unsigned int bus)
466{
467#if defined(CONFIG_I2C_MUX)
468 if (bus < CONFIG_SYS_MAX_I2C_BUS) {
469 i2c_bus_num = bus;
470 } else {
471 int ret;
472
473 ret = i2x_mux_select_mux(bus);
474 if (ret)
475 return ret;
476 i2c_bus_num = 0;
477 }
478 i2c_bus_num_mux = bus;
479#else
480 if (bus > 0) {
481 return -1;
482 }
483
484 i2c_bus_num = bus;
485#endif
486 return 0;
487}
488
489unsigned int i2c_get_bus_num(void)
490{
491#if defined(CONFIG_I2C_MUX)
492 return i2c_bus_num_mux;
493#else
494 return i2c_bus_num;
495#endif
496}