~pmdj/ubuntu/trusty/qemu/2.9+applesmc+fadtv3

« back to all changes in this revision

Viewing changes to roms/u-boot/board/evb64260/i2c.c

  • Committer: Phil Dennis-Jordan
  • Date: 2017-07-21 08:03:43 UTC
  • mfrom: (1.1.1)
  • Revision ID: phil@philjordan.eu-20170721080343-2yr2vdj7713czahv
New upstream release 2.9.0.

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
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
}