1 //==========================================================================
5 // I2C support on Freescale MXC platforms
7 //==========================================================================
8 //####ECOSGPLCOPYRIGHTBEGIN####
9 // -------------------------------------------
10 // This file is part of eCos, the Embedded Configurable Operating System.
11 // Copyright (C) 1998, 1999, 2000, 2001, 2002 Red Hat, Inc.
13 // eCos is free software; you can redistribute it and/or modify it under
14 // the terms of the GNU General Public License as published by the Free
15 // Software Foundation; either version 2 or (at your option) any later version.
17 // eCos is distributed in the hope that it will be useful, but WITHOUT ANY
18 // WARRANTY; without even the implied warranty of MERCHANTABILITY or
19 // FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
22 // You should have received a copy of the GNU General Public License along
23 // with eCos; if not, write to the Free Software Foundation, Inc.,
24 // 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
26 // As a special exception, if other files instantiate templates or use macros
27 // or inline functions from this file, or you compile this file and link it
28 // with other works to produce a work based on this file, this file does not
29 // by itself cause the resulting work to be covered by the GNU General Public
30 // License. However the source code for this file must still be made available
31 // in accordance with section (3) of the GNU General Public License.
33 // This exception does not invalidate any other reasons why a work based on
34 // this file might be covered by the GNU General Public License.
36 // Alternative licenses for eCos may be arranged by contacting Red Hat, Inc.
37 // at http://sources.redhat.com/ecos/ecos-license/
38 // -------------------------------------------
39 //####ECOSGPLCOPYRIGHTEND####
40 //==========================================================================
44 #include <pkgconf/hal.h>
45 #include <cyg/hal/hal_arch.h>
46 #include <cyg/hal/hal_cache.h>
47 #include <cyg/hal/hal_io.h>
49 #include <cyg/hal/fsl_board.h>
50 #include <cyg/io/mxc_i2c.h>
52 extern void mxc_i2c_init(unsigned int module_base);
54 //#define MXC_I2C_DEBUG
58 #define diag_printf1 diag_printf
60 #define diag_printf1(fmt,args...)
63 struct clk_div_table {
68 static const struct clk_div_table i2c_clk_table[] = {
69 {0x20, 22}, {0x21, 24}, {0x22, 26}, {0x23, 28},
70 {0, 30}, {1, 32}, {0x24, 32}, {2, 36},
71 {0x25, 36}, {0x26, 40}, {3, 42}, {0x27, 44},
72 {4, 48}, {0x28, 48}, {5, 52}, {0x29, 56},
73 {6, 60}, {0x2A, 64}, {7, 72}, {0x2B, 72},
74 {8, 80}, {0x2C, 80}, {9, 88}, {0x2D, 96},
75 {0xA, 104}, {0x2E, 112}, {0xB, 128}, {0x2F, 128},
76 {0xC, 144}, {0xD, 160}, {0x30, 160}, {0xE, 192},
77 {0x31, 192}, {0x32, 224}, {0xF, 240}, {0x33, 256},
78 {0x10, 288}, {0x11, 320}, {0x34, 320}, {0x12, 384},
79 {0x35, 384}, {0x36, 448}, {0x13, 480}, {0x37, 512},
80 {0x14, 576}, {0x15, 640}, {0x38, 640}, {0x16, 768},
81 {0x39, 768}, {0x3A, 896}, {0x17, 960}, {0x3B, 1024},
82 {0x18, 1152}, {0x19, 1280}, {0x3C, 1280}, {0x1A, 1536},
83 {0x3D, 1536}, {0x3E, 1792}, {0x1B, 1920}, {0x3F, 2048},
84 {0x1C, 2304}, {0x1D, 2560}, {0x1E, 3072}, {0x1F, 3840},
90 #define ERR_ARB_LOST -3
95 static inline int wait_till_busy(unsigned int base)
99 while(((readw(base + I2C_I2SR) & I2C_I2SR_IBB) == 0) && (--i > 0)) {
100 if (readw(base + I2C_I2SR) & I2C_I2SR_IAL) {
101 diag_printf1("Error: arbitration lost!\n");
113 static unsigned int g_dev_addr_width, g_dev_data_width;
114 static unsigned char g_dev_value[4];
115 static unsigned int g_i2c_nr = -1;
117 static inline int is_bus_free(unsigned int base)
119 return ((readw(base + I2C_I2SR) & I2C_I2SR_IBB) == 0);
122 #define ASSERT_NO_ARBITRATION_LOST(stat) \
124 if (stat & I2C_I2SR_IAL) { \
125 diag_printf("Error %d: Arbitration lost\n", __LINE__); \
126 return ERR_ARB_LOST; \
130 #define WAIT_RXAK_LOOPS 1000000
132 static inline unsigned short wait_op_done(unsigned int base, int is_tx)
134 volatile unsigned short v;
135 int i = WAIT_RXAK_LOOPS;
137 while ((((v = readw(base + I2C_I2SR)) & I2C_I2SR_IIF) == 0 ||
138 (v & I2C_I2SR_ICF) == 0) && --i > 0) {
139 if (v & I2C_I2SR_IAL) {
140 diag_printf1("Error %d: Arbitration lost\n", __LINE__);
146 diag_printf1("I2C Error: timeout unexpected\n");
150 if (v & I2C_I2SR_IAL) {
151 diag_printf1("Error %d: Arbitration lost\n", __LINE__);
154 if (v & I2C_I2SR_RXAK) {
155 diag_printf1("Error %d: no ack received\n", __LINE__);
163 // For master TX, always expect a RXAK signal to be set!
164 static int tx_byte(unsigned char *data, unsigned int base)
166 diag_printf1("%s(data=0x%02x, base=0x%x)\n", __FUNCTION__, *data, base);
168 // clear both IAL and IIF bits
169 writew(0, base + I2C_I2SR);
171 writew(*data, base + I2C_I2DR);
173 if (wait_op_done(base, 1) != 0)
180 static int rx_bytes(unsigned char *data, unsigned int base, int sz)
185 for (i = 0; sz > 0; sz--, i++) {
186 if (wait_op_done(base, 0) != 0)
189 // clear both IAL and IIF bits
190 writew(0, base + I2C_I2SR);
192 // the next two if-statements setup for the next read control register value
194 // last byte --> generate STOP
195 i2cr = readw(base + I2C_I2CR);
196 writew(i2cr & ~(I2C_I2CR_MSTA | I2C_I2CR_MTX), base + I2C_I2CR);
199 // 2nd last byte --> set TXAK bit to NOT generate ACK
200 i2cr = readw(base + I2C_I2CR);
201 writew(i2cr | I2C_I2CR_TXAK, base + I2C_I2CR);
204 // read the true data
205 data[i] = readw(base + I2C_I2DR);
206 diag_printf1("OK 0x%02x\n", data[i]);
211 int i2c_xfer(unsigned int i2c_nr, struct mxc_i2c_request *rq, int dir)
213 unsigned int base, reg;
214 unsigned char i, data;
218 if ( rq == NULL || i2c_nr >= i2c_num) {
219 diag_printf("Invalid request or invalid i2c port number\n");
223 base = i2c_base_addr[i2c_nr];
224 if (rq->reg_addr_sz == 0 || rq->buffer_sz == 0 || rq->buffer == NULL) {
225 diag_printf("Invalid register address size=%x, buffer size=%x, buffer=%x\n",
226 rq->reg_addr_sz, rq->buffer_sz, (unsigned int)rq->buffer);
230 // reset and enable I2C
231 writew(0, base + I2C_I2CR);
233 writew(I2C_I2CR_IEN, base + I2C_I2CR);
235 /* Need wait at least 2 cycles of per_clk*/
236 for (i = 0; i < 16; i++) {
239 // Step 1: generate START signal
240 // 1.1 make sure bus is free
241 if (!is_bus_free(base)) {
244 // 1.2 clear both IAL and IIF bits
245 writew(0, base + I2C_I2SR);
247 // 1.3 assert START signal and also indicate TX mode
248 i2cr = I2C_I2CR_IEN | I2C_I2CR_MSTA | I2C_I2CR_MTX;
249 writew(i2cr, base + I2C_I2CR);
251 // 1.4 make sure bus is busy after the START signal
252 if (wait_till_busy(base) != 0) {
256 // Step 2: send slave address + read/write at the LSB
257 data = (rq->dev_addr << 1) | I2C_WRITE;
258 if (tx_byte(&data, base) != 0) {
262 // Step 3: send I2C device register address
263 if (rq->reg_addr_sz > 4) {
264 diag_printf("Warning register address size %d should less than 4\n",
270 for (i = 0; i < rq->reg_addr_sz; i++, reg>>=8) {
272 diag_printf1("sending I2C=0x%x device register: data=0x%x, byte %d\n",
274 if (tx_byte(&data, base) != 0) {
278 // Step 4: read/write data
279 if (dir == I2C_READ) {
281 i2cr = readw(base + I2C_I2CR);
282 writew(i2cr | I2C_I2CR_RSTA, base + I2C_I2CR);
284 // send slave address again, but indicate read operation
285 data = (rq->dev_addr << 1) | I2C_READ;
286 if (tx_byte(&data, base) != 0) {
290 // change to receive mode
291 i2cr = readw(base + I2C_I2CR);
292 if (rq->buffer_sz == 1) {
293 // if only one byte to read, make sure don't send ack
294 i2cr |= I2C_I2CR_TXAK;
296 writew(i2cr & ~I2C_I2CR_MTX, base + I2C_I2CR);
298 readw(base + I2C_I2DR);
301 if (rx_bytes(rq->buffer, base, rq->buffer_sz) != 0) {
306 for (i = 0; i < rq->buffer_sz; i++) {
307 // send device register value
308 data = rq->buffer[i];
309 if ((ret = tx_byte(&data, base)) != 0) {
313 // generate STOP by clearing MSTA bit
314 writew(I2C_I2CR_IEN | I2C_I2CR_MTX, base + I2C_I2CR);
321 * Initialize and enable a i2c module -- mainly enable the I2C clock, module
322 * itself and the I2C clock prescaler.
324 * @param base base address of i2c module (also assigned for I2Cx_CLK)
325 * @param baue the desired data rate
327 * @return 0 if successful; non-zero otherwise
329 int i2c_init(unsigned int base, unsigned int baud)
331 unsigned int clock = get_main_clock(IPG_PER_CLK);
332 int div = clock / baud;
333 struct clk_div_table *p = (struct clk_div_table *)&i2c_clk_table[0];
337 // reset and enable I2C
338 writew(0, base + I2C_I2CR);
339 writew(I2C_I2CR_IEN, base + I2C_I2CR);
341 while (p->div != 0) {
348 diag_printf("Error: can't meet I2C baud rate request (%d) for 0x%x)\n",
353 diag_printf1("baud=%d, div=%d, reg_val=%d\n", baud, p->div, p->reg_value);
355 writew(p->reg_value, base + I2C_IFDR);
357 diag_printf1("requested data rate is: %d, actual rate is: %d\n",
358 baud, clock / p->div);
363 static void do_i2c(int argc, char *argv[]);
365 "i2c R/W operations as master",
366 "<i2c slave addr> <register index> [<regisetr val>]]",
371 static void do_i2c(int argc,char *argv[])
373 int dir = I2C_READ, i;
375 unsigned long dev_addr, dev_reg;
376 struct mxc_i2c_request rq;
378 if (g_i2c_nr == -1) {
379 diag_printf("I2C module [%d] not initialized. Issue i2c_init first\n\n", g_i2c_nr);
383 diag_printf("\tRead: i2c <i2c_dev_addr> <dev_reg_addr>\n");
384 diag_printf("\tWrite: i2c <i2c_dev_addr> <dev_reg_addr> <dev_reg_val>\n");
388 if (!parse_num(argv[1], &dev_addr, &argv[1], ":")) {
389 diag_printf("Error: Invalid parameter %d\n", __LINE__);
393 if (!parse_num(argv[2], &dev_reg, &argv[2], ":")) {
394 diag_printf("Error: Invalid parameter %d\n", __LINE__);
399 if (!parse_num(argv[3], &v, &argv[3], ":")) {
400 diag_printf("Error: Invalid parameter\n");
404 diag_printf("Writing I2C[%d] for addr 0x%x register 0x%x with value 0x%08lx\n",
405 g_i2c_nr, dev_addr, dev_reg, v);
406 for (i = 0; i < g_dev_data_width; i++) {
407 g_dev_value[i] = v >> (8 * (g_dev_data_width - i - 1)) & 0xff;
409 diag_printf1("testing reversed data: 0x%08x\n", *(unsigned int*)g_dev_value);
412 diag_printf("Reading I2C [%d] from slave addr [0x%x] register [0x%x]\n",
413 g_i2c_nr, dev_addr, dev_reg);
416 rq.dev_addr = dev_addr;
417 rq.reg_addr = dev_reg;
418 rq.reg_addr_sz = g_dev_addr_width;
419 rq.buffer = g_dev_value;
420 rq.buffer_sz = g_dev_data_width;
422 if (i2c_xfer(g_i2c_nr, &rq, dir) != 0) {
423 diag_printf("Error I2C transfer 1\n\n");
427 if (dir == I2C_READ) {
428 diag_printf("---> ");
429 for (i = 0; i < g_dev_data_width; i++) {
430 diag_printf("0x%02x ", g_dev_value[i]);
436 static void do_i2c_init(int argc, char *argv[]);
437 RedBoot_cmd("i2c_init",
438 "Initialize i2c (i2c_num is 0-indexed)",
439 "<i2c_num> <frequency> <device addr width> <device reg width>",
443 static void do_i2c_init(int argc, char *argv[])
447 if (argc == 1 || argc != 5) {
448 diag_printf("\ni2c_init <i2c_num> <frequency> <device addr width> <device data width>\n\n");
452 if (!parse_num(argv[1], (unsigned long *)&g_i2c_nr, &argv[1], ":")) {
453 diag_printf("Error: Invalid parameter\n");
457 if (g_i2c_nr > i2c_num - 1) {
458 diag_printf("invalide i2c number: %d, max number is: %d\n", g_i2c_nr, i2c_num - 1);
461 diag_printf1("i2c max number is: %d\n", i2c_num - 1);
463 if (!parse_num(argv[2], (unsigned long *)&freq, &argv[2], ":")) {
464 diag_printf("Error: Invalid parameter\n");
467 if (!parse_num(argv[3], (unsigned long *)&g_dev_addr_width, &argv[3], ":")) {
468 diag_printf("Error: Invalid parameter\n");
471 if (!parse_num(argv[4], (unsigned long *)&g_dev_data_width, &argv[4], ":")) {
472 diag_printf("Error: Invalid parameter\n");
476 i2c_init(i2c_base_addr[g_i2c_nr], freq);
478 diag_printf("initializing i2c:%d, addr-width:%d, data-width:%d\n\n",
479 g_i2c_nr, g_dev_addr_width, g_dev_data_width);