Merge tag 'selinux-pr-20180516' of git://git.kernel.org/pub/scm/linux/kernel/git...
[sfrench/cifs-2.6.git] / drivers / media / pci / cobalt / cobalt-i2c.c
1 // SPDX-License-Identifier: GPL-2.0-only
2 /*
3  *  cobalt I2C functions
4  *
5  *  Derived from cx18-i2c.c
6  *
7  *  Copyright 2012-2015 Cisco Systems, Inc. and/or its affiliates.
8  *  All rights reserved.
9  */
10
11 #include "cobalt-driver.h"
12 #include "cobalt-i2c.h"
13
14 struct cobalt_i2c_regs {
15         /* Clock prescaler register lo-byte */
16         u8 prerlo;
17         u8 dummy0[3];
18         /* Clock prescaler register high-byte */
19         u8 prerhi;
20         u8 dummy1[3];
21         /* Control register */
22         u8 ctr;
23         u8 dummy2[3];
24         /* Transmit/Receive register */
25         u8 txr_rxr;
26         u8 dummy3[3];
27         /* Command and Status register */
28         u8 cr_sr;
29         u8 dummy4[3];
30 };
31
32 /* CTR[7:0] - Control register */
33
34 /* I2C Core enable bit */
35 #define M00018_CTR_BITMAP_EN_MSK        (1 << 7)
36
37 /* I2C Core interrupt enable bit */
38 #define M00018_CTR_BITMAP_IEN_MSK       (1 << 6)
39
40 /* CR[7:0] - Command register */
41
42 /* I2C start condition */
43 #define M00018_CR_BITMAP_STA_MSK        (1 << 7)
44
45 /* I2C stop condition */
46 #define M00018_CR_BITMAP_STO_MSK        (1 << 6)
47
48 /* I2C read from slave */
49 #define M00018_CR_BITMAP_RD_MSK         (1 << 5)
50
51 /* I2C write to slave */
52 #define M00018_CR_BITMAP_WR_MSK         (1 << 4)
53
54 /* I2C ack */
55 #define M00018_CR_BITMAP_ACK_MSK        (1 << 3)
56
57 /* I2C Interrupt ack */
58 #define M00018_CR_BITMAP_IACK_MSK       (1 << 0)
59
60 /* SR[7:0] - Status register */
61
62 /* Receive acknowledge from slave */
63 #define M00018_SR_BITMAP_RXACK_MSK      (1 << 7)
64
65 /* Busy, I2C bus busy (as defined by start / stop bits) */
66 #define M00018_SR_BITMAP_BUSY_MSK       (1 << 6)
67
68 /* Arbitration lost - core lost arbitration */
69 #define M00018_SR_BITMAP_AL_MSK         (1 << 5)
70
71 /* Transfer in progress */
72 #define M00018_SR_BITMAP_TIP_MSK        (1 << 1)
73
74 /* Interrupt flag */
75 #define M00018_SR_BITMAP_IF_MSK         (1 << 0)
76
77 /* Frequency, in Hz */
78 #define I2C_FREQUENCY                   400000
79 #define ALT_CPU_FREQ                    83333333
80
81 static struct cobalt_i2c_regs __iomem *
82 cobalt_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 /* Do low-level i2c byte transfer.
105  * Returns -1 in case of an error or 0 otherwise.
106  */
107 static 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                 /* Setup data */
118                 iowrite8(data[i], &regs->txr_rxr);
119
120                 /* Setup command */
121                 if (i == 0 && start != 0) {
122                         /* Write + Start */
123                         cmd = M00018_CR_BITMAP_WR_MSK |
124                               M00018_CR_BITMAP_STA_MSK;
125                 } else if (i == len - 1 && stop != 0) {
126                         /* Write + Stop */
127                         cmd = M00018_CR_BITMAP_WR_MSK |
128                               M00018_CR_BITMAP_STO_MSK;
129                 } else {
130                         /* Write only */
131                         cmd = M00018_CR_BITMAP_WR_MSK;
132                 }
133
134                 /* Execute command */
135                 iowrite8(cmd, &regs->cr_sr);
136
137                 /* Wait for transfer to complete (TIP = 0) */
138                 start_time = jiffies;
139                 status = ioread8(&regs->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(&regs->cr_sr);
145                 }
146
147                 /* Verify ACK */
148                 if (status & M00018_SR_BITMAP_RXACK_MSK) {
149                         /* NO ACK! */
150                         return -EIO;
151                 }
152
153                 /* Verify arbitration */
154                 if (status & M00018_SR_BITMAP_AL_MSK) {
155                         /* Arbitration lost! */
156                         return -EIO;
157                 }
158         }
159         return 0;
160 }
161
162 /* Do low-level i2c byte read.
163  * Returns -1 in case of an error or 0 otherwise.
164  */
165 static 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                 /* Setup command */
176                 if (i == 0 && start != 0) {
177                         /* Read + Start */
178                         cmd = M00018_CR_BITMAP_RD_MSK |
179                               M00018_CR_BITMAP_STA_MSK;
180                 } else if (i == len - 1 && stop != 0) {
181                         /* Read + Stop */
182                         cmd = M00018_CR_BITMAP_RD_MSK |
183                               M00018_CR_BITMAP_STO_MSK;
184                 } else {
185                         /* Read only */
186                         cmd = M00018_CR_BITMAP_RD_MSK;
187                 }
188
189                 /* Last byte to read, no ACK */
190                 if (i == len - 1)
191                         cmd |= M00018_CR_BITMAP_ACK_MSK;
192
193                 /* Execute command */
194                 iowrite8(cmd, &regs->cr_sr);
195
196                 /* Wait for transfer to complete (TIP = 0) */
197                 start_time = jiffies;
198                 status = ioread8(&regs->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(&regs->cr_sr);
204                 }
205
206                 /* Verify arbitration */
207                 if (status & M00018_SR_BITMAP_AL_MSK) {
208                         /* Arbitration lost! */
209                         return -EIO;
210                 }
211
212                 /* Store data */
213                 data[i] = ioread8(&regs->txr_rxr);
214         }
215         return 0;
216 }
217
218 /* Generate stop condition on i2c bus.
219  * The m00018 stop isn't doing the right thing (wrong timing).
220  * So instead send a start condition, 8 zeroes and a stop condition.
221  */
222 static 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
230 static 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                         /* read bytes into buffer */
266                         ret = cobalt_rx_bytes(regs, adap, false, stop,
267                                         pmsg->buf, pmsg->len);
268                         if (ret < 0)
269                                 goto bailout;
270                 } else {
271                         /* write bytes from buffer */
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
280 bailout:
281         if (ret < 0)
282                 cobalt_stop(regs, adap);
283         return ret;
284 }
285
286 static u32 cobalt_func(struct i2c_adapter *adap)
287 {
288         return I2C_FUNC_I2C | I2C_FUNC_SMBUS_EMUL;
289 }
290
291 /* template for i2c-bit-algo */
292 static const struct i2c_adapter cobalt_i2c_adap_template = {
293         .name = "cobalt i2c driver",
294         .algo = NULL,                   /* set by i2c-algo-bit */
295         .algo_data = NULL,              /* filled from template */
296         .owner = THIS_MODULE,
297 };
298
299 static const struct i2c_algorithm cobalt_algo = {
300         .master_xfer    = cobalt_xfer,
301         .functionality  = cobalt_func,
302 };
303
304 /* init + register i2c algo-bit adapter */
305 int 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         /* Define I2C clock prescaler */
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                 /* Disable I2C */
323                 iowrite8(M00018_CTR_BITMAP_EN_MSK, &regs->cr_sr);
324                 iowrite8(0, &regs->ctr);
325                 iowrite8(0, &regs->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(&regs->cr_sr);
337                 } while (status & M00018_SR_BITMAP_TIP_MSK);
338
339                 /* Disable I2C */
340                 iowrite8(0, &regs->ctr);
341                 iowrite8(0, &regs->cr_sr);
342
343                 /* Calculate i2c prescaler */
344                 iowrite8(prescale & 0xff, &regs->prerlo);
345                 iowrite8((prescale >> 8) & 0xff, &regs->prerhi);
346                 /* Enable I2C, interrupts disabled */
347                 iowrite8(M00018_CTR_BITMAP_EN_MSK, &regs->ctr);
348                 /* Setup algorithm for adapter */
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
374 void 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 }