]> git.kernelconcepts.de Git - karo-tx-redboot.git/blob - packages/devs/i2c/arm/mxc/v2_0/src/mxc_i2c.c
Merge branch 'master' of git+ssh://git.kernelconcepts.de/karo-tx-redboot
[karo-tx-redboot.git] / packages / devs / i2c / arm / mxc / v2_0 / src / mxc_i2c.c
1 //==========================================================================
2 //
3 //      mxc_i2c.c
4 //
5 //      I2C support on Freescale MXC platforms
6 //
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.
12 //
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.
16 //
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
20 // for more details.
21 //
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.
25 //
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.
32 //
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.
35 //
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>
42 #ifdef CYGPKG_REDBOOT
43 #include <redboot.h>
44 #endif
45 #include <stdlib.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>
50
51 #ifdef CYGBLD_HAL_PLF_DEFS_H
52 #include CYGBLD_HAL_PLF_DEFS_H
53 #else
54 #include <cyg/hal/fsl_board.h>
55 #endif
56 #include <cyg/io/mxc_i2c.h>
57
58 extern void mxc_i2c_init(unsigned int module_base);
59
60 //#define MXC_I2C_DEBUG
61 #undef MXC_I2C_DEBUG
62
63 #ifdef MXC_I2C_DEBUG
64 #define diag_printf1    diag_printf
65 #else
66 #define diag_printf1(fmt,args...)
67 #endif
68
69 struct clk_div_table {
70         int reg_value;
71         int div;
72 };
73
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},
91         {0, 0}
92 };
93
94 #define ERR_TX                  (-1)
95 #define ERR_RX                  (-2)
96 #define ERR_ARB_LOST    (-3)
97 #define ERR_NO_ACK              (-4)
98 #define ERR_XFER                (-5)
99 #define ERR_RX_ACK              (-6)
100
101 static inline int wait_till_busy(unsigned int base)
102 {
103         int i = 10000;
104
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");
108                         return ERR_ARB_LOST;
109                 }
110         }
111
112         if (i <= 0) {
113                 return -1;
114         }
115
116         return 0;
117 }
118
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;
122
123 static inline int is_bus_free(unsigned int base)
124 {
125         return ((readw(base + I2C_I2SR) & I2C_I2SR_IBB) == 0);
126 }
127
128 #define ASSERT_NO_ARBITRATION_LOST(stat)                                                        \
129         {                                                                                                                               \
130                 if (stat & I2C_I2SR_IAL) {                                                                      \
131                         diag_printf("Error %d: Arbitration lost\n", __LINE__);  \
132                         return ERR_ARB_LOST;                                                                    \
133                 }                                                                                                                       \
134         }
135
136 #define WAIT_RXAK_LOOPS         1000000
137
138 static inline unsigned short wait_op_done(unsigned int base, int is_tx)
139 {
140         volatile unsigned short v;
141         int i = WAIT_RXAK_LOOPS;
142
143         while ((((v = readw(base + I2C_I2SR)) & I2C_I2SR_IIF) == 0) && (--i > 0));
144
145         if (i <= 0) {
146                 diag_printf1("I2C Error: timeout unexpected\n");
147                 return -1;
148         }
149
150         writew(0x0, base + I2C_I2SR);
151         if (v & I2C_I2SR_IAL) {
152                 diag_printf1("Error %d: Arbitration lost\n", __LINE__);
153                 return ERR_ARB_LOST;
154         }
155
156         if (is_tx) {
157                 if (v & I2C_I2SR_RXAK) {
158                         diag_printf1("Error %d: no ack received\n", __LINE__);
159                         return -1;
160                 }
161         }
162         return 0;
163 }
164
165 //
166 // For master TX, always expect a RXAK signal to be set!
167 static int tx_byte(unsigned char *data, unsigned int base)
168 {
169         diag_printf1("%s(data=0x%02x, base=0x%x)\n", __FUNCTION__, *data, base);
170
171         // clear both IAL and IIF bits
172         writew(0, base + I2C_I2SR);
173
174         writew(*data, base + I2C_I2DR);
175
176         if (wait_op_done(base, 1) != 0)
177                 return -1;
178
179         return 0;
180 }
181
182 // For master RX
183 static int rx_bytes(unsigned char *data, unsigned int base, int sz)
184 {
185         unsigned short i2cr;
186         int i;
187
188         for (i = 0; sz > 0; sz--, i++) {
189                 if (wait_op_done(base, 0) != 0)
190                         return -1;
191
192                 // the next two if-statements setup for the next read control register value
193                 if (sz == 1) {
194                         // last byte --> generate STOP
195                         i2cr = readw(base + I2C_I2CR);
196                         writew(i2cr & ~(I2C_I2CR_MSTA | I2C_I2CR_MTX), base + I2C_I2CR);
197                 }
198                 if (sz == 2) {
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);
202                 }
203
204                 // read the true data
205                 data[i] = readw(base + I2C_I2DR);
206                 diag_printf1("OK 0x%02x\n", data[i]);
207         }
208         return 0;
209 }
210
211 int i2c_xfer(unsigned int i2c_nr, struct mxc_i2c_request *rq, int dir)
212 {
213         unsigned int base, reg;
214         unsigned char i, data;
215         unsigned short i2cr;
216         int ret = 0;
217
218         if ( rq == NULL || i2c_nr >= i2c_num) {
219                 diag_printf("Invalid request or invalid i2c port number\n");
220                 return -1;
221         }
222
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);
227                 return -1;
228         }
229
230         // reset and enable I2C
231         writew(0, base + I2C_I2CR);
232
233         writew(I2C_I2CR_IEN, base + I2C_I2CR);
234
235         /* Need wait at least 2 cycles of per_clk*/
236         hal_delay_us(5000);
237         // Step 1: generate START signal
238         // 1.1 make sure bus is free
239         if (!is_bus_free(base)) {
240                 return -1;
241         }
242         // 1.2 clear both IAL and IIF bits
243         writew(0, base + I2C_I2SR);
244
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);
248
249         // 1.4 make sure bus is busy after the START signal
250         if (wait_till_busy(base) != 0) {
251                 return ERR_TX;
252         }
253
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) {
257                 return -1;
258         }
259
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",
263                                         rq->reg_addr_sz);
264                 rq->reg_addr_sz = 4;
265         }
266         reg = rq->reg_addr;
267
268         for (i = 0; i <  rq->reg_addr_sz; i++, reg>>=8) {
269                 data = reg & 0xFF;
270                 diag_printf1("sending I2C=0x%x device register: data=0x%x, byte %d\n",
271                                         base, data, i);
272                 if (tx_byte(&data, base) != 0) {
273                         return -1;
274                 }
275         }
276         // Step 4: read/write data
277         if (dir == I2C_READ) {
278                 // do repeat-start
279                 i2cr = readw(base + I2C_I2CR);
280                 writew(i2cr | I2C_I2CR_RSTA, base + I2C_I2CR);
281
282                 // make sure bus is busy after the repeat-start signal
283                 if (wait_till_busy(base) != 0) {
284                         return ERR_TX;
285                 }
286                 // send slave address again, but indicate read operation
287                 data = (rq->dev_addr << 1) | I2C_READ;
288                 if (tx_byte(&data, base) != 0) {
289                         return -1;
290                 }
291
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;
297                 }
298                 writew(i2cr & ~I2C_I2CR_MTX, base + I2C_I2CR);
299                 // dummy read
300                 readw(base + I2C_I2DR);
301
302                 // now reading ...
303                 if (rx_bytes(rq->buffer, base, rq->buffer_sz) != 0) {
304                         return -1;
305                 }
306         } else {
307                 // I2C_WRITE
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) {
312                                 break;
313                         }
314                 }
315                 // generate STOP by clearing MSTA bit
316                 writew(I2C_I2CR_IEN | I2C_I2CR_MTX, base + I2C_I2CR);
317         }
318
319         return ret;
320 }
321
322 /*!
323  * Initialize and enable a i2c module -- mainly enable the I2C clock, module
324  * itself and the I2C clock prescaler.
325  *
326  * @param   base        base address of i2c module (also assigned for I2Cx_CLK)
327  * @param   baue        the desired data rate
328  *
329  * @return              0 if successful; non-zero otherwise
330  */
331 int i2c_init(unsigned int base, unsigned int baud)
332 {
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];
336
337         mxc_i2c_init(base);
338
339         // reset and enable I2C
340         writew(0, base + I2C_I2CR);
341         writew(I2C_I2CR_IEN, base + I2C_I2CR);
342
343         while (p->div != 0) {
344                 if (div <= p->div)
345                         break;
346                 p++;
347         }
348
349         if (p->div == 0) {
350                 diag_printf("Error: can't meet I2C baud rate request (%d) for 0x%x)\n",
351                                         baud, base);
352                 return -1;
353         }
354
355         diag_printf1("baud=%d, div=%d, reg_val=%d\n", baud, p->div, p->reg_value);
356
357         writew(p->reg_value, base + I2C_IFDR);
358
359         diag_printf1("requested data rate is: %d, actual rate is: %d\n",
360                                 baud, clock / p->div);
361
362         return 0;
363 }
364
365 #ifdef CYGPKG_REDBOOT
366 static void do_i2c(int argc, char *argv[]);
367 RedBoot_cmd("i2c",
368                         "i2c R/W operations as master",
369                         "<i2c slave addr> <register index> [<regisetr val>]]",
370                         do_i2c
371         );
372
373
374 static void do_i2c(int argc,char *argv[])
375 {
376         int dir = I2C_READ, i;
377         unsigned long v;
378         unsigned int dev_addr, dev_reg;
379         struct mxc_i2c_request rq;
380
381         if (g_i2c_nr == -1) {
382                 diag_printf("I2C module [%d] not initialized. Issue i2c_init first\n\n", g_i2c_nr);
383                 return;
384         }
385         if (argc == 1) {
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");
388                 return;
389         }
390
391         if (!parse_num(*(&argv[1]), (unsigned long *)&dev_addr, &argv[1], ":")) {
392                 diag_printf("Error: Invalid parameter %d\n", __LINE__);
393                 return;
394         }
395
396         if (!parse_num(*(&argv[2]), (unsigned long *)&dev_reg, &argv[2], ":")) {
397                 diag_printf("Error: Invalid parameter %d\n", __LINE__);
398                 return;
399         }
400
401         if (argc == 4) {
402                 if (!parse_num(*(&argv[3]), &v, &argv[3], ":")) {
403                         diag_printf("Error: Invalid parameter\n");
404                         return;
405                 }
406                 dir = I2C_WRITE;
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;
411                 }
412                 diag_printf1("testing reversed data: 0x%08x\n", *(unsigned int*)g_dev_value);
413
414         } else {
415                 diag_printf("Reading I2C [%d] from slave addr [0x%x] register [0x%x]\n",
416                                         g_i2c_nr, dev_addr,  dev_reg);
417         }
418
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;
424
425         if (i2c_xfer(g_i2c_nr, &rq, dir) != 0) {
426                 diag_printf("Error I2C transfer 1\n\n");
427                 return;
428         }
429
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]);
434                 }
435                 diag_printf("\n\n");
436         }
437 }
438
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>",
443                         do_i2c_init
444         );
445
446 static void do_i2c_init(int argc,char *argv[])
447 {
448         unsigned freq;
449
450         if (argc == 1 || argc != 5) {
451                 diag_printf("\ni2c_init <i2c_num> <frequency> <device addr width> <device data width>\n\n");
452                 return;
453         }
454
455         if (!parse_num(*(&argv[1]), (unsigned long *)&g_i2c_nr, &argv[1], ":")) {
456                 diag_printf("Error: Invalid parameter\n");
457                 return;
458         }
459
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);
462                 return;
463         }
464         diag_printf1("i2c max number is: %d\n", i2c_num - 1);
465
466         if (!parse_num(*(&argv[2]), (unsigned long *)&freq, &argv[2], ":")) {
467                 diag_printf("Error: Invalid parameter\n");
468                 return;
469         }
470         if (!parse_num(*(&argv[3]), (unsigned long *)&g_dev_addr_width, &argv[3], ":")) {
471                 diag_printf("Error: Invalid parameter\n");
472                 return;
473         }
474         if (!parse_num(*(&argv[4]), (unsigned long *)&g_dev_data_width, &argv[4], ":")) {
475                 diag_printf("Error: Invalid parameter\n");
476                 return;
477         }
478
479         i2c_init(i2c_base_addr[g_i2c_nr], freq);
480
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);
483 }
484 #endif