blob: 8119fced486926d7d174fdcd18c1d29f016d67e0 [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;
Heiko Schocher7d5ff542011-11-17 07:57:20 +010023 unsigned int actualn = 0, actualm = 0;
wdenkaffae2b2002-08-17 09:36:01 +000024 unsigned int control, status;
Heiko Schocher7d5ff542011-11-17 07:57:20 +010025 unsigned int minmargin = 0xffffffff;
wdenkaffae2b2002-08-17 09:36:01 +000026 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++) {
Heiko Schocher7d5ff542011-11-17 07:57:20 +010032 power = 2 << n; /* power = 2^(n+1) */
33 freq = tclk / (10 * (m + 1) * power);
wdenkaffae2b2002-08-17 09:36:01 +000034 if (speed > freq)
35 margin = speed - freq;
36 else
37 margin = freq - speed;
Heiko Schocher7d5ff542011-11-17 07:57:20 +010038 if (margin < minmargin) {
39 minmargin = margin;
40 actualn = n;
41 actualm = m;
wdenkaffae2b2002-08-17 09:36:01 +000042 }
43 }
44 }
45
46 DP(puts("setup i2c bus\n"));
47
48 /* Setup bus */
49
50 GT_REG_WRITE(I2C_SOFT_RESET, 0);
51
52 DP(puts("udelay...\n"));
53
54 udelay(I2C_DELAY);
55
56 DP(puts("set baudrate\n"));
57
Heiko Schocher7d5ff542011-11-17 07:57:20 +010058 GT_REG_WRITE(I2C_STATUS_BAUDE_RATE, (actualm << 3) | actualn);
wdenkaffae2b2002-08-17 09:36:01 +000059 GT_REG_WRITE(I2C_CONTROL, (0x1 << 2) | (0x1 << 6));
60
61 udelay(I2C_DELAY * 10);
62
63 DP(puts("read control, baudrate\n"));
64
65 GT_REG_READ(I2C_STATUS_BAUDE_RATE, &status);
66 GT_REG_READ(I2C_CONTROL, &control);
67}
68
69static uchar
70i2c_start(void)
71{
72 unsigned int control, status;
73 int count = 0;
74
75 DP(puts("i2c_start\n"));
76
77 /* Set the start bit */
78
79 GT_REG_READ(I2C_CONTROL, &control);
80 control |= (0x1 << 5);
81 GT_REG_WRITE(I2C_CONTROL, control);
82
83 GT_REG_READ(I2C_STATUS_BAUDE_RATE, &status);
84
85 count = 0;
86 while ((status & 0xff) != 0x08) {
87 udelay(I2C_DELAY);
88 if (count > 20) {
89 GT_REG_WRITE(I2C_CONTROL, (0x1 << 4)); /*stop*/
Wolfgang Denkfecf63e2011-11-09 09:28:55 +000090 return status;
wdenkaffae2b2002-08-17 09:36:01 +000091 }
92 GT_REG_READ(I2C_STATUS_BAUDE_RATE, &status);
93 count++;
94 }
95
Wolfgang Denkfecf63e2011-11-09 09:28:55 +000096 return 0;
wdenkaffae2b2002-08-17 09:36:01 +000097}
98
99static uchar
100i2c_select_device(uchar dev_addr, uchar read, int ten_bit)
101{
102 unsigned int status, data, bits = 7;
103 int count = 0;
104
105 DP(puts("i2c_select_device\n"));
106
107 /* Output slave address */
108
Wolfgang Denkfecf63e2011-11-09 09:28:55 +0000109 if (ten_bit)
wdenkaffae2b2002-08-17 09:36:01 +0000110 bits = 10;
wdenkaffae2b2002-08-17 09:36:01 +0000111
112 data = (dev_addr << 1);
113 /* set the read bit */
114 data |= read;
115 GT_REG_WRITE(I2C_DATA, data);
116 /* assert the address */
117 RESET_REG_BITS(I2C_CONTROL, BIT3);
118
119 udelay(I2C_DELAY);
120
121 GT_REG_READ(I2C_STATUS_BAUDE_RATE, &status);
122 count = 0;
123 while (((status & 0xff) != 0x40) && ((status & 0xff) != 0x18)) {
124 udelay(I2C_DELAY);
125 if (count > 20) {
126 GT_REG_WRITE(I2C_CONTROL, (0x1 << 4)); /*stop*/
Wolfgang Denkfecf63e2011-11-09 09:28:55 +0000127 return status;
wdenkaffae2b2002-08-17 09:36:01 +0000128 }
129 GT_REG_READ(I2C_STATUS_BAUDE_RATE, &status);
130 count++;
131 }
132
133 if (bits == 10) {
134 printf("10 bit I2C addressing not yet implemented\n");
Wolfgang Denkfecf63e2011-11-09 09:28:55 +0000135 return 0xff;
wdenkaffae2b2002-08-17 09:36:01 +0000136 }
137
Wolfgang Denkfecf63e2011-11-09 09:28:55 +0000138 return 0;
wdenkaffae2b2002-08-17 09:36:01 +0000139}
140
141static uchar
Wolfgang Denkfecf63e2011-11-09 09:28:55 +0000142i2c_get_data(uchar *return_data, int len) {
wdenkaffae2b2002-08-17 09:36:01 +0000143
Wolfgang Denk77ddac92005-10-13 16:45:02 +0200144 unsigned int data, status = 0;
wdenkaffae2b2002-08-17 09:36:01 +0000145 int count = 0;
146
147 DP(puts("i2c_get_data\n"));
148
149 while (len) {
150
151 /* Get and return the data */
152
153 RESET_REG_BITS(I2C_CONTROL, (0x1 << 3));
154
155 udelay(I2C_DELAY * 5);
156
157 GT_REG_READ(I2C_STATUS_BAUDE_RATE, &status);
158 count++;
159 while ((status & 0xff) != 0x50) {
160 udelay(I2C_DELAY);
Wolfgang Denkfecf63e2011-11-09 09:28:55 +0000161 if (count > 2) {
wdenkaffae2b2002-08-17 09:36:01 +0000162 GT_REG_WRITE(I2C_CONTROL, (0x1 << 4)); /*stop*/
163 return 0;
164 }
165 GT_REG_READ(I2C_STATUS_BAUDE_RATE, &status);
166 count++;
167 }
168 GT_REG_READ(I2C_DATA, &data);
169 len--;
170 *return_data = (uchar)data;
171 return_data++;
172 }
173 RESET_REG_BITS(I2C_CONTROL, BIT2|BIT3);
174 while ((status & 0xff) != 0x58) {
175 udelay(I2C_DELAY);
Wolfgang Denkfecf63e2011-11-09 09:28:55 +0000176 if (count > 200) {
wdenkaffae2b2002-08-17 09:36:01 +0000177 GT_REG_WRITE(I2C_CONTROL, (0x1 << 4)); /*stop*/
Wolfgang Denkfecf63e2011-11-09 09:28:55 +0000178 return status;
wdenkaffae2b2002-08-17 09:36:01 +0000179 }
180 GT_REG_READ(I2C_STATUS_BAUDE_RATE, &status);
181 count++;
182 }
183 GT_REG_WRITE(I2C_CONTROL, (0x1 << 4)); /* stop */
184
Wolfgang Denkfecf63e2011-11-09 09:28:55 +0000185 return 0;
wdenkaffae2b2002-08-17 09:36:01 +0000186}
187
188static uchar
189i2c_write_data(unsigned int data, int len)
190{
191 unsigned int status;
192 int count = 0;
193
194 DP(puts("i2c_write_data\n"));
195
196 if (len > 4)
197 return -1;
198
199 while (len) {
200 /* Set and assert the data */
201
202 GT_REG_WRITE(I2C_DATA, (unsigned int)data);
203 RESET_REG_BITS(I2C_CONTROL, (0x1 << 3));
204
205 udelay(I2C_DELAY);
206
207 GT_REG_READ(I2C_STATUS_BAUDE_RATE, &status);
208 count++;
209 while ((status & 0xff) != 0x28) {
210 udelay(I2C_DELAY);
Wolfgang Denkfecf63e2011-11-09 09:28:55 +0000211 if (count > 20) {
wdenkaffae2b2002-08-17 09:36:01 +0000212 GT_REG_WRITE(I2C_CONTROL, (0x1 << 4)); /*stop*/
Wolfgang Denkfecf63e2011-11-09 09:28:55 +0000213 return status;
wdenkaffae2b2002-08-17 09:36:01 +0000214 }
215 GT_REG_READ(I2C_STATUS_BAUDE_RATE, &status);
216 count++;
217 }
218 len--;
219 }
220 GT_REG_WRITE(I2C_CONTROL, (0x1 << 3) | (0x1 << 4));
221 GT_REG_WRITE(I2C_CONTROL, (0x1 << 4));
222
223 udelay(I2C_DELAY * 10);
224
Wolfgang Denkfecf63e2011-11-09 09:28:55 +0000225 return 0;
wdenkaffae2b2002-08-17 09:36:01 +0000226}
227
228static uchar
229i2c_set_dev_offset(uchar dev_addr, unsigned int offset, int ten_bit)
230{
231 uchar status;
232
233 DP(puts("i2c_set_dev_offset\n"));
234
235 status = i2c_select_device(dev_addr, 0, ten_bit);
236 if (status) {
237#ifdef DEBUG_I2C
238 printf("Failed to select device setting offset: 0x%02x\n",
239 status);
240#endif
241 return status;
242 }
243
244 status = i2c_write_data(offset, 1);
245 if (status) {
246#ifdef DEBUG_I2C
247 printf("Failed to write data: 0x%02x\n", status);
248#endif
249 return status;
250 }
251
Wolfgang Denkfecf63e2011-11-09 09:28:55 +0000252 return 0;
wdenkaffae2b2002-08-17 09:36:01 +0000253}
254
255uchar
Wolfgang Denkfecf63e2011-11-09 09:28:55 +0000256i2c_read(uchar dev_addr, unsigned int offset, int len, uchar *data,
wdenkaffae2b2002-08-17 09:36:01 +0000257 int ten_bit)
258{
259 uchar status = 0;
Heiko Schocher7d5ff542011-11-17 07:57:20 +0100260 unsigned int i2cfreq = 400000;
wdenkaffae2b2002-08-17 09:36:01 +0000261
262 DP(puts("i2c_read\n"));
263
Heiko Schocher7d5ff542011-11-17 07:57:20 +0100264 i2c_init(i2cfreq, 0);
wdenkaffae2b2002-08-17 09:36:01 +0000265
266 status = i2c_start();
267
268 if (status) {
269#ifdef DEBUG_I2C
270 printf("Transaction start failed: 0x%02x\n", status);
271#endif
272 return status;
273 }
274
275 status = i2c_set_dev_offset(dev_addr, 0, 0);
276 if (status) {
277#ifdef DEBUG_I2C
278 printf("Failed to set offset: 0x%02x\n", status);
279#endif
280 return status;
281 }
282
Heiko Schocher7d5ff542011-11-17 07:57:20 +0100283 i2c_init(i2cfreq, 0);
wdenkaffae2b2002-08-17 09:36:01 +0000284
285 status = i2c_start();
286 if (status) {
287#ifdef DEBUG_I2C
288 printf("Transaction restart failed: 0x%02x\n", status);
289#endif
290 return status;
291 }
292
293 status = i2c_select_device(dev_addr, 1, ten_bit);
294 if (status) {
295#ifdef DEBUG_I2C
296 printf("Address not acknowledged: 0x%02x\n", status);
297#endif
298 return status;
299 }
300
301 status = i2c_get_data(data, len);
302 if (status) {
303#ifdef DEBUG_I2C
Mike Williams16263082011-07-22 04:01:30 +0000304 printf("Data not received: 0x%02x\n", status);
wdenkaffae2b2002-08-17 09:36:01 +0000305#endif
306 return status;
307 }
308
309 return 0;
310}