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 //==========================================================================
41 #include <pkgconf/system.h>
46 #include <pkgconf/hal.h>
47 #include <cyg/hal/hal_arch.h>
48 #include <cyg/hal/hal_cache.h>
49 #include <cyg/hal/hal_io.h>
51 #ifdef CYGBLD_HAL_PLF_DEFS_H
52 #include CYGBLD_HAL_PLF_DEFS_H
54 #include <cyg/hal/fsl_board.h>
56 #include <cyg/io/mxc_i2c.h>
58 extern void mxc_i2c_init(unsigned int module_base);
60 //#define MXC_I2C_DEBUG
64 #define diag_printf1 diag_printf
66 #define diag_printf1(fmt,args...)
69 struct clk_div_table {
74 static const struct clk_div_table i2c_clk_table[] = {
75 {0x20, 22}, {0x21, 24}, {0x22, 26}, {0x23, 28},
76 {0, 30}, {1, 32}, {0x24, 32}, {2, 36},
77 {0x25, 36}, {0x26, 40}, {3, 42}, {0x27, 44},
78 {4, 48}, {0x28, 48}, {5, 52}, {0x29, 56},
79 {6, 60}, {0x2A, 64}, {7, 72}, {0x2B, 72},
80 {8, 80}, {0x2C, 80}, {9, 88}, {0x2D, 96},
81 {0xA, 104}, {0x2E, 112}, {0xB, 128}, {0x2F, 128},
82 {0xC, 144}, {0xD, 160}, {0x30, 160}, {0xE, 192},
83 {0x31, 192}, {0x32, 224}, {0xF, 240}, {0x33, 256},
84 {0x10, 288}, {0x11, 320}, {0x34, 320}, {0x12, 384},
85 {0x35, 384}, {0x36, 448}, {0x13, 480}, {0x37, 512},
86 {0x14, 576}, {0x15, 640}, {0x38, 640}, {0x16, 768},
87 {0x39, 768}, {0x3A, 896}, {0x17, 960}, {0x3B, 1024},
88 {0x18, 1152}, {0x19, 1280}, {0x3C, 1280}, {0x1A, 1536},
89 {0x3D, 1536}, {0x3E, 1792}, {0x1B, 1920}, {0x3F, 2048},
90 {0x1C, 2304}, {0x1D, 2560}, {0x1E, 3072}, {0x1F, 3840},
96 #define ERR_ARB_LOST (-3)
97 #define ERR_NO_ACK (-4)
99 #define ERR_RX_ACK (-6)
101 static inline int wait_till_busy(unsigned int base)
105 while(((readw(base + I2C_I2SR) & I2C_I2SR_IBB) == 0) && (--i > 0)) {
106 if (readw(base + I2C_I2SR) & I2C_I2SR_IAL) {
107 diag_printf1("Error: arbitration lost!\n");
119 static unsigned int g_dev_addr_width, g_dev_data_width;
120 static unsigned char g_dev_value[4];
121 static unsigned int g_i2c_nr = -1;
123 static inline int is_bus_free(unsigned int base)
125 return ((readw(base + I2C_I2SR) & I2C_I2SR_IBB) == 0);
128 #define ASSERT_NO_ARBITRATION_LOST(stat) \
130 if (stat & I2C_I2SR_IAL) { \
131 diag_printf("Error %d: Arbitration lost\n", __LINE__); \
132 return ERR_ARB_LOST; \
136 #define WAIT_RXAK_LOOPS 1000000
138 static inline unsigned short wait_op_done(unsigned int base, int is_tx)
140 volatile unsigned short v;
141 int i = WAIT_RXAK_LOOPS;
143 while ((((v = readw(base + I2C_I2SR)) & I2C_I2SR_IIF) == 0) && (--i > 0));
146 diag_printf1("I2C Error: timeout unexpected\n");
150 writew(0x0, base + I2C_I2SR);
151 if (v & I2C_I2SR_IAL) {
152 diag_printf1("Error %d: Arbitration lost\n", __LINE__);
157 if (v & I2C_I2SR_RXAK) {
158 diag_printf1("Error %d: no ack received\n", __LINE__);
166 // For master TX, always expect a RXAK signal to be set!
167 static int tx_byte(unsigned char *data, unsigned int base)
169 diag_printf1("%s(data=0x%02x, base=0x%x)\n", __FUNCTION__, *data, base);
171 // clear both IAL and IIF bits
172 writew(0, base + I2C_I2SR);
174 writew(*data, base + I2C_I2DR);
176 if (wait_op_done(base, 1) != 0)
183 static int rx_bytes(unsigned char *data, unsigned int base, int sz)
188 for (i = 0; sz > 0; sz--, i++) {
189 if (wait_op_done(base, 0) != 0)
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*/
237 // Step 1: generate START signal
238 // 1.1 make sure bus is free
239 if (!is_bus_free(base)) {
242 // 1.2 clear both IAL and IIF bits
243 writew(0, base + I2C_I2SR);
245 // 1.3 assert START signal and also indicate TX mode
246 i2cr = I2C_I2CR_IEN | I2C_I2CR_MSTA | I2C_I2CR_MTX;
247 writew(i2cr, base + I2C_I2CR);
249 // 1.4 make sure bus is busy after the START signal
250 if (wait_till_busy(base) != 0) {
254 // Step 2: send slave address + read/write at the LSB
255 data = (rq->dev_addr << 1) | I2C_WRITE;
256 if (tx_byte(&data, base) != 0) {
260 // Step 3: send I2C device register address
261 if (rq->reg_addr_sz > 4) {
262 diag_printf("Warning register address size %d should less than 4\n",
268 for (i = 0; i < rq->reg_addr_sz; i++, reg>>=8) {
270 diag_printf1("sending I2C=0x%x device register: data=0x%x, byte %d\n",
272 if (tx_byte(&data, base) != 0) {
276 // Step 4: read/write data
277 if (dir == I2C_READ) {
279 i2cr = readw(base + I2C_I2CR);
280 writew(i2cr | I2C_I2CR_RSTA, base + I2C_I2CR);
282 // make sure bus is busy after the repeat-start signal
283 if (wait_till_busy(base) != 0) {
286 // send slave address again, but indicate read operation
287 data = (rq->dev_addr << 1) | I2C_READ;
288 if (tx_byte(&data, base) != 0) {
292 // change to receive mode
293 i2cr = readw(base + I2C_I2CR);
294 if (rq->buffer_sz == 1) {
295 // if only one byte to read, make sure don't send ack
296 i2cr |= I2C_I2CR_TXAK;
298 writew(i2cr & ~I2C_I2CR_MTX, base + I2C_I2CR);
300 readw(base + I2C_I2DR);
303 if (rx_bytes(rq->buffer, base, rq->buffer_sz) != 0) {
308 for (i = 0; i < rq->buffer_sz; i++) {
309 // send device register value
310 data = rq->buffer[i];
311 if ((ret = tx_byte(&data, base)) != 0) {
315 // generate STOP by clearing MSTA bit
316 writew(I2C_I2CR_IEN | I2C_I2CR_MTX, base + I2C_I2CR);
323 * Initialize and enable a i2c module -- mainly enable the I2C clock, module
324 * itself and the I2C clock prescaler.
326 * @param base base address of i2c module (also assigned for I2Cx_CLK)
327 * @param baue the desired data rate
329 * @return 0 if successful; non-zero otherwise
331 int i2c_init(unsigned int base, unsigned int baud)
333 unsigned int clock = get_main_clock(IPG_PER_CLK);
334 int div = clock / baud;
335 struct clk_div_table *p = (struct clk_div_table *)&i2c_clk_table[0];
339 // reset and enable I2C
340 writew(0, base + I2C_I2CR);
341 writew(I2C_I2CR_IEN, base + I2C_I2CR);
343 while (p->div != 0) {
350 diag_printf("Error: can't meet I2C baud rate request (%d) for 0x%x)\n",
355 diag_printf1("baud=%d, div=%d, reg_val=%d\n", baud, p->div, p->reg_value);
357 writew(p->reg_value, base + I2C_IFDR);
359 diag_printf1("requested data rate is: %d, actual rate is: %d\n",
360 baud, clock / p->div);
365 #ifdef CYGPKG_REDBOOT
366 static void do_i2c(int argc, char *argv[]);
368 "i2c R/W operations as master",
369 "<i2c slave addr> <register index> [<regisetr val>]]",
374 static void do_i2c(int argc,char *argv[])
376 int dir = I2C_READ, i;
378 unsigned int dev_addr, dev_reg;
379 struct mxc_i2c_request rq;
381 if (g_i2c_nr == -1) {
382 diag_printf("I2C module [%d] not initialized. Issue i2c_init first\n\n", g_i2c_nr);
386 diag_printf("\tRead: i2c <i2c_dev_addr> <dev_reg_addr>\n");
387 diag_printf("\tWrite: i2c <i2c_dev_addr> <dev_reg_addr> <dev_reg_val>\n");
391 if (!parse_num(*(&argv[1]), (unsigned long *)&dev_addr, &argv[1], ":")) {
392 diag_printf("Error: Invalid parameter %d\n", __LINE__);
396 if (!parse_num(*(&argv[2]), (unsigned long *)&dev_reg, &argv[2], ":")) {
397 diag_printf("Error: Invalid parameter %d\n", __LINE__);
402 if (!parse_num(*(&argv[3]), &v, &argv[3], ":")) {
403 diag_printf("Error: Invalid parameter\n");
407 diag_printf("Writing I2C[%d] for addr 0x%x register 0x%x with value 0x%08lx\n",
408 g_i2c_nr, dev_addr, dev_reg, v);
409 for (i = 0; i < g_dev_data_width; i++) {
410 g_dev_value[i] = v >> (8 * (g_dev_data_width - i - 1)) & 0xff;
412 diag_printf1("testing reversed data: 0x%08x\n", *(unsigned int*)g_dev_value);
415 diag_printf("Reading I2C [%d] from slave addr [0x%x] register [0x%x]\n",
416 g_i2c_nr, dev_addr, dev_reg);
419 rq.dev_addr = dev_addr;
420 rq.reg_addr = dev_reg;
421 rq.reg_addr_sz = g_dev_addr_width;
422 rq.buffer = g_dev_value;
423 rq.buffer_sz = g_dev_data_width;
425 if (i2c_xfer(g_i2c_nr, &rq, dir) != 0) {
426 diag_printf("Error I2C transfer 1\n\n");
430 if (dir == I2C_READ) {
431 diag_printf("---> ");
432 for (i = 0; i < g_dev_data_width; i++) {
433 diag_printf("0x%02x ", g_dev_value[i]);
439 static void do_i2c_init(int argc, char *argv[]);
440 RedBoot_cmd("i2c_init",
441 "Initialize i2c (i2c_num is 0-indexed)",
442 "<i2c_num> <frequency> <device addr width> <device reg width>",
446 static void do_i2c_init(int argc,char *argv[])
450 if (argc == 1 || argc != 5) {
451 diag_printf("\ni2c_init <i2c_num> <frequency> <device addr width> <device data width>\n\n");
455 if (!parse_num(*(&argv[1]), (unsigned long *)&g_i2c_nr, &argv[1], ":")) {
456 diag_printf("Error: Invalid parameter\n");
460 if (g_i2c_nr > i2c_num - 1) {
461 diag_printf("invalide i2c number: %d, max number is: %d\n", g_i2c_nr, i2c_num - 1);
464 diag_printf1("i2c max number is: %d\n", i2c_num - 1);
466 if (!parse_num(*(&argv[2]), (unsigned long *)&freq, &argv[2], ":")) {
467 diag_printf("Error: Invalid parameter\n");
470 if (!parse_num(*(&argv[3]), (unsigned long *)&g_dev_addr_width, &argv[3], ":")) {
471 diag_printf("Error: Invalid parameter\n");
474 if (!parse_num(*(&argv[4]), (unsigned long *)&g_dev_data_width, &argv[4], ":")) {
475 diag_printf("Error: Invalid parameter\n");
479 i2c_init(i2c_base_addr[g_i2c_nr], freq);
481 diag_printf("initializing i2c:%d, addr-width:%d, data-width:%d\n\n",
482 g_i2c_nr, g_dev_addr_width, g_dev_data_width);