xref: /openbmc/linux/drivers/i2c/busses/i2c-owl.c (revision d211e62af46693f90f6386085817e22239e3fe79)
1*d211e62aSManivannan Sadhasivam // SPDX-License-Identifier: GPL-2.0-or-later
2*d211e62aSManivannan Sadhasivam /*
3*d211e62aSManivannan Sadhasivam  * Actions Semiconductor Owl SoC's I2C driver
4*d211e62aSManivannan Sadhasivam  *
5*d211e62aSManivannan Sadhasivam  * Copyright (c) 2014 Actions Semi Inc.
6*d211e62aSManivannan Sadhasivam  * Author: David Liu <liuwei@actions-semi.com>
7*d211e62aSManivannan Sadhasivam  *
8*d211e62aSManivannan Sadhasivam  * Copyright (c) 2018 Linaro Ltd.
9*d211e62aSManivannan Sadhasivam  * Author: Manivannan Sadhasivam <manivannan.sadhasivam@linaro.org>
10*d211e62aSManivannan Sadhasivam  */
11*d211e62aSManivannan Sadhasivam 
12*d211e62aSManivannan Sadhasivam #include <linux/clk.h>
13*d211e62aSManivannan Sadhasivam #include <linux/delay.h>
14*d211e62aSManivannan Sadhasivam #include <linux/i2c.h>
15*d211e62aSManivannan Sadhasivam #include <linux/interrupt.h>
16*d211e62aSManivannan Sadhasivam #include <linux/io.h>
17*d211e62aSManivannan Sadhasivam #include <linux/module.h>
18*d211e62aSManivannan Sadhasivam #include <linux/of_device.h>
19*d211e62aSManivannan Sadhasivam 
20*d211e62aSManivannan Sadhasivam /* I2C registers */
21*d211e62aSManivannan Sadhasivam #define OWL_I2C_REG_CTL		0x0000
22*d211e62aSManivannan Sadhasivam #define OWL_I2C_REG_CLKDIV	0x0004
23*d211e62aSManivannan Sadhasivam #define OWL_I2C_REG_STAT	0x0008
24*d211e62aSManivannan Sadhasivam #define OWL_I2C_REG_ADDR	0x000C
25*d211e62aSManivannan Sadhasivam #define OWL_I2C_REG_TXDAT	0x0010
26*d211e62aSManivannan Sadhasivam #define OWL_I2C_REG_RXDAT	0x0014
27*d211e62aSManivannan Sadhasivam #define OWL_I2C_REG_CMD		0x0018
28*d211e62aSManivannan Sadhasivam #define OWL_I2C_REG_FIFOCTL	0x001C
29*d211e62aSManivannan Sadhasivam #define OWL_I2C_REG_FIFOSTAT	0x0020
30*d211e62aSManivannan Sadhasivam #define OWL_I2C_REG_DATCNT	0x0024
31*d211e62aSManivannan Sadhasivam #define OWL_I2C_REG_RCNT	0x0028
32*d211e62aSManivannan Sadhasivam 
33*d211e62aSManivannan Sadhasivam /* I2Cx_CTL Bit Mask */
34*d211e62aSManivannan Sadhasivam #define OWL_I2C_CTL_RB		BIT(1)
35*d211e62aSManivannan Sadhasivam #define OWL_I2C_CTL_GBCC(x)	(((x) & 0x3) << 2)
36*d211e62aSManivannan Sadhasivam #define	OWL_I2C_CTL_GBCC_NONE	OWL_I2C_CTL_GBCC(0)
37*d211e62aSManivannan Sadhasivam #define	OWL_I2C_CTL_GBCC_START	OWL_I2C_CTL_GBCC(1)
38*d211e62aSManivannan Sadhasivam #define	OWL_I2C_CTL_GBCC_STOP	OWL_I2C_CTL_GBCC(2)
39*d211e62aSManivannan Sadhasivam #define	OWL_I2C_CTL_GBCC_RSTART	OWL_I2C_CTL_GBCC(3)
40*d211e62aSManivannan Sadhasivam #define OWL_I2C_CTL_IRQE	BIT(5)
41*d211e62aSManivannan Sadhasivam #define OWL_I2C_CTL_EN		BIT(7)
42*d211e62aSManivannan Sadhasivam #define OWL_I2C_CTL_AE		BIT(8)
43*d211e62aSManivannan Sadhasivam #define OWL_I2C_CTL_SHSM	BIT(10)
44*d211e62aSManivannan Sadhasivam 
45*d211e62aSManivannan Sadhasivam #define OWL_I2C_DIV_FACTOR(x)	((x) & 0xff)
46*d211e62aSManivannan Sadhasivam 
47*d211e62aSManivannan Sadhasivam /* I2Cx_STAT Bit Mask */
48*d211e62aSManivannan Sadhasivam #define OWL_I2C_STAT_RACK	BIT(0)
49*d211e62aSManivannan Sadhasivam #define OWL_I2C_STAT_BEB	BIT(1)
50*d211e62aSManivannan Sadhasivam #define OWL_I2C_STAT_IRQP	BIT(2)
51*d211e62aSManivannan Sadhasivam #define OWL_I2C_STAT_LAB	BIT(3)
52*d211e62aSManivannan Sadhasivam #define OWL_I2C_STAT_STPD	BIT(4)
53*d211e62aSManivannan Sadhasivam #define OWL_I2C_STAT_STAD	BIT(5)
54*d211e62aSManivannan Sadhasivam #define OWL_I2C_STAT_BBB	BIT(6)
55*d211e62aSManivannan Sadhasivam #define OWL_I2C_STAT_TCB	BIT(7)
56*d211e62aSManivannan Sadhasivam #define OWL_I2C_STAT_LBST	BIT(8)
57*d211e62aSManivannan Sadhasivam #define OWL_I2C_STAT_SAMB	BIT(9)
58*d211e62aSManivannan Sadhasivam #define OWL_I2C_STAT_SRGC	BIT(10)
59*d211e62aSManivannan Sadhasivam 
60*d211e62aSManivannan Sadhasivam /* I2Cx_CMD Bit Mask */
61*d211e62aSManivannan Sadhasivam #define OWL_I2C_CMD_SBE		BIT(0)
62*d211e62aSManivannan Sadhasivam #define OWL_I2C_CMD_RBE		BIT(4)
63*d211e62aSManivannan Sadhasivam #define OWL_I2C_CMD_DE		BIT(8)
64*d211e62aSManivannan Sadhasivam #define OWL_I2C_CMD_NS		BIT(9)
65*d211e62aSManivannan Sadhasivam #define OWL_I2C_CMD_SE		BIT(10)
66*d211e62aSManivannan Sadhasivam #define OWL_I2C_CMD_MSS		BIT(11)
67*d211e62aSManivannan Sadhasivam #define OWL_I2C_CMD_WRS		BIT(12)
68*d211e62aSManivannan Sadhasivam #define OWL_I2C_CMD_SECL	BIT(15)
69*d211e62aSManivannan Sadhasivam 
70*d211e62aSManivannan Sadhasivam #define OWL_I2C_CMD_AS(x)	(((x) & 0x7) << 1)
71*d211e62aSManivannan Sadhasivam #define OWL_I2C_CMD_SAS(x)	(((x) & 0x7) << 5)
72*d211e62aSManivannan Sadhasivam 
73*d211e62aSManivannan Sadhasivam /* I2Cx_FIFOCTL Bit Mask */
74*d211e62aSManivannan Sadhasivam #define OWL_I2C_FIFOCTL_NIB	BIT(0)
75*d211e62aSManivannan Sadhasivam #define OWL_I2C_FIFOCTL_RFR	BIT(1)
76*d211e62aSManivannan Sadhasivam #define OWL_I2C_FIFOCTL_TFR	BIT(2)
77*d211e62aSManivannan Sadhasivam 
78*d211e62aSManivannan Sadhasivam /* I2Cc_FIFOSTAT Bit Mask */
79*d211e62aSManivannan Sadhasivam #define OWL_I2C_FIFOSTAT_RNB	BIT(1)
80*d211e62aSManivannan Sadhasivam #define OWL_I2C_FIFOSTAT_RFE	BIT(2)
81*d211e62aSManivannan Sadhasivam #define OWL_I2C_FIFOSTAT_TFF	BIT(5)
82*d211e62aSManivannan Sadhasivam #define OWL_I2C_FIFOSTAT_TFD	GENMASK(23, 16)
83*d211e62aSManivannan Sadhasivam #define OWL_I2C_FIFOSTAT_RFD	GENMASK(15, 8)
84*d211e62aSManivannan Sadhasivam 
85*d211e62aSManivannan Sadhasivam /* I2C bus timeout */
86*d211e62aSManivannan Sadhasivam #define OWL_I2C_TIMEOUT		msecs_to_jiffies(4 * 1000)
87*d211e62aSManivannan Sadhasivam 
88*d211e62aSManivannan Sadhasivam #define OWL_I2C_MAX_RETRIES	50
89*d211e62aSManivannan Sadhasivam 
90*d211e62aSManivannan Sadhasivam #define OWL_I2C_DEF_SPEED_HZ	100000
91*d211e62aSManivannan Sadhasivam #define OWL_I2C_MAX_SPEED_HZ	400000
92*d211e62aSManivannan Sadhasivam 
93*d211e62aSManivannan Sadhasivam struct owl_i2c_dev {
94*d211e62aSManivannan Sadhasivam 	struct i2c_adapter	adap;
95*d211e62aSManivannan Sadhasivam 	struct i2c_msg		*msg;
96*d211e62aSManivannan Sadhasivam 	struct completion	msg_complete;
97*d211e62aSManivannan Sadhasivam 	struct clk		*clk;
98*d211e62aSManivannan Sadhasivam 	spinlock_t		lock;
99*d211e62aSManivannan Sadhasivam 	void __iomem		*base;
100*d211e62aSManivannan Sadhasivam 	unsigned long		clk_rate;
101*d211e62aSManivannan Sadhasivam 	u32			bus_freq;
102*d211e62aSManivannan Sadhasivam 	u32			msg_ptr;
103*d211e62aSManivannan Sadhasivam 	int			err;
104*d211e62aSManivannan Sadhasivam };
105*d211e62aSManivannan Sadhasivam 
106*d211e62aSManivannan Sadhasivam static void owl_i2c_update_reg(void __iomem *reg, unsigned int val, bool state)
107*d211e62aSManivannan Sadhasivam {
108*d211e62aSManivannan Sadhasivam 	unsigned int regval;
109*d211e62aSManivannan Sadhasivam 
110*d211e62aSManivannan Sadhasivam 	regval = readl(reg);
111*d211e62aSManivannan Sadhasivam 
112*d211e62aSManivannan Sadhasivam 	if (state)
113*d211e62aSManivannan Sadhasivam 		regval |= val;
114*d211e62aSManivannan Sadhasivam 	else
115*d211e62aSManivannan Sadhasivam 		regval &= ~val;
116*d211e62aSManivannan Sadhasivam 
117*d211e62aSManivannan Sadhasivam 	writel(regval, reg);
118*d211e62aSManivannan Sadhasivam }
119*d211e62aSManivannan Sadhasivam 
120*d211e62aSManivannan Sadhasivam static void owl_i2c_reset(struct owl_i2c_dev *i2c_dev)
121*d211e62aSManivannan Sadhasivam {
122*d211e62aSManivannan Sadhasivam 	owl_i2c_update_reg(i2c_dev->base + OWL_I2C_REG_CTL,
123*d211e62aSManivannan Sadhasivam 			   OWL_I2C_CTL_EN, false);
124*d211e62aSManivannan Sadhasivam 	mdelay(1);
125*d211e62aSManivannan Sadhasivam 	owl_i2c_update_reg(i2c_dev->base + OWL_I2C_REG_CTL,
126*d211e62aSManivannan Sadhasivam 			   OWL_I2C_CTL_EN, true);
127*d211e62aSManivannan Sadhasivam 
128*d211e62aSManivannan Sadhasivam 	/* Clear status registers */
129*d211e62aSManivannan Sadhasivam 	writel(0, i2c_dev->base + OWL_I2C_REG_STAT);
130*d211e62aSManivannan Sadhasivam }
131*d211e62aSManivannan Sadhasivam 
132*d211e62aSManivannan Sadhasivam static int owl_i2c_reset_fifo(struct owl_i2c_dev *i2c_dev)
133*d211e62aSManivannan Sadhasivam {
134*d211e62aSManivannan Sadhasivam 	unsigned int val, timeout = 0;
135*d211e62aSManivannan Sadhasivam 
136*d211e62aSManivannan Sadhasivam 	/* Reset FIFO */
137*d211e62aSManivannan Sadhasivam 	owl_i2c_update_reg(i2c_dev->base + OWL_I2C_REG_FIFOCTL,
138*d211e62aSManivannan Sadhasivam 			   OWL_I2C_FIFOCTL_RFR | OWL_I2C_FIFOCTL_TFR,
139*d211e62aSManivannan Sadhasivam 			   true);
140*d211e62aSManivannan Sadhasivam 
141*d211e62aSManivannan Sadhasivam 	/* Wait 50ms for FIFO reset complete */
142*d211e62aSManivannan Sadhasivam 	do {
143*d211e62aSManivannan Sadhasivam 		val = readl(i2c_dev->base + OWL_I2C_REG_FIFOCTL);
144*d211e62aSManivannan Sadhasivam 		if (!(val & (OWL_I2C_FIFOCTL_RFR | OWL_I2C_FIFOCTL_TFR)))
145*d211e62aSManivannan Sadhasivam 			break;
146*d211e62aSManivannan Sadhasivam 		usleep_range(500, 1000);
147*d211e62aSManivannan Sadhasivam 	} while (timeout++ < OWL_I2C_MAX_RETRIES);
148*d211e62aSManivannan Sadhasivam 
149*d211e62aSManivannan Sadhasivam 	if (timeout > OWL_I2C_MAX_RETRIES) {
150*d211e62aSManivannan Sadhasivam 		dev_err(&i2c_dev->adap.dev, "FIFO reset timeout\n");
151*d211e62aSManivannan Sadhasivam 		return -ETIMEDOUT;
152*d211e62aSManivannan Sadhasivam 	}
153*d211e62aSManivannan Sadhasivam 
154*d211e62aSManivannan Sadhasivam 	return 0;
155*d211e62aSManivannan Sadhasivam }
156*d211e62aSManivannan Sadhasivam 
157*d211e62aSManivannan Sadhasivam static void owl_i2c_set_freq(struct owl_i2c_dev *i2c_dev)
158*d211e62aSManivannan Sadhasivam {
159*d211e62aSManivannan Sadhasivam 	unsigned int val;
160*d211e62aSManivannan Sadhasivam 
161*d211e62aSManivannan Sadhasivam 	val = DIV_ROUND_UP(i2c_dev->clk_rate, i2c_dev->bus_freq * 16);
162*d211e62aSManivannan Sadhasivam 
163*d211e62aSManivannan Sadhasivam 	/* Set clock divider factor */
164*d211e62aSManivannan Sadhasivam 	writel(OWL_I2C_DIV_FACTOR(val), i2c_dev->base + OWL_I2C_REG_CLKDIV);
165*d211e62aSManivannan Sadhasivam }
166*d211e62aSManivannan Sadhasivam 
167*d211e62aSManivannan Sadhasivam static irqreturn_t owl_i2c_interrupt(int irq, void *_dev)
168*d211e62aSManivannan Sadhasivam {
169*d211e62aSManivannan Sadhasivam 	struct owl_i2c_dev *i2c_dev = _dev;
170*d211e62aSManivannan Sadhasivam 	struct i2c_msg *msg = i2c_dev->msg;
171*d211e62aSManivannan Sadhasivam 	unsigned long flags;
172*d211e62aSManivannan Sadhasivam 	unsigned int stat, fifostat;
173*d211e62aSManivannan Sadhasivam 
174*d211e62aSManivannan Sadhasivam 	spin_lock_irqsave(&i2c_dev->lock, flags);
175*d211e62aSManivannan Sadhasivam 
176*d211e62aSManivannan Sadhasivam 	i2c_dev->err = 0;
177*d211e62aSManivannan Sadhasivam 
178*d211e62aSManivannan Sadhasivam 	/* Handle NACK from slave */
179*d211e62aSManivannan Sadhasivam 	fifostat = readl(i2c_dev->base + OWL_I2C_REG_FIFOSTAT);
180*d211e62aSManivannan Sadhasivam 	if (fifostat & OWL_I2C_FIFOSTAT_RNB) {
181*d211e62aSManivannan Sadhasivam 		i2c_dev->err = -ENXIO;
182*d211e62aSManivannan Sadhasivam 		goto stop;
183*d211e62aSManivannan Sadhasivam 	}
184*d211e62aSManivannan Sadhasivam 
185*d211e62aSManivannan Sadhasivam 	/* Handle bus error */
186*d211e62aSManivannan Sadhasivam 	stat = readl(i2c_dev->base + OWL_I2C_REG_STAT);
187*d211e62aSManivannan Sadhasivam 	if (stat & OWL_I2C_STAT_BEB) {
188*d211e62aSManivannan Sadhasivam 		i2c_dev->err = -EIO;
189*d211e62aSManivannan Sadhasivam 		goto stop;
190*d211e62aSManivannan Sadhasivam 	}
191*d211e62aSManivannan Sadhasivam 
192*d211e62aSManivannan Sadhasivam 	/* Handle FIFO read */
193*d211e62aSManivannan Sadhasivam 	if (msg->flags & I2C_M_RD) {
194*d211e62aSManivannan Sadhasivam 		while ((readl(i2c_dev->base + OWL_I2C_REG_FIFOSTAT) &
195*d211e62aSManivannan Sadhasivam 			OWL_I2C_FIFOSTAT_RFE) && i2c_dev->msg_ptr < msg->len) {
196*d211e62aSManivannan Sadhasivam 			msg->buf[i2c_dev->msg_ptr++] = readl(i2c_dev->base +
197*d211e62aSManivannan Sadhasivam 							     OWL_I2C_REG_RXDAT);
198*d211e62aSManivannan Sadhasivam 		}
199*d211e62aSManivannan Sadhasivam 	} else {
200*d211e62aSManivannan Sadhasivam 		/* Handle the remaining bytes which were not sent */
201*d211e62aSManivannan Sadhasivam 		while (!(readl(i2c_dev->base + OWL_I2C_REG_FIFOSTAT) &
202*d211e62aSManivannan Sadhasivam 			 OWL_I2C_FIFOSTAT_TFF) && i2c_dev->msg_ptr < msg->len) {
203*d211e62aSManivannan Sadhasivam 			writel(msg->buf[i2c_dev->msg_ptr++],
204*d211e62aSManivannan Sadhasivam 			       i2c_dev->base + OWL_I2C_REG_TXDAT);
205*d211e62aSManivannan Sadhasivam 		}
206*d211e62aSManivannan Sadhasivam 	}
207*d211e62aSManivannan Sadhasivam 
208*d211e62aSManivannan Sadhasivam stop:
209*d211e62aSManivannan Sadhasivam 	/* Clear pending interrupts */
210*d211e62aSManivannan Sadhasivam 	owl_i2c_update_reg(i2c_dev->base + OWL_I2C_REG_STAT,
211*d211e62aSManivannan Sadhasivam 			   OWL_I2C_STAT_IRQP, true);
212*d211e62aSManivannan Sadhasivam 
213*d211e62aSManivannan Sadhasivam 	complete_all(&i2c_dev->msg_complete);
214*d211e62aSManivannan Sadhasivam 	spin_unlock_irqrestore(&i2c_dev->lock, flags);
215*d211e62aSManivannan Sadhasivam 
216*d211e62aSManivannan Sadhasivam 	return IRQ_HANDLED;
217*d211e62aSManivannan Sadhasivam }
218*d211e62aSManivannan Sadhasivam 
219*d211e62aSManivannan Sadhasivam static u32 owl_i2c_func(struct i2c_adapter *adap)
220*d211e62aSManivannan Sadhasivam {
221*d211e62aSManivannan Sadhasivam 	return I2C_FUNC_I2C | I2C_FUNC_SMBUS_EMUL;
222*d211e62aSManivannan Sadhasivam }
223*d211e62aSManivannan Sadhasivam 
224*d211e62aSManivannan Sadhasivam static int owl_i2c_check_bus_busy(struct i2c_adapter *adap)
225*d211e62aSManivannan Sadhasivam {
226*d211e62aSManivannan Sadhasivam 	struct owl_i2c_dev *i2c_dev = i2c_get_adapdata(adap);
227*d211e62aSManivannan Sadhasivam 	unsigned long timeout;
228*d211e62aSManivannan Sadhasivam 
229*d211e62aSManivannan Sadhasivam 	/* Check for Bus busy */
230*d211e62aSManivannan Sadhasivam 	timeout = jiffies + OWL_I2C_TIMEOUT;
231*d211e62aSManivannan Sadhasivam 	while (readl(i2c_dev->base + OWL_I2C_REG_STAT) & OWL_I2C_STAT_BBB) {
232*d211e62aSManivannan Sadhasivam 		if (time_after(jiffies, timeout)) {
233*d211e62aSManivannan Sadhasivam 			dev_err(&adap->dev, "Bus busy timeout\n");
234*d211e62aSManivannan Sadhasivam 			return -ETIMEDOUT;
235*d211e62aSManivannan Sadhasivam 		}
236*d211e62aSManivannan Sadhasivam 	}
237*d211e62aSManivannan Sadhasivam 
238*d211e62aSManivannan Sadhasivam 	return 0;
239*d211e62aSManivannan Sadhasivam }
240*d211e62aSManivannan Sadhasivam 
241*d211e62aSManivannan Sadhasivam static int owl_i2c_master_xfer(struct i2c_adapter *adap, struct i2c_msg *msgs,
242*d211e62aSManivannan Sadhasivam 			       int num)
243*d211e62aSManivannan Sadhasivam {
244*d211e62aSManivannan Sadhasivam 	struct owl_i2c_dev *i2c_dev = i2c_get_adapdata(adap);
245*d211e62aSManivannan Sadhasivam 	struct i2c_msg *msg;
246*d211e62aSManivannan Sadhasivam 	unsigned long time_left, flags;
247*d211e62aSManivannan Sadhasivam 	unsigned int i2c_cmd, val;
248*d211e62aSManivannan Sadhasivam 	unsigned int addr;
249*d211e62aSManivannan Sadhasivam 	int ret, idx;
250*d211e62aSManivannan Sadhasivam 
251*d211e62aSManivannan Sadhasivam 	spin_lock_irqsave(&i2c_dev->lock, flags);
252*d211e62aSManivannan Sadhasivam 
253*d211e62aSManivannan Sadhasivam 	/* Reset I2C controller */
254*d211e62aSManivannan Sadhasivam 	owl_i2c_reset(i2c_dev);
255*d211e62aSManivannan Sadhasivam 
256*d211e62aSManivannan Sadhasivam 	/* Set bus frequency */
257*d211e62aSManivannan Sadhasivam 	owl_i2c_set_freq(i2c_dev);
258*d211e62aSManivannan Sadhasivam 
259*d211e62aSManivannan Sadhasivam 	/*
260*d211e62aSManivannan Sadhasivam 	 * Spinlock should be released before calling reset FIFO and
261*d211e62aSManivannan Sadhasivam 	 * bus busy check since those functions may sleep
262*d211e62aSManivannan Sadhasivam 	 */
263*d211e62aSManivannan Sadhasivam 	spin_unlock_irqrestore(&i2c_dev->lock, flags);
264*d211e62aSManivannan Sadhasivam 
265*d211e62aSManivannan Sadhasivam 	/* Reset FIFO */
266*d211e62aSManivannan Sadhasivam 	ret = owl_i2c_reset_fifo(i2c_dev);
267*d211e62aSManivannan Sadhasivam 	if (ret)
268*d211e62aSManivannan Sadhasivam 		goto unlocked_err_exit;
269*d211e62aSManivannan Sadhasivam 
270*d211e62aSManivannan Sadhasivam 	/* Check for bus busy */
271*d211e62aSManivannan Sadhasivam 	ret = owl_i2c_check_bus_busy(adap);
272*d211e62aSManivannan Sadhasivam 	if (ret)
273*d211e62aSManivannan Sadhasivam 		goto unlocked_err_exit;
274*d211e62aSManivannan Sadhasivam 
275*d211e62aSManivannan Sadhasivam 	spin_lock_irqsave(&i2c_dev->lock, flags);
276*d211e62aSManivannan Sadhasivam 
277*d211e62aSManivannan Sadhasivam 	/* Check for Arbitration lost */
278*d211e62aSManivannan Sadhasivam 	val = readl(i2c_dev->base + OWL_I2C_REG_STAT);
279*d211e62aSManivannan Sadhasivam 	if (val & OWL_I2C_STAT_LAB) {
280*d211e62aSManivannan Sadhasivam 		val &= ~OWL_I2C_STAT_LAB;
281*d211e62aSManivannan Sadhasivam 		writel(val, i2c_dev->base + OWL_I2C_REG_STAT);
282*d211e62aSManivannan Sadhasivam 		ret = -EAGAIN;
283*d211e62aSManivannan Sadhasivam 		goto err_exit;
284*d211e62aSManivannan Sadhasivam 	}
285*d211e62aSManivannan Sadhasivam 
286*d211e62aSManivannan Sadhasivam 	reinit_completion(&i2c_dev->msg_complete);
287*d211e62aSManivannan Sadhasivam 
288*d211e62aSManivannan Sadhasivam 	/* Enable I2C controller interrupt */
289*d211e62aSManivannan Sadhasivam 	owl_i2c_update_reg(i2c_dev->base + OWL_I2C_REG_CTL,
290*d211e62aSManivannan Sadhasivam 			   OWL_I2C_CTL_IRQE, true);
291*d211e62aSManivannan Sadhasivam 
292*d211e62aSManivannan Sadhasivam 	/*
293*d211e62aSManivannan Sadhasivam 	 * Select: FIFO enable, Master mode, Stop enable, Data count enable,
294*d211e62aSManivannan Sadhasivam 	 * Send start bit
295*d211e62aSManivannan Sadhasivam 	 */
296*d211e62aSManivannan Sadhasivam 	i2c_cmd = OWL_I2C_CMD_SECL | OWL_I2C_CMD_MSS | OWL_I2C_CMD_SE |
297*d211e62aSManivannan Sadhasivam 		  OWL_I2C_CMD_NS | OWL_I2C_CMD_DE | OWL_I2C_CMD_SBE;
298*d211e62aSManivannan Sadhasivam 
299*d211e62aSManivannan Sadhasivam 	/* Handle repeated start condition */
300*d211e62aSManivannan Sadhasivam 	if (num > 1) {
301*d211e62aSManivannan Sadhasivam 		/* Set internal address length and enable repeated start */
302*d211e62aSManivannan Sadhasivam 		i2c_cmd |= OWL_I2C_CMD_AS(msgs[0].len + 1) |
303*d211e62aSManivannan Sadhasivam 			   OWL_I2C_CMD_SAS(1) | OWL_I2C_CMD_RBE;
304*d211e62aSManivannan Sadhasivam 
305*d211e62aSManivannan Sadhasivam 		/* Write slave address */
306*d211e62aSManivannan Sadhasivam 		addr = i2c_8bit_addr_from_msg(&msgs[0]);
307*d211e62aSManivannan Sadhasivam 		writel(addr, i2c_dev->base + OWL_I2C_REG_TXDAT);
308*d211e62aSManivannan Sadhasivam 
309*d211e62aSManivannan Sadhasivam 		/* Write internal register address */
310*d211e62aSManivannan Sadhasivam 		for (idx = 0; idx < msgs[0].len; idx++)
311*d211e62aSManivannan Sadhasivam 			writel(msgs[0].buf[idx],
312*d211e62aSManivannan Sadhasivam 			       i2c_dev->base + OWL_I2C_REG_TXDAT);
313*d211e62aSManivannan Sadhasivam 
314*d211e62aSManivannan Sadhasivam 		msg = &msgs[1];
315*d211e62aSManivannan Sadhasivam 	} else {
316*d211e62aSManivannan Sadhasivam 		/* Set address length */
317*d211e62aSManivannan Sadhasivam 		i2c_cmd |= OWL_I2C_CMD_AS(1);
318*d211e62aSManivannan Sadhasivam 		msg = &msgs[0];
319*d211e62aSManivannan Sadhasivam 	}
320*d211e62aSManivannan Sadhasivam 
321*d211e62aSManivannan Sadhasivam 	i2c_dev->msg = msg;
322*d211e62aSManivannan Sadhasivam 	i2c_dev->msg_ptr = 0;
323*d211e62aSManivannan Sadhasivam 
324*d211e62aSManivannan Sadhasivam 	/* Set data count for the message */
325*d211e62aSManivannan Sadhasivam 	writel(msg->len, i2c_dev->base + OWL_I2C_REG_DATCNT);
326*d211e62aSManivannan Sadhasivam 
327*d211e62aSManivannan Sadhasivam 	addr = i2c_8bit_addr_from_msg(msg);
328*d211e62aSManivannan Sadhasivam 	writel(addr, i2c_dev->base + OWL_I2C_REG_TXDAT);
329*d211e62aSManivannan Sadhasivam 
330*d211e62aSManivannan Sadhasivam 	if (!(msg->flags & I2C_M_RD)) {
331*d211e62aSManivannan Sadhasivam 		/* Write data to FIFO */
332*d211e62aSManivannan Sadhasivam 		for (idx = 0; idx < msg->len; idx++) {
333*d211e62aSManivannan Sadhasivam 			/* Check for FIFO full */
334*d211e62aSManivannan Sadhasivam 			if (readl(i2c_dev->base + OWL_I2C_REG_FIFOSTAT) &
335*d211e62aSManivannan Sadhasivam 			    OWL_I2C_FIFOSTAT_TFF)
336*d211e62aSManivannan Sadhasivam 				break;
337*d211e62aSManivannan Sadhasivam 
338*d211e62aSManivannan Sadhasivam 			writel(msg->buf[idx],
339*d211e62aSManivannan Sadhasivam 			       i2c_dev->base + OWL_I2C_REG_TXDAT);
340*d211e62aSManivannan Sadhasivam 		}
341*d211e62aSManivannan Sadhasivam 
342*d211e62aSManivannan Sadhasivam 		i2c_dev->msg_ptr = idx;
343*d211e62aSManivannan Sadhasivam 	}
344*d211e62aSManivannan Sadhasivam 
345*d211e62aSManivannan Sadhasivam 	/* Ignore the NACK if needed */
346*d211e62aSManivannan Sadhasivam 	if (msg->flags & I2C_M_IGNORE_NAK)
347*d211e62aSManivannan Sadhasivam 		owl_i2c_update_reg(i2c_dev->base + OWL_I2C_REG_FIFOCTL,
348*d211e62aSManivannan Sadhasivam 				   OWL_I2C_FIFOCTL_NIB, true);
349*d211e62aSManivannan Sadhasivam 	else
350*d211e62aSManivannan Sadhasivam 		owl_i2c_update_reg(i2c_dev->base + OWL_I2C_REG_FIFOCTL,
351*d211e62aSManivannan Sadhasivam 				   OWL_I2C_FIFOCTL_NIB, false);
352*d211e62aSManivannan Sadhasivam 
353*d211e62aSManivannan Sadhasivam 	/* Start the transfer */
354*d211e62aSManivannan Sadhasivam 	writel(i2c_cmd, i2c_dev->base + OWL_I2C_REG_CMD);
355*d211e62aSManivannan Sadhasivam 
356*d211e62aSManivannan Sadhasivam 	spin_unlock_irqrestore(&i2c_dev->lock, flags);
357*d211e62aSManivannan Sadhasivam 
358*d211e62aSManivannan Sadhasivam 	time_left = wait_for_completion_timeout(&i2c_dev->msg_complete,
359*d211e62aSManivannan Sadhasivam 						adap->timeout);
360*d211e62aSManivannan Sadhasivam 
361*d211e62aSManivannan Sadhasivam 	spin_lock_irqsave(&i2c_dev->lock, flags);
362*d211e62aSManivannan Sadhasivam 	if (time_left == 0) {
363*d211e62aSManivannan Sadhasivam 		dev_err(&adap->dev, "Transaction timed out\n");
364*d211e62aSManivannan Sadhasivam 		/* Send stop condition and release the bus */
365*d211e62aSManivannan Sadhasivam 		owl_i2c_update_reg(i2c_dev->base + OWL_I2C_REG_CTL,
366*d211e62aSManivannan Sadhasivam 				   OWL_I2C_CTL_GBCC_STOP | OWL_I2C_CTL_RB,
367*d211e62aSManivannan Sadhasivam 				   true);
368*d211e62aSManivannan Sadhasivam 		ret = -ETIMEDOUT;
369*d211e62aSManivannan Sadhasivam 		goto err_exit;
370*d211e62aSManivannan Sadhasivam 	}
371*d211e62aSManivannan Sadhasivam 
372*d211e62aSManivannan Sadhasivam 	ret = i2c_dev->err < 0 ? i2c_dev->err : num;
373*d211e62aSManivannan Sadhasivam 
374*d211e62aSManivannan Sadhasivam err_exit:
375*d211e62aSManivannan Sadhasivam 	spin_unlock_irqrestore(&i2c_dev->lock, flags);
376*d211e62aSManivannan Sadhasivam 
377*d211e62aSManivannan Sadhasivam unlocked_err_exit:
378*d211e62aSManivannan Sadhasivam 	/* Disable I2C controller */
379*d211e62aSManivannan Sadhasivam 	owl_i2c_update_reg(i2c_dev->base + OWL_I2C_REG_CTL,
380*d211e62aSManivannan Sadhasivam 			   OWL_I2C_CTL_EN, false);
381*d211e62aSManivannan Sadhasivam 
382*d211e62aSManivannan Sadhasivam 	return ret;
383*d211e62aSManivannan Sadhasivam }
384*d211e62aSManivannan Sadhasivam 
385*d211e62aSManivannan Sadhasivam static const struct i2c_algorithm owl_i2c_algorithm = {
386*d211e62aSManivannan Sadhasivam 	.master_xfer    = owl_i2c_master_xfer,
387*d211e62aSManivannan Sadhasivam 	.functionality  = owl_i2c_func,
388*d211e62aSManivannan Sadhasivam };
389*d211e62aSManivannan Sadhasivam 
390*d211e62aSManivannan Sadhasivam static const struct i2c_adapter_quirks owl_i2c_quirks = {
391*d211e62aSManivannan Sadhasivam 	.flags		= I2C_AQ_COMB | I2C_AQ_COMB_WRITE_FIRST,
392*d211e62aSManivannan Sadhasivam 	.max_read_len   = 240,
393*d211e62aSManivannan Sadhasivam 	.max_write_len  = 240,
394*d211e62aSManivannan Sadhasivam 	.max_comb_1st_msg_len = 6,
395*d211e62aSManivannan Sadhasivam 	.max_comb_2nd_msg_len = 240,
396*d211e62aSManivannan Sadhasivam };
397*d211e62aSManivannan Sadhasivam 
398*d211e62aSManivannan Sadhasivam static int owl_i2c_probe(struct platform_device *pdev)
399*d211e62aSManivannan Sadhasivam {
400*d211e62aSManivannan Sadhasivam 	struct device *dev = &pdev->dev;
401*d211e62aSManivannan Sadhasivam 	struct owl_i2c_dev *i2c_dev;
402*d211e62aSManivannan Sadhasivam 	struct resource *res;
403*d211e62aSManivannan Sadhasivam 	int ret, irq;
404*d211e62aSManivannan Sadhasivam 
405*d211e62aSManivannan Sadhasivam 	i2c_dev = devm_kzalloc(dev, sizeof(*i2c_dev), GFP_KERNEL);
406*d211e62aSManivannan Sadhasivam 	if (!i2c_dev)
407*d211e62aSManivannan Sadhasivam 		return -ENOMEM;
408*d211e62aSManivannan Sadhasivam 
409*d211e62aSManivannan Sadhasivam 	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
410*d211e62aSManivannan Sadhasivam 	i2c_dev->base = devm_ioremap_resource(dev, res);
411*d211e62aSManivannan Sadhasivam 	if (IS_ERR(i2c_dev->base))
412*d211e62aSManivannan Sadhasivam 		return PTR_ERR(i2c_dev->base);
413*d211e62aSManivannan Sadhasivam 
414*d211e62aSManivannan Sadhasivam 	irq = platform_get_irq(pdev, 0);
415*d211e62aSManivannan Sadhasivam 	if (irq < 0) {
416*d211e62aSManivannan Sadhasivam 		dev_err(dev, "failed to get IRQ number\n");
417*d211e62aSManivannan Sadhasivam 		return irq;
418*d211e62aSManivannan Sadhasivam 	}
419*d211e62aSManivannan Sadhasivam 
420*d211e62aSManivannan Sadhasivam 	if (of_property_read_u32(dev->of_node, "clock-frequency",
421*d211e62aSManivannan Sadhasivam 				 &i2c_dev->bus_freq))
422*d211e62aSManivannan Sadhasivam 		i2c_dev->bus_freq = OWL_I2C_DEF_SPEED_HZ;
423*d211e62aSManivannan Sadhasivam 
424*d211e62aSManivannan Sadhasivam 	/* We support only frequencies of 100k and 400k for now */
425*d211e62aSManivannan Sadhasivam 	if (i2c_dev->bus_freq != OWL_I2C_DEF_SPEED_HZ &&
426*d211e62aSManivannan Sadhasivam 	    i2c_dev->bus_freq != OWL_I2C_MAX_SPEED_HZ) {
427*d211e62aSManivannan Sadhasivam 		dev_err(dev, "invalid clock-frequency %d\n", i2c_dev->bus_freq);
428*d211e62aSManivannan Sadhasivam 		return -EINVAL;
429*d211e62aSManivannan Sadhasivam 	}
430*d211e62aSManivannan Sadhasivam 
431*d211e62aSManivannan Sadhasivam 	i2c_dev->clk = devm_clk_get(dev, NULL);
432*d211e62aSManivannan Sadhasivam 	if (IS_ERR(i2c_dev->clk)) {
433*d211e62aSManivannan Sadhasivam 		dev_err(dev, "failed to get clock\n");
434*d211e62aSManivannan Sadhasivam 		return PTR_ERR(i2c_dev->clk);
435*d211e62aSManivannan Sadhasivam 	}
436*d211e62aSManivannan Sadhasivam 
437*d211e62aSManivannan Sadhasivam 	ret = clk_prepare_enable(i2c_dev->clk);
438*d211e62aSManivannan Sadhasivam 	if (ret)
439*d211e62aSManivannan Sadhasivam 		return ret;
440*d211e62aSManivannan Sadhasivam 
441*d211e62aSManivannan Sadhasivam 	i2c_dev->clk_rate = clk_get_rate(i2c_dev->clk);
442*d211e62aSManivannan Sadhasivam 	if (!i2c_dev->clk_rate) {
443*d211e62aSManivannan Sadhasivam 		dev_err(dev, "input clock rate should not be zero\n");
444*d211e62aSManivannan Sadhasivam 		ret = -EINVAL;
445*d211e62aSManivannan Sadhasivam 		goto disable_clk;
446*d211e62aSManivannan Sadhasivam 	}
447*d211e62aSManivannan Sadhasivam 
448*d211e62aSManivannan Sadhasivam 	init_completion(&i2c_dev->msg_complete);
449*d211e62aSManivannan Sadhasivam 	spin_lock_init(&i2c_dev->lock);
450*d211e62aSManivannan Sadhasivam 	i2c_dev->adap.owner = THIS_MODULE;
451*d211e62aSManivannan Sadhasivam 	i2c_dev->adap.algo = &owl_i2c_algorithm;
452*d211e62aSManivannan Sadhasivam 	i2c_dev->adap.timeout = OWL_I2C_TIMEOUT;
453*d211e62aSManivannan Sadhasivam 	i2c_dev->adap.quirks = &owl_i2c_quirks;
454*d211e62aSManivannan Sadhasivam 	i2c_dev->adap.dev.parent = dev;
455*d211e62aSManivannan Sadhasivam 	i2c_dev->adap.dev.of_node = dev->of_node;
456*d211e62aSManivannan Sadhasivam 	snprintf(i2c_dev->adap.name, sizeof(i2c_dev->adap.name),
457*d211e62aSManivannan Sadhasivam 		 "%s", "OWL I2C adapter");
458*d211e62aSManivannan Sadhasivam 	i2c_set_adapdata(&i2c_dev->adap, i2c_dev);
459*d211e62aSManivannan Sadhasivam 
460*d211e62aSManivannan Sadhasivam 	platform_set_drvdata(pdev, i2c_dev);
461*d211e62aSManivannan Sadhasivam 
462*d211e62aSManivannan Sadhasivam 	ret = devm_request_irq(dev, irq, owl_i2c_interrupt, 0, pdev->name,
463*d211e62aSManivannan Sadhasivam 			       i2c_dev);
464*d211e62aSManivannan Sadhasivam 	if (ret) {
465*d211e62aSManivannan Sadhasivam 		dev_err(dev, "failed to request irq %d\n", irq);
466*d211e62aSManivannan Sadhasivam 		goto disable_clk;
467*d211e62aSManivannan Sadhasivam 	}
468*d211e62aSManivannan Sadhasivam 
469*d211e62aSManivannan Sadhasivam 	return i2c_add_adapter(&i2c_dev->adap);
470*d211e62aSManivannan Sadhasivam 
471*d211e62aSManivannan Sadhasivam disable_clk:
472*d211e62aSManivannan Sadhasivam 	clk_disable_unprepare(i2c_dev->clk);
473*d211e62aSManivannan Sadhasivam 
474*d211e62aSManivannan Sadhasivam 	return ret;
475*d211e62aSManivannan Sadhasivam }
476*d211e62aSManivannan Sadhasivam 
477*d211e62aSManivannan Sadhasivam static const struct of_device_id owl_i2c_of_match[] = {
478*d211e62aSManivannan Sadhasivam 	{ .compatible = "actions,s900-i2c" },
479*d211e62aSManivannan Sadhasivam 	{ /* sentinel */ }
480*d211e62aSManivannan Sadhasivam };
481*d211e62aSManivannan Sadhasivam MODULE_DEVICE_TABLE(of, owl_i2c_of_match);
482*d211e62aSManivannan Sadhasivam 
483*d211e62aSManivannan Sadhasivam static struct platform_driver owl_i2c_driver = {
484*d211e62aSManivannan Sadhasivam 	.probe		= owl_i2c_probe,
485*d211e62aSManivannan Sadhasivam 	.driver		= {
486*d211e62aSManivannan Sadhasivam 		.name	= "owl-i2c",
487*d211e62aSManivannan Sadhasivam 		.of_match_table = of_match_ptr(owl_i2c_of_match),
488*d211e62aSManivannan Sadhasivam 	},
489*d211e62aSManivannan Sadhasivam };
490*d211e62aSManivannan Sadhasivam module_platform_driver(owl_i2c_driver);
491*d211e62aSManivannan Sadhasivam 
492*d211e62aSManivannan Sadhasivam MODULE_AUTHOR("David Liu <liuwei@actions-semi.com>");
493*d211e62aSManivannan Sadhasivam MODULE_AUTHOR("Manivannan Sadhasivam <manivannan.sadhasivam@linaro.org>");
494*d211e62aSManivannan Sadhasivam MODULE_DESCRIPTION("Actions Semiconductor Owl SoC's I2C driver");
495*d211e62aSManivannan Sadhasivam MODULE_LICENSE("GPL");
496