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
14struct 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
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/* Do low-level i2c byte transfer.
105 * Returns -1 in case of an error or 0 otherwise.
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		/* Setup data */
118		iowrite8(data[i], &regs->txr_rxr);
119
120		/* Setup command */
121		if (i == 0 && start) {
122			/* Write + Start */
123			cmd = M00018_CR_BITMAP_WR_MSK |
124			      M00018_CR_BITMAP_STA_MSK;
125		} else if (i == len - 1 && stop) {
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 */
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		/* Setup command */
176		if (i == 0 && start) {
177			/* Read + Start */
178			cmd = M00018_CR_BITMAP_RD_MSK |
179			      M00018_CR_BITMAP_STA_MSK;
180		} else if (i == len - 1 && stop) {
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 */
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			/* 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
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/* template for i2c-bit-algo */
292static 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
299static const struct i2c_algorithm cobalt_algo = {
300	.master_xfer	= cobalt_xfer,
301	.functionality	= cobalt_func,
302};
303
304/* init + register i2c algo-bit adapter */
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	/* 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
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