blob: 60f03d47a154f712585f99f9a0fc58a55d81454a [file] [log] [blame]
Mike Frysinger9171fc82008-03-30 15:46:13 -04001/*
2 * i2c.c - driver for Blackfin on-chip TWI/I2C
3 *
4 * Copyright (c) 2006-2008 Analog Devices Inc.
5 *
6 * Licensed under the GPL-2 or later.
7 */
Aubrey Li26bf7de2007-03-19 01:24:52 +08008
9#include <common.h>
10
11#ifdef CONFIG_HARD_I2C
12
13#include <asm/blackfin.h>
14#include <i2c.h>
15#include <asm/io.h>
Mike Frysingerd4d77302008-02-04 19:26:55 -050016#include <asm/mach-common/bits/twi.h>
Aubrey Li26bf7de2007-03-19 01:24:52 +080017
Mike Frysinger9171fc82008-03-30 15:46:13 -040018/* Two-Wire Interface (0xFFC01400 - 0xFFC014FF) */
19#ifdef TWI0_CLKDIV
20#define bfin_read_TWI_CLKDIV() bfin_read_TWI0_CLKDIV()
21#define bfin_write_TWI_CLKDIV(val) bfin_write_TWI0_CLKDIV(val)
22#define bfin_read_TWI_CONTROL() bfin_read_TWI0_CONTROL()
23#define bfin_write_TWI_CONTROL(val) bfin_write_TWI0_CONTROL(val)
24#define bfin_read_TWI_SLAVE_CTL() bfin_read_TWI0_SLAVE_CTL()
25#define bfin_write_TWI_SLAVE_CTL(val) bfin_write_TWI0_SLAVE_CTL(val)
26#define bfin_read_TWI_SLAVE_STAT() bfin_read_TWI0_SLAVE_STAT()
27#define bfin_write_TWI_SLAVE_STAT(val) bfin_write_TWI0_SLAVE_STAT(val)
28#define bfin_read_TWI_SLAVE_ADDR() bfin_read_TWI0_SLAVE_ADDR()
29#define bfin_write_TWI_SLAVE_ADDR(val) bfin_write_TWI0_SLAVE_ADDR(val)
30#define bfin_read_TWI_MASTER_CTL() bfin_read_TWI0_MASTER_CTL()
31#define bfin_write_TWI_MASTER_CTL(val) bfin_write_TWI0_MASTER_CTL(val)
32#define bfin_read_TWI_MASTER_STAT() bfin_read_TWI0_MASTER_STAT()
33#define bfin_write_TWI_MASTER_STAT(val) bfin_write_TWI0_MASTER_STAT(val)
34#define bfin_read_TWI_MASTER_ADDR() bfin_read_TWI0_MASTER_ADDR()
35#define bfin_write_TWI_MASTER_ADDR(val) bfin_write_TWI0_MASTER_ADDR(val)
36#define bfin_read_TWI_INT_STAT() bfin_read_TWI0_INT_STAT()
37#define bfin_write_TWI_INT_STAT(val) bfin_write_TWI0_INT_STAT(val)
38#define bfin_read_TWI_INT_MASK() bfin_read_TWI0_INT_MASK()
39#define bfin_write_TWI_INT_MASK(val) bfin_write_TWI0_INT_MASK(val)
40#define bfin_read_TWI_FIFO_CTL() bfin_read_TWI0_FIFO_CTL()
41#define bfin_write_TWI_FIFO_CTL(val) bfin_write_TWI0_FIFO_CTL(val)
42#define bfin_read_TWI_FIFO_STAT() bfin_read_TWI0_FIFO_STAT()
43#define bfin_write_TWI_FIFO_STAT(val) bfin_write_TWI0_FIFO_STAT(val)
44#define bfin_read_TWI_XMT_DATA8() bfin_read_TWI0_XMT_DATA8()
45#define bfin_write_TWI_XMT_DATA8(val) bfin_write_TWI0_XMT_DATA8(val)
46#define bfin_read_TWI_XMT_DATA_16() bfin_read_TWI0_XMT_DATA16()
47#define bfin_write_TWI_XMT_DATA16(val) bfin_write_TWI0_XMT_DATA16(val)
48#define bfin_read_TWI_RCV_DATA8() bfin_read_TWI0_RCV_DATA8()
49#define bfin_write_TWI_RCV_DATA8(val) bfin_write_TWI0_RCV_DATA8(val)
50#define bfin_read_TWI_RCV_DATA16() bfin_read_TWI0_RCV_DATA16()
51#define bfin_write_TWI_RCV_DATA16(val) bfin_write_TWI0_RCV_DATA16(val)
52#endif
Wolfgang Denk1218abf2007-09-15 20:48:41 +020053
Aubrey Li26bf7de2007-03-19 01:24:52 +080054#ifdef DEBUG_I2C
55#define PRINTD(fmt,args...) do { \
Mike Frysinger9171fc82008-03-30 15:46:13 -040056 DECLARE_GLOBAL_DATA_PTR; \
Aubrey Li26bf7de2007-03-19 01:24:52 +080057 if (gd->have_console) \
58 printf(fmt ,##args); \
59 } while (0)
60#else
61#define PRINTD(fmt,args...)
62#endif
63
64#ifndef CONFIG_TWICLK_KHZ
65#define CONFIG_TWICLK_KHZ 50
66#endif
67
68/* All transfers are described by this data structure */
69struct i2c_msg {
70 u16 addr; /* slave address */
71 u16 flags;
72#define I2C_M_STOP 0x2
73#define I2C_M_RD 0x1
74 u16 len; /* msg length */
75 u8 *buf; /* pointer to msg data */
76};
77
78/**
79 * i2c_reset: - reset the host controller
Aubrey Li26bf7de2007-03-19 01:24:52 +080080 */
Aubrey Li26bf7de2007-03-19 01:24:52 +080081static void i2c_reset(void)
82{
83 /* Disable TWI */
84 bfin_write_TWI_CONTROL(0);
Mike Frysinger9171fc82008-03-30 15:46:13 -040085 SSYNC();
Aubrey Li26bf7de2007-03-19 01:24:52 +080086
87 /* Set TWI internal clock as 10MHz */
88 bfin_write_TWI_CONTROL(((get_sclk() / 1024 / 1024 + 5) / 10) & 0x7F);
89
90 /* Set Twi interface clock as specified */
91 if (CONFIG_TWICLK_KHZ > 400)
92 bfin_write_TWI_CLKDIV(((5 * 1024 / 400) << 8) | ((5 * 1024 /
93 400) & 0xFF));
94 else
95 bfin_write_TWI_CLKDIV(((5 * 1024 /
96 CONFIG_TWICLK_KHZ) << 8) | ((5 * 1024 /
97 CONFIG_TWICLK_KHZ)
98 & 0xFF));
99
100 /* Enable TWI */
101 bfin_write_TWI_CONTROL(bfin_read_TWI_CONTROL() | TWI_ENA);
Mike Frysinger9171fc82008-03-30 15:46:13 -0400102 SSYNC();
Aubrey Li26bf7de2007-03-19 01:24:52 +0800103}
104
105int wait_for_completion(struct i2c_msg *msg, int timeout_count)
106{
107 unsigned short twi_int_stat;
108 unsigned short mast_stat;
109 int i;
110
111 for (i = 0; i < timeout_count; i++) {
112 twi_int_stat = bfin_read_TWI_INT_STAT();
113 mast_stat = bfin_read_TWI_MASTER_STAT();
114
115 if (XMTSERV & twi_int_stat) {
116 /* Transmit next data */
117 if (msg->len > 0) {
118 bfin_write_TWI_XMT_DATA8(*(msg->buf++));
119 msg->len--;
120 } else if (msg->flags & I2C_M_STOP)
121 bfin_write_TWI_MASTER_CTL
122 (bfin_read_TWI_MASTER_CTL() | STOP);
Mike Frysinger9171fc82008-03-30 15:46:13 -0400123 SSYNC();
Aubrey Li26bf7de2007-03-19 01:24:52 +0800124 /* Clear status */
125 bfin_write_TWI_INT_STAT(XMTSERV);
Mike Frysinger9171fc82008-03-30 15:46:13 -0400126 SSYNC();
Aubrey Li26bf7de2007-03-19 01:24:52 +0800127 i = 0;
128 }
129 if (RCVSERV & twi_int_stat) {
130 if (msg->len > 0) {
131 /* Receive next data */
132 *(msg->buf++) = bfin_read_TWI_RCV_DATA8();
133 msg->len--;
134 } else if (msg->flags & I2C_M_STOP) {
135 bfin_write_TWI_MASTER_CTL
136 (bfin_read_TWI_MASTER_CTL() | STOP);
Mike Frysinger9171fc82008-03-30 15:46:13 -0400137 SSYNC();
Aubrey Li26bf7de2007-03-19 01:24:52 +0800138 }
139 /* Clear interrupt source */
140 bfin_write_TWI_INT_STAT(RCVSERV);
Mike Frysinger9171fc82008-03-30 15:46:13 -0400141 SSYNC();
Aubrey Li26bf7de2007-03-19 01:24:52 +0800142 i = 0;
143 }
144 if (MERR & twi_int_stat) {
145 bfin_write_TWI_INT_STAT(MERR);
146 bfin_write_TWI_INT_MASK(0);
147 bfin_write_TWI_MASTER_STAT(0x3e);
148 bfin_write_TWI_MASTER_CTL(0);
Mike Frysinger9171fc82008-03-30 15:46:13 -0400149 SSYNC();
Aubrey Li26bf7de2007-03-19 01:24:52 +0800150 /*
151 * if both err and complete int stats are set,
152 * return proper results.
153 */
154 if (MCOMP & twi_int_stat) {
155 bfin_write_TWI_INT_STAT(MCOMP);
156 bfin_write_TWI_INT_MASK(0);
157 bfin_write_TWI_MASTER_CTL(0);
Mike Frysinger9171fc82008-03-30 15:46:13 -0400158 SSYNC();
Aubrey Li26bf7de2007-03-19 01:24:52 +0800159 /*
160 * If it is a quick transfer,
161 * only address bug no data, not an err.
162 */
163 if (msg->len == 0 && mast_stat & BUFRDERR)
164 return 0;
165 /*
166 * If address not acknowledged return -3,
167 * else return 0.
168 */
169 else if (!(mast_stat & ANAK))
170 return 0;
171 else
172 return -3;
173 }
174 return -1;
175 }
176 if (MCOMP & twi_int_stat) {
177 bfin_write_TWI_INT_STAT(MCOMP);
Mike Frysinger9171fc82008-03-30 15:46:13 -0400178 SSYNC();
Aubrey Li26bf7de2007-03-19 01:24:52 +0800179 bfin_write_TWI_INT_MASK(0);
180 bfin_write_TWI_MASTER_CTL(0);
Mike Frysinger9171fc82008-03-30 15:46:13 -0400181 SSYNC();
Aubrey Li26bf7de2007-03-19 01:24:52 +0800182 return 0;
183 }
184 }
185 if (msg->flags & I2C_M_RD)
186 return -4;
187 else
188 return -2;
189}
190
191/**
192 * i2c_transfer: - Transfer one byte over the i2c bus
193 *
194 * This function can tranfer a byte over the i2c bus in both directions.
195 * It is used by the public API functions.
196 *
197 * @return: 0: transfer successful
198 * -1: transfer fail
199 * -2: transmit timeout
200 * -3: ACK missing
201 * -4: receive timeout
202 * -5: controller not ready
203 */
204int i2c_transfer(struct i2c_msg *msg)
205{
206 int ret = 0;
207 int timeout_count = 10000;
208 int len = msg->len;
209
210 if (!(bfin_read_TWI_CONTROL() & TWI_ENA)) {
211 ret = -5;
212 goto transfer_error;
213 }
214
Mike Frysinger9171fc82008-03-30 15:46:13 -0400215 while (bfin_read_TWI_MASTER_STAT() & BUSBUSY)
216 continue;
Aubrey Li26bf7de2007-03-19 01:24:52 +0800217
218 /* Set Transmit device address */
219 bfin_write_TWI_MASTER_ADDR(msg->addr);
220
221 /*
222 * FIFO Initiation.
223 * Data in FIFO should be discarded before start a new operation.
224 */
225 bfin_write_TWI_FIFO_CTL(0x3);
Mike Frysinger9171fc82008-03-30 15:46:13 -0400226 SSYNC();
Aubrey Li26bf7de2007-03-19 01:24:52 +0800227 bfin_write_TWI_FIFO_CTL(0);
Mike Frysinger9171fc82008-03-30 15:46:13 -0400228 SSYNC();
Aubrey Li26bf7de2007-03-19 01:24:52 +0800229
230 if (!(msg->flags & I2C_M_RD)) {
231 /* Transmit first data */
232 if (msg->len > 0) {
233 PRINTD("1 in i2c_transfer: buf=%d, len=%d\n", *msg->buf,
234 len);
235 bfin_write_TWI_XMT_DATA8(*(msg->buf++));
236 msg->len--;
Mike Frysinger9171fc82008-03-30 15:46:13 -0400237 SSYNC();
Aubrey Li26bf7de2007-03-19 01:24:52 +0800238 }
239 }
240
241 /* clear int stat */
242 bfin_write_TWI_INT_STAT(MERR | MCOMP | XMTSERV | RCVSERV);
243
244 /* Interrupt mask . Enable XMT, RCV interrupt */
245 bfin_write_TWI_INT_MASK(MCOMP | MERR |
246 ((msg->flags & I2C_M_RD) ? RCVSERV : XMTSERV));
Mike Frysinger9171fc82008-03-30 15:46:13 -0400247 SSYNC();
Aubrey Li26bf7de2007-03-19 01:24:52 +0800248
249 if (len > 0 && len <= 255)
250 bfin_write_TWI_MASTER_CTL((len << 6));
251 else if (msg->len > 255) {
252 bfin_write_TWI_MASTER_CTL((0xff << 6));
253 msg->flags &= I2C_M_STOP;
254 } else
255 bfin_write_TWI_MASTER_CTL(0);
256
257 /* Master enable */
258 bfin_write_TWI_MASTER_CTL(bfin_read_TWI_MASTER_CTL() | MEN |
259 ((msg->flags & I2C_M_RD)
260 ? MDIR : 0) | ((CONFIG_TWICLK_KHZ >
261 100) ? FAST : 0));
Mike Frysinger9171fc82008-03-30 15:46:13 -0400262 SSYNC();
Aubrey Li26bf7de2007-03-19 01:24:52 +0800263
264 ret = wait_for_completion(msg, timeout_count);
265 PRINTD("3 in i2c_transfer: ret=%d\n", ret);
266
Mike Frysinger9171fc82008-03-30 15:46:13 -0400267 transfer_error:
Aubrey Li26bf7de2007-03-19 01:24:52 +0800268 switch (ret) {
269 case 1:
270 PRINTD(("i2c_transfer: error: transfer fail\n"));
271 break;
272 case 2:
273 PRINTD(("i2c_transfer: error: transmit timeout\n"));
274 break;
275 case 3:
276 PRINTD(("i2c_transfer: error: ACK missing\n"));
277 break;
278 case 4:
279 PRINTD(("i2c_transfer: error: receive timeout\n"));
280 break;
281 case 5:
282 PRINTD(("i2c_transfer: error: controller not ready\n"));
283 i2c_reset();
284 break;
285 default:
286 break;
287 }
288 return ret;
289
290}
291
292/* ---------------------------------------------------------------------*/
293/* API Functions */
294/* ---------------------------------------------------------------------*/
295
296void i2c_init(int speed, int slaveaddr)
297{
298 i2c_reset();
299}
300
301/**
302 * i2c_probe: - Test if a chip answers for a given i2c address
303 *
304 * @chip: address of the chip which is searched for
Wolfgang Denk53677ef2008-05-20 16:00:29 +0200305 * @return: 0 if a chip was found, -1 otherwhise
Aubrey Li26bf7de2007-03-19 01:24:52 +0800306 */
307
308int i2c_probe(uchar chip)
309{
310 struct i2c_msg msg;
311 u8 probebuf;
312
313 i2c_reset();
314
315 probebuf = 0;
316 msg.addr = chip;
317 msg.flags = 0;
318 msg.len = 1;
319 msg.buf = &probebuf;
320 if (i2c_transfer(&msg))
321 return -1;
322
323 msg.addr = chip;
324 msg.flags = I2C_M_RD;
325 msg.len = 1;
326 msg.buf = &probebuf;
327 if (i2c_transfer(&msg))
328 return -1;
329
330 return 0;
331}
332
333/**
334 * i2c_read: - Read multiple bytes from an i2c device
335 *
336 * chip: I2C chip address, range 0..127
337 * addr: Memory (register) address within the chip
338 * alen: Number of bytes to use for addr (typically 1, 2 for larger
339 * memories, 0 for register type devices with only one
340 * register)
341 * buffer: Where to read/write the data
342 * len: How many bytes to read/write
343 *
344 * Returns: 0 on success, not 0 on failure
345 */
346
347int i2c_read(uchar chip, uint addr, int alen, uchar * buffer, int len)
348{
349 struct i2c_msg msg;
350 u8 addr_bytes[3]; /* lowest...highest byte of data address */
351
352 PRINTD("i2c_read: chip=0x%x, addr=0x%x, alen=0x%x, len=0x%x\n", chip,
353 addr, alen, len);
354
355 if (alen > 0) {
356 addr_bytes[0] = (u8) ((addr >> 0) & 0x000000FF);
357 addr_bytes[1] = (u8) ((addr >> 8) & 0x000000FF);
358 addr_bytes[2] = (u8) ((addr >> 16) & 0x000000FF);
359 msg.addr = chip;
360 msg.flags = 0;
361 msg.len = alen;
362 msg.buf = addr_bytes;
363 if (i2c_transfer(&msg))
364 return -1;
365 }
366
367 /* start read sequence */
368 PRINTD(("i2c_read: start read sequence\n"));
369 msg.addr = chip;
370 msg.flags = I2C_M_RD;
371 msg.len = len;
372 msg.buf = buffer;
373 if (i2c_transfer(&msg))
374 return -1;
375
376 return 0;
377}
378
379/**
380 * i2c_write: - Write multiple bytes to an i2c device
381 *
382 * chip: I2C chip address, range 0..127
383 * addr: Memory (register) address within the chip
384 * alen: Number of bytes to use for addr (typically 1, 2 for larger
385 * memories, 0 for register type devices with only one
386 * register)
387 * buffer: Where to read/write the data
388 * len: How many bytes to read/write
389 *
390 * Returns: 0 on success, not 0 on failure
391 */
392
393int i2c_write(uchar chip, uint addr, int alen, uchar * buffer, int len)
394{
395 struct i2c_msg msg;
396 u8 addr_bytes[3]; /* lowest...highest byte of data address */
397
398 PRINTD
399 ("i2c_write: chip=0x%x, addr=0x%x, alen=0x%x, len=0x%x, buf0=0x%x\n",
400 chip, addr, alen, len, buffer[0]);
401
402 /* chip address write */
403 if (alen > 0) {
404 addr_bytes[0] = (u8) ((addr >> 0) & 0x000000FF);
405 addr_bytes[1] = (u8) ((addr >> 8) & 0x000000FF);
406 addr_bytes[2] = (u8) ((addr >> 16) & 0x000000FF);
407 msg.addr = chip;
408 msg.flags = 0;
409 msg.len = alen;
410 msg.buf = addr_bytes;
411 if (i2c_transfer(&msg))
412 return -1;
413 }
414
415 /* start read sequence */
416 PRINTD(("i2c_write: start write sequence\n"));
417 msg.addr = chip;
418 msg.flags = 0;
419 msg.len = len;
420 msg.buf = buffer;
421 if (i2c_transfer(&msg))
422 return -1;
423
424 return 0;
425
426}
427
428uchar i2c_reg_read(uchar chip, uchar reg)
429{
430 uchar buf;
431
432 PRINTD("i2c_reg_read: chip=0x%02x, reg=0x%02x\n", chip, reg);
433 i2c_read(chip, reg, 0, &buf, 1);
434 return (buf);
435}
436
437void i2c_reg_write(uchar chip, uchar reg, uchar val)
438{
439 PRINTD("i2c_reg_write: chip=0x%02x, reg=0x%02x, val=0x%02x\n", chip,
440 reg, val);
441 i2c_write(chip, reg, 0, &val, 1);
442}
443
Mike Frysinger9171fc82008-03-30 15:46:13 -0400444#endif /* CONFIG_HARD_I2C */