]> git.kernelconcepts.de Git - karo-tx-uboot.git/blob - board/evb64260/i2c.c
Merge branch 'master' of git://git.denx.de/u-boot-mpc83xx
[karo-tx-uboot.git] / board / evb64260 / i2c.c
1 #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
19 static void
20 i2c_init(int speed, int slaveaddr)
21 {
22         unsigned int n, m, freq, margin, power;
23         unsigned int actualn = 0, actualm = 0;
24         unsigned int control, status;
25         unsigned int minmargin = 0xffffffff;
26         unsigned int tclk = 125000000;
27
28         DP(puts("i2c_init\n"));
29
30         for (n = 0 ; n < 8 ; n++) {
31                 for (m = 0 ; m < 16 ; m++) {
32                         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;
38                         if (margin < minmargin) {
39                                 minmargin   = margin;
40                                 actualn     = n;
41                                 actualm     = m;
42                         }
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
58         GT_REG_WRITE(I2C_STATUS_BAUDE_RATE, (actualm << 3) | actualn);
59         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
69 static uchar
70 i2c_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*/
90                         return status;
91                 }
92                 GT_REG_READ(I2C_STATUS_BAUDE_RATE, &status);
93                 count++;
94         }
95
96         return 0;
97 }
98
99 static uchar
100 i2c_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
109         if (ten_bit)
110                 bits = 10;
111
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*/
127                         return status;
128                 }
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");
135                 return 0xff;
136         }
137
138         return 0;
139 }
140
141 static uchar
142 i2c_get_data(uchar *return_data, int len) {
143
144         unsigned int data, status = 0;
145         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);
161                         if (count > 2) {
162                                 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);
176                 if (count > 200) {
177                         GT_REG_WRITE(I2C_CONTROL, (0x1 << 4)); /*stop*/
178                         return status;
179                 }
180                 GT_REG_READ(I2C_STATUS_BAUDE_RATE, &status);
181                 count++;
182         }
183         GT_REG_WRITE(I2C_CONTROL, (0x1 << 4)); /* stop */
184
185         return 0;
186 }
187
188 static uchar
189 i2c_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);
211                         if (count > 20) {
212                                 GT_REG_WRITE(I2C_CONTROL, (0x1 << 4)); /*stop*/
213                                 return status;
214                         }
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
225         return 0;
226 }
227
228 static uchar
229 i2c_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
252         return 0;
253 }
254
255 uchar
256 i2c_read(uchar dev_addr, unsigned int offset, int len, uchar *data,
257          int ten_bit)
258 {
259         uchar status = 0;
260         unsigned int i2cfreq = 400000;
261
262         DP(puts("i2c_read\n"));
263
264         i2c_init(i2cfreq, 0);
265
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
283         i2c_init(i2cfreq, 0);
284
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
304                 printf("Data not received: 0x%02x\n", status);
305 #endif
306                 return status;
307         }
308
309         return 0;
310 }