18c2ecf20Sopenharmony_ci/*
28c2ecf20Sopenharmony_ci * Copyright (C) 2017 Spreadtrum Communications Inc.
38c2ecf20Sopenharmony_ci *
48c2ecf20Sopenharmony_ci * SPDX-License-Identifier: (GPL-2.0+ OR MIT)
58c2ecf20Sopenharmony_ci */
68c2ecf20Sopenharmony_ci
78c2ecf20Sopenharmony_ci#include <linux/clk.h>
88c2ecf20Sopenharmony_ci#include <linux/delay.h>
98c2ecf20Sopenharmony_ci#include <linux/err.h>
108c2ecf20Sopenharmony_ci#include <linux/io.h>
118c2ecf20Sopenharmony_ci#include <linux/i2c.h>
128c2ecf20Sopenharmony_ci#include <linux/init.h>
138c2ecf20Sopenharmony_ci#include <linux/interrupt.h>
148c2ecf20Sopenharmony_ci#include <linux/kernel.h>
158c2ecf20Sopenharmony_ci#include <linux/module.h>
168c2ecf20Sopenharmony_ci#include <linux/of.h>
178c2ecf20Sopenharmony_ci#include <linux/of_device.h>
188c2ecf20Sopenharmony_ci#include <linux/platform_device.h>
198c2ecf20Sopenharmony_ci#include <linux/pm_runtime.h>
208c2ecf20Sopenharmony_ci
218c2ecf20Sopenharmony_ci#define I2C_CTL			0x00
228c2ecf20Sopenharmony_ci#define I2C_ADDR_CFG		0x04
238c2ecf20Sopenharmony_ci#define I2C_COUNT		0x08
248c2ecf20Sopenharmony_ci#define I2C_RX			0x0c
258c2ecf20Sopenharmony_ci#define I2C_TX			0x10
268c2ecf20Sopenharmony_ci#define I2C_STATUS		0x14
278c2ecf20Sopenharmony_ci#define I2C_HSMODE_CFG		0x18
288c2ecf20Sopenharmony_ci#define I2C_VERSION		0x1c
298c2ecf20Sopenharmony_ci#define ADDR_DVD0		0x20
308c2ecf20Sopenharmony_ci#define ADDR_DVD1		0x24
318c2ecf20Sopenharmony_ci#define ADDR_STA0_DVD		0x28
328c2ecf20Sopenharmony_ci#define ADDR_RST		0x2c
338c2ecf20Sopenharmony_ci
348c2ecf20Sopenharmony_ci/* I2C_CTL */
358c2ecf20Sopenharmony_ci#define STP_EN			BIT(20)
368c2ecf20Sopenharmony_ci#define FIFO_AF_LVL_MASK	GENMASK(19, 16)
378c2ecf20Sopenharmony_ci#define FIFO_AF_LVL		16
388c2ecf20Sopenharmony_ci#define FIFO_AE_LVL_MASK	GENMASK(15, 12)
398c2ecf20Sopenharmony_ci#define FIFO_AE_LVL		12
408c2ecf20Sopenharmony_ci#define I2C_DMA_EN		BIT(11)
418c2ecf20Sopenharmony_ci#define FULL_INTEN		BIT(10)
428c2ecf20Sopenharmony_ci#define EMPTY_INTEN		BIT(9)
438c2ecf20Sopenharmony_ci#define I2C_DVD_OPT		BIT(8)
448c2ecf20Sopenharmony_ci#define I2C_OUT_OPT		BIT(7)
458c2ecf20Sopenharmony_ci#define I2C_TRIM_OPT		BIT(6)
468c2ecf20Sopenharmony_ci#define I2C_HS_MODE		BIT(4)
478c2ecf20Sopenharmony_ci#define I2C_MODE		BIT(3)
488c2ecf20Sopenharmony_ci#define I2C_EN			BIT(2)
498c2ecf20Sopenharmony_ci#define I2C_INT_EN		BIT(1)
508c2ecf20Sopenharmony_ci#define I2C_START		BIT(0)
518c2ecf20Sopenharmony_ci
528c2ecf20Sopenharmony_ci/* I2C_STATUS */
538c2ecf20Sopenharmony_ci#define SDA_IN			BIT(21)
548c2ecf20Sopenharmony_ci#define SCL_IN			BIT(20)
558c2ecf20Sopenharmony_ci#define FIFO_FULL		BIT(4)
568c2ecf20Sopenharmony_ci#define FIFO_EMPTY		BIT(3)
578c2ecf20Sopenharmony_ci#define I2C_INT			BIT(2)
588c2ecf20Sopenharmony_ci#define I2C_RX_ACK		BIT(1)
598c2ecf20Sopenharmony_ci#define I2C_BUSY		BIT(0)
608c2ecf20Sopenharmony_ci
618c2ecf20Sopenharmony_ci/* ADDR_RST */
628c2ecf20Sopenharmony_ci#define I2C_RST			BIT(0)
638c2ecf20Sopenharmony_ci
648c2ecf20Sopenharmony_ci#define I2C_FIFO_DEEP		12
658c2ecf20Sopenharmony_ci#define I2C_FIFO_FULL_THLD	15
668c2ecf20Sopenharmony_ci#define I2C_FIFO_EMPTY_THLD	4
678c2ecf20Sopenharmony_ci#define I2C_DATA_STEP		8
688c2ecf20Sopenharmony_ci#define I2C_ADDR_DVD0_CALC(high, low)	\
698c2ecf20Sopenharmony_ci	((((high) & GENMASK(15, 0)) << 16) | ((low) & GENMASK(15, 0)))
708c2ecf20Sopenharmony_ci#define I2C_ADDR_DVD1_CALC(high, low)	\
718c2ecf20Sopenharmony_ci	(((high) & GENMASK(31, 16)) | (((low) & GENMASK(31, 16)) >> 16))
728c2ecf20Sopenharmony_ci
738c2ecf20Sopenharmony_ci/* timeout (ms) for pm runtime autosuspend */
748c2ecf20Sopenharmony_ci#define SPRD_I2C_PM_TIMEOUT	1000
758c2ecf20Sopenharmony_ci/* timeout (ms) for transfer message */
768c2ecf20Sopenharmony_ci#define I2C_XFER_TIMEOUT	1000
778c2ecf20Sopenharmony_ci
788c2ecf20Sopenharmony_ci/* SPRD i2c data structure */
798c2ecf20Sopenharmony_cistruct sprd_i2c {
808c2ecf20Sopenharmony_ci	struct i2c_adapter adap;
818c2ecf20Sopenharmony_ci	struct device *dev;
828c2ecf20Sopenharmony_ci	void __iomem *base;
838c2ecf20Sopenharmony_ci	struct i2c_msg *msg;
848c2ecf20Sopenharmony_ci	struct clk *clk;
858c2ecf20Sopenharmony_ci	u32 src_clk;
868c2ecf20Sopenharmony_ci	u32 bus_freq;
878c2ecf20Sopenharmony_ci	struct completion complete;
888c2ecf20Sopenharmony_ci	u8 *buf;
898c2ecf20Sopenharmony_ci	u32 count;
908c2ecf20Sopenharmony_ci	int irq;
918c2ecf20Sopenharmony_ci	int err;
928c2ecf20Sopenharmony_ci};
938c2ecf20Sopenharmony_ci
948c2ecf20Sopenharmony_cistatic void sprd_i2c_set_count(struct sprd_i2c *i2c_dev, u32 count)
958c2ecf20Sopenharmony_ci{
968c2ecf20Sopenharmony_ci	writel(count, i2c_dev->base + I2C_COUNT);
978c2ecf20Sopenharmony_ci}
988c2ecf20Sopenharmony_ci
998c2ecf20Sopenharmony_cistatic void sprd_i2c_send_stop(struct sprd_i2c *i2c_dev, int stop)
1008c2ecf20Sopenharmony_ci{
1018c2ecf20Sopenharmony_ci	u32 tmp = readl(i2c_dev->base + I2C_CTL);
1028c2ecf20Sopenharmony_ci
1038c2ecf20Sopenharmony_ci	if (stop)
1048c2ecf20Sopenharmony_ci		writel(tmp & ~STP_EN, i2c_dev->base + I2C_CTL);
1058c2ecf20Sopenharmony_ci	else
1068c2ecf20Sopenharmony_ci		writel(tmp | STP_EN, i2c_dev->base + I2C_CTL);
1078c2ecf20Sopenharmony_ci}
1088c2ecf20Sopenharmony_ci
1098c2ecf20Sopenharmony_cistatic void sprd_i2c_clear_start(struct sprd_i2c *i2c_dev)
1108c2ecf20Sopenharmony_ci{
1118c2ecf20Sopenharmony_ci	u32 tmp = readl(i2c_dev->base + I2C_CTL);
1128c2ecf20Sopenharmony_ci
1138c2ecf20Sopenharmony_ci	writel(tmp & ~I2C_START, i2c_dev->base + I2C_CTL);
1148c2ecf20Sopenharmony_ci}
1158c2ecf20Sopenharmony_ci
1168c2ecf20Sopenharmony_cistatic void sprd_i2c_clear_ack(struct sprd_i2c *i2c_dev)
1178c2ecf20Sopenharmony_ci{
1188c2ecf20Sopenharmony_ci	u32 tmp = readl(i2c_dev->base + I2C_STATUS);
1198c2ecf20Sopenharmony_ci
1208c2ecf20Sopenharmony_ci	writel(tmp & ~I2C_RX_ACK, i2c_dev->base + I2C_STATUS);
1218c2ecf20Sopenharmony_ci}
1228c2ecf20Sopenharmony_ci
1238c2ecf20Sopenharmony_cistatic void sprd_i2c_clear_irq(struct sprd_i2c *i2c_dev)
1248c2ecf20Sopenharmony_ci{
1258c2ecf20Sopenharmony_ci	u32 tmp = readl(i2c_dev->base + I2C_STATUS);
1268c2ecf20Sopenharmony_ci
1278c2ecf20Sopenharmony_ci	writel(tmp & ~I2C_INT, i2c_dev->base + I2C_STATUS);
1288c2ecf20Sopenharmony_ci}
1298c2ecf20Sopenharmony_ci
1308c2ecf20Sopenharmony_cistatic void sprd_i2c_reset_fifo(struct sprd_i2c *i2c_dev)
1318c2ecf20Sopenharmony_ci{
1328c2ecf20Sopenharmony_ci	writel(I2C_RST, i2c_dev->base + ADDR_RST);
1338c2ecf20Sopenharmony_ci}
1348c2ecf20Sopenharmony_ci
1358c2ecf20Sopenharmony_cistatic void sprd_i2c_set_devaddr(struct sprd_i2c *i2c_dev, struct i2c_msg *m)
1368c2ecf20Sopenharmony_ci{
1378c2ecf20Sopenharmony_ci	writel(m->addr << 1, i2c_dev->base + I2C_ADDR_CFG);
1388c2ecf20Sopenharmony_ci}
1398c2ecf20Sopenharmony_ci
1408c2ecf20Sopenharmony_cistatic void sprd_i2c_write_bytes(struct sprd_i2c *i2c_dev, u8 *buf, u32 len)
1418c2ecf20Sopenharmony_ci{
1428c2ecf20Sopenharmony_ci	u32 i;
1438c2ecf20Sopenharmony_ci
1448c2ecf20Sopenharmony_ci	for (i = 0; i < len; i++)
1458c2ecf20Sopenharmony_ci		writeb(buf[i], i2c_dev->base + I2C_TX);
1468c2ecf20Sopenharmony_ci}
1478c2ecf20Sopenharmony_ci
1488c2ecf20Sopenharmony_cistatic void sprd_i2c_read_bytes(struct sprd_i2c *i2c_dev, u8 *buf, u32 len)
1498c2ecf20Sopenharmony_ci{
1508c2ecf20Sopenharmony_ci	u32 i;
1518c2ecf20Sopenharmony_ci
1528c2ecf20Sopenharmony_ci	for (i = 0; i < len; i++)
1538c2ecf20Sopenharmony_ci		buf[i] = readb(i2c_dev->base + I2C_RX);
1548c2ecf20Sopenharmony_ci}
1558c2ecf20Sopenharmony_ci
1568c2ecf20Sopenharmony_cistatic void sprd_i2c_set_full_thld(struct sprd_i2c *i2c_dev, u32 full_thld)
1578c2ecf20Sopenharmony_ci{
1588c2ecf20Sopenharmony_ci	u32 tmp = readl(i2c_dev->base + I2C_CTL);
1598c2ecf20Sopenharmony_ci
1608c2ecf20Sopenharmony_ci	tmp &= ~FIFO_AF_LVL_MASK;
1618c2ecf20Sopenharmony_ci	tmp |= full_thld << FIFO_AF_LVL;
1628c2ecf20Sopenharmony_ci	writel(tmp, i2c_dev->base + I2C_CTL);
1638c2ecf20Sopenharmony_ci};
1648c2ecf20Sopenharmony_ci
1658c2ecf20Sopenharmony_cistatic void sprd_i2c_set_empty_thld(struct sprd_i2c *i2c_dev, u32 empty_thld)
1668c2ecf20Sopenharmony_ci{
1678c2ecf20Sopenharmony_ci	u32 tmp = readl(i2c_dev->base + I2C_CTL);
1688c2ecf20Sopenharmony_ci
1698c2ecf20Sopenharmony_ci	tmp &= ~FIFO_AE_LVL_MASK;
1708c2ecf20Sopenharmony_ci	tmp |= empty_thld << FIFO_AE_LVL;
1718c2ecf20Sopenharmony_ci	writel(tmp, i2c_dev->base + I2C_CTL);
1728c2ecf20Sopenharmony_ci};
1738c2ecf20Sopenharmony_ci
1748c2ecf20Sopenharmony_cistatic void sprd_i2c_set_fifo_full_int(struct sprd_i2c *i2c_dev, int enable)
1758c2ecf20Sopenharmony_ci{
1768c2ecf20Sopenharmony_ci	u32 tmp = readl(i2c_dev->base + I2C_CTL);
1778c2ecf20Sopenharmony_ci
1788c2ecf20Sopenharmony_ci	if (enable)
1798c2ecf20Sopenharmony_ci		tmp |= FULL_INTEN;
1808c2ecf20Sopenharmony_ci	else
1818c2ecf20Sopenharmony_ci		tmp &= ~FULL_INTEN;
1828c2ecf20Sopenharmony_ci
1838c2ecf20Sopenharmony_ci	writel(tmp, i2c_dev->base + I2C_CTL);
1848c2ecf20Sopenharmony_ci};
1858c2ecf20Sopenharmony_ci
1868c2ecf20Sopenharmony_cistatic void sprd_i2c_set_fifo_empty_int(struct sprd_i2c *i2c_dev, int enable)
1878c2ecf20Sopenharmony_ci{
1888c2ecf20Sopenharmony_ci	u32 tmp = readl(i2c_dev->base + I2C_CTL);
1898c2ecf20Sopenharmony_ci
1908c2ecf20Sopenharmony_ci	if (enable)
1918c2ecf20Sopenharmony_ci		tmp |= EMPTY_INTEN;
1928c2ecf20Sopenharmony_ci	else
1938c2ecf20Sopenharmony_ci		tmp &= ~EMPTY_INTEN;
1948c2ecf20Sopenharmony_ci
1958c2ecf20Sopenharmony_ci	writel(tmp, i2c_dev->base + I2C_CTL);
1968c2ecf20Sopenharmony_ci};
1978c2ecf20Sopenharmony_ci
1988c2ecf20Sopenharmony_cistatic void sprd_i2c_opt_start(struct sprd_i2c *i2c_dev)
1998c2ecf20Sopenharmony_ci{
2008c2ecf20Sopenharmony_ci	u32 tmp = readl(i2c_dev->base + I2C_CTL);
2018c2ecf20Sopenharmony_ci
2028c2ecf20Sopenharmony_ci	writel(tmp | I2C_START, i2c_dev->base + I2C_CTL);
2038c2ecf20Sopenharmony_ci}
2048c2ecf20Sopenharmony_ci
2058c2ecf20Sopenharmony_cistatic void sprd_i2c_opt_mode(struct sprd_i2c *i2c_dev, int rw)
2068c2ecf20Sopenharmony_ci{
2078c2ecf20Sopenharmony_ci	u32 cmd = readl(i2c_dev->base + I2C_CTL) & ~I2C_MODE;
2088c2ecf20Sopenharmony_ci
2098c2ecf20Sopenharmony_ci	writel(cmd | rw << 3, i2c_dev->base + I2C_CTL);
2108c2ecf20Sopenharmony_ci}
2118c2ecf20Sopenharmony_ci
2128c2ecf20Sopenharmony_cistatic void sprd_i2c_data_transfer(struct sprd_i2c *i2c_dev)
2138c2ecf20Sopenharmony_ci{
2148c2ecf20Sopenharmony_ci	u32 i2c_count = i2c_dev->count;
2158c2ecf20Sopenharmony_ci	u32 need_tran = i2c_count <= I2C_FIFO_DEEP ? i2c_count : I2C_FIFO_DEEP;
2168c2ecf20Sopenharmony_ci	struct i2c_msg *msg = i2c_dev->msg;
2178c2ecf20Sopenharmony_ci
2188c2ecf20Sopenharmony_ci	if (msg->flags & I2C_M_RD) {
2198c2ecf20Sopenharmony_ci		sprd_i2c_read_bytes(i2c_dev, i2c_dev->buf, I2C_FIFO_FULL_THLD);
2208c2ecf20Sopenharmony_ci		i2c_dev->count -= I2C_FIFO_FULL_THLD;
2218c2ecf20Sopenharmony_ci		i2c_dev->buf += I2C_FIFO_FULL_THLD;
2228c2ecf20Sopenharmony_ci
2238c2ecf20Sopenharmony_ci		/*
2248c2ecf20Sopenharmony_ci		 * If the read data count is larger than rx fifo full threshold,
2258c2ecf20Sopenharmony_ci		 * we should enable the rx fifo full interrupt to read data
2268c2ecf20Sopenharmony_ci		 * again.
2278c2ecf20Sopenharmony_ci		 */
2288c2ecf20Sopenharmony_ci		if (i2c_dev->count >= I2C_FIFO_FULL_THLD)
2298c2ecf20Sopenharmony_ci			sprd_i2c_set_fifo_full_int(i2c_dev, 1);
2308c2ecf20Sopenharmony_ci	} else {
2318c2ecf20Sopenharmony_ci		sprd_i2c_write_bytes(i2c_dev, i2c_dev->buf, need_tran);
2328c2ecf20Sopenharmony_ci		i2c_dev->buf += need_tran;
2338c2ecf20Sopenharmony_ci		i2c_dev->count -= need_tran;
2348c2ecf20Sopenharmony_ci
2358c2ecf20Sopenharmony_ci		/*
2368c2ecf20Sopenharmony_ci		 * If the write data count is arger than tx fifo depth which
2378c2ecf20Sopenharmony_ci		 * means we can not write all data in one time, then we should
2388c2ecf20Sopenharmony_ci		 * enable the tx fifo empty interrupt to write again.
2398c2ecf20Sopenharmony_ci		 */
2408c2ecf20Sopenharmony_ci		if (i2c_count > I2C_FIFO_DEEP)
2418c2ecf20Sopenharmony_ci			sprd_i2c_set_fifo_empty_int(i2c_dev, 1);
2428c2ecf20Sopenharmony_ci	}
2438c2ecf20Sopenharmony_ci}
2448c2ecf20Sopenharmony_ci
2458c2ecf20Sopenharmony_cistatic int sprd_i2c_handle_msg(struct i2c_adapter *i2c_adap,
2468c2ecf20Sopenharmony_ci			       struct i2c_msg *msg, bool is_last_msg)
2478c2ecf20Sopenharmony_ci{
2488c2ecf20Sopenharmony_ci	struct sprd_i2c *i2c_dev = i2c_adap->algo_data;
2498c2ecf20Sopenharmony_ci	unsigned long time_left;
2508c2ecf20Sopenharmony_ci
2518c2ecf20Sopenharmony_ci	i2c_dev->msg = msg;
2528c2ecf20Sopenharmony_ci	i2c_dev->buf = msg->buf;
2538c2ecf20Sopenharmony_ci	i2c_dev->count = msg->len;
2548c2ecf20Sopenharmony_ci
2558c2ecf20Sopenharmony_ci	reinit_completion(&i2c_dev->complete);
2568c2ecf20Sopenharmony_ci	sprd_i2c_reset_fifo(i2c_dev);
2578c2ecf20Sopenharmony_ci	sprd_i2c_set_devaddr(i2c_dev, msg);
2588c2ecf20Sopenharmony_ci	sprd_i2c_set_count(i2c_dev, msg->len);
2598c2ecf20Sopenharmony_ci
2608c2ecf20Sopenharmony_ci	if (msg->flags & I2C_M_RD) {
2618c2ecf20Sopenharmony_ci		sprd_i2c_opt_mode(i2c_dev, 1);
2628c2ecf20Sopenharmony_ci		sprd_i2c_send_stop(i2c_dev, 1);
2638c2ecf20Sopenharmony_ci	} else {
2648c2ecf20Sopenharmony_ci		sprd_i2c_opt_mode(i2c_dev, 0);
2658c2ecf20Sopenharmony_ci		sprd_i2c_send_stop(i2c_dev, !!is_last_msg);
2668c2ecf20Sopenharmony_ci	}
2678c2ecf20Sopenharmony_ci
2688c2ecf20Sopenharmony_ci	/*
2698c2ecf20Sopenharmony_ci	 * We should enable rx fifo full interrupt to get data when receiving
2708c2ecf20Sopenharmony_ci	 * full data.
2718c2ecf20Sopenharmony_ci	 */
2728c2ecf20Sopenharmony_ci	if (msg->flags & I2C_M_RD)
2738c2ecf20Sopenharmony_ci		sprd_i2c_set_fifo_full_int(i2c_dev, 1);
2748c2ecf20Sopenharmony_ci	else
2758c2ecf20Sopenharmony_ci		sprd_i2c_data_transfer(i2c_dev);
2768c2ecf20Sopenharmony_ci
2778c2ecf20Sopenharmony_ci	sprd_i2c_opt_start(i2c_dev);
2788c2ecf20Sopenharmony_ci
2798c2ecf20Sopenharmony_ci	time_left = wait_for_completion_timeout(&i2c_dev->complete,
2808c2ecf20Sopenharmony_ci				msecs_to_jiffies(I2C_XFER_TIMEOUT));
2818c2ecf20Sopenharmony_ci	if (!time_left)
2828c2ecf20Sopenharmony_ci		return -ETIMEDOUT;
2838c2ecf20Sopenharmony_ci
2848c2ecf20Sopenharmony_ci	return i2c_dev->err;
2858c2ecf20Sopenharmony_ci}
2868c2ecf20Sopenharmony_ci
2878c2ecf20Sopenharmony_cistatic int sprd_i2c_master_xfer(struct i2c_adapter *i2c_adap,
2888c2ecf20Sopenharmony_ci				struct i2c_msg *msgs, int num)
2898c2ecf20Sopenharmony_ci{
2908c2ecf20Sopenharmony_ci	struct sprd_i2c *i2c_dev = i2c_adap->algo_data;
2918c2ecf20Sopenharmony_ci	int im, ret;
2928c2ecf20Sopenharmony_ci
2938c2ecf20Sopenharmony_ci	ret = pm_runtime_resume_and_get(i2c_dev->dev);
2948c2ecf20Sopenharmony_ci	if (ret < 0)
2958c2ecf20Sopenharmony_ci		return ret;
2968c2ecf20Sopenharmony_ci
2978c2ecf20Sopenharmony_ci	for (im = 0; im < num - 1; im++) {
2988c2ecf20Sopenharmony_ci		ret = sprd_i2c_handle_msg(i2c_adap, &msgs[im], 0);
2998c2ecf20Sopenharmony_ci		if (ret)
3008c2ecf20Sopenharmony_ci			goto err_msg;
3018c2ecf20Sopenharmony_ci	}
3028c2ecf20Sopenharmony_ci
3038c2ecf20Sopenharmony_ci	ret = sprd_i2c_handle_msg(i2c_adap, &msgs[im++], 1);
3048c2ecf20Sopenharmony_ci
3058c2ecf20Sopenharmony_cierr_msg:
3068c2ecf20Sopenharmony_ci	pm_runtime_mark_last_busy(i2c_dev->dev);
3078c2ecf20Sopenharmony_ci	pm_runtime_put_autosuspend(i2c_dev->dev);
3088c2ecf20Sopenharmony_ci
3098c2ecf20Sopenharmony_ci	return ret < 0 ? ret : im;
3108c2ecf20Sopenharmony_ci}
3118c2ecf20Sopenharmony_ci
3128c2ecf20Sopenharmony_cistatic u32 sprd_i2c_func(struct i2c_adapter *adap)
3138c2ecf20Sopenharmony_ci{
3148c2ecf20Sopenharmony_ci	return I2C_FUNC_I2C | I2C_FUNC_SMBUS_EMUL;
3158c2ecf20Sopenharmony_ci}
3168c2ecf20Sopenharmony_ci
3178c2ecf20Sopenharmony_cistatic const struct i2c_algorithm sprd_i2c_algo = {
3188c2ecf20Sopenharmony_ci	.master_xfer = sprd_i2c_master_xfer,
3198c2ecf20Sopenharmony_ci	.functionality = sprd_i2c_func,
3208c2ecf20Sopenharmony_ci};
3218c2ecf20Sopenharmony_ci
3228c2ecf20Sopenharmony_cistatic void sprd_i2c_set_clk(struct sprd_i2c *i2c_dev, u32 freq)
3238c2ecf20Sopenharmony_ci{
3248c2ecf20Sopenharmony_ci	u32 apb_clk = i2c_dev->src_clk;
3258c2ecf20Sopenharmony_ci	/*
3268c2ecf20Sopenharmony_ci	 * From I2C databook, the prescale calculation formula:
3278c2ecf20Sopenharmony_ci	 * prescale = freq_i2c / (4 * freq_scl) - 1;
3288c2ecf20Sopenharmony_ci	 */
3298c2ecf20Sopenharmony_ci	u32 i2c_dvd = apb_clk / (4 * freq) - 1;
3308c2ecf20Sopenharmony_ci	/*
3318c2ecf20Sopenharmony_ci	 * From I2C databook, the high period of SCL clock is recommended as
3328c2ecf20Sopenharmony_ci	 * 40% (2/5), and the low period of SCL clock is recommended as 60%
3338c2ecf20Sopenharmony_ci	 * (3/5), then the formula should be:
3348c2ecf20Sopenharmony_ci	 * high = (prescale * 2 * 2) / 5
3358c2ecf20Sopenharmony_ci	 * low = (prescale * 2 * 3) / 5
3368c2ecf20Sopenharmony_ci	 */
3378c2ecf20Sopenharmony_ci	u32 high = ((i2c_dvd << 1) * 2) / 5;
3388c2ecf20Sopenharmony_ci	u32 low = ((i2c_dvd << 1) * 3) / 5;
3398c2ecf20Sopenharmony_ci	u32 div0 = I2C_ADDR_DVD0_CALC(high, low);
3408c2ecf20Sopenharmony_ci	u32 div1 = I2C_ADDR_DVD1_CALC(high, low);
3418c2ecf20Sopenharmony_ci
3428c2ecf20Sopenharmony_ci	writel(div0, i2c_dev->base + ADDR_DVD0);
3438c2ecf20Sopenharmony_ci	writel(div1, i2c_dev->base + ADDR_DVD1);
3448c2ecf20Sopenharmony_ci
3458c2ecf20Sopenharmony_ci	/* Start hold timing = hold time(us) * source clock */
3468c2ecf20Sopenharmony_ci	if (freq == I2C_MAX_FAST_MODE_FREQ)
3478c2ecf20Sopenharmony_ci		writel((6 * apb_clk) / 10000000, i2c_dev->base + ADDR_STA0_DVD);
3488c2ecf20Sopenharmony_ci	else if (freq == I2C_MAX_STANDARD_MODE_FREQ)
3498c2ecf20Sopenharmony_ci		writel((4 * apb_clk) / 1000000, i2c_dev->base + ADDR_STA0_DVD);
3508c2ecf20Sopenharmony_ci}
3518c2ecf20Sopenharmony_ci
3528c2ecf20Sopenharmony_cistatic void sprd_i2c_enable(struct sprd_i2c *i2c_dev)
3538c2ecf20Sopenharmony_ci{
3548c2ecf20Sopenharmony_ci	u32 tmp = I2C_DVD_OPT;
3558c2ecf20Sopenharmony_ci
3568c2ecf20Sopenharmony_ci	writel(tmp, i2c_dev->base + I2C_CTL);
3578c2ecf20Sopenharmony_ci
3588c2ecf20Sopenharmony_ci	sprd_i2c_set_full_thld(i2c_dev, I2C_FIFO_FULL_THLD);
3598c2ecf20Sopenharmony_ci	sprd_i2c_set_empty_thld(i2c_dev, I2C_FIFO_EMPTY_THLD);
3608c2ecf20Sopenharmony_ci
3618c2ecf20Sopenharmony_ci	sprd_i2c_set_clk(i2c_dev, i2c_dev->bus_freq);
3628c2ecf20Sopenharmony_ci	sprd_i2c_reset_fifo(i2c_dev);
3638c2ecf20Sopenharmony_ci	sprd_i2c_clear_irq(i2c_dev);
3648c2ecf20Sopenharmony_ci
3658c2ecf20Sopenharmony_ci	tmp = readl(i2c_dev->base + I2C_CTL);
3668c2ecf20Sopenharmony_ci	writel(tmp | I2C_EN | I2C_INT_EN, i2c_dev->base + I2C_CTL);
3678c2ecf20Sopenharmony_ci}
3688c2ecf20Sopenharmony_ci
3698c2ecf20Sopenharmony_cistatic irqreturn_t sprd_i2c_isr_thread(int irq, void *dev_id)
3708c2ecf20Sopenharmony_ci{
3718c2ecf20Sopenharmony_ci	struct sprd_i2c *i2c_dev = dev_id;
3728c2ecf20Sopenharmony_ci	struct i2c_msg *msg = i2c_dev->msg;
3738c2ecf20Sopenharmony_ci	bool ack = !(readl(i2c_dev->base + I2C_STATUS) & I2C_RX_ACK);
3748c2ecf20Sopenharmony_ci	u32 i2c_tran;
3758c2ecf20Sopenharmony_ci
3768c2ecf20Sopenharmony_ci	if (msg->flags & I2C_M_RD)
3778c2ecf20Sopenharmony_ci		i2c_tran = i2c_dev->count >= I2C_FIFO_FULL_THLD;
3788c2ecf20Sopenharmony_ci	else
3798c2ecf20Sopenharmony_ci		i2c_tran = i2c_dev->count;
3808c2ecf20Sopenharmony_ci
3818c2ecf20Sopenharmony_ci	/*
3828c2ecf20Sopenharmony_ci	 * If we got one ACK from slave when writing data, and we did not
3838c2ecf20Sopenharmony_ci	 * finish this transmission (i2c_tran is not zero), then we should
3848c2ecf20Sopenharmony_ci	 * continue to write data.
3858c2ecf20Sopenharmony_ci	 *
3868c2ecf20Sopenharmony_ci	 * For reading data, ack is always true, if i2c_tran is not 0 which
3878c2ecf20Sopenharmony_ci	 * means we still need to contine to read data from slave.
3888c2ecf20Sopenharmony_ci	 */
3898c2ecf20Sopenharmony_ci	if (i2c_tran && ack) {
3908c2ecf20Sopenharmony_ci		sprd_i2c_data_transfer(i2c_dev);
3918c2ecf20Sopenharmony_ci		return IRQ_HANDLED;
3928c2ecf20Sopenharmony_ci	}
3938c2ecf20Sopenharmony_ci
3948c2ecf20Sopenharmony_ci	i2c_dev->err = 0;
3958c2ecf20Sopenharmony_ci
3968c2ecf20Sopenharmony_ci	/*
3978c2ecf20Sopenharmony_ci	 * If we did not get one ACK from slave when writing data, we should
3988c2ecf20Sopenharmony_ci	 * return -EIO to notify users.
3998c2ecf20Sopenharmony_ci	 */
4008c2ecf20Sopenharmony_ci	if (!ack)
4018c2ecf20Sopenharmony_ci		i2c_dev->err = -EIO;
4028c2ecf20Sopenharmony_ci	else if (msg->flags & I2C_M_RD && i2c_dev->count)
4038c2ecf20Sopenharmony_ci		sprd_i2c_read_bytes(i2c_dev, i2c_dev->buf, i2c_dev->count);
4048c2ecf20Sopenharmony_ci
4058c2ecf20Sopenharmony_ci	/* Transmission is done and clear ack and start operation */
4068c2ecf20Sopenharmony_ci	sprd_i2c_clear_ack(i2c_dev);
4078c2ecf20Sopenharmony_ci	sprd_i2c_clear_start(i2c_dev);
4088c2ecf20Sopenharmony_ci	complete(&i2c_dev->complete);
4098c2ecf20Sopenharmony_ci
4108c2ecf20Sopenharmony_ci	return IRQ_HANDLED;
4118c2ecf20Sopenharmony_ci}
4128c2ecf20Sopenharmony_ci
4138c2ecf20Sopenharmony_cistatic irqreturn_t sprd_i2c_isr(int irq, void *dev_id)
4148c2ecf20Sopenharmony_ci{
4158c2ecf20Sopenharmony_ci	struct sprd_i2c *i2c_dev = dev_id;
4168c2ecf20Sopenharmony_ci	struct i2c_msg *msg = i2c_dev->msg;
4178c2ecf20Sopenharmony_ci	bool ack = !(readl(i2c_dev->base + I2C_STATUS) & I2C_RX_ACK);
4188c2ecf20Sopenharmony_ci	u32 i2c_tran;
4198c2ecf20Sopenharmony_ci
4208c2ecf20Sopenharmony_ci	if (msg->flags & I2C_M_RD)
4218c2ecf20Sopenharmony_ci		i2c_tran = i2c_dev->count >= I2C_FIFO_FULL_THLD;
4228c2ecf20Sopenharmony_ci	else
4238c2ecf20Sopenharmony_ci		i2c_tran = i2c_dev->count;
4248c2ecf20Sopenharmony_ci
4258c2ecf20Sopenharmony_ci	/*
4268c2ecf20Sopenharmony_ci	 * If we did not get one ACK from slave when writing data, then we
4278c2ecf20Sopenharmony_ci	 * should finish this transmission since we got some errors.
4288c2ecf20Sopenharmony_ci	 *
4298c2ecf20Sopenharmony_ci	 * When writing data, if i2c_tran == 0 which means we have writen
4308c2ecf20Sopenharmony_ci	 * done all data, then we can finish this transmission.
4318c2ecf20Sopenharmony_ci	 *
4328c2ecf20Sopenharmony_ci	 * When reading data, if conut < rx fifo full threshold, which
4338c2ecf20Sopenharmony_ci	 * means we can read all data in one time, then we can finish this
4348c2ecf20Sopenharmony_ci	 * transmission too.
4358c2ecf20Sopenharmony_ci	 */
4368c2ecf20Sopenharmony_ci	if (!i2c_tran || !ack) {
4378c2ecf20Sopenharmony_ci		sprd_i2c_clear_start(i2c_dev);
4388c2ecf20Sopenharmony_ci		sprd_i2c_clear_irq(i2c_dev);
4398c2ecf20Sopenharmony_ci	}
4408c2ecf20Sopenharmony_ci
4418c2ecf20Sopenharmony_ci	sprd_i2c_set_fifo_empty_int(i2c_dev, 0);
4428c2ecf20Sopenharmony_ci	sprd_i2c_set_fifo_full_int(i2c_dev, 0);
4438c2ecf20Sopenharmony_ci
4448c2ecf20Sopenharmony_ci	return IRQ_WAKE_THREAD;
4458c2ecf20Sopenharmony_ci}
4468c2ecf20Sopenharmony_ci
4478c2ecf20Sopenharmony_cistatic int sprd_i2c_clk_init(struct sprd_i2c *i2c_dev)
4488c2ecf20Sopenharmony_ci{
4498c2ecf20Sopenharmony_ci	struct clk *clk_i2c, *clk_parent;
4508c2ecf20Sopenharmony_ci
4518c2ecf20Sopenharmony_ci	clk_i2c = devm_clk_get(i2c_dev->dev, "i2c");
4528c2ecf20Sopenharmony_ci	if (IS_ERR(clk_i2c)) {
4538c2ecf20Sopenharmony_ci		dev_warn(i2c_dev->dev, "i2c%d can't get the i2c clock\n",
4548c2ecf20Sopenharmony_ci			 i2c_dev->adap.nr);
4558c2ecf20Sopenharmony_ci		clk_i2c = NULL;
4568c2ecf20Sopenharmony_ci	}
4578c2ecf20Sopenharmony_ci
4588c2ecf20Sopenharmony_ci	clk_parent = devm_clk_get(i2c_dev->dev, "source");
4598c2ecf20Sopenharmony_ci	if (IS_ERR(clk_parent)) {
4608c2ecf20Sopenharmony_ci		dev_warn(i2c_dev->dev, "i2c%d can't get the source clock\n",
4618c2ecf20Sopenharmony_ci			 i2c_dev->adap.nr);
4628c2ecf20Sopenharmony_ci		clk_parent = NULL;
4638c2ecf20Sopenharmony_ci	}
4648c2ecf20Sopenharmony_ci
4658c2ecf20Sopenharmony_ci	if (clk_set_parent(clk_i2c, clk_parent))
4668c2ecf20Sopenharmony_ci		i2c_dev->src_clk = clk_get_rate(clk_i2c);
4678c2ecf20Sopenharmony_ci	else
4688c2ecf20Sopenharmony_ci		i2c_dev->src_clk = 26000000;
4698c2ecf20Sopenharmony_ci
4708c2ecf20Sopenharmony_ci	dev_dbg(i2c_dev->dev, "i2c%d set source clock is %d\n",
4718c2ecf20Sopenharmony_ci		i2c_dev->adap.nr, i2c_dev->src_clk);
4728c2ecf20Sopenharmony_ci
4738c2ecf20Sopenharmony_ci	i2c_dev->clk = devm_clk_get(i2c_dev->dev, "enable");
4748c2ecf20Sopenharmony_ci	if (IS_ERR(i2c_dev->clk)) {
4758c2ecf20Sopenharmony_ci		dev_err(i2c_dev->dev, "i2c%d can't get the enable clock\n",
4768c2ecf20Sopenharmony_ci			i2c_dev->adap.nr);
4778c2ecf20Sopenharmony_ci		return PTR_ERR(i2c_dev->clk);
4788c2ecf20Sopenharmony_ci	}
4798c2ecf20Sopenharmony_ci
4808c2ecf20Sopenharmony_ci	return 0;
4818c2ecf20Sopenharmony_ci}
4828c2ecf20Sopenharmony_ci
4838c2ecf20Sopenharmony_cistatic int sprd_i2c_probe(struct platform_device *pdev)
4848c2ecf20Sopenharmony_ci{
4858c2ecf20Sopenharmony_ci	struct device *dev = &pdev->dev;
4868c2ecf20Sopenharmony_ci	struct sprd_i2c *i2c_dev;
4878c2ecf20Sopenharmony_ci	u32 prop;
4888c2ecf20Sopenharmony_ci	int ret;
4898c2ecf20Sopenharmony_ci
4908c2ecf20Sopenharmony_ci	pdev->id = of_alias_get_id(dev->of_node, "i2c");
4918c2ecf20Sopenharmony_ci
4928c2ecf20Sopenharmony_ci	i2c_dev = devm_kzalloc(dev, sizeof(struct sprd_i2c), GFP_KERNEL);
4938c2ecf20Sopenharmony_ci	if (!i2c_dev)
4948c2ecf20Sopenharmony_ci		return -ENOMEM;
4958c2ecf20Sopenharmony_ci
4968c2ecf20Sopenharmony_ci	i2c_dev->base = devm_platform_ioremap_resource(pdev, 0);
4978c2ecf20Sopenharmony_ci	if (IS_ERR(i2c_dev->base))
4988c2ecf20Sopenharmony_ci		return PTR_ERR(i2c_dev->base);
4998c2ecf20Sopenharmony_ci
5008c2ecf20Sopenharmony_ci	i2c_dev->irq = platform_get_irq(pdev, 0);
5018c2ecf20Sopenharmony_ci	if (i2c_dev->irq < 0)
5028c2ecf20Sopenharmony_ci		return i2c_dev->irq;
5038c2ecf20Sopenharmony_ci
5048c2ecf20Sopenharmony_ci	i2c_set_adapdata(&i2c_dev->adap, i2c_dev);
5058c2ecf20Sopenharmony_ci	init_completion(&i2c_dev->complete);
5068c2ecf20Sopenharmony_ci	snprintf(i2c_dev->adap.name, sizeof(i2c_dev->adap.name),
5078c2ecf20Sopenharmony_ci		 "%s", "sprd-i2c");
5088c2ecf20Sopenharmony_ci
5098c2ecf20Sopenharmony_ci	i2c_dev->bus_freq = I2C_MAX_STANDARD_MODE_FREQ;
5108c2ecf20Sopenharmony_ci	i2c_dev->adap.owner = THIS_MODULE;
5118c2ecf20Sopenharmony_ci	i2c_dev->dev = dev;
5128c2ecf20Sopenharmony_ci	i2c_dev->adap.retries = 3;
5138c2ecf20Sopenharmony_ci	i2c_dev->adap.algo = &sprd_i2c_algo;
5148c2ecf20Sopenharmony_ci	i2c_dev->adap.algo_data = i2c_dev;
5158c2ecf20Sopenharmony_ci	i2c_dev->adap.dev.parent = dev;
5168c2ecf20Sopenharmony_ci	i2c_dev->adap.nr = pdev->id;
5178c2ecf20Sopenharmony_ci	i2c_dev->adap.dev.of_node = dev->of_node;
5188c2ecf20Sopenharmony_ci
5198c2ecf20Sopenharmony_ci	if (!of_property_read_u32(dev->of_node, "clock-frequency", &prop))
5208c2ecf20Sopenharmony_ci		i2c_dev->bus_freq = prop;
5218c2ecf20Sopenharmony_ci
5228c2ecf20Sopenharmony_ci	/* We only support 100k and 400k now, otherwise will return error. */
5238c2ecf20Sopenharmony_ci	if (i2c_dev->bus_freq != I2C_MAX_STANDARD_MODE_FREQ &&
5248c2ecf20Sopenharmony_ci	    i2c_dev->bus_freq != I2C_MAX_FAST_MODE_FREQ)
5258c2ecf20Sopenharmony_ci		return -EINVAL;
5268c2ecf20Sopenharmony_ci
5278c2ecf20Sopenharmony_ci	ret = sprd_i2c_clk_init(i2c_dev);
5288c2ecf20Sopenharmony_ci	if (ret)
5298c2ecf20Sopenharmony_ci		return ret;
5308c2ecf20Sopenharmony_ci
5318c2ecf20Sopenharmony_ci	platform_set_drvdata(pdev, i2c_dev);
5328c2ecf20Sopenharmony_ci
5338c2ecf20Sopenharmony_ci	ret = clk_prepare_enable(i2c_dev->clk);
5348c2ecf20Sopenharmony_ci	if (ret)
5358c2ecf20Sopenharmony_ci		return ret;
5368c2ecf20Sopenharmony_ci
5378c2ecf20Sopenharmony_ci	sprd_i2c_enable(i2c_dev);
5388c2ecf20Sopenharmony_ci
5398c2ecf20Sopenharmony_ci	pm_runtime_set_autosuspend_delay(i2c_dev->dev, SPRD_I2C_PM_TIMEOUT);
5408c2ecf20Sopenharmony_ci	pm_runtime_use_autosuspend(i2c_dev->dev);
5418c2ecf20Sopenharmony_ci	pm_runtime_set_active(i2c_dev->dev);
5428c2ecf20Sopenharmony_ci	pm_runtime_enable(i2c_dev->dev);
5438c2ecf20Sopenharmony_ci
5448c2ecf20Sopenharmony_ci	ret = pm_runtime_get_sync(i2c_dev->dev);
5458c2ecf20Sopenharmony_ci	if (ret < 0)
5468c2ecf20Sopenharmony_ci		goto err_rpm_put;
5478c2ecf20Sopenharmony_ci
5488c2ecf20Sopenharmony_ci	ret = devm_request_threaded_irq(dev, i2c_dev->irq,
5498c2ecf20Sopenharmony_ci		sprd_i2c_isr, sprd_i2c_isr_thread,
5508c2ecf20Sopenharmony_ci		IRQF_NO_SUSPEND | IRQF_ONESHOT,
5518c2ecf20Sopenharmony_ci		pdev->name, i2c_dev);
5528c2ecf20Sopenharmony_ci	if (ret) {
5538c2ecf20Sopenharmony_ci		dev_err(&pdev->dev, "failed to request irq %d\n", i2c_dev->irq);
5548c2ecf20Sopenharmony_ci		goto err_rpm_put;
5558c2ecf20Sopenharmony_ci	}
5568c2ecf20Sopenharmony_ci
5578c2ecf20Sopenharmony_ci	ret = i2c_add_numbered_adapter(&i2c_dev->adap);
5588c2ecf20Sopenharmony_ci	if (ret) {
5598c2ecf20Sopenharmony_ci		dev_err(&pdev->dev, "add adapter failed\n");
5608c2ecf20Sopenharmony_ci		goto err_rpm_put;
5618c2ecf20Sopenharmony_ci	}
5628c2ecf20Sopenharmony_ci
5638c2ecf20Sopenharmony_ci	pm_runtime_mark_last_busy(i2c_dev->dev);
5648c2ecf20Sopenharmony_ci	pm_runtime_put_autosuspend(i2c_dev->dev);
5658c2ecf20Sopenharmony_ci	return 0;
5668c2ecf20Sopenharmony_ci
5678c2ecf20Sopenharmony_cierr_rpm_put:
5688c2ecf20Sopenharmony_ci	pm_runtime_put_noidle(i2c_dev->dev);
5698c2ecf20Sopenharmony_ci	pm_runtime_disable(i2c_dev->dev);
5708c2ecf20Sopenharmony_ci	clk_disable_unprepare(i2c_dev->clk);
5718c2ecf20Sopenharmony_ci	return ret;
5728c2ecf20Sopenharmony_ci}
5738c2ecf20Sopenharmony_ci
5748c2ecf20Sopenharmony_cistatic int sprd_i2c_remove(struct platform_device *pdev)
5758c2ecf20Sopenharmony_ci{
5768c2ecf20Sopenharmony_ci	struct sprd_i2c *i2c_dev = platform_get_drvdata(pdev);
5778c2ecf20Sopenharmony_ci	int ret;
5788c2ecf20Sopenharmony_ci
5798c2ecf20Sopenharmony_ci	ret = pm_runtime_get_sync(i2c_dev->dev);
5808c2ecf20Sopenharmony_ci	if (ret < 0)
5818c2ecf20Sopenharmony_ci		dev_err(&pdev->dev, "Failed to resume device (%pe)\n", ERR_PTR(ret));
5828c2ecf20Sopenharmony_ci
5838c2ecf20Sopenharmony_ci	i2c_del_adapter(&i2c_dev->adap);
5848c2ecf20Sopenharmony_ci
5858c2ecf20Sopenharmony_ci	if (ret >= 0)
5868c2ecf20Sopenharmony_ci		clk_disable_unprepare(i2c_dev->clk);
5878c2ecf20Sopenharmony_ci
5888c2ecf20Sopenharmony_ci	pm_runtime_put_noidle(i2c_dev->dev);
5898c2ecf20Sopenharmony_ci	pm_runtime_disable(i2c_dev->dev);
5908c2ecf20Sopenharmony_ci
5918c2ecf20Sopenharmony_ci	return 0;
5928c2ecf20Sopenharmony_ci}
5938c2ecf20Sopenharmony_ci
5948c2ecf20Sopenharmony_cistatic int __maybe_unused sprd_i2c_suspend_noirq(struct device *dev)
5958c2ecf20Sopenharmony_ci{
5968c2ecf20Sopenharmony_ci	struct sprd_i2c *i2c_dev = dev_get_drvdata(dev);
5978c2ecf20Sopenharmony_ci
5988c2ecf20Sopenharmony_ci	i2c_mark_adapter_suspended(&i2c_dev->adap);
5998c2ecf20Sopenharmony_ci	return pm_runtime_force_suspend(dev);
6008c2ecf20Sopenharmony_ci}
6018c2ecf20Sopenharmony_ci
6028c2ecf20Sopenharmony_cistatic int __maybe_unused sprd_i2c_resume_noirq(struct device *dev)
6038c2ecf20Sopenharmony_ci{
6048c2ecf20Sopenharmony_ci	struct sprd_i2c *i2c_dev = dev_get_drvdata(dev);
6058c2ecf20Sopenharmony_ci
6068c2ecf20Sopenharmony_ci	i2c_mark_adapter_resumed(&i2c_dev->adap);
6078c2ecf20Sopenharmony_ci	return pm_runtime_force_resume(dev);
6088c2ecf20Sopenharmony_ci}
6098c2ecf20Sopenharmony_ci
6108c2ecf20Sopenharmony_cistatic int __maybe_unused sprd_i2c_runtime_suspend(struct device *dev)
6118c2ecf20Sopenharmony_ci{
6128c2ecf20Sopenharmony_ci	struct sprd_i2c *i2c_dev = dev_get_drvdata(dev);
6138c2ecf20Sopenharmony_ci
6148c2ecf20Sopenharmony_ci	clk_disable_unprepare(i2c_dev->clk);
6158c2ecf20Sopenharmony_ci
6168c2ecf20Sopenharmony_ci	return 0;
6178c2ecf20Sopenharmony_ci}
6188c2ecf20Sopenharmony_ci
6198c2ecf20Sopenharmony_cistatic int __maybe_unused sprd_i2c_runtime_resume(struct device *dev)
6208c2ecf20Sopenharmony_ci{
6218c2ecf20Sopenharmony_ci	struct sprd_i2c *i2c_dev = dev_get_drvdata(dev);
6228c2ecf20Sopenharmony_ci	int ret;
6238c2ecf20Sopenharmony_ci
6248c2ecf20Sopenharmony_ci	ret = clk_prepare_enable(i2c_dev->clk);
6258c2ecf20Sopenharmony_ci	if (ret)
6268c2ecf20Sopenharmony_ci		return ret;
6278c2ecf20Sopenharmony_ci
6288c2ecf20Sopenharmony_ci	sprd_i2c_enable(i2c_dev);
6298c2ecf20Sopenharmony_ci
6308c2ecf20Sopenharmony_ci	return 0;
6318c2ecf20Sopenharmony_ci}
6328c2ecf20Sopenharmony_ci
6338c2ecf20Sopenharmony_cistatic const struct dev_pm_ops sprd_i2c_pm_ops = {
6348c2ecf20Sopenharmony_ci	SET_RUNTIME_PM_OPS(sprd_i2c_runtime_suspend,
6358c2ecf20Sopenharmony_ci			   sprd_i2c_runtime_resume, NULL)
6368c2ecf20Sopenharmony_ci
6378c2ecf20Sopenharmony_ci	SET_NOIRQ_SYSTEM_SLEEP_PM_OPS(sprd_i2c_suspend_noirq,
6388c2ecf20Sopenharmony_ci				      sprd_i2c_resume_noirq)
6398c2ecf20Sopenharmony_ci};
6408c2ecf20Sopenharmony_ci
6418c2ecf20Sopenharmony_cistatic const struct of_device_id sprd_i2c_of_match[] = {
6428c2ecf20Sopenharmony_ci	{ .compatible = "sprd,sc9860-i2c", },
6438c2ecf20Sopenharmony_ci	{},
6448c2ecf20Sopenharmony_ci};
6458c2ecf20Sopenharmony_ci
6468c2ecf20Sopenharmony_cistatic struct platform_driver sprd_i2c_driver = {
6478c2ecf20Sopenharmony_ci	.probe = sprd_i2c_probe,
6488c2ecf20Sopenharmony_ci	.remove = sprd_i2c_remove,
6498c2ecf20Sopenharmony_ci	.driver = {
6508c2ecf20Sopenharmony_ci		   .name = "sprd-i2c",
6518c2ecf20Sopenharmony_ci		   .of_match_table = sprd_i2c_of_match,
6528c2ecf20Sopenharmony_ci		   .pm = &sprd_i2c_pm_ops,
6538c2ecf20Sopenharmony_ci	},
6548c2ecf20Sopenharmony_ci};
6558c2ecf20Sopenharmony_ci
6568c2ecf20Sopenharmony_cimodule_platform_driver(sprd_i2c_driver);
6578c2ecf20Sopenharmony_ci
6588c2ecf20Sopenharmony_ciMODULE_DESCRIPTION("Spreadtrum I2C master controller driver");
6598c2ecf20Sopenharmony_ciMODULE_LICENSE("GPL v2");
660