blob: 573f31f9570e184006f2012d0c852346cfc4b78c [file] [log] [blame]
wdenkaffae2b2002-08-17 09:36:01 +00001#include <common.h>
2#include <mpc8xx.h>
3#include <malloc.h>
4#include <galileo/gt64260R.h>
5#include <galileo/core.h>
6
7#define MAX_I2C_RETRYS 10
8#define I2C_DELAY 1000 /* Should be at least the # of MHz of Tclk */
9#undef DEBUG_I2C
10
11#ifdef DEBUG_I2C
12#define DP(x) x
13#else
14#define DP(x)
15#endif
16
17/* Assuming that there is only one master on the bus (us) */
18
19static void
20i2c_init(int speed, int slaveaddr)
21{
22 unsigned int n, m, freq, margin, power;
Wolfgang Denkfecf63e2011-11-09 09:28:55 +000023 unsigned int actualFreq, actualN = 0, actualM = 0;
wdenkaffae2b2002-08-17 09:36:01 +000024 unsigned int control, status;
25 unsigned int minMargin = 0xffffffff;
26 unsigned int tclk = 125000000;
27
28 DP(puts("i2c_init\n"));
29
Wolfgang Denkfecf63e2011-11-09 09:28:55 +000030 for (n = 0 ; n < 8 ; n++) {
31 for (m = 0 ; m < 16 ; m++) {
wdenkaffae2b2002-08-17 09:36:01 +000032 power = 2<<n; /* power = 2^(n+1) */
33 freq = tclk/(10*(m+1)*power);
34 if (speed > freq)
35 margin = speed - freq;
36 else
37 margin = freq - speed;
Wolfgang Denkfecf63e2011-11-09 09:28:55 +000038 if (margin < minMargin) {
wdenkaffae2b2002-08-17 09:36:01 +000039 minMargin = margin;
40 actualFreq = freq;
41 actualN = n;
42 actualM = m;
43 }
44 }
45 }
46
47 DP(puts("setup i2c bus\n"));
48
49 /* Setup bus */
50
51 GT_REG_WRITE(I2C_SOFT_RESET, 0);
52
53 DP(puts("udelay...\n"));
54
55 udelay(I2C_DELAY);
56
57 DP(puts("set baudrate\n"));
58
59 GT_REG_WRITE(I2C_STATUS_BAUDE_RATE, (actualM << 3) | actualN);
60 GT_REG_WRITE(I2C_CONTROL, (0x1 << 2) | (0x1 << 6));
61
62 udelay(I2C_DELAY * 10);
63
64 DP(puts("read control, baudrate\n"));
65
66 GT_REG_READ(I2C_STATUS_BAUDE_RATE, &status);
67 GT_REG_READ(I2C_CONTROL, &control);
68}
69
70static uchar
71i2c_start(void)
72{
73 unsigned int control, status;
74 int count = 0;
75
76 DP(puts("i2c_start\n"));
77
78 /* Set the start bit */
79
80 GT_REG_READ(I2C_CONTROL, &control);
81 control |= (0x1 << 5);
82 GT_REG_WRITE(I2C_CONTROL, control);
83
84 GT_REG_READ(I2C_STATUS_BAUDE_RATE, &status);
85
86 count = 0;
87 while ((status & 0xff) != 0x08) {
88 udelay(I2C_DELAY);
89 if (count > 20) {
90 GT_REG_WRITE(I2C_CONTROL, (0x1 << 4)); /*stop*/
Wolfgang Denkfecf63e2011-11-09 09:28:55 +000091 return status;
wdenkaffae2b2002-08-17 09:36:01 +000092 }
93 GT_REG_READ(I2C_STATUS_BAUDE_RATE, &status);
94 count++;
95 }
96
Wolfgang Denkfecf63e2011-11-09 09:28:55 +000097 return 0;
wdenkaffae2b2002-08-17 09:36:01 +000098}
99
100static uchar
101i2c_select_device(uchar dev_addr, uchar read, int ten_bit)
102{
103 unsigned int status, data, bits = 7;
104 int count = 0;
105
106 DP(puts("i2c_select_device\n"));
107
108 /* Output slave address */
109
Wolfgang Denkfecf63e2011-11-09 09:28:55 +0000110 if (ten_bit)
wdenkaffae2b2002-08-17 09:36:01 +0000111 bits = 10;
wdenkaffae2b2002-08-17 09:36:01 +0000112
113 data = (dev_addr << 1);
114 /* set the read bit */
115 data |= read;
116 GT_REG_WRITE(I2C_DATA, data);
117 /* assert the address */
118 RESET_REG_BITS(I2C_CONTROL, BIT3);
119
120 udelay(I2C_DELAY);
121
122 GT_REG_READ(I2C_STATUS_BAUDE_RATE, &status);
123 count = 0;
124 while (((status & 0xff) != 0x40) && ((status & 0xff) != 0x18)) {
125 udelay(I2C_DELAY);
126 if (count > 20) {
127 GT_REG_WRITE(I2C_CONTROL, (0x1 << 4)); /*stop*/
Wolfgang Denkfecf63e2011-11-09 09:28:55 +0000128 return status;
wdenkaffae2b2002-08-17 09:36:01 +0000129 }
130 GT_REG_READ(I2C_STATUS_BAUDE_RATE, &status);
131 count++;
132 }
133
134 if (bits == 10) {
135 printf("10 bit I2C addressing not yet implemented\n");
Wolfgang Denkfecf63e2011-11-09 09:28:55 +0000136 return 0xff;
wdenkaffae2b2002-08-17 09:36:01 +0000137 }
138
Wolfgang Denkfecf63e2011-11-09 09:28:55 +0000139 return 0;
wdenkaffae2b2002-08-17 09:36:01 +0000140}
141
142static uchar
Wolfgang Denkfecf63e2011-11-09 09:28:55 +0000143i2c_get_data(uchar *return_data, int len) {
wdenkaffae2b2002-08-17 09:36:01 +0000144
Wolfgang Denk77ddac92005-10-13 16:45:02 +0200145 unsigned int data, status = 0;
wdenkaffae2b2002-08-17 09:36:01 +0000146 int count = 0;
147
148 DP(puts("i2c_get_data\n"));
149
150 while (len) {
151
152 /* Get and return the data */
153
154 RESET_REG_BITS(I2C_CONTROL, (0x1 << 3));
155
156 udelay(I2C_DELAY * 5);
157
158 GT_REG_READ(I2C_STATUS_BAUDE_RATE, &status);
159 count++;
160 while ((status & 0xff) != 0x50) {
161 udelay(I2C_DELAY);
Wolfgang Denkfecf63e2011-11-09 09:28:55 +0000162 if (count > 2) {
wdenkaffae2b2002-08-17 09:36:01 +0000163 GT_REG_WRITE(I2C_CONTROL, (0x1 << 4)); /*stop*/
164 return 0;
165 }
166 GT_REG_READ(I2C_STATUS_BAUDE_RATE, &status);
167 count++;
168 }
169 GT_REG_READ(I2C_DATA, &data);
170 len--;
171 *return_data = (uchar)data;
172 return_data++;
173 }
174 RESET_REG_BITS(I2C_CONTROL, BIT2|BIT3);
175 while ((status & 0xff) != 0x58) {
176 udelay(I2C_DELAY);
Wolfgang Denkfecf63e2011-11-09 09:28:55 +0000177 if (count > 200) {
wdenkaffae2b2002-08-17 09:36:01 +0000178 GT_REG_WRITE(I2C_CONTROL, (0x1 << 4)); /*stop*/
Wolfgang Denkfecf63e2011-11-09 09:28:55 +0000179 return status;
wdenkaffae2b2002-08-17 09:36:01 +0000180 }
181 GT_REG_READ(I2C_STATUS_BAUDE_RATE, &status);
182 count++;
183 }
184 GT_REG_WRITE(I2C_CONTROL, (0x1 << 4)); /* stop */
185
Wolfgang Denkfecf63e2011-11-09 09:28:55 +0000186 return 0;
wdenkaffae2b2002-08-17 09:36:01 +0000187}
188
189static uchar
190i2c_write_data(unsigned int data, int len)
191{
192 unsigned int status;
193 int count = 0;
194
195 DP(puts("i2c_write_data\n"));
196
197 if (len > 4)
198 return -1;
199
200 while (len) {
201 /* Set and assert the data */
202
203 GT_REG_WRITE(I2C_DATA, (unsigned int)data);
204 RESET_REG_BITS(I2C_CONTROL, (0x1 << 3));
205
206 udelay(I2C_DELAY);
207
208 GT_REG_READ(I2C_STATUS_BAUDE_RATE, &status);
209 count++;
210 while ((status & 0xff) != 0x28) {
211 udelay(I2C_DELAY);
Wolfgang Denkfecf63e2011-11-09 09:28:55 +0000212 if (count > 20) {
wdenkaffae2b2002-08-17 09:36:01 +0000213 GT_REG_WRITE(I2C_CONTROL, (0x1 << 4)); /*stop*/
Wolfgang Denkfecf63e2011-11-09 09:28:55 +0000214 return status;
wdenkaffae2b2002-08-17 09:36:01 +0000215 }
216 GT_REG_READ(I2C_STATUS_BAUDE_RATE, &status);
217 count++;
218 }
219 len--;
220 }
221 GT_REG_WRITE(I2C_CONTROL, (0x1 << 3) | (0x1 << 4));
222 GT_REG_WRITE(I2C_CONTROL, (0x1 << 4));
223
224 udelay(I2C_DELAY * 10);
225
Wolfgang Denkfecf63e2011-11-09 09:28:55 +0000226 return 0;
wdenkaffae2b2002-08-17 09:36:01 +0000227}
228
229static uchar
230i2c_set_dev_offset(uchar dev_addr, unsigned int offset, int ten_bit)
231{
232 uchar status;
233
234 DP(puts("i2c_set_dev_offset\n"));
235
236 status = i2c_select_device(dev_addr, 0, ten_bit);
237 if (status) {
238#ifdef DEBUG_I2C
239 printf("Failed to select device setting offset: 0x%02x\n",
240 status);
241#endif
242 return status;
243 }
244
245 status = i2c_write_data(offset, 1);
246 if (status) {
247#ifdef DEBUG_I2C
248 printf("Failed to write data: 0x%02x\n", status);
249#endif
250 return status;
251 }
252
Wolfgang Denkfecf63e2011-11-09 09:28:55 +0000253 return 0;
wdenkaffae2b2002-08-17 09:36:01 +0000254}
255
256uchar
Wolfgang Denkfecf63e2011-11-09 09:28:55 +0000257i2c_read(uchar dev_addr, unsigned int offset, int len, uchar *data,
wdenkaffae2b2002-08-17 09:36:01 +0000258 int ten_bit)
259{
260 uchar status = 0;
261 unsigned int i2cFreq = 400000;
262
263 DP(puts("i2c_read\n"));
264
Wolfgang Denkfecf63e2011-11-09 09:28:55 +0000265 i2c_init(i2cFreq, 0);
wdenkaffae2b2002-08-17 09:36:01 +0000266
267 status = i2c_start();
268
269 if (status) {
270#ifdef DEBUG_I2C
271 printf("Transaction start failed: 0x%02x\n", status);
272#endif
273 return status;
274 }
275
276 status = i2c_set_dev_offset(dev_addr, 0, 0);
277 if (status) {
278#ifdef DEBUG_I2C
279 printf("Failed to set offset: 0x%02x\n", status);
280#endif
281 return status;
282 }
283
Wolfgang Denkfecf63e2011-11-09 09:28:55 +0000284 i2c_init(i2cFreq, 0);
wdenkaffae2b2002-08-17 09:36:01 +0000285
286 status = i2c_start();
287 if (status) {
288#ifdef DEBUG_I2C
289 printf("Transaction restart failed: 0x%02x\n", status);
290#endif
291 return status;
292 }
293
294 status = i2c_select_device(dev_addr, 1, ten_bit);
295 if (status) {
296#ifdef DEBUG_I2C
297 printf("Address not acknowledged: 0x%02x\n", status);
298#endif
299 return status;
300 }
301
302 status = i2c_get_data(data, len);
303 if (status) {
304#ifdef DEBUG_I2C
Mike Williams16263082011-07-22 04:01:30 +0000305 printf("Data not received: 0x%02x\n", status);
wdenkaffae2b2002-08-17 09:36:01 +0000306#endif
307 return status;
308 }
309
310 return 0;
311}