1
2
3
4
5
6
7
8
9
10
11#include "cobalt-driver.h"
12#include "cobalt-i2c.h"
13
14struct cobalt_i2c_regs {
15
16 u8 prerlo;
17 u8 dummy0[3];
18
19 u8 prerhi;
20 u8 dummy1[3];
21
22 u8 ctr;
23 u8 dummy2[3];
24
25 u8 txr_rxr;
26 u8 dummy3[3];
27
28 u8 cr_sr;
29 u8 dummy4[3];
30};
31
32
33
34
35#define M00018_CTR_BITMAP_EN_MSK (1 << 7)
36
37
38#define M00018_CTR_BITMAP_IEN_MSK (1 << 6)
39
40
41
42
43#define M00018_CR_BITMAP_STA_MSK (1 << 7)
44
45
46#define M00018_CR_BITMAP_STO_MSK (1 << 6)
47
48
49#define M00018_CR_BITMAP_RD_MSK (1 << 5)
50
51
52#define M00018_CR_BITMAP_WR_MSK (1 << 4)
53
54
55#define M00018_CR_BITMAP_ACK_MSK (1 << 3)
56
57
58#define M00018_CR_BITMAP_IACK_MSK (1 << 0)
59
60
61
62
63#define M00018_SR_BITMAP_RXACK_MSK (1 << 7)
64
65
66#define M00018_SR_BITMAP_BUSY_MSK (1 << 6)
67
68
69#define M00018_SR_BITMAP_AL_MSK (1 << 5)
70
71
72#define M00018_SR_BITMAP_TIP_MSK (1 << 1)
73
74
75#define M00018_SR_BITMAP_IF_MSK (1 << 0)
76
77
78#define I2C_FREQUENCY 400000
79#define ALT_CPU_FREQ 83333333
80
81static struct cobalt_i2c_regs __iomem *
82cobalt_i2c_regs(struct cobalt *cobalt, unsigned idx)
83{
84 switch (idx) {
85 case 0:
86 default:
87 return (struct cobalt_i2c_regs __iomem *)
88 (cobalt->bar1 + COBALT_I2C_0_BASE);
89 case 1:
90 return (struct cobalt_i2c_regs __iomem *)
91 (cobalt->bar1 + COBALT_I2C_1_BASE);
92 case 2:
93 return (struct cobalt_i2c_regs __iomem *)
94 (cobalt->bar1 + COBALT_I2C_2_BASE);
95 case 3:
96 return (struct cobalt_i2c_regs __iomem *)
97 (cobalt->bar1 + COBALT_I2C_3_BASE);
98 case 4:
99 return (struct cobalt_i2c_regs __iomem *)
100 (cobalt->bar1 + COBALT_I2C_HSMA_BASE);
101 }
102}
103
104
105
106
107static int cobalt_tx_bytes(struct cobalt_i2c_regs __iomem *regs,
108 struct i2c_adapter *adap, bool start, bool stop,
109 u8 *data, u16 len)
110{
111 unsigned long start_time;
112 int status;
113 int cmd;
114 int i;
115
116 for (i = 0; i < len; i++) {
117
118 iowrite8(data[i], ®s->txr_rxr);
119
120
121 if (i == 0 && start) {
122
123 cmd = M00018_CR_BITMAP_WR_MSK |
124 M00018_CR_BITMAP_STA_MSK;
125 } else if (i == len - 1 && stop) {
126
127 cmd = M00018_CR_BITMAP_WR_MSK |
128 M00018_CR_BITMAP_STO_MSK;
129 } else {
130
131 cmd = M00018_CR_BITMAP_WR_MSK;
132 }
133
134
135 iowrite8(cmd, ®s->cr_sr);
136
137
138 start_time = jiffies;
139 status = ioread8(®s->cr_sr);
140 while (status & M00018_SR_BITMAP_TIP_MSK) {
141 if (time_after(jiffies, start_time + adap->timeout))
142 return -ETIMEDOUT;
143 cond_resched();
144 status = ioread8(®s->cr_sr);
145 }
146
147
148 if (status & M00018_SR_BITMAP_RXACK_MSK) {
149
150 return -EIO;
151 }
152
153
154 if (status & M00018_SR_BITMAP_AL_MSK) {
155
156 return -EIO;
157 }
158 }
159 return 0;
160}
161
162
163
164
165static int cobalt_rx_bytes(struct cobalt_i2c_regs __iomem *regs,
166 struct i2c_adapter *adap, bool start, bool stop,
167 u8 *data, u16 len)
168{
169 unsigned long start_time;
170 int status;
171 int cmd;
172 int i;
173
174 for (i = 0; i < len; i++) {
175
176 if (i == 0 && start) {
177
178 cmd = M00018_CR_BITMAP_RD_MSK |
179 M00018_CR_BITMAP_STA_MSK;
180 } else if (i == len - 1 && stop) {
181
182 cmd = M00018_CR_BITMAP_RD_MSK |
183 M00018_CR_BITMAP_STO_MSK;
184 } else {
185
186 cmd = M00018_CR_BITMAP_RD_MSK;
187 }
188
189
190 if (i == len - 1)
191 cmd |= M00018_CR_BITMAP_ACK_MSK;
192
193
194 iowrite8(cmd, ®s->cr_sr);
195
196
197 start_time = jiffies;
198 status = ioread8(®s->cr_sr);
199 while (status & M00018_SR_BITMAP_TIP_MSK) {
200 if (time_after(jiffies, start_time + adap->timeout))
201 return -ETIMEDOUT;
202 cond_resched();
203 status = ioread8(®s->cr_sr);
204 }
205
206
207 if (status & M00018_SR_BITMAP_AL_MSK) {
208
209 return -EIO;
210 }
211
212
213 data[i] = ioread8(®s->txr_rxr);
214 }
215 return 0;
216}
217
218
219
220
221
222static int cobalt_stop(struct cobalt_i2c_regs __iomem *regs,
223 struct i2c_adapter *adap)
224{
225 u8 data = 0;
226
227 return cobalt_tx_bytes(regs, adap, true, true, &data, 1);
228}
229
230static int cobalt_xfer(struct i2c_adapter *adap,
231 struct i2c_msg msgs[], int num)
232{
233 struct cobalt_i2c_data *data = adap->algo_data;
234 struct cobalt_i2c_regs __iomem *regs = data->regs;
235 struct i2c_msg *pmsg;
236 unsigned short flags;
237 int ret = 0;
238 int i, j;
239
240 for (i = 0; i < num; i++) {
241 int stop = (i == num - 1);
242
243 pmsg = &msgs[i];
244 flags = pmsg->flags;
245
246 if (!(pmsg->flags & I2C_M_NOSTART)) {
247 u8 addr = pmsg->addr << 1;
248
249 if (flags & I2C_M_RD)
250 addr |= 1;
251 if (flags & I2C_M_REV_DIR_ADDR)
252 addr ^= 1;
253 for (j = 0; j < adap->retries; j++) {
254 ret = cobalt_tx_bytes(regs, adap, true, false,
255 &addr, 1);
256 if (!ret)
257 break;
258 cobalt_stop(regs, adap);
259 }
260 if (ret < 0)
261 return ret;
262 ret = 0;
263 }
264 if (pmsg->flags & I2C_M_RD) {
265
266 ret = cobalt_rx_bytes(regs, adap, false, stop,
267 pmsg->buf, pmsg->len);
268 if (ret < 0)
269 goto bailout;
270 } else {
271
272 ret = cobalt_tx_bytes(regs, adap, false, stop,
273 pmsg->buf, pmsg->len);
274 if (ret < 0)
275 goto bailout;
276 }
277 }
278 ret = i;
279
280bailout:
281 if (ret < 0)
282 cobalt_stop(regs, adap);
283 return ret;
284}
285
286static u32 cobalt_func(struct i2c_adapter *adap)
287{
288 return I2C_FUNC_I2C | I2C_FUNC_SMBUS_EMUL;
289}
290
291
292static const struct i2c_adapter cobalt_i2c_adap_template = {
293 .name = "cobalt i2c driver",
294 .algo = NULL,
295 .algo_data = NULL,
296 .owner = THIS_MODULE,
297};
298
299static const struct i2c_algorithm cobalt_algo = {
300 .master_xfer = cobalt_xfer,
301 .functionality = cobalt_func,
302};
303
304
305int cobalt_i2c_init(struct cobalt *cobalt)
306{
307 int i, err;
308 int status;
309 int prescale;
310 unsigned long start_time;
311
312 cobalt_dbg(1, "i2c init\n");
313
314
315 prescale = ((ALT_CPU_FREQ) / (5 * I2C_FREQUENCY)) - 1;
316
317 for (i = 0; i < COBALT_NUM_ADAPTERS; i++) {
318 struct cobalt_i2c_regs __iomem *regs =
319 cobalt_i2c_regs(cobalt, i);
320 struct i2c_adapter *adap = &cobalt->i2c_adap[i];
321
322
323 iowrite8(M00018_CTR_BITMAP_EN_MSK, ®s->cr_sr);
324 iowrite8(0, ®s->ctr);
325 iowrite8(0, ®s->cr_sr);
326
327 start_time = jiffies;
328 do {
329 if (time_after(jiffies, start_time + HZ)) {
330 if (cobalt_ignore_err) {
331 adap->dev.parent = NULL;
332 return 0;
333 }
334 return -ETIMEDOUT;
335 }
336 status = ioread8(®s->cr_sr);
337 } while (status & M00018_SR_BITMAP_TIP_MSK);
338
339
340 iowrite8(0, ®s->ctr);
341 iowrite8(0, ®s->cr_sr);
342
343
344 iowrite8(prescale & 0xff, ®s->prerlo);
345 iowrite8((prescale >> 8) & 0xff, ®s->prerhi);
346
347 iowrite8(M00018_CTR_BITMAP_EN_MSK, ®s->ctr);
348
349 cobalt->i2c_data[i].cobalt = cobalt;
350 cobalt->i2c_data[i].regs = regs;
351 *adap = cobalt_i2c_adap_template;
352 adap->algo = &cobalt_algo;
353 adap->algo_data = &cobalt->i2c_data[i];
354 adap->retries = 3;
355 sprintf(adap->name + strlen(adap->name),
356 " #%d-%d", cobalt->instance, i);
357 i2c_set_adapdata(adap, &cobalt->v4l2_dev);
358 adap->dev.parent = &cobalt->pci_dev->dev;
359 err = i2c_add_adapter(adap);
360 if (err) {
361 if (cobalt_ignore_err) {
362 adap->dev.parent = NULL;
363 return 0;
364 }
365 while (i--)
366 i2c_del_adapter(&cobalt->i2c_adap[i]);
367 return err;
368 }
369 cobalt_info("registered bus %s\n", adap->name);
370 }
371 return 0;
372}
373
374void cobalt_i2c_exit(struct cobalt *cobalt)
375{
376 int i;
377
378 cobalt_dbg(1, "i2c exit\n");
379
380 for (i = 0; i < COBALT_NUM_ADAPTERS; i++) {
381 cobalt_err("unregistered bus %s\n", cobalt->i2c_adap[i].name);
382 i2c_del_adapter(&cobalt->i2c_adap[i]);
383 }
384}
385