xref: /linux/drivers/i2c/busses/i2c-rzv2m.c (revision a1ff5a7d78a036d6c2178ee5acd6ba4946243800)
1e0ca796aSPhil Edworthy // SPDX-License-Identifier: GPL-2.0
2e0ca796aSPhil Edworthy /*
3e0ca796aSPhil Edworthy  * Driver for the Renesas RZ/V2M I2C unit
4e0ca796aSPhil Edworthy  *
5e0ca796aSPhil Edworthy  * Copyright (C) 2016-2022 Renesas Electronics Corporation
6e0ca796aSPhil Edworthy  */
7e0ca796aSPhil Edworthy 
8e0ca796aSPhil Edworthy #include <linux/bits.h>
9e0ca796aSPhil Edworthy #include <linux/clk.h>
10e0ca796aSPhil Edworthy #include <linux/device.h>
11e0ca796aSPhil Edworthy #include <linux/err.h>
12e0ca796aSPhil Edworthy #include <linux/interrupt.h>
13e0ca796aSPhil Edworthy #include <linux/io.h>
14e0ca796aSPhil Edworthy #include <linux/iopoll.h>
15e0ca796aSPhil Edworthy #include <linux/i2c.h>
16e0ca796aSPhil Edworthy #include <linux/jiffies.h>
17e0ca796aSPhil Edworthy #include <linux/kernel.h>
18e0ca796aSPhil Edworthy #include <linux/math64.h>
19e0ca796aSPhil Edworthy #include <linux/module.h>
20e0ca796aSPhil Edworthy #include <linux/mod_devicetable.h>
21e0ca796aSPhil Edworthy #include <linux/platform_device.h>
22e0ca796aSPhil Edworthy #include <linux/pm_runtime.h>
23e0ca796aSPhil Edworthy #include <linux/reset.h>
24e0ca796aSPhil Edworthy 
25e0ca796aSPhil Edworthy /* Register offsets */
26e0ca796aSPhil Edworthy #define IICB0DAT	0x00		/* Data Register */
27e0ca796aSPhil Edworthy #define IICB0CTL0	0x08		/* Control Register 0 */
28e0ca796aSPhil Edworthy #define IICB0TRG	0x0C		/* Trigger Register */
29e0ca796aSPhil Edworthy #define IICB0STR0	0x10		/* Status Register 0 */
30e0ca796aSPhil Edworthy #define IICB0CTL1	0x20		/* Control Register 1 */
31e0ca796aSPhil Edworthy #define IICB0WL		0x24		/* Low Level Width Setting Reg */
32e0ca796aSPhil Edworthy #define IICB0WH		0x28		/* How Level Width Setting Reg */
33e0ca796aSPhil Edworthy 
34e0ca796aSPhil Edworthy /* IICB0CTL0 */
35e0ca796aSPhil Edworthy #define IICB0IICE	BIT(7)		/* I2C Enable */
36e0ca796aSPhil Edworthy #define IICB0SLWT	BIT(1)		/* Interrupt Request Timing */
37e0ca796aSPhil Edworthy #define IICB0SLAC	BIT(0)		/* Acknowledge */
38e0ca796aSPhil Edworthy 
39e0ca796aSPhil Edworthy /* IICB0TRG */
40e0ca796aSPhil Edworthy #define IICB0WRET	BIT(2)		/* Quit Wait Trigger */
41e0ca796aSPhil Edworthy #define IICB0STT	BIT(1)		/* Create Start Condition Trigger */
42e0ca796aSPhil Edworthy #define IICB0SPT	BIT(0)		/* Create Stop Condition Trigger */
43e0ca796aSPhil Edworthy 
44e0ca796aSPhil Edworthy /* IICB0STR0 */
45e0ca796aSPhil Edworthy #define IICB0SSAC	BIT(8)		/* Ack Flag */
46e0ca796aSPhil Edworthy #define IICB0SSBS	BIT(6)		/* Bus Flag */
47e0ca796aSPhil Edworthy #define IICB0SSSP	BIT(4)		/* Stop Condition Flag */
48e0ca796aSPhil Edworthy 
49e0ca796aSPhil Edworthy /* IICB0CTL1 */
50e0ca796aSPhil Edworthy #define IICB0MDSC	BIT(7)		/* Bus Mode */
51e0ca796aSPhil Edworthy #define IICB0SLSE	BIT(1)		/* Start condition output */
52e0ca796aSPhil Edworthy 
53e0ca796aSPhil Edworthy struct rzv2m_i2c_priv {
54e0ca796aSPhil Edworthy 	void __iomem *base;
55e0ca796aSPhil Edworthy 	struct i2c_adapter adap;
56e0ca796aSPhil Edworthy 	struct clk *clk;
57e0ca796aSPhil Edworthy 	int bus_mode;
58e0ca796aSPhil Edworthy 	struct completion msg_tia_done;
59e0ca796aSPhil Edworthy 	u32 iicb0wl;
60e0ca796aSPhil Edworthy 	u32 iicb0wh;
61e0ca796aSPhil Edworthy };
62e0ca796aSPhil Edworthy 
63e0ca796aSPhil Edworthy enum bcr_index {
64e0ca796aSPhil Edworthy 	RZV2M_I2C_100K = 0,
65e0ca796aSPhil Edworthy 	RZV2M_I2C_400K,
66e0ca796aSPhil Edworthy };
67e0ca796aSPhil Edworthy 
68e0ca796aSPhil Edworthy struct bitrate_config {
69e0ca796aSPhil Edworthy 	unsigned int percent_low;
70e0ca796aSPhil Edworthy 	unsigned int min_hold_time_ns;
71e0ca796aSPhil Edworthy };
72e0ca796aSPhil Edworthy 
73e0ca796aSPhil Edworthy static const struct bitrate_config bitrate_configs[] = {
74e0ca796aSPhil Edworthy 	[RZV2M_I2C_100K] = { 47, 3450 },
75e0ca796aSPhil Edworthy 	[RZV2M_I2C_400K] = { 52, 900 },
76e0ca796aSPhil Edworthy };
77e0ca796aSPhil Edworthy 
bit_setl(void __iomem * addr,u32 val)78252f211bSBiju Das static inline void bit_setl(void __iomem *addr, u32 val)
79252f211bSBiju Das {
80252f211bSBiju Das 	writel(readl(addr) | val, addr);
81252f211bSBiju Das }
82252f211bSBiju Das 
bit_clrl(void __iomem * addr,u32 val)83252f211bSBiju Das static inline void bit_clrl(void __iomem *addr, u32 val)
84252f211bSBiju Das {
85252f211bSBiju Das 	writel(readl(addr) & ~val, addr);
86252f211bSBiju Das }
87252f211bSBiju Das 
rzv2m_i2c_tia_irq_handler(int this_irq,void * dev_id)88e0ca796aSPhil Edworthy static irqreturn_t rzv2m_i2c_tia_irq_handler(int this_irq, void *dev_id)
89e0ca796aSPhil Edworthy {
90e0ca796aSPhil Edworthy 	struct rzv2m_i2c_priv *priv = dev_id;
91e0ca796aSPhil Edworthy 
92e0ca796aSPhil Edworthy 	complete(&priv->msg_tia_done);
93e0ca796aSPhil Edworthy 
94e0ca796aSPhil Edworthy 	return IRQ_HANDLED;
95e0ca796aSPhil Edworthy }
96e0ca796aSPhil Edworthy 
97e0ca796aSPhil Edworthy /* Calculate IICB0WL and IICB0WH */
rzv2m_i2c_clock_calculate(struct device * dev,struct rzv2m_i2c_priv * priv)98e0ca796aSPhil Edworthy static int rzv2m_i2c_clock_calculate(struct device *dev,
99e0ca796aSPhil Edworthy 				     struct rzv2m_i2c_priv *priv)
100e0ca796aSPhil Edworthy {
101e0ca796aSPhil Edworthy 	const struct bitrate_config *config;
102e0ca796aSPhil Edworthy 	unsigned int hold_time_ns;
103e0ca796aSPhil Edworthy 	unsigned int total_pclks;
104e0ca796aSPhil Edworthy 	unsigned int trf_pclks;
105e0ca796aSPhil Edworthy 	unsigned long pclk_hz;
106e0ca796aSPhil Edworthy 	struct i2c_timings t;
107e0ca796aSPhil Edworthy 	u32 trf_ns;
108e0ca796aSPhil Edworthy 
109e0ca796aSPhil Edworthy 	i2c_parse_fw_timings(dev, &t, true);
110e0ca796aSPhil Edworthy 
111e0ca796aSPhil Edworthy 	pclk_hz = clk_get_rate(priv->clk);
112e0ca796aSPhil Edworthy 	total_pclks = pclk_hz / t.bus_freq_hz;
113e0ca796aSPhil Edworthy 
114e0ca796aSPhil Edworthy 	trf_ns = t.scl_rise_ns + t.scl_fall_ns;
115e0ca796aSPhil Edworthy 	trf_pclks = mul_u64_u32_div(pclk_hz, trf_ns, NSEC_PER_SEC);
116e0ca796aSPhil Edworthy 
117e0ca796aSPhil Edworthy 	/* Config setting */
118e0ca796aSPhil Edworthy 	switch (t.bus_freq_hz) {
119e0ca796aSPhil Edworthy 	case I2C_MAX_FAST_MODE_FREQ:
120e0ca796aSPhil Edworthy 		priv->bus_mode = RZV2M_I2C_400K;
121e0ca796aSPhil Edworthy 		break;
122e0ca796aSPhil Edworthy 	case I2C_MAX_STANDARD_MODE_FREQ:
123e0ca796aSPhil Edworthy 		priv->bus_mode = RZV2M_I2C_100K;
124e0ca796aSPhil Edworthy 		break;
125e0ca796aSPhil Edworthy 	default:
126e0ca796aSPhil Edworthy 		dev_err(dev, "transfer speed is invalid\n");
127e0ca796aSPhil Edworthy 		return -EINVAL;
128e0ca796aSPhil Edworthy 	}
129e0ca796aSPhil Edworthy 	config = &bitrate_configs[priv->bus_mode];
130e0ca796aSPhil Edworthy 
131e0ca796aSPhil Edworthy 	/* IICB0WL = (percent_low / Transfer clock) x PCLK */
132e0ca796aSPhil Edworthy 	priv->iicb0wl = total_pclks * config->percent_low / 100;
133e0ca796aSPhil Edworthy 	if (priv->iicb0wl > (BIT(10) - 1))
134e0ca796aSPhil Edworthy 		return -EINVAL;
135e0ca796aSPhil Edworthy 
136e0ca796aSPhil Edworthy 	/* IICB0WH = ((percent_high / Transfer clock) x PCLK) - (tR + tF) */
137e0ca796aSPhil Edworthy 	priv->iicb0wh = total_pclks - priv->iicb0wl - trf_pclks;
138e0ca796aSPhil Edworthy 	if (priv->iicb0wh > (BIT(10) - 1))
139e0ca796aSPhil Edworthy 		return -EINVAL;
140e0ca796aSPhil Edworthy 
141e0ca796aSPhil Edworthy 	/*
142e0ca796aSPhil Edworthy 	 * Data hold time must be less than 0.9us in fast mode and
143e0ca796aSPhil Edworthy 	 * 3.45us in standard mode.
144e0ca796aSPhil Edworthy 	 * Data hold time = IICB0WL[9:2] / PCLK
145e0ca796aSPhil Edworthy 	 */
146e0ca796aSPhil Edworthy 	hold_time_ns = div64_ul((u64)(priv->iicb0wl >> 2) * NSEC_PER_SEC, pclk_hz);
147e0ca796aSPhil Edworthy 	if (hold_time_ns > config->min_hold_time_ns) {
148e0ca796aSPhil Edworthy 		dev_err(dev, "data hold time %dns is over %dns\n",
149e0ca796aSPhil Edworthy 			hold_time_ns, config->min_hold_time_ns);
150e0ca796aSPhil Edworthy 		return -EINVAL;
151e0ca796aSPhil Edworthy 	}
152e0ca796aSPhil Edworthy 
153e0ca796aSPhil Edworthy 	return 0;
154e0ca796aSPhil Edworthy }
155e0ca796aSPhil Edworthy 
rzv2m_i2c_init(struct rzv2m_i2c_priv * priv)156e0ca796aSPhil Edworthy static void rzv2m_i2c_init(struct rzv2m_i2c_priv *priv)
157e0ca796aSPhil Edworthy {
158e0ca796aSPhil Edworthy 	u32 i2c_ctl0;
159e0ca796aSPhil Edworthy 	u32 i2c_ctl1;
160e0ca796aSPhil Edworthy 
161e0ca796aSPhil Edworthy 	/* i2c disable */
162e0ca796aSPhil Edworthy 	writel(0, priv->base + IICB0CTL0);
163e0ca796aSPhil Edworthy 
164e0ca796aSPhil Edworthy 	/* IICB0CTL1 setting */
165e0ca796aSPhil Edworthy 	i2c_ctl1 = IICB0SLSE;
166e0ca796aSPhil Edworthy 	if (priv->bus_mode == RZV2M_I2C_400K)
167e0ca796aSPhil Edworthy 		i2c_ctl1 |= IICB0MDSC;
168e0ca796aSPhil Edworthy 	writel(i2c_ctl1, priv->base + IICB0CTL1);
169e0ca796aSPhil Edworthy 
170e0ca796aSPhil Edworthy 	/* IICB0WL IICB0WH setting */
171e0ca796aSPhil Edworthy 	writel(priv->iicb0wl, priv->base + IICB0WL);
172e0ca796aSPhil Edworthy 	writel(priv->iicb0wh, priv->base + IICB0WH);
173e0ca796aSPhil Edworthy 
174e0ca796aSPhil Edworthy 	/* i2c enable after setting */
175e0ca796aSPhil Edworthy 	i2c_ctl0 = IICB0SLWT | IICB0SLAC | IICB0IICE;
176e0ca796aSPhil Edworthy 	writel(i2c_ctl0, priv->base + IICB0CTL0);
177e0ca796aSPhil Edworthy }
178e0ca796aSPhil Edworthy 
rzv2m_i2c_write_with_ack(struct rzv2m_i2c_priv * priv,u32 data)179e0ca796aSPhil Edworthy static int rzv2m_i2c_write_with_ack(struct rzv2m_i2c_priv *priv, u32 data)
180e0ca796aSPhil Edworthy {
181e0ca796aSPhil Edworthy 	unsigned long time_left;
182e0ca796aSPhil Edworthy 
183e0ca796aSPhil Edworthy 	reinit_completion(&priv->msg_tia_done);
184e0ca796aSPhil Edworthy 
185e0ca796aSPhil Edworthy 	writel(data, priv->base + IICB0DAT);
186e0ca796aSPhil Edworthy 
187e0ca796aSPhil Edworthy 	time_left = wait_for_completion_timeout(&priv->msg_tia_done,
188e0ca796aSPhil Edworthy 						priv->adap.timeout);
189e0ca796aSPhil Edworthy 	if (!time_left)
190e0ca796aSPhil Edworthy 		return -ETIMEDOUT;
191e0ca796aSPhil Edworthy 
192e0ca796aSPhil Edworthy 	/* Confirm ACK */
193e0ca796aSPhil Edworthy 	if ((readl(priv->base + IICB0STR0) & IICB0SSAC) != IICB0SSAC)
194e0ca796aSPhil Edworthy 		return -ENXIO;
195e0ca796aSPhil Edworthy 
196e0ca796aSPhil Edworthy 	return 0;
197e0ca796aSPhil Edworthy }
198e0ca796aSPhil Edworthy 
rzv2m_i2c_read_with_ack(struct rzv2m_i2c_priv * priv,u8 * data,bool last)199e0ca796aSPhil Edworthy static int rzv2m_i2c_read_with_ack(struct rzv2m_i2c_priv *priv, u8 *data,
200e0ca796aSPhil Edworthy 				   bool last)
201e0ca796aSPhil Edworthy {
202e0ca796aSPhil Edworthy 	unsigned long time_left;
203e0ca796aSPhil Edworthy 	u32 data_tmp;
204e0ca796aSPhil Edworthy 
205e0ca796aSPhil Edworthy 	reinit_completion(&priv->msg_tia_done);
206e0ca796aSPhil Edworthy 
207e0ca796aSPhil Edworthy 	/* Interrupt request timing : 8th clock */
208e0ca796aSPhil Edworthy 	bit_clrl(priv->base + IICB0CTL0, IICB0SLWT);
209e0ca796aSPhil Edworthy 
210e0ca796aSPhil Edworthy 	/* Exit the wait state */
211e0ca796aSPhil Edworthy 	writel(IICB0WRET, priv->base + IICB0TRG);
212e0ca796aSPhil Edworthy 
213e0ca796aSPhil Edworthy 	/* Wait for transaction */
214e0ca796aSPhil Edworthy 	time_left = wait_for_completion_timeout(&priv->msg_tia_done,
215e0ca796aSPhil Edworthy 						priv->adap.timeout);
216e0ca796aSPhil Edworthy 	if (!time_left)
217e0ca796aSPhil Edworthy 		return -ETIMEDOUT;
218e0ca796aSPhil Edworthy 
219e0ca796aSPhil Edworthy 	if (last) {
220e0ca796aSPhil Edworthy 		/* Disable ACK */
221e0ca796aSPhil Edworthy 		bit_clrl(priv->base + IICB0CTL0, IICB0SLAC);
222e0ca796aSPhil Edworthy 
223e0ca796aSPhil Edworthy 		/* Read data*/
224e0ca796aSPhil Edworthy 		data_tmp = readl(priv->base + IICB0DAT);
225e0ca796aSPhil Edworthy 
226e0ca796aSPhil Edworthy 		/* Interrupt request timing : 9th clock */
227e0ca796aSPhil Edworthy 		bit_setl(priv->base + IICB0CTL0, IICB0SLWT);
228e0ca796aSPhil Edworthy 
229e0ca796aSPhil Edworthy 		/* Exit the wait state */
230e0ca796aSPhil Edworthy 		writel(IICB0WRET, priv->base + IICB0TRG);
231e0ca796aSPhil Edworthy 
232e0ca796aSPhil Edworthy 		/* Wait for transaction */
233e0ca796aSPhil Edworthy 		time_left = wait_for_completion_timeout(&priv->msg_tia_done,
234e0ca796aSPhil Edworthy 							priv->adap.timeout);
235e0ca796aSPhil Edworthy 		if (!time_left)
236e0ca796aSPhil Edworthy 			return -ETIMEDOUT;
237e0ca796aSPhil Edworthy 
238e0ca796aSPhil Edworthy 		/* Enable ACK */
239e0ca796aSPhil Edworthy 		bit_setl(priv->base + IICB0CTL0, IICB0SLAC);
240e0ca796aSPhil Edworthy 	} else {
241e0ca796aSPhil Edworthy 		/* Read data */
242e0ca796aSPhil Edworthy 		data_tmp = readl(priv->base + IICB0DAT);
243e0ca796aSPhil Edworthy 	}
244e0ca796aSPhil Edworthy 
245e0ca796aSPhil Edworthy 	*data = data_tmp;
246e0ca796aSPhil Edworthy 
247e0ca796aSPhil Edworthy 	return 0;
248e0ca796aSPhil Edworthy }
249e0ca796aSPhil Edworthy 
rzv2m_i2c_send(struct rzv2m_i2c_priv * priv,struct i2c_msg * msg,unsigned int * count)250e0ca796aSPhil Edworthy static int rzv2m_i2c_send(struct rzv2m_i2c_priv *priv, struct i2c_msg *msg,
251e0ca796aSPhil Edworthy 			  unsigned int *count)
252e0ca796aSPhil Edworthy {
253e0ca796aSPhil Edworthy 	unsigned int i;
254e0ca796aSPhil Edworthy 	int ret;
255e0ca796aSPhil Edworthy 
256e0ca796aSPhil Edworthy 	for (i = 0; i < msg->len; i++) {
257e0ca796aSPhil Edworthy 		ret = rzv2m_i2c_write_with_ack(priv, msg->buf[i]);
258e0ca796aSPhil Edworthy 		if (ret < 0)
259e0ca796aSPhil Edworthy 			return ret;
260e0ca796aSPhil Edworthy 	}
261e0ca796aSPhil Edworthy 	*count = i;
262e0ca796aSPhil Edworthy 
263e0ca796aSPhil Edworthy 	return 0;
264e0ca796aSPhil Edworthy }
265e0ca796aSPhil Edworthy 
rzv2m_i2c_receive(struct rzv2m_i2c_priv * priv,struct i2c_msg * msg,unsigned int * count)266e0ca796aSPhil Edworthy static int rzv2m_i2c_receive(struct rzv2m_i2c_priv *priv, struct i2c_msg *msg,
267e0ca796aSPhil Edworthy 			     unsigned int *count)
268e0ca796aSPhil Edworthy {
269e0ca796aSPhil Edworthy 	unsigned int i;
270e0ca796aSPhil Edworthy 	int ret;
271e0ca796aSPhil Edworthy 
272e0ca796aSPhil Edworthy 	for (i = 0; i < msg->len; i++) {
273e0ca796aSPhil Edworthy 		ret = rzv2m_i2c_read_with_ack(priv, &msg->buf[i],
274e0ca796aSPhil Edworthy 					      (msg->len - 1) == i);
275e0ca796aSPhil Edworthy 		if (ret < 0)
276e0ca796aSPhil Edworthy 			return ret;
277e0ca796aSPhil Edworthy 	}
278e0ca796aSPhil Edworthy 	*count = i;
279e0ca796aSPhil Edworthy 
280e0ca796aSPhil Edworthy 	return 0;
281e0ca796aSPhil Edworthy }
282e0ca796aSPhil Edworthy 
rzv2m_i2c_send_address(struct rzv2m_i2c_priv * priv,struct i2c_msg * msg)283e0ca796aSPhil Edworthy static int rzv2m_i2c_send_address(struct rzv2m_i2c_priv *priv,
284e0ca796aSPhil Edworthy 				  struct i2c_msg *msg)
285e0ca796aSPhil Edworthy {
286e0ca796aSPhil Edworthy 	u32 addr;
287e0ca796aSPhil Edworthy 	int ret;
288e0ca796aSPhil Edworthy 
289e0ca796aSPhil Edworthy 	if (msg->flags & I2C_M_TEN) {
290e0ca796aSPhil Edworthy 		/*
291e0ca796aSPhil Edworthy 		 * 10-bit address
292e0ca796aSPhil Edworthy 		 *   addr_1: 5'b11110 | addr[9:8] | (R/nW)
293e0ca796aSPhil Edworthy 		 *   addr_2: addr[7:0]
294e0ca796aSPhil Edworthy 		 */
295e0ca796aSPhil Edworthy 		addr = 0xf0 | ((msg->addr & GENMASK(9, 8)) >> 7);
296e0ca796aSPhil Edworthy 		addr |= !!(msg->flags & I2C_M_RD);
297e0ca796aSPhil Edworthy 		/* Send 1st address(extend code) */
298e0ca796aSPhil Edworthy 		ret = rzv2m_i2c_write_with_ack(priv, addr);
299e0ca796aSPhil Edworthy 		if (ret)
300e0ca796aSPhil Edworthy 			return ret;
301e0ca796aSPhil Edworthy 
302e0ca796aSPhil Edworthy 		/* Send 2nd address */
303e0ca796aSPhil Edworthy 		ret = rzv2m_i2c_write_with_ack(priv, msg->addr & 0xff);
304e0ca796aSPhil Edworthy 	} else {
305e0ca796aSPhil Edworthy 		/* 7-bit address */
306e0ca796aSPhil Edworthy 		addr = i2c_8bit_addr_from_msg(msg);
307e0ca796aSPhil Edworthy 		ret = rzv2m_i2c_write_with_ack(priv, addr);
308e0ca796aSPhil Edworthy 	}
309e0ca796aSPhil Edworthy 
310e0ca796aSPhil Edworthy 	return ret;
311e0ca796aSPhil Edworthy }
312e0ca796aSPhil Edworthy 
rzv2m_i2c_stop_condition(struct rzv2m_i2c_priv * priv)313e0ca796aSPhil Edworthy static int rzv2m_i2c_stop_condition(struct rzv2m_i2c_priv *priv)
314e0ca796aSPhil Edworthy {
315e0ca796aSPhil Edworthy 	u32 value;
316e0ca796aSPhil Edworthy 
317e0ca796aSPhil Edworthy 	/* Send stop condition */
318e0ca796aSPhil Edworthy 	writel(IICB0SPT, priv->base + IICB0TRG);
319e0ca796aSPhil Edworthy 	return readl_poll_timeout(priv->base + IICB0STR0,
320e0ca796aSPhil Edworthy 				  value, value & IICB0SSSP,
321e0ca796aSPhil Edworthy 				  100, jiffies_to_usecs(priv->adap.timeout));
322e0ca796aSPhil Edworthy }
323e0ca796aSPhil Edworthy 
rzv2m_i2c_xfer_msg(struct rzv2m_i2c_priv * priv,struct i2c_msg * msg,int stop)324*39a6695fSWolfram Sang static int rzv2m_i2c_xfer_msg(struct rzv2m_i2c_priv *priv,
325e0ca796aSPhil Edworthy 			      struct i2c_msg *msg, int stop)
326e0ca796aSPhil Edworthy {
327e0ca796aSPhil Edworthy 	unsigned int count = 0;
328e0ca796aSPhil Edworthy 	int ret, read = !!(msg->flags & I2C_M_RD);
329e0ca796aSPhil Edworthy 
330e0ca796aSPhil Edworthy 	/* Send start condition */
331e0ca796aSPhil Edworthy 	writel(IICB0STT, priv->base + IICB0TRG);
332e0ca796aSPhil Edworthy 
333e0ca796aSPhil Edworthy 	ret = rzv2m_i2c_send_address(priv, msg);
334e0ca796aSPhil Edworthy 	if (!ret) {
335e0ca796aSPhil Edworthy 		if (read)
336e0ca796aSPhil Edworthy 			ret = rzv2m_i2c_receive(priv, msg, &count);
337e0ca796aSPhil Edworthy 		else
338e0ca796aSPhil Edworthy 			ret = rzv2m_i2c_send(priv, msg, &count);
339e0ca796aSPhil Edworthy 
340e0ca796aSPhil Edworthy 		if (!ret && stop)
341e0ca796aSPhil Edworthy 			ret = rzv2m_i2c_stop_condition(priv);
342e0ca796aSPhil Edworthy 	}
343e0ca796aSPhil Edworthy 
344e0ca796aSPhil Edworthy 	if (ret == -ENXIO)
345e0ca796aSPhil Edworthy 		rzv2m_i2c_stop_condition(priv);
346e0ca796aSPhil Edworthy 	else if (ret < 0)
347e0ca796aSPhil Edworthy 		rzv2m_i2c_init(priv);
348e0ca796aSPhil Edworthy 	else
349e0ca796aSPhil Edworthy 		ret = count;
350e0ca796aSPhil Edworthy 
351e0ca796aSPhil Edworthy 	return ret;
352e0ca796aSPhil Edworthy }
353e0ca796aSPhil Edworthy 
rzv2m_i2c_xfer(struct i2c_adapter * adap,struct i2c_msg * msgs,int num)354*39a6695fSWolfram Sang static int rzv2m_i2c_xfer(struct i2c_adapter *adap,
355e0ca796aSPhil Edworthy 			  struct i2c_msg *msgs, int num)
356e0ca796aSPhil Edworthy {
357e0ca796aSPhil Edworthy 	struct rzv2m_i2c_priv *priv = i2c_get_adapdata(adap);
358e0ca796aSPhil Edworthy 	struct device *dev = priv->adap.dev.parent;
359e0ca796aSPhil Edworthy 	unsigned int i;
360e0ca796aSPhil Edworthy 	int ret;
361e0ca796aSPhil Edworthy 
362e0ca796aSPhil Edworthy 	ret = pm_runtime_resume_and_get(dev);
363e0ca796aSPhil Edworthy 	if (ret < 0)
364e0ca796aSPhil Edworthy 		return ret;
365e0ca796aSPhil Edworthy 
366e0ca796aSPhil Edworthy 	if (readl(priv->base + IICB0STR0) & IICB0SSBS) {
367e0ca796aSPhil Edworthy 		ret = -EAGAIN;
368e0ca796aSPhil Edworthy 		goto out;
369e0ca796aSPhil Edworthy 	}
370e0ca796aSPhil Edworthy 
371e0ca796aSPhil Edworthy 	/* I2C main transfer */
372e0ca796aSPhil Edworthy 	for (i = 0; i < num; i++) {
373*39a6695fSWolfram Sang 		ret = rzv2m_i2c_xfer_msg(priv, &msgs[i], i == (num - 1));
374e0ca796aSPhil Edworthy 		if (ret < 0)
375e0ca796aSPhil Edworthy 			goto out;
376e0ca796aSPhil Edworthy 	}
377e0ca796aSPhil Edworthy 	ret = num;
378e0ca796aSPhil Edworthy 
379e0ca796aSPhil Edworthy out:
380e0ca796aSPhil Edworthy 	pm_runtime_mark_last_busy(dev);
381e0ca796aSPhil Edworthy 	pm_runtime_put_autosuspend(dev);
382e0ca796aSPhil Edworthy 
383e0ca796aSPhil Edworthy 	return ret;
384e0ca796aSPhil Edworthy }
385e0ca796aSPhil Edworthy 
rzv2m_i2c_func(struct i2c_adapter * adap)386e0ca796aSPhil Edworthy static u32 rzv2m_i2c_func(struct i2c_adapter *adap)
387e0ca796aSPhil Edworthy {
388e0ca796aSPhil Edworthy 	return I2C_FUNC_I2C | (I2C_FUNC_SMBUS_EMUL & ~I2C_FUNC_SMBUS_QUICK) |
389e0ca796aSPhil Edworthy 	       I2C_FUNC_10BIT_ADDR;
390e0ca796aSPhil Edworthy }
391e0ca796aSPhil Edworthy 
rzv2m_i2c_disable(struct device * dev,struct rzv2m_i2c_priv * priv)392c3cc5c59SBiju Das static int rzv2m_i2c_disable(struct device *dev, struct rzv2m_i2c_priv *priv)
393c3cc5c59SBiju Das {
394c3cc5c59SBiju Das 	int ret;
395c3cc5c59SBiju Das 
396c3cc5c59SBiju Das 	ret = pm_runtime_resume_and_get(dev);
397c3cc5c59SBiju Das 	if (ret < 0)
398c3cc5c59SBiju Das 		return ret;
399c3cc5c59SBiju Das 
400c3cc5c59SBiju Das 	bit_clrl(priv->base + IICB0CTL0, IICB0IICE);
401c3cc5c59SBiju Das 	pm_runtime_put(dev);
402c3cc5c59SBiju Das 
403c3cc5c59SBiju Das 	return 0;
404c3cc5c59SBiju Das }
405c3cc5c59SBiju Das 
406e0ca796aSPhil Edworthy static const struct i2c_adapter_quirks rzv2m_i2c_quirks = {
407e0ca796aSPhil Edworthy 	.flags = I2C_AQ_NO_ZERO_LEN,
408e0ca796aSPhil Edworthy };
409e0ca796aSPhil Edworthy 
410e0ca796aSPhil Edworthy static struct i2c_algorithm rzv2m_i2c_algo = {
411*39a6695fSWolfram Sang 	.xfer = rzv2m_i2c_xfer,
412e0ca796aSPhil Edworthy 	.functionality = rzv2m_i2c_func,
413e0ca796aSPhil Edworthy };
414e0ca796aSPhil Edworthy 
rzv2m_i2c_probe(struct platform_device * pdev)415e0ca796aSPhil Edworthy static int rzv2m_i2c_probe(struct platform_device *pdev)
416e0ca796aSPhil Edworthy {
417e0ca796aSPhil Edworthy 	struct device *dev = &pdev->dev;
418e0ca796aSPhil Edworthy 	struct rzv2m_i2c_priv *priv;
419e0ca796aSPhil Edworthy 	struct reset_control *rstc;
420e0ca796aSPhil Edworthy 	struct i2c_adapter *adap;
421e0ca796aSPhil Edworthy 	struct resource *res;
422e0ca796aSPhil Edworthy 	int irq, ret;
423e0ca796aSPhil Edworthy 
424e0ca796aSPhil Edworthy 	priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL);
425e0ca796aSPhil Edworthy 	if (!priv)
426e0ca796aSPhil Edworthy 		return -ENOMEM;
427e0ca796aSPhil Edworthy 
428e0ca796aSPhil Edworthy 	priv->base = devm_platform_get_and_ioremap_resource(pdev, 0, &res);
429e0ca796aSPhil Edworthy 	if (IS_ERR(priv->base))
430e0ca796aSPhil Edworthy 		return PTR_ERR(priv->base);
431e0ca796aSPhil Edworthy 
432e0ca796aSPhil Edworthy 	priv->clk = devm_clk_get(dev, NULL);
433e0ca796aSPhil Edworthy 	if (IS_ERR(priv->clk))
434e0ca796aSPhil Edworthy 		return dev_err_probe(dev, PTR_ERR(priv->clk), "Can't get clock\n");
435e0ca796aSPhil Edworthy 
436e0ca796aSPhil Edworthy 	rstc = devm_reset_control_get_shared(dev, NULL);
437e0ca796aSPhil Edworthy 	if (IS_ERR(rstc))
438e0ca796aSPhil Edworthy 		return dev_err_probe(dev, PTR_ERR(rstc), "Missing reset ctrl\n");
439e0ca796aSPhil Edworthy 	/*
440e0ca796aSPhil Edworthy 	 * The reset also affects other HW that is not under the control
441e0ca796aSPhil Edworthy 	 * of Linux. Therefore, all we can do is deassert the reset.
442e0ca796aSPhil Edworthy 	 */
443e0ca796aSPhil Edworthy 	reset_control_deassert(rstc);
444e0ca796aSPhil Edworthy 
445e0ca796aSPhil Edworthy 	irq = platform_get_irq(pdev, 0);
446e0ca796aSPhil Edworthy 	if (irq < 0)
447e0ca796aSPhil Edworthy 		return irq;
448e0ca796aSPhil Edworthy 
449e0ca796aSPhil Edworthy 	ret = devm_request_irq(dev, irq, rzv2m_i2c_tia_irq_handler, 0,
450e0ca796aSPhil Edworthy 			       dev_name(dev), priv);
451e0ca796aSPhil Edworthy 	if (ret < 0)
452e0ca796aSPhil Edworthy 		return dev_err_probe(dev, ret, "Unable to request irq %d\n", irq);
453e0ca796aSPhil Edworthy 
454e0ca796aSPhil Edworthy 	adap = &priv->adap;
455e0ca796aSPhil Edworthy 	adap->nr = pdev->id;
456e0ca796aSPhil Edworthy 	adap->algo = &rzv2m_i2c_algo;
457e0ca796aSPhil Edworthy 	adap->quirks = &rzv2m_i2c_quirks;
458e0ca796aSPhil Edworthy 	adap->dev.parent = dev;
459e0ca796aSPhil Edworthy 	adap->owner = THIS_MODULE;
460e0ca796aSPhil Edworthy 	device_set_node(&adap->dev, dev_fwnode(dev));
461e0ca796aSPhil Edworthy 	i2c_set_adapdata(adap, priv);
462e0ca796aSPhil Edworthy 	strscpy(adap->name, pdev->name, sizeof(adap->name));
463e0ca796aSPhil Edworthy 	init_completion(&priv->msg_tia_done);
464e0ca796aSPhil Edworthy 
465e0ca796aSPhil Edworthy 	ret = rzv2m_i2c_clock_calculate(dev, priv);
466e0ca796aSPhil Edworthy 	if (ret < 0)
467e0ca796aSPhil Edworthy 		return ret;
468e0ca796aSPhil Edworthy 
469e0ca796aSPhil Edworthy 	pm_runtime_enable(dev);
470e0ca796aSPhil Edworthy 
471e0ca796aSPhil Edworthy 	pm_runtime_get_sync(dev);
472e0ca796aSPhil Edworthy 	rzv2m_i2c_init(priv);
473e0ca796aSPhil Edworthy 	pm_runtime_put(dev);
474e0ca796aSPhil Edworthy 
475e0ca796aSPhil Edworthy 	platform_set_drvdata(pdev, priv);
476e0ca796aSPhil Edworthy 
477e0ca796aSPhil Edworthy 	ret = i2c_add_numbered_adapter(adap);
478c3cc5c59SBiju Das 	if (ret < 0) {
479c3cc5c59SBiju Das 		rzv2m_i2c_disable(dev, priv);
480e0ca796aSPhil Edworthy 		pm_runtime_disable(dev);
481c3cc5c59SBiju Das 	}
482e0ca796aSPhil Edworthy 
483e0ca796aSPhil Edworthy 	return ret;
484e0ca796aSPhil Edworthy }
485e0ca796aSPhil Edworthy 
rzv2m_i2c_remove(struct platform_device * pdev)486e190a0c3SUwe Kleine-König static void rzv2m_i2c_remove(struct platform_device *pdev)
487e0ca796aSPhil Edworthy {
488e0ca796aSPhil Edworthy 	struct rzv2m_i2c_priv *priv = platform_get_drvdata(pdev);
489e0ca796aSPhil Edworthy 	struct device *dev = priv->adap.dev.parent;
490e0ca796aSPhil Edworthy 
491e0ca796aSPhil Edworthy 	i2c_del_adapter(&priv->adap);
492c3cc5c59SBiju Das 	rzv2m_i2c_disable(dev, priv);
493e0ca796aSPhil Edworthy 	pm_runtime_disable(dev);
494e0ca796aSPhil Edworthy }
495e0ca796aSPhil Edworthy 
rzv2m_i2c_suspend(struct device * dev)496e0ca796aSPhil Edworthy static int rzv2m_i2c_suspend(struct device *dev)
497e0ca796aSPhil Edworthy {
498e0ca796aSPhil Edworthy 	struct rzv2m_i2c_priv *priv = dev_get_drvdata(dev);
499e0ca796aSPhil Edworthy 
500c3cc5c59SBiju Das 	return rzv2m_i2c_disable(dev, priv);
501e0ca796aSPhil Edworthy }
502e0ca796aSPhil Edworthy 
rzv2m_i2c_resume(struct device * dev)503e0ca796aSPhil Edworthy static int rzv2m_i2c_resume(struct device *dev)
504e0ca796aSPhil Edworthy {
505e0ca796aSPhil Edworthy 	struct rzv2m_i2c_priv *priv = dev_get_drvdata(dev);
506e0ca796aSPhil Edworthy 	int ret;
507e0ca796aSPhil Edworthy 
508e0ca796aSPhil Edworthy 	ret = rzv2m_i2c_clock_calculate(dev, priv);
509e0ca796aSPhil Edworthy 	if (ret < 0)
510e0ca796aSPhil Edworthy 		return ret;
511e0ca796aSPhil Edworthy 
512e0ca796aSPhil Edworthy 	ret = pm_runtime_resume_and_get(dev);
513e0ca796aSPhil Edworthy 	if (ret < 0)
514e0ca796aSPhil Edworthy 		return ret;
515e0ca796aSPhil Edworthy 
516e0ca796aSPhil Edworthy 	rzv2m_i2c_init(priv);
517e0ca796aSPhil Edworthy 	pm_runtime_put(dev);
518e0ca796aSPhil Edworthy 
519e0ca796aSPhil Edworthy 	return 0;
520e0ca796aSPhil Edworthy }
521e0ca796aSPhil Edworthy 
522e0ca796aSPhil Edworthy static const struct of_device_id rzv2m_i2c_ids[] = {
523e0ca796aSPhil Edworthy 	{ .compatible = "renesas,rzv2m-i2c" },
524e0ca796aSPhil Edworthy 	{ }
525e0ca796aSPhil Edworthy };
526e0ca796aSPhil Edworthy MODULE_DEVICE_TABLE(of, rzv2m_i2c_ids);
527e0ca796aSPhil Edworthy 
528e0ca796aSPhil Edworthy static const struct dev_pm_ops rzv2m_i2c_pm_ops = {
529e0ca796aSPhil Edworthy 	SYSTEM_SLEEP_PM_OPS(rzv2m_i2c_suspend, rzv2m_i2c_resume)
530e0ca796aSPhil Edworthy };
531e0ca796aSPhil Edworthy 
532e0ca796aSPhil Edworthy static struct platform_driver rzv2m_i2c_driver = {
533e0ca796aSPhil Edworthy 	.driver = {
534e0ca796aSPhil Edworthy 		.name = "rzv2m-i2c",
535e0ca796aSPhil Edworthy 		.of_match_table = rzv2m_i2c_ids,
536e0ca796aSPhil Edworthy 		.pm = pm_sleep_ptr(&rzv2m_i2c_pm_ops),
537e0ca796aSPhil Edworthy 	},
538e0ca796aSPhil Edworthy 	.probe	= rzv2m_i2c_probe,
539e190a0c3SUwe Kleine-König 	.remove_new = rzv2m_i2c_remove,
540e0ca796aSPhil Edworthy };
541e0ca796aSPhil Edworthy module_platform_driver(rzv2m_i2c_driver);
542e0ca796aSPhil Edworthy 
543e0ca796aSPhil Edworthy MODULE_DESCRIPTION("RZ/V2M I2C bus driver");
544e0ca796aSPhil Edworthy MODULE_AUTHOR("Renesas Electronics Corporation");
545e0ca796aSPhil Edworthy MODULE_LICENSE("GPL");
546