162306a36Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0-or-later
262306a36Sopenharmony_ci/*
362306a36Sopenharmony_ci * Actions Semiconductor Owl SoC's I2C driver
462306a36Sopenharmony_ci *
562306a36Sopenharmony_ci * Copyright (c) 2014 Actions Semi Inc.
662306a36Sopenharmony_ci * Author: David Liu <liuwei@actions-semi.com>
762306a36Sopenharmony_ci *
862306a36Sopenharmony_ci * Copyright (c) 2018 Linaro Ltd.
962306a36Sopenharmony_ci * Author: Manivannan Sadhasivam <manivannan.sadhasivam@linaro.org>
1062306a36Sopenharmony_ci */
1162306a36Sopenharmony_ci
1262306a36Sopenharmony_ci#include <linux/clk.h>
1362306a36Sopenharmony_ci#include <linux/delay.h>
1462306a36Sopenharmony_ci#include <linux/i2c.h>
1562306a36Sopenharmony_ci#include <linux/interrupt.h>
1662306a36Sopenharmony_ci#include <linux/io.h>
1762306a36Sopenharmony_ci#include <linux/iopoll.h>
1862306a36Sopenharmony_ci#include <linux/module.h>
1962306a36Sopenharmony_ci#include <linux/of.h>
2062306a36Sopenharmony_ci#include <linux/platform_device.h>
2162306a36Sopenharmony_ci
2262306a36Sopenharmony_ci/* I2C registers */
2362306a36Sopenharmony_ci#define OWL_I2C_REG_CTL		0x0000
2462306a36Sopenharmony_ci#define OWL_I2C_REG_CLKDIV	0x0004
2562306a36Sopenharmony_ci#define OWL_I2C_REG_STAT	0x0008
2662306a36Sopenharmony_ci#define OWL_I2C_REG_ADDR	0x000C
2762306a36Sopenharmony_ci#define OWL_I2C_REG_TXDAT	0x0010
2862306a36Sopenharmony_ci#define OWL_I2C_REG_RXDAT	0x0014
2962306a36Sopenharmony_ci#define OWL_I2C_REG_CMD		0x0018
3062306a36Sopenharmony_ci#define OWL_I2C_REG_FIFOCTL	0x001C
3162306a36Sopenharmony_ci#define OWL_I2C_REG_FIFOSTAT	0x0020
3262306a36Sopenharmony_ci#define OWL_I2C_REG_DATCNT	0x0024
3362306a36Sopenharmony_ci#define OWL_I2C_REG_RCNT	0x0028
3462306a36Sopenharmony_ci
3562306a36Sopenharmony_ci/* I2Cx_CTL Bit Mask */
3662306a36Sopenharmony_ci#define OWL_I2C_CTL_RB		BIT(1)
3762306a36Sopenharmony_ci#define OWL_I2C_CTL_GBCC(x)	(((x) & 0x3) << 2)
3862306a36Sopenharmony_ci#define	OWL_I2C_CTL_GBCC_NONE	OWL_I2C_CTL_GBCC(0)
3962306a36Sopenharmony_ci#define	OWL_I2C_CTL_GBCC_START	OWL_I2C_CTL_GBCC(1)
4062306a36Sopenharmony_ci#define	OWL_I2C_CTL_GBCC_STOP	OWL_I2C_CTL_GBCC(2)
4162306a36Sopenharmony_ci#define	OWL_I2C_CTL_GBCC_RSTART	OWL_I2C_CTL_GBCC(3)
4262306a36Sopenharmony_ci#define OWL_I2C_CTL_IRQE	BIT(5)
4362306a36Sopenharmony_ci#define OWL_I2C_CTL_EN		BIT(7)
4462306a36Sopenharmony_ci#define OWL_I2C_CTL_AE		BIT(8)
4562306a36Sopenharmony_ci#define OWL_I2C_CTL_SHSM	BIT(10)
4662306a36Sopenharmony_ci
4762306a36Sopenharmony_ci#define OWL_I2C_DIV_FACTOR(x)	((x) & 0xff)
4862306a36Sopenharmony_ci
4962306a36Sopenharmony_ci/* I2Cx_STAT Bit Mask */
5062306a36Sopenharmony_ci#define OWL_I2C_STAT_RACK	BIT(0)
5162306a36Sopenharmony_ci#define OWL_I2C_STAT_BEB	BIT(1)
5262306a36Sopenharmony_ci#define OWL_I2C_STAT_IRQP	BIT(2)
5362306a36Sopenharmony_ci#define OWL_I2C_STAT_LAB	BIT(3)
5462306a36Sopenharmony_ci#define OWL_I2C_STAT_STPD	BIT(4)
5562306a36Sopenharmony_ci#define OWL_I2C_STAT_STAD	BIT(5)
5662306a36Sopenharmony_ci#define OWL_I2C_STAT_BBB	BIT(6)
5762306a36Sopenharmony_ci#define OWL_I2C_STAT_TCB	BIT(7)
5862306a36Sopenharmony_ci#define OWL_I2C_STAT_LBST	BIT(8)
5962306a36Sopenharmony_ci#define OWL_I2C_STAT_SAMB	BIT(9)
6062306a36Sopenharmony_ci#define OWL_I2C_STAT_SRGC	BIT(10)
6162306a36Sopenharmony_ci
6262306a36Sopenharmony_ci/* I2Cx_CMD Bit Mask */
6362306a36Sopenharmony_ci#define OWL_I2C_CMD_SBE		BIT(0)
6462306a36Sopenharmony_ci#define OWL_I2C_CMD_RBE		BIT(4)
6562306a36Sopenharmony_ci#define OWL_I2C_CMD_DE		BIT(8)
6662306a36Sopenharmony_ci#define OWL_I2C_CMD_NS		BIT(9)
6762306a36Sopenharmony_ci#define OWL_I2C_CMD_SE		BIT(10)
6862306a36Sopenharmony_ci#define OWL_I2C_CMD_MSS		BIT(11)
6962306a36Sopenharmony_ci#define OWL_I2C_CMD_WRS		BIT(12)
7062306a36Sopenharmony_ci#define OWL_I2C_CMD_SECL	BIT(15)
7162306a36Sopenharmony_ci
7262306a36Sopenharmony_ci#define OWL_I2C_CMD_AS(x)	(((x) & 0x7) << 1)
7362306a36Sopenharmony_ci#define OWL_I2C_CMD_SAS(x)	(((x) & 0x7) << 5)
7462306a36Sopenharmony_ci
7562306a36Sopenharmony_ci/* I2Cx_FIFOCTL Bit Mask */
7662306a36Sopenharmony_ci#define OWL_I2C_FIFOCTL_NIB	BIT(0)
7762306a36Sopenharmony_ci#define OWL_I2C_FIFOCTL_RFR	BIT(1)
7862306a36Sopenharmony_ci#define OWL_I2C_FIFOCTL_TFR	BIT(2)
7962306a36Sopenharmony_ci
8062306a36Sopenharmony_ci/* I2Cc_FIFOSTAT Bit Mask */
8162306a36Sopenharmony_ci#define OWL_I2C_FIFOSTAT_CECB	BIT(0)
8262306a36Sopenharmony_ci#define OWL_I2C_FIFOSTAT_RNB	BIT(1)
8362306a36Sopenharmony_ci#define OWL_I2C_FIFOSTAT_RFE	BIT(2)
8462306a36Sopenharmony_ci#define OWL_I2C_FIFOSTAT_TFF	BIT(5)
8562306a36Sopenharmony_ci#define OWL_I2C_FIFOSTAT_TFD	GENMASK(23, 16)
8662306a36Sopenharmony_ci#define OWL_I2C_FIFOSTAT_RFD	GENMASK(15, 8)
8762306a36Sopenharmony_ci
8862306a36Sopenharmony_ci/* I2C bus timeout */
8962306a36Sopenharmony_ci#define OWL_I2C_TIMEOUT_MS	(4 * 1000)
9062306a36Sopenharmony_ci#define OWL_I2C_TIMEOUT		msecs_to_jiffies(OWL_I2C_TIMEOUT_MS)
9162306a36Sopenharmony_ci
9262306a36Sopenharmony_ci#define OWL_I2C_MAX_RETRIES	50
9362306a36Sopenharmony_ci
9462306a36Sopenharmony_cistruct owl_i2c_dev {
9562306a36Sopenharmony_ci	struct i2c_adapter	adap;
9662306a36Sopenharmony_ci	struct i2c_msg		*msg;
9762306a36Sopenharmony_ci	struct completion	msg_complete;
9862306a36Sopenharmony_ci	struct clk		*clk;
9962306a36Sopenharmony_ci	spinlock_t		lock;
10062306a36Sopenharmony_ci	void __iomem		*base;
10162306a36Sopenharmony_ci	unsigned long		clk_rate;
10262306a36Sopenharmony_ci	u32			bus_freq;
10362306a36Sopenharmony_ci	u32			msg_ptr;
10462306a36Sopenharmony_ci	int			err;
10562306a36Sopenharmony_ci};
10662306a36Sopenharmony_ci
10762306a36Sopenharmony_cistatic void owl_i2c_update_reg(void __iomem *reg, unsigned int val, bool state)
10862306a36Sopenharmony_ci{
10962306a36Sopenharmony_ci	unsigned int regval;
11062306a36Sopenharmony_ci
11162306a36Sopenharmony_ci	regval = readl(reg);
11262306a36Sopenharmony_ci
11362306a36Sopenharmony_ci	if (state)
11462306a36Sopenharmony_ci		regval |= val;
11562306a36Sopenharmony_ci	else
11662306a36Sopenharmony_ci		regval &= ~val;
11762306a36Sopenharmony_ci
11862306a36Sopenharmony_ci	writel(regval, reg);
11962306a36Sopenharmony_ci}
12062306a36Sopenharmony_ci
12162306a36Sopenharmony_cistatic void owl_i2c_reset(struct owl_i2c_dev *i2c_dev)
12262306a36Sopenharmony_ci{
12362306a36Sopenharmony_ci	owl_i2c_update_reg(i2c_dev->base + OWL_I2C_REG_CTL,
12462306a36Sopenharmony_ci			   OWL_I2C_CTL_EN, false);
12562306a36Sopenharmony_ci	mdelay(1);
12662306a36Sopenharmony_ci	owl_i2c_update_reg(i2c_dev->base + OWL_I2C_REG_CTL,
12762306a36Sopenharmony_ci			   OWL_I2C_CTL_EN, true);
12862306a36Sopenharmony_ci
12962306a36Sopenharmony_ci	/* Clear status registers */
13062306a36Sopenharmony_ci	writel(0, i2c_dev->base + OWL_I2C_REG_STAT);
13162306a36Sopenharmony_ci}
13262306a36Sopenharmony_ci
13362306a36Sopenharmony_cistatic int owl_i2c_reset_fifo(struct owl_i2c_dev *i2c_dev)
13462306a36Sopenharmony_ci{
13562306a36Sopenharmony_ci	unsigned int val, timeout = 0;
13662306a36Sopenharmony_ci
13762306a36Sopenharmony_ci	/* Reset FIFO */
13862306a36Sopenharmony_ci	owl_i2c_update_reg(i2c_dev->base + OWL_I2C_REG_FIFOCTL,
13962306a36Sopenharmony_ci			   OWL_I2C_FIFOCTL_RFR | OWL_I2C_FIFOCTL_TFR,
14062306a36Sopenharmony_ci			   true);
14162306a36Sopenharmony_ci
14262306a36Sopenharmony_ci	/* Wait 50ms for FIFO reset complete */
14362306a36Sopenharmony_ci	do {
14462306a36Sopenharmony_ci		val = readl(i2c_dev->base + OWL_I2C_REG_FIFOCTL);
14562306a36Sopenharmony_ci		if (!(val & (OWL_I2C_FIFOCTL_RFR | OWL_I2C_FIFOCTL_TFR)))
14662306a36Sopenharmony_ci			break;
14762306a36Sopenharmony_ci		usleep_range(500, 1000);
14862306a36Sopenharmony_ci	} while (timeout++ < OWL_I2C_MAX_RETRIES);
14962306a36Sopenharmony_ci
15062306a36Sopenharmony_ci	if (timeout > OWL_I2C_MAX_RETRIES) {
15162306a36Sopenharmony_ci		dev_err(&i2c_dev->adap.dev, "FIFO reset timeout\n");
15262306a36Sopenharmony_ci		return -ETIMEDOUT;
15362306a36Sopenharmony_ci	}
15462306a36Sopenharmony_ci
15562306a36Sopenharmony_ci	return 0;
15662306a36Sopenharmony_ci}
15762306a36Sopenharmony_ci
15862306a36Sopenharmony_cistatic void owl_i2c_set_freq(struct owl_i2c_dev *i2c_dev)
15962306a36Sopenharmony_ci{
16062306a36Sopenharmony_ci	unsigned int val;
16162306a36Sopenharmony_ci
16262306a36Sopenharmony_ci	val = DIV_ROUND_UP(i2c_dev->clk_rate, i2c_dev->bus_freq * 16);
16362306a36Sopenharmony_ci
16462306a36Sopenharmony_ci	/* Set clock divider factor */
16562306a36Sopenharmony_ci	writel(OWL_I2C_DIV_FACTOR(val), i2c_dev->base + OWL_I2C_REG_CLKDIV);
16662306a36Sopenharmony_ci}
16762306a36Sopenharmony_ci
16862306a36Sopenharmony_cistatic void owl_i2c_xfer_data(struct owl_i2c_dev *i2c_dev)
16962306a36Sopenharmony_ci{
17062306a36Sopenharmony_ci	struct i2c_msg *msg = i2c_dev->msg;
17162306a36Sopenharmony_ci	unsigned int stat, fifostat;
17262306a36Sopenharmony_ci
17362306a36Sopenharmony_ci	i2c_dev->err = 0;
17462306a36Sopenharmony_ci
17562306a36Sopenharmony_ci	/* Handle NACK from slave */
17662306a36Sopenharmony_ci	fifostat = readl(i2c_dev->base + OWL_I2C_REG_FIFOSTAT);
17762306a36Sopenharmony_ci	if (fifostat & OWL_I2C_FIFOSTAT_RNB) {
17862306a36Sopenharmony_ci		i2c_dev->err = -ENXIO;
17962306a36Sopenharmony_ci		/* Clear NACK error bit by writing "1" */
18062306a36Sopenharmony_ci		owl_i2c_update_reg(i2c_dev->base + OWL_I2C_REG_FIFOSTAT,
18162306a36Sopenharmony_ci				   OWL_I2C_FIFOSTAT_RNB, true);
18262306a36Sopenharmony_ci		return;
18362306a36Sopenharmony_ci	}
18462306a36Sopenharmony_ci
18562306a36Sopenharmony_ci	/* Handle bus error */
18662306a36Sopenharmony_ci	stat = readl(i2c_dev->base + OWL_I2C_REG_STAT);
18762306a36Sopenharmony_ci	if (stat & OWL_I2C_STAT_BEB) {
18862306a36Sopenharmony_ci		i2c_dev->err = -EIO;
18962306a36Sopenharmony_ci		/* Clear BUS error bit by writing "1" */
19062306a36Sopenharmony_ci		owl_i2c_update_reg(i2c_dev->base + OWL_I2C_REG_STAT,
19162306a36Sopenharmony_ci				   OWL_I2C_STAT_BEB, true);
19262306a36Sopenharmony_ci		return;
19362306a36Sopenharmony_ci	}
19462306a36Sopenharmony_ci
19562306a36Sopenharmony_ci	/* Handle FIFO read */
19662306a36Sopenharmony_ci	if (msg->flags & I2C_M_RD) {
19762306a36Sopenharmony_ci		while ((readl(i2c_dev->base + OWL_I2C_REG_FIFOSTAT) &
19862306a36Sopenharmony_ci			OWL_I2C_FIFOSTAT_RFE) && i2c_dev->msg_ptr < msg->len) {
19962306a36Sopenharmony_ci			msg->buf[i2c_dev->msg_ptr++] = readl(i2c_dev->base +
20062306a36Sopenharmony_ci							     OWL_I2C_REG_RXDAT);
20162306a36Sopenharmony_ci		}
20262306a36Sopenharmony_ci	} else {
20362306a36Sopenharmony_ci		/* Handle the remaining bytes which were not sent */
20462306a36Sopenharmony_ci		while (!(readl(i2c_dev->base + OWL_I2C_REG_FIFOSTAT) &
20562306a36Sopenharmony_ci			 OWL_I2C_FIFOSTAT_TFF) && i2c_dev->msg_ptr < msg->len) {
20662306a36Sopenharmony_ci			writel(msg->buf[i2c_dev->msg_ptr++],
20762306a36Sopenharmony_ci			       i2c_dev->base + OWL_I2C_REG_TXDAT);
20862306a36Sopenharmony_ci		}
20962306a36Sopenharmony_ci	}
21062306a36Sopenharmony_ci}
21162306a36Sopenharmony_ci
21262306a36Sopenharmony_cistatic irqreturn_t owl_i2c_interrupt(int irq, void *_dev)
21362306a36Sopenharmony_ci{
21462306a36Sopenharmony_ci	struct owl_i2c_dev *i2c_dev = _dev;
21562306a36Sopenharmony_ci
21662306a36Sopenharmony_ci	spin_lock(&i2c_dev->lock);
21762306a36Sopenharmony_ci
21862306a36Sopenharmony_ci	owl_i2c_xfer_data(i2c_dev);
21962306a36Sopenharmony_ci
22062306a36Sopenharmony_ci	/* Clear pending interrupts */
22162306a36Sopenharmony_ci	owl_i2c_update_reg(i2c_dev->base + OWL_I2C_REG_STAT,
22262306a36Sopenharmony_ci			   OWL_I2C_STAT_IRQP, true);
22362306a36Sopenharmony_ci
22462306a36Sopenharmony_ci	complete_all(&i2c_dev->msg_complete);
22562306a36Sopenharmony_ci	spin_unlock(&i2c_dev->lock);
22662306a36Sopenharmony_ci
22762306a36Sopenharmony_ci	return IRQ_HANDLED;
22862306a36Sopenharmony_ci}
22962306a36Sopenharmony_ci
23062306a36Sopenharmony_cistatic u32 owl_i2c_func(struct i2c_adapter *adap)
23162306a36Sopenharmony_ci{
23262306a36Sopenharmony_ci	return I2C_FUNC_I2C | I2C_FUNC_SMBUS_EMUL;
23362306a36Sopenharmony_ci}
23462306a36Sopenharmony_ci
23562306a36Sopenharmony_cistatic int owl_i2c_check_bus_busy(struct i2c_adapter *adap)
23662306a36Sopenharmony_ci{
23762306a36Sopenharmony_ci	struct owl_i2c_dev *i2c_dev = i2c_get_adapdata(adap);
23862306a36Sopenharmony_ci	unsigned long timeout;
23962306a36Sopenharmony_ci
24062306a36Sopenharmony_ci	/* Check for Bus busy */
24162306a36Sopenharmony_ci	timeout = jiffies + OWL_I2C_TIMEOUT;
24262306a36Sopenharmony_ci	while (readl(i2c_dev->base + OWL_I2C_REG_STAT) & OWL_I2C_STAT_BBB) {
24362306a36Sopenharmony_ci		if (time_after(jiffies, timeout)) {
24462306a36Sopenharmony_ci			dev_err(&adap->dev, "Bus busy timeout\n");
24562306a36Sopenharmony_ci			return -ETIMEDOUT;
24662306a36Sopenharmony_ci		}
24762306a36Sopenharmony_ci	}
24862306a36Sopenharmony_ci
24962306a36Sopenharmony_ci	return 0;
25062306a36Sopenharmony_ci}
25162306a36Sopenharmony_ci
25262306a36Sopenharmony_cistatic int owl_i2c_xfer_common(struct i2c_adapter *adap, struct i2c_msg *msgs,
25362306a36Sopenharmony_ci			       int num, bool atomic)
25462306a36Sopenharmony_ci{
25562306a36Sopenharmony_ci	struct owl_i2c_dev *i2c_dev = i2c_get_adapdata(adap);
25662306a36Sopenharmony_ci	struct i2c_msg *msg;
25762306a36Sopenharmony_ci	unsigned long time_left, flags;
25862306a36Sopenharmony_ci	unsigned int i2c_cmd, val;
25962306a36Sopenharmony_ci	unsigned int addr;
26062306a36Sopenharmony_ci	int ret, idx;
26162306a36Sopenharmony_ci
26262306a36Sopenharmony_ci	spin_lock_irqsave(&i2c_dev->lock, flags);
26362306a36Sopenharmony_ci
26462306a36Sopenharmony_ci	/* Reset I2C controller */
26562306a36Sopenharmony_ci	owl_i2c_reset(i2c_dev);
26662306a36Sopenharmony_ci
26762306a36Sopenharmony_ci	/* Set bus frequency */
26862306a36Sopenharmony_ci	owl_i2c_set_freq(i2c_dev);
26962306a36Sopenharmony_ci
27062306a36Sopenharmony_ci	/*
27162306a36Sopenharmony_ci	 * Spinlock should be released before calling reset FIFO and
27262306a36Sopenharmony_ci	 * bus busy check since those functions may sleep
27362306a36Sopenharmony_ci	 */
27462306a36Sopenharmony_ci	spin_unlock_irqrestore(&i2c_dev->lock, flags);
27562306a36Sopenharmony_ci
27662306a36Sopenharmony_ci	/* Reset FIFO */
27762306a36Sopenharmony_ci	ret = owl_i2c_reset_fifo(i2c_dev);
27862306a36Sopenharmony_ci	if (ret)
27962306a36Sopenharmony_ci		goto unlocked_err_exit;
28062306a36Sopenharmony_ci
28162306a36Sopenharmony_ci	/* Check for bus busy */
28262306a36Sopenharmony_ci	ret = owl_i2c_check_bus_busy(adap);
28362306a36Sopenharmony_ci	if (ret)
28462306a36Sopenharmony_ci		goto unlocked_err_exit;
28562306a36Sopenharmony_ci
28662306a36Sopenharmony_ci	spin_lock_irqsave(&i2c_dev->lock, flags);
28762306a36Sopenharmony_ci
28862306a36Sopenharmony_ci	/* Check for Arbitration lost */
28962306a36Sopenharmony_ci	val = readl(i2c_dev->base + OWL_I2C_REG_STAT);
29062306a36Sopenharmony_ci	if (val & OWL_I2C_STAT_LAB) {
29162306a36Sopenharmony_ci		val &= ~OWL_I2C_STAT_LAB;
29262306a36Sopenharmony_ci		writel(val, i2c_dev->base + OWL_I2C_REG_STAT);
29362306a36Sopenharmony_ci		ret = -EAGAIN;
29462306a36Sopenharmony_ci		goto err_exit;
29562306a36Sopenharmony_ci	}
29662306a36Sopenharmony_ci
29762306a36Sopenharmony_ci	if (!atomic)
29862306a36Sopenharmony_ci		reinit_completion(&i2c_dev->msg_complete);
29962306a36Sopenharmony_ci
30062306a36Sopenharmony_ci	/* Enable/disable I2C controller interrupt */
30162306a36Sopenharmony_ci	owl_i2c_update_reg(i2c_dev->base + OWL_I2C_REG_CTL,
30262306a36Sopenharmony_ci			   OWL_I2C_CTL_IRQE, !atomic);
30362306a36Sopenharmony_ci
30462306a36Sopenharmony_ci	/*
30562306a36Sopenharmony_ci	 * Select: FIFO enable, Master mode, Stop enable, Data count enable,
30662306a36Sopenharmony_ci	 * Send start bit
30762306a36Sopenharmony_ci	 */
30862306a36Sopenharmony_ci	i2c_cmd = OWL_I2C_CMD_SECL | OWL_I2C_CMD_MSS | OWL_I2C_CMD_SE |
30962306a36Sopenharmony_ci		  OWL_I2C_CMD_NS | OWL_I2C_CMD_DE | OWL_I2C_CMD_SBE;
31062306a36Sopenharmony_ci
31162306a36Sopenharmony_ci	/* Handle repeated start condition */
31262306a36Sopenharmony_ci	if (num > 1) {
31362306a36Sopenharmony_ci		/* Set internal address length and enable repeated start */
31462306a36Sopenharmony_ci		i2c_cmd |= OWL_I2C_CMD_AS(msgs[0].len + 1) |
31562306a36Sopenharmony_ci			   OWL_I2C_CMD_SAS(1) | OWL_I2C_CMD_RBE;
31662306a36Sopenharmony_ci
31762306a36Sopenharmony_ci		/* Write slave address */
31862306a36Sopenharmony_ci		addr = i2c_8bit_addr_from_msg(&msgs[0]);
31962306a36Sopenharmony_ci		writel(addr, i2c_dev->base + OWL_I2C_REG_TXDAT);
32062306a36Sopenharmony_ci
32162306a36Sopenharmony_ci		/* Write internal register address */
32262306a36Sopenharmony_ci		for (idx = 0; idx < msgs[0].len; idx++)
32362306a36Sopenharmony_ci			writel(msgs[0].buf[idx],
32462306a36Sopenharmony_ci			       i2c_dev->base + OWL_I2C_REG_TXDAT);
32562306a36Sopenharmony_ci
32662306a36Sopenharmony_ci		msg = &msgs[1];
32762306a36Sopenharmony_ci	} else {
32862306a36Sopenharmony_ci		/* Set address length */
32962306a36Sopenharmony_ci		i2c_cmd |= OWL_I2C_CMD_AS(1);
33062306a36Sopenharmony_ci		msg = &msgs[0];
33162306a36Sopenharmony_ci	}
33262306a36Sopenharmony_ci
33362306a36Sopenharmony_ci	i2c_dev->msg = msg;
33462306a36Sopenharmony_ci	i2c_dev->msg_ptr = 0;
33562306a36Sopenharmony_ci
33662306a36Sopenharmony_ci	/* Set data count for the message */
33762306a36Sopenharmony_ci	writel(msg->len, i2c_dev->base + OWL_I2C_REG_DATCNT);
33862306a36Sopenharmony_ci
33962306a36Sopenharmony_ci	addr = i2c_8bit_addr_from_msg(msg);
34062306a36Sopenharmony_ci	writel(addr, i2c_dev->base + OWL_I2C_REG_TXDAT);
34162306a36Sopenharmony_ci
34262306a36Sopenharmony_ci	if (!(msg->flags & I2C_M_RD)) {
34362306a36Sopenharmony_ci		/* Write data to FIFO */
34462306a36Sopenharmony_ci		for (idx = 0; idx < msg->len; idx++) {
34562306a36Sopenharmony_ci			/* Check for FIFO full */
34662306a36Sopenharmony_ci			if (readl(i2c_dev->base + OWL_I2C_REG_FIFOSTAT) &
34762306a36Sopenharmony_ci			    OWL_I2C_FIFOSTAT_TFF)
34862306a36Sopenharmony_ci				break;
34962306a36Sopenharmony_ci
35062306a36Sopenharmony_ci			writel(msg->buf[idx],
35162306a36Sopenharmony_ci			       i2c_dev->base + OWL_I2C_REG_TXDAT);
35262306a36Sopenharmony_ci		}
35362306a36Sopenharmony_ci
35462306a36Sopenharmony_ci		i2c_dev->msg_ptr = idx;
35562306a36Sopenharmony_ci	}
35662306a36Sopenharmony_ci
35762306a36Sopenharmony_ci	/* Ignore the NACK if needed */
35862306a36Sopenharmony_ci	if (msg->flags & I2C_M_IGNORE_NAK)
35962306a36Sopenharmony_ci		owl_i2c_update_reg(i2c_dev->base + OWL_I2C_REG_FIFOCTL,
36062306a36Sopenharmony_ci				   OWL_I2C_FIFOCTL_NIB, true);
36162306a36Sopenharmony_ci	else
36262306a36Sopenharmony_ci		owl_i2c_update_reg(i2c_dev->base + OWL_I2C_REG_FIFOCTL,
36362306a36Sopenharmony_ci				   OWL_I2C_FIFOCTL_NIB, false);
36462306a36Sopenharmony_ci
36562306a36Sopenharmony_ci	/* Start the transfer */
36662306a36Sopenharmony_ci	writel(i2c_cmd, i2c_dev->base + OWL_I2C_REG_CMD);
36762306a36Sopenharmony_ci
36862306a36Sopenharmony_ci	spin_unlock_irqrestore(&i2c_dev->lock, flags);
36962306a36Sopenharmony_ci
37062306a36Sopenharmony_ci	if (atomic) {
37162306a36Sopenharmony_ci		/* Wait for Command Execute Completed or NACK Error bits */
37262306a36Sopenharmony_ci		ret = readl_poll_timeout_atomic(i2c_dev->base + OWL_I2C_REG_FIFOSTAT,
37362306a36Sopenharmony_ci						val, val & (OWL_I2C_FIFOSTAT_CECB |
37462306a36Sopenharmony_ci							    OWL_I2C_FIFOSTAT_RNB),
37562306a36Sopenharmony_ci						10, OWL_I2C_TIMEOUT_MS * 1000);
37662306a36Sopenharmony_ci	} else {
37762306a36Sopenharmony_ci		time_left = wait_for_completion_timeout(&i2c_dev->msg_complete,
37862306a36Sopenharmony_ci							adap->timeout);
37962306a36Sopenharmony_ci		if (!time_left)
38062306a36Sopenharmony_ci			ret = -ETIMEDOUT;
38162306a36Sopenharmony_ci	}
38262306a36Sopenharmony_ci
38362306a36Sopenharmony_ci	spin_lock_irqsave(&i2c_dev->lock, flags);
38462306a36Sopenharmony_ci
38562306a36Sopenharmony_ci	if (ret) {
38662306a36Sopenharmony_ci		dev_err(&adap->dev, "Transaction timed out\n");
38762306a36Sopenharmony_ci		/* Send stop condition and release the bus */
38862306a36Sopenharmony_ci		owl_i2c_update_reg(i2c_dev->base + OWL_I2C_REG_CTL,
38962306a36Sopenharmony_ci				   OWL_I2C_CTL_GBCC_STOP | OWL_I2C_CTL_RB,
39062306a36Sopenharmony_ci				   true);
39162306a36Sopenharmony_ci		goto err_exit;
39262306a36Sopenharmony_ci	}
39362306a36Sopenharmony_ci
39462306a36Sopenharmony_ci	if (atomic)
39562306a36Sopenharmony_ci		owl_i2c_xfer_data(i2c_dev);
39662306a36Sopenharmony_ci
39762306a36Sopenharmony_ci	ret = i2c_dev->err < 0 ? i2c_dev->err : num;
39862306a36Sopenharmony_ci
39962306a36Sopenharmony_cierr_exit:
40062306a36Sopenharmony_ci	spin_unlock_irqrestore(&i2c_dev->lock, flags);
40162306a36Sopenharmony_ci
40262306a36Sopenharmony_ciunlocked_err_exit:
40362306a36Sopenharmony_ci	/* Disable I2C controller */
40462306a36Sopenharmony_ci	owl_i2c_update_reg(i2c_dev->base + OWL_I2C_REG_CTL,
40562306a36Sopenharmony_ci			   OWL_I2C_CTL_EN, false);
40662306a36Sopenharmony_ci
40762306a36Sopenharmony_ci	return ret;
40862306a36Sopenharmony_ci}
40962306a36Sopenharmony_ci
41062306a36Sopenharmony_cistatic int owl_i2c_xfer(struct i2c_adapter *adap, struct i2c_msg *msgs,
41162306a36Sopenharmony_ci			int num)
41262306a36Sopenharmony_ci{
41362306a36Sopenharmony_ci	return owl_i2c_xfer_common(adap, msgs, num, false);
41462306a36Sopenharmony_ci}
41562306a36Sopenharmony_ci
41662306a36Sopenharmony_cistatic int owl_i2c_xfer_atomic(struct i2c_adapter *adap,
41762306a36Sopenharmony_ci			       struct i2c_msg *msgs, int num)
41862306a36Sopenharmony_ci{
41962306a36Sopenharmony_ci	return owl_i2c_xfer_common(adap, msgs, num, true);
42062306a36Sopenharmony_ci}
42162306a36Sopenharmony_ci
42262306a36Sopenharmony_cistatic const struct i2c_algorithm owl_i2c_algorithm = {
42362306a36Sopenharmony_ci	.master_xfer	     = owl_i2c_xfer,
42462306a36Sopenharmony_ci	.master_xfer_atomic  = owl_i2c_xfer_atomic,
42562306a36Sopenharmony_ci	.functionality	     = owl_i2c_func,
42662306a36Sopenharmony_ci};
42762306a36Sopenharmony_ci
42862306a36Sopenharmony_cistatic const struct i2c_adapter_quirks owl_i2c_quirks = {
42962306a36Sopenharmony_ci	.flags		= I2C_AQ_COMB | I2C_AQ_COMB_WRITE_FIRST,
43062306a36Sopenharmony_ci	.max_read_len   = 240,
43162306a36Sopenharmony_ci	.max_write_len  = 240,
43262306a36Sopenharmony_ci	.max_comb_1st_msg_len = 6,
43362306a36Sopenharmony_ci	.max_comb_2nd_msg_len = 240,
43462306a36Sopenharmony_ci};
43562306a36Sopenharmony_ci
43662306a36Sopenharmony_cistatic int owl_i2c_probe(struct platform_device *pdev)
43762306a36Sopenharmony_ci{
43862306a36Sopenharmony_ci	struct device *dev = &pdev->dev;
43962306a36Sopenharmony_ci	struct owl_i2c_dev *i2c_dev;
44062306a36Sopenharmony_ci	int ret, irq;
44162306a36Sopenharmony_ci
44262306a36Sopenharmony_ci	i2c_dev = devm_kzalloc(dev, sizeof(*i2c_dev), GFP_KERNEL);
44362306a36Sopenharmony_ci	if (!i2c_dev)
44462306a36Sopenharmony_ci		return -ENOMEM;
44562306a36Sopenharmony_ci
44662306a36Sopenharmony_ci	i2c_dev->base = devm_platform_ioremap_resource(pdev, 0);
44762306a36Sopenharmony_ci	if (IS_ERR(i2c_dev->base))
44862306a36Sopenharmony_ci		return PTR_ERR(i2c_dev->base);
44962306a36Sopenharmony_ci
45062306a36Sopenharmony_ci	irq = platform_get_irq(pdev, 0);
45162306a36Sopenharmony_ci	if (irq < 0)
45262306a36Sopenharmony_ci		return irq;
45362306a36Sopenharmony_ci
45462306a36Sopenharmony_ci	if (of_property_read_u32(dev->of_node, "clock-frequency",
45562306a36Sopenharmony_ci				 &i2c_dev->bus_freq))
45662306a36Sopenharmony_ci		i2c_dev->bus_freq = I2C_MAX_STANDARD_MODE_FREQ;
45762306a36Sopenharmony_ci
45862306a36Sopenharmony_ci	/* We support only frequencies of 100k and 400k for now */
45962306a36Sopenharmony_ci	if (i2c_dev->bus_freq != I2C_MAX_STANDARD_MODE_FREQ &&
46062306a36Sopenharmony_ci	    i2c_dev->bus_freq != I2C_MAX_FAST_MODE_FREQ) {
46162306a36Sopenharmony_ci		dev_err(dev, "invalid clock-frequency %d\n", i2c_dev->bus_freq);
46262306a36Sopenharmony_ci		return -EINVAL;
46362306a36Sopenharmony_ci	}
46462306a36Sopenharmony_ci
46562306a36Sopenharmony_ci	i2c_dev->clk = devm_clk_get_enabled(dev, NULL);
46662306a36Sopenharmony_ci	if (IS_ERR(i2c_dev->clk)) {
46762306a36Sopenharmony_ci		dev_err(dev, "failed to enable clock\n");
46862306a36Sopenharmony_ci		return PTR_ERR(i2c_dev->clk);
46962306a36Sopenharmony_ci	}
47062306a36Sopenharmony_ci
47162306a36Sopenharmony_ci	i2c_dev->clk_rate = clk_get_rate(i2c_dev->clk);
47262306a36Sopenharmony_ci	if (!i2c_dev->clk_rate) {
47362306a36Sopenharmony_ci		dev_err(dev, "input clock rate should not be zero\n");
47462306a36Sopenharmony_ci		return -EINVAL;
47562306a36Sopenharmony_ci	}
47662306a36Sopenharmony_ci
47762306a36Sopenharmony_ci	init_completion(&i2c_dev->msg_complete);
47862306a36Sopenharmony_ci	spin_lock_init(&i2c_dev->lock);
47962306a36Sopenharmony_ci	i2c_dev->adap.owner = THIS_MODULE;
48062306a36Sopenharmony_ci	i2c_dev->adap.algo = &owl_i2c_algorithm;
48162306a36Sopenharmony_ci	i2c_dev->adap.timeout = OWL_I2C_TIMEOUT;
48262306a36Sopenharmony_ci	i2c_dev->adap.quirks = &owl_i2c_quirks;
48362306a36Sopenharmony_ci	i2c_dev->adap.dev.parent = dev;
48462306a36Sopenharmony_ci	i2c_dev->adap.dev.of_node = dev->of_node;
48562306a36Sopenharmony_ci	snprintf(i2c_dev->adap.name, sizeof(i2c_dev->adap.name),
48662306a36Sopenharmony_ci		 "%s", "OWL I2C adapter");
48762306a36Sopenharmony_ci	i2c_set_adapdata(&i2c_dev->adap, i2c_dev);
48862306a36Sopenharmony_ci
48962306a36Sopenharmony_ci	platform_set_drvdata(pdev, i2c_dev);
49062306a36Sopenharmony_ci
49162306a36Sopenharmony_ci	ret = devm_request_irq(dev, irq, owl_i2c_interrupt, 0, pdev->name,
49262306a36Sopenharmony_ci			       i2c_dev);
49362306a36Sopenharmony_ci	if (ret) {
49462306a36Sopenharmony_ci		dev_err(dev, "failed to request irq %d\n", irq);
49562306a36Sopenharmony_ci		return ret;
49662306a36Sopenharmony_ci	}
49762306a36Sopenharmony_ci
49862306a36Sopenharmony_ci	return i2c_add_adapter(&i2c_dev->adap);
49962306a36Sopenharmony_ci}
50062306a36Sopenharmony_ci
50162306a36Sopenharmony_cistatic const struct of_device_id owl_i2c_of_match[] = {
50262306a36Sopenharmony_ci	{ .compatible = "actions,s500-i2c" },
50362306a36Sopenharmony_ci	{ .compatible = "actions,s700-i2c" },
50462306a36Sopenharmony_ci	{ .compatible = "actions,s900-i2c" },
50562306a36Sopenharmony_ci	{ /* sentinel */ }
50662306a36Sopenharmony_ci};
50762306a36Sopenharmony_ciMODULE_DEVICE_TABLE(of, owl_i2c_of_match);
50862306a36Sopenharmony_ci
50962306a36Sopenharmony_cistatic struct platform_driver owl_i2c_driver = {
51062306a36Sopenharmony_ci	.probe		= owl_i2c_probe,
51162306a36Sopenharmony_ci	.driver		= {
51262306a36Sopenharmony_ci		.name	= "owl-i2c",
51362306a36Sopenharmony_ci		.of_match_table = owl_i2c_of_match,
51462306a36Sopenharmony_ci		.probe_type = PROBE_PREFER_ASYNCHRONOUS,
51562306a36Sopenharmony_ci	},
51662306a36Sopenharmony_ci};
51762306a36Sopenharmony_cimodule_platform_driver(owl_i2c_driver);
51862306a36Sopenharmony_ci
51962306a36Sopenharmony_ciMODULE_AUTHOR("David Liu <liuwei@actions-semi.com>");
52062306a36Sopenharmony_ciMODULE_AUTHOR("Manivannan Sadhasivam <manivannan.sadhasivam@linaro.org>");
52162306a36Sopenharmony_ciMODULE_DESCRIPTION("Actions Semiconductor Owl SoC's I2C driver");
52262306a36Sopenharmony_ciMODULE_LICENSE("GPL");
523