162306a36Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0
262306a36Sopenharmony_ci/*
362306a36Sopenharmony_ci * HiSilicon I2C Controller Driver for Kunpeng SoC
462306a36Sopenharmony_ci *
562306a36Sopenharmony_ci * Copyright (c) 2021 HiSilicon Technologies Co., Ltd.
662306a36Sopenharmony_ci */
762306a36Sopenharmony_ci
862306a36Sopenharmony_ci#include <linux/bits.h>
962306a36Sopenharmony_ci#include <linux/bitfield.h>
1062306a36Sopenharmony_ci#include <linux/clk.h>
1162306a36Sopenharmony_ci#include <linux/completion.h>
1262306a36Sopenharmony_ci#include <linux/i2c.h>
1362306a36Sopenharmony_ci#include <linux/interrupt.h>
1462306a36Sopenharmony_ci#include <linux/io.h>
1562306a36Sopenharmony_ci#include <linux/module.h>
1662306a36Sopenharmony_ci#include <linux/mod_devicetable.h>
1762306a36Sopenharmony_ci#include <linux/platform_device.h>
1862306a36Sopenharmony_ci#include <linux/property.h>
1962306a36Sopenharmony_ci#include <linux/units.h>
2062306a36Sopenharmony_ci
2162306a36Sopenharmony_ci#define HISI_I2C_FRAME_CTRL		0x0000
2262306a36Sopenharmony_ci#define   HISI_I2C_FRAME_CTRL_SPEED_MODE	GENMASK(1, 0)
2362306a36Sopenharmony_ci#define   HISI_I2C_FRAME_CTRL_ADDR_TEN	BIT(2)
2462306a36Sopenharmony_ci#define HISI_I2C_SLV_ADDR		0x0004
2562306a36Sopenharmony_ci#define   HISI_I2C_SLV_ADDR_VAL		GENMASK(9, 0)
2662306a36Sopenharmony_ci#define   HISI_I2C_SLV_ADDR_GC_S_MODE	BIT(10)
2762306a36Sopenharmony_ci#define   HISI_I2C_SLV_ADDR_GC_S_EN	BIT(11)
2862306a36Sopenharmony_ci#define HISI_I2C_CMD_TXDATA		0x0008
2962306a36Sopenharmony_ci#define   HISI_I2C_CMD_TXDATA_DATA	GENMASK(7, 0)
3062306a36Sopenharmony_ci#define   HISI_I2C_CMD_TXDATA_RW	BIT(8)
3162306a36Sopenharmony_ci#define   HISI_I2C_CMD_TXDATA_P_EN	BIT(9)
3262306a36Sopenharmony_ci#define   HISI_I2C_CMD_TXDATA_SR_EN	BIT(10)
3362306a36Sopenharmony_ci#define HISI_I2C_RXDATA			0x000c
3462306a36Sopenharmony_ci#define   HISI_I2C_RXDATA_DATA		GENMASK(7, 0)
3562306a36Sopenharmony_ci#define HISI_I2C_SS_SCL_HCNT		0x0010
3662306a36Sopenharmony_ci#define HISI_I2C_SS_SCL_LCNT		0x0014
3762306a36Sopenharmony_ci#define HISI_I2C_FS_SCL_HCNT		0x0018
3862306a36Sopenharmony_ci#define HISI_I2C_FS_SCL_LCNT		0x001c
3962306a36Sopenharmony_ci#define HISI_I2C_HS_SCL_HCNT		0x0020
4062306a36Sopenharmony_ci#define HISI_I2C_HS_SCL_LCNT		0x0024
4162306a36Sopenharmony_ci#define HISI_I2C_FIFO_CTRL		0x0028
4262306a36Sopenharmony_ci#define   HISI_I2C_FIFO_RX_CLR		BIT(0)
4362306a36Sopenharmony_ci#define   HISI_I2C_FIFO_TX_CLR		BIT(1)
4462306a36Sopenharmony_ci#define   HISI_I2C_FIFO_RX_AF_THRESH	GENMASK(7, 2)
4562306a36Sopenharmony_ci#define   HISI_I2C_FIFO_TX_AE_THRESH	GENMASK(13, 8)
4662306a36Sopenharmony_ci#define HISI_I2C_FIFO_STATE		0x002c
4762306a36Sopenharmony_ci#define   HISI_I2C_FIFO_STATE_RX_RERR	BIT(0)
4862306a36Sopenharmony_ci#define   HISI_I2C_FIFO_STATE_RX_WERR	BIT(1)
4962306a36Sopenharmony_ci#define   HISI_I2C_FIFO_STATE_RX_EMPTY	BIT(3)
5062306a36Sopenharmony_ci#define   HISI_I2C_FIFO_STATE_TX_RERR	BIT(6)
5162306a36Sopenharmony_ci#define   HISI_I2C_FIFO_STATE_TX_WERR	BIT(7)
5262306a36Sopenharmony_ci#define   HISI_I2C_FIFO_STATE_TX_FULL	BIT(11)
5362306a36Sopenharmony_ci#define HISI_I2C_SDA_HOLD		0x0030
5462306a36Sopenharmony_ci#define   HISI_I2C_SDA_HOLD_TX		GENMASK(15, 0)
5562306a36Sopenharmony_ci#define   HISI_I2C_SDA_HOLD_RX		GENMASK(23, 16)
5662306a36Sopenharmony_ci#define HISI_I2C_FS_SPK_LEN		0x0038
5762306a36Sopenharmony_ci#define   HISI_I2C_FS_SPK_LEN_CNT	GENMASK(7, 0)
5862306a36Sopenharmony_ci#define HISI_I2C_HS_SPK_LEN		0x003c
5962306a36Sopenharmony_ci#define   HISI_I2C_HS_SPK_LEN_CNT	GENMASK(7, 0)
6062306a36Sopenharmony_ci#define HISI_I2C_INT_MSTAT		0x0044
6162306a36Sopenharmony_ci#define HISI_I2C_INT_CLR		0x0048
6262306a36Sopenharmony_ci#define HISI_I2C_INT_MASK		0x004C
6362306a36Sopenharmony_ci#define HISI_I2C_TRANS_STATE		0x0050
6462306a36Sopenharmony_ci#define HISI_I2C_TRANS_ERR		0x0054
6562306a36Sopenharmony_ci#define HISI_I2C_VERSION		0x0058
6662306a36Sopenharmony_ci
6762306a36Sopenharmony_ci#define HISI_I2C_INT_ALL	GENMASK(4, 0)
6862306a36Sopenharmony_ci#define HISI_I2C_INT_TRANS_CPLT	BIT(0)
6962306a36Sopenharmony_ci#define HISI_I2C_INT_TRANS_ERR	BIT(1)
7062306a36Sopenharmony_ci#define HISI_I2C_INT_FIFO_ERR	BIT(2)
7162306a36Sopenharmony_ci#define HISI_I2C_INT_RX_FULL	BIT(3)
7262306a36Sopenharmony_ci#define HISI_I2C_INT_TX_EMPTY	BIT(4)
7362306a36Sopenharmony_ci#define HISI_I2C_INT_ERR \
7462306a36Sopenharmony_ci	(HISI_I2C_INT_TRANS_ERR | HISI_I2C_INT_FIFO_ERR)
7562306a36Sopenharmony_ci
7662306a36Sopenharmony_ci#define HISI_I2C_STD_SPEED_MODE		0
7762306a36Sopenharmony_ci#define HISI_I2C_FAST_SPEED_MODE	1
7862306a36Sopenharmony_ci#define HISI_I2C_HIGH_SPEED_MODE	2
7962306a36Sopenharmony_ci
8062306a36Sopenharmony_ci#define HISI_I2C_TX_FIFO_DEPTH		64
8162306a36Sopenharmony_ci#define HISI_I2C_RX_FIFO_DEPTH		64
8262306a36Sopenharmony_ci#define HISI_I2C_TX_F_AE_THRESH		1
8362306a36Sopenharmony_ci#define HISI_I2C_RX_F_AF_THRESH		60
8462306a36Sopenharmony_ci
8562306a36Sopenharmony_ci#define NSEC_TO_CYCLES(ns, clk_rate_khz) \
8662306a36Sopenharmony_ci	DIV_ROUND_UP_ULL((clk_rate_khz) * (ns), NSEC_PER_MSEC)
8762306a36Sopenharmony_ci
8862306a36Sopenharmony_cistruct hisi_i2c_controller {
8962306a36Sopenharmony_ci	struct i2c_adapter adapter;
9062306a36Sopenharmony_ci	void __iomem *iobase;
9162306a36Sopenharmony_ci	struct device *dev;
9262306a36Sopenharmony_ci	struct clk *clk;
9362306a36Sopenharmony_ci	int irq;
9462306a36Sopenharmony_ci
9562306a36Sopenharmony_ci	/* Intermediates for recording the transfer process */
9662306a36Sopenharmony_ci	struct completion *completion;
9762306a36Sopenharmony_ci	struct i2c_msg *msgs;
9862306a36Sopenharmony_ci	int msg_num;
9962306a36Sopenharmony_ci	int msg_tx_idx;
10062306a36Sopenharmony_ci	int buf_tx_idx;
10162306a36Sopenharmony_ci	int msg_rx_idx;
10262306a36Sopenharmony_ci	int buf_rx_idx;
10362306a36Sopenharmony_ci	u16 tar_addr;
10462306a36Sopenharmony_ci	u32 xfer_err;
10562306a36Sopenharmony_ci
10662306a36Sopenharmony_ci	/* I2C bus configuration */
10762306a36Sopenharmony_ci	struct i2c_timings t;
10862306a36Sopenharmony_ci	u32 clk_rate_khz;
10962306a36Sopenharmony_ci	u32 spk_len;
11062306a36Sopenharmony_ci};
11162306a36Sopenharmony_ci
11262306a36Sopenharmony_cistatic void hisi_i2c_enable_int(struct hisi_i2c_controller *ctlr, u32 mask)
11362306a36Sopenharmony_ci{
11462306a36Sopenharmony_ci	writel_relaxed(mask, ctlr->iobase + HISI_I2C_INT_MASK);
11562306a36Sopenharmony_ci}
11662306a36Sopenharmony_ci
11762306a36Sopenharmony_cistatic void hisi_i2c_disable_int(struct hisi_i2c_controller *ctlr, u32 mask)
11862306a36Sopenharmony_ci{
11962306a36Sopenharmony_ci	writel_relaxed((~mask) & HISI_I2C_INT_ALL, ctlr->iobase + HISI_I2C_INT_MASK);
12062306a36Sopenharmony_ci}
12162306a36Sopenharmony_ci
12262306a36Sopenharmony_cistatic void hisi_i2c_clear_int(struct hisi_i2c_controller *ctlr, u32 mask)
12362306a36Sopenharmony_ci{
12462306a36Sopenharmony_ci	writel_relaxed(mask, ctlr->iobase + HISI_I2C_INT_CLR);
12562306a36Sopenharmony_ci}
12662306a36Sopenharmony_ci
12762306a36Sopenharmony_cistatic void hisi_i2c_handle_errors(struct hisi_i2c_controller *ctlr)
12862306a36Sopenharmony_ci{
12962306a36Sopenharmony_ci	u32 int_err = ctlr->xfer_err, reg;
13062306a36Sopenharmony_ci
13162306a36Sopenharmony_ci	if (int_err & HISI_I2C_INT_FIFO_ERR) {
13262306a36Sopenharmony_ci		reg = readl(ctlr->iobase + HISI_I2C_FIFO_STATE);
13362306a36Sopenharmony_ci
13462306a36Sopenharmony_ci		if (reg & HISI_I2C_FIFO_STATE_RX_RERR)
13562306a36Sopenharmony_ci			dev_err(ctlr->dev, "rx fifo error read\n");
13662306a36Sopenharmony_ci
13762306a36Sopenharmony_ci		if (reg & HISI_I2C_FIFO_STATE_RX_WERR)
13862306a36Sopenharmony_ci			dev_err(ctlr->dev, "rx fifo error write\n");
13962306a36Sopenharmony_ci
14062306a36Sopenharmony_ci		if (reg & HISI_I2C_FIFO_STATE_TX_RERR)
14162306a36Sopenharmony_ci			dev_err(ctlr->dev, "tx fifo error read\n");
14262306a36Sopenharmony_ci
14362306a36Sopenharmony_ci		if (reg & HISI_I2C_FIFO_STATE_TX_WERR)
14462306a36Sopenharmony_ci			dev_err(ctlr->dev, "tx fifo error write\n");
14562306a36Sopenharmony_ci	}
14662306a36Sopenharmony_ci}
14762306a36Sopenharmony_ci
14862306a36Sopenharmony_cistatic int hisi_i2c_start_xfer(struct hisi_i2c_controller *ctlr)
14962306a36Sopenharmony_ci{
15062306a36Sopenharmony_ci	struct i2c_msg *msg = ctlr->msgs;
15162306a36Sopenharmony_ci	u32 reg;
15262306a36Sopenharmony_ci
15362306a36Sopenharmony_ci	reg = readl(ctlr->iobase + HISI_I2C_FRAME_CTRL);
15462306a36Sopenharmony_ci	reg &= ~HISI_I2C_FRAME_CTRL_ADDR_TEN;
15562306a36Sopenharmony_ci	if (msg->flags & I2C_M_TEN)
15662306a36Sopenharmony_ci		reg |= HISI_I2C_FRAME_CTRL_ADDR_TEN;
15762306a36Sopenharmony_ci	writel(reg, ctlr->iobase + HISI_I2C_FRAME_CTRL);
15862306a36Sopenharmony_ci
15962306a36Sopenharmony_ci	reg = readl(ctlr->iobase + HISI_I2C_SLV_ADDR);
16062306a36Sopenharmony_ci	reg &= ~HISI_I2C_SLV_ADDR_VAL;
16162306a36Sopenharmony_ci	reg |= FIELD_PREP(HISI_I2C_SLV_ADDR_VAL, msg->addr);
16262306a36Sopenharmony_ci	writel(reg, ctlr->iobase + HISI_I2C_SLV_ADDR);
16362306a36Sopenharmony_ci
16462306a36Sopenharmony_ci	reg = readl(ctlr->iobase + HISI_I2C_FIFO_CTRL);
16562306a36Sopenharmony_ci	reg |= HISI_I2C_FIFO_RX_CLR | HISI_I2C_FIFO_TX_CLR;
16662306a36Sopenharmony_ci	writel(reg, ctlr->iobase + HISI_I2C_FIFO_CTRL);
16762306a36Sopenharmony_ci	reg &= ~(HISI_I2C_FIFO_RX_CLR | HISI_I2C_FIFO_TX_CLR);
16862306a36Sopenharmony_ci	writel(reg, ctlr->iobase + HISI_I2C_FIFO_CTRL);
16962306a36Sopenharmony_ci
17062306a36Sopenharmony_ci	hisi_i2c_clear_int(ctlr, HISI_I2C_INT_ALL);
17162306a36Sopenharmony_ci	hisi_i2c_enable_int(ctlr, HISI_I2C_INT_ALL);
17262306a36Sopenharmony_ci
17362306a36Sopenharmony_ci	return 0;
17462306a36Sopenharmony_ci}
17562306a36Sopenharmony_ci
17662306a36Sopenharmony_cistatic void hisi_i2c_reset_xfer(struct hisi_i2c_controller *ctlr)
17762306a36Sopenharmony_ci{
17862306a36Sopenharmony_ci	ctlr->msg_num = 0;
17962306a36Sopenharmony_ci	ctlr->xfer_err = 0;
18062306a36Sopenharmony_ci	ctlr->msg_tx_idx = 0;
18162306a36Sopenharmony_ci	ctlr->msg_rx_idx = 0;
18262306a36Sopenharmony_ci	ctlr->buf_tx_idx = 0;
18362306a36Sopenharmony_ci	ctlr->buf_rx_idx = 0;
18462306a36Sopenharmony_ci}
18562306a36Sopenharmony_ci
18662306a36Sopenharmony_ci/*
18762306a36Sopenharmony_ci * Initialize the transfer information and start the I2C bus transfer.
18862306a36Sopenharmony_ci * We only configure the transfer and do some pre/post works here, and
18962306a36Sopenharmony_ci * wait for the transfer done. The major transfer process is performed
19062306a36Sopenharmony_ci * in the IRQ handler.
19162306a36Sopenharmony_ci */
19262306a36Sopenharmony_cistatic int hisi_i2c_master_xfer(struct i2c_adapter *adap, struct i2c_msg *msgs,
19362306a36Sopenharmony_ci				int num)
19462306a36Sopenharmony_ci{
19562306a36Sopenharmony_ci	struct hisi_i2c_controller *ctlr = i2c_get_adapdata(adap);
19662306a36Sopenharmony_ci	DECLARE_COMPLETION_ONSTACK(done);
19762306a36Sopenharmony_ci	int ret = num;
19862306a36Sopenharmony_ci
19962306a36Sopenharmony_ci	hisi_i2c_reset_xfer(ctlr);
20062306a36Sopenharmony_ci	ctlr->completion = &done;
20162306a36Sopenharmony_ci	ctlr->msg_num = num;
20262306a36Sopenharmony_ci	ctlr->msgs = msgs;
20362306a36Sopenharmony_ci
20462306a36Sopenharmony_ci	hisi_i2c_start_xfer(ctlr);
20562306a36Sopenharmony_ci
20662306a36Sopenharmony_ci	if (!wait_for_completion_timeout(ctlr->completion, adap->timeout)) {
20762306a36Sopenharmony_ci		hisi_i2c_disable_int(ctlr, HISI_I2C_INT_ALL);
20862306a36Sopenharmony_ci		synchronize_irq(ctlr->irq);
20962306a36Sopenharmony_ci		i2c_recover_bus(&ctlr->adapter);
21062306a36Sopenharmony_ci		dev_err(ctlr->dev, "bus transfer timeout\n");
21162306a36Sopenharmony_ci		ret = -EIO;
21262306a36Sopenharmony_ci	}
21362306a36Sopenharmony_ci
21462306a36Sopenharmony_ci	if (ctlr->xfer_err) {
21562306a36Sopenharmony_ci		hisi_i2c_handle_errors(ctlr);
21662306a36Sopenharmony_ci		ret = -EIO;
21762306a36Sopenharmony_ci	}
21862306a36Sopenharmony_ci
21962306a36Sopenharmony_ci	hisi_i2c_reset_xfer(ctlr);
22062306a36Sopenharmony_ci	ctlr->completion = NULL;
22162306a36Sopenharmony_ci
22262306a36Sopenharmony_ci	return ret;
22362306a36Sopenharmony_ci}
22462306a36Sopenharmony_ci
22562306a36Sopenharmony_cistatic u32 hisi_i2c_functionality(struct i2c_adapter *adap)
22662306a36Sopenharmony_ci{
22762306a36Sopenharmony_ci	return I2C_FUNC_I2C | I2C_FUNC_10BIT_ADDR | I2C_FUNC_SMBUS_EMUL;
22862306a36Sopenharmony_ci}
22962306a36Sopenharmony_ci
23062306a36Sopenharmony_cistatic const struct i2c_algorithm hisi_i2c_algo = {
23162306a36Sopenharmony_ci	.master_xfer	= hisi_i2c_master_xfer,
23262306a36Sopenharmony_ci	.functionality	= hisi_i2c_functionality,
23362306a36Sopenharmony_ci};
23462306a36Sopenharmony_ci
23562306a36Sopenharmony_cistatic int hisi_i2c_read_rx_fifo(struct hisi_i2c_controller *ctlr)
23662306a36Sopenharmony_ci{
23762306a36Sopenharmony_ci	struct i2c_msg *cur_msg;
23862306a36Sopenharmony_ci	u32 fifo_state;
23962306a36Sopenharmony_ci
24062306a36Sopenharmony_ci	while (ctlr->msg_rx_idx < ctlr->msg_num) {
24162306a36Sopenharmony_ci		cur_msg = ctlr->msgs + ctlr->msg_rx_idx;
24262306a36Sopenharmony_ci
24362306a36Sopenharmony_ci		if (!(cur_msg->flags & I2C_M_RD)) {
24462306a36Sopenharmony_ci			ctlr->msg_rx_idx++;
24562306a36Sopenharmony_ci			continue;
24662306a36Sopenharmony_ci		}
24762306a36Sopenharmony_ci
24862306a36Sopenharmony_ci		fifo_state = readl(ctlr->iobase + HISI_I2C_FIFO_STATE);
24962306a36Sopenharmony_ci		while (!(fifo_state & HISI_I2C_FIFO_STATE_RX_EMPTY) &&
25062306a36Sopenharmony_ci		       ctlr->buf_rx_idx < cur_msg->len) {
25162306a36Sopenharmony_ci			cur_msg->buf[ctlr->buf_rx_idx++] = readl(ctlr->iobase + HISI_I2C_RXDATA);
25262306a36Sopenharmony_ci			fifo_state = readl(ctlr->iobase + HISI_I2C_FIFO_STATE);
25362306a36Sopenharmony_ci		}
25462306a36Sopenharmony_ci
25562306a36Sopenharmony_ci		if (ctlr->buf_rx_idx == cur_msg->len) {
25662306a36Sopenharmony_ci			ctlr->buf_rx_idx = 0;
25762306a36Sopenharmony_ci			ctlr->msg_rx_idx++;
25862306a36Sopenharmony_ci		}
25962306a36Sopenharmony_ci
26062306a36Sopenharmony_ci		if (fifo_state & HISI_I2C_FIFO_STATE_RX_EMPTY)
26162306a36Sopenharmony_ci			break;
26262306a36Sopenharmony_ci	}
26362306a36Sopenharmony_ci
26462306a36Sopenharmony_ci	return 0;
26562306a36Sopenharmony_ci}
26662306a36Sopenharmony_ci
26762306a36Sopenharmony_cistatic void hisi_i2c_xfer_msg(struct hisi_i2c_controller *ctlr)
26862306a36Sopenharmony_ci{
26962306a36Sopenharmony_ci	int max_write = HISI_I2C_TX_FIFO_DEPTH;
27062306a36Sopenharmony_ci	bool need_restart = false, last_msg;
27162306a36Sopenharmony_ci	struct i2c_msg *cur_msg;
27262306a36Sopenharmony_ci	u32 cmd, fifo_state;
27362306a36Sopenharmony_ci
27462306a36Sopenharmony_ci	while (ctlr->msg_tx_idx < ctlr->msg_num) {
27562306a36Sopenharmony_ci		cur_msg = ctlr->msgs + ctlr->msg_tx_idx;
27662306a36Sopenharmony_ci		last_msg = (ctlr->msg_tx_idx == ctlr->msg_num - 1);
27762306a36Sopenharmony_ci
27862306a36Sopenharmony_ci		/* Signal the SR bit when we start transferring a new message */
27962306a36Sopenharmony_ci		if (ctlr->msg_tx_idx && !ctlr->buf_tx_idx)
28062306a36Sopenharmony_ci			need_restart = true;
28162306a36Sopenharmony_ci
28262306a36Sopenharmony_ci		fifo_state = readl(ctlr->iobase + HISI_I2C_FIFO_STATE);
28362306a36Sopenharmony_ci		while (!(fifo_state & HISI_I2C_FIFO_STATE_TX_FULL) &&
28462306a36Sopenharmony_ci		       ctlr->buf_tx_idx < cur_msg->len && max_write) {
28562306a36Sopenharmony_ci			cmd = 0;
28662306a36Sopenharmony_ci
28762306a36Sopenharmony_ci			if (need_restart) {
28862306a36Sopenharmony_ci				cmd |= HISI_I2C_CMD_TXDATA_SR_EN;
28962306a36Sopenharmony_ci				need_restart = false;
29062306a36Sopenharmony_ci			}
29162306a36Sopenharmony_ci
29262306a36Sopenharmony_ci			/* Signal the STOP bit at the last frame of the last message */
29362306a36Sopenharmony_ci			if (ctlr->buf_tx_idx == cur_msg->len - 1 && last_msg)
29462306a36Sopenharmony_ci				cmd |= HISI_I2C_CMD_TXDATA_P_EN;
29562306a36Sopenharmony_ci
29662306a36Sopenharmony_ci			if (cur_msg->flags & I2C_M_RD)
29762306a36Sopenharmony_ci				cmd |= HISI_I2C_CMD_TXDATA_RW;
29862306a36Sopenharmony_ci			else
29962306a36Sopenharmony_ci				cmd |= FIELD_PREP(HISI_I2C_CMD_TXDATA_DATA,
30062306a36Sopenharmony_ci						  cur_msg->buf[ctlr->buf_tx_idx]);
30162306a36Sopenharmony_ci
30262306a36Sopenharmony_ci			writel(cmd, ctlr->iobase + HISI_I2C_CMD_TXDATA);
30362306a36Sopenharmony_ci			ctlr->buf_tx_idx++;
30462306a36Sopenharmony_ci			max_write--;
30562306a36Sopenharmony_ci
30662306a36Sopenharmony_ci			fifo_state = readl(ctlr->iobase + HISI_I2C_FIFO_STATE);
30762306a36Sopenharmony_ci		}
30862306a36Sopenharmony_ci
30962306a36Sopenharmony_ci		/* Update the transfer index after per message transfer is done. */
31062306a36Sopenharmony_ci		if (ctlr->buf_tx_idx == cur_msg->len) {
31162306a36Sopenharmony_ci			ctlr->buf_tx_idx = 0;
31262306a36Sopenharmony_ci			ctlr->msg_tx_idx++;
31362306a36Sopenharmony_ci		}
31462306a36Sopenharmony_ci
31562306a36Sopenharmony_ci		if ((fifo_state & HISI_I2C_FIFO_STATE_TX_FULL) ||
31662306a36Sopenharmony_ci		    max_write == 0)
31762306a36Sopenharmony_ci			break;
31862306a36Sopenharmony_ci	}
31962306a36Sopenharmony_ci
32062306a36Sopenharmony_ci	/*
32162306a36Sopenharmony_ci	 * Disable the TX_EMPTY interrupt after finishing all the messages to
32262306a36Sopenharmony_ci	 * avoid overwhelming the CPU.
32362306a36Sopenharmony_ci	 */
32462306a36Sopenharmony_ci	if (ctlr->msg_tx_idx == ctlr->msg_num)
32562306a36Sopenharmony_ci		hisi_i2c_disable_int(ctlr, HISI_I2C_INT_TX_EMPTY);
32662306a36Sopenharmony_ci}
32762306a36Sopenharmony_ci
32862306a36Sopenharmony_cistatic irqreturn_t hisi_i2c_irq(int irq, void *context)
32962306a36Sopenharmony_ci{
33062306a36Sopenharmony_ci	struct hisi_i2c_controller *ctlr = context;
33162306a36Sopenharmony_ci	u32 int_stat;
33262306a36Sopenharmony_ci
33362306a36Sopenharmony_ci	/*
33462306a36Sopenharmony_ci	 * Don't handle the interrupt if cltr->completion is NULL. We may
33562306a36Sopenharmony_ci	 * reach here because the interrupt is spurious or the transfer is
33662306a36Sopenharmony_ci	 * started by another port (e.g. firmware) rather than us.
33762306a36Sopenharmony_ci	 */
33862306a36Sopenharmony_ci	if (!ctlr->completion)
33962306a36Sopenharmony_ci		return IRQ_NONE;
34062306a36Sopenharmony_ci
34162306a36Sopenharmony_ci	int_stat = readl(ctlr->iobase + HISI_I2C_INT_MSTAT);
34262306a36Sopenharmony_ci	hisi_i2c_clear_int(ctlr, int_stat);
34362306a36Sopenharmony_ci	if (!(int_stat & HISI_I2C_INT_ALL))
34462306a36Sopenharmony_ci		return IRQ_NONE;
34562306a36Sopenharmony_ci
34662306a36Sopenharmony_ci	if (int_stat & HISI_I2C_INT_TX_EMPTY)
34762306a36Sopenharmony_ci		hisi_i2c_xfer_msg(ctlr);
34862306a36Sopenharmony_ci
34962306a36Sopenharmony_ci	if (int_stat & HISI_I2C_INT_ERR) {
35062306a36Sopenharmony_ci		ctlr->xfer_err = int_stat;
35162306a36Sopenharmony_ci		goto out;
35262306a36Sopenharmony_ci	}
35362306a36Sopenharmony_ci
35462306a36Sopenharmony_ci	/* Drain the rx fifo before finish the transfer */
35562306a36Sopenharmony_ci	if (int_stat & (HISI_I2C_INT_TRANS_CPLT | HISI_I2C_INT_RX_FULL))
35662306a36Sopenharmony_ci		hisi_i2c_read_rx_fifo(ctlr);
35762306a36Sopenharmony_ci
35862306a36Sopenharmony_ciout:
35962306a36Sopenharmony_ci	/*
36062306a36Sopenharmony_ci	 * Only use TRANS_CPLT to indicate the completion. On error cases we'll
36162306a36Sopenharmony_ci	 * get two interrupts, INT_ERR first then TRANS_CPLT.
36262306a36Sopenharmony_ci	 */
36362306a36Sopenharmony_ci	if (int_stat & HISI_I2C_INT_TRANS_CPLT) {
36462306a36Sopenharmony_ci		hisi_i2c_disable_int(ctlr, HISI_I2C_INT_ALL);
36562306a36Sopenharmony_ci		hisi_i2c_clear_int(ctlr, HISI_I2C_INT_ALL);
36662306a36Sopenharmony_ci		complete(ctlr->completion);
36762306a36Sopenharmony_ci	}
36862306a36Sopenharmony_ci
36962306a36Sopenharmony_ci	return IRQ_HANDLED;
37062306a36Sopenharmony_ci}
37162306a36Sopenharmony_ci
37262306a36Sopenharmony_ci/*
37362306a36Sopenharmony_ci * Helper function for calculating and configuring the HIGH and LOW
37462306a36Sopenharmony_ci * periods of SCL clock. The caller will pass the ratio of the
37562306a36Sopenharmony_ci * counts (divide / divisor) according to the target speed mode,
37662306a36Sopenharmony_ci * and the target registers.
37762306a36Sopenharmony_ci */
37862306a36Sopenharmony_cistatic void hisi_i2c_set_scl(struct hisi_i2c_controller *ctlr,
37962306a36Sopenharmony_ci			     u32 divide, u32 divisor,
38062306a36Sopenharmony_ci			     u32 reg_hcnt, u32 reg_lcnt)
38162306a36Sopenharmony_ci{
38262306a36Sopenharmony_ci	u32 total_cnt, t_scl_hcnt, t_scl_lcnt, scl_fall_cnt, scl_rise_cnt;
38362306a36Sopenharmony_ci	u32 scl_hcnt, scl_lcnt;
38462306a36Sopenharmony_ci
38562306a36Sopenharmony_ci	/* Total SCL clock cycles per speed period */
38662306a36Sopenharmony_ci	total_cnt = DIV_ROUND_UP_ULL(ctlr->clk_rate_khz * HZ_PER_KHZ, ctlr->t.bus_freq_hz);
38762306a36Sopenharmony_ci	/* Total HIGH level SCL clock cycles including edges */
38862306a36Sopenharmony_ci	t_scl_hcnt = DIV_ROUND_UP_ULL(total_cnt * divide, divisor);
38962306a36Sopenharmony_ci	/* Total LOW level SCL clock cycles including edges */
39062306a36Sopenharmony_ci	t_scl_lcnt = total_cnt - t_scl_hcnt;
39162306a36Sopenharmony_ci	/* Fall edge SCL clock cycles */
39262306a36Sopenharmony_ci	scl_fall_cnt = NSEC_TO_CYCLES(ctlr->t.scl_fall_ns, ctlr->clk_rate_khz);
39362306a36Sopenharmony_ci	/* Rise edge SCL clock cycles */
39462306a36Sopenharmony_ci	scl_rise_cnt = NSEC_TO_CYCLES(ctlr->t.scl_rise_ns, ctlr->clk_rate_khz);
39562306a36Sopenharmony_ci
39662306a36Sopenharmony_ci	/* Calculated HIGH and LOW periods of SCL clock */
39762306a36Sopenharmony_ci	scl_hcnt = t_scl_hcnt - ctlr->spk_len - 7 - scl_fall_cnt;
39862306a36Sopenharmony_ci	scl_lcnt = t_scl_lcnt - 1 - scl_rise_cnt;
39962306a36Sopenharmony_ci
40062306a36Sopenharmony_ci	writel(scl_hcnt, ctlr->iobase + reg_hcnt);
40162306a36Sopenharmony_ci	writel(scl_lcnt, ctlr->iobase + reg_lcnt);
40262306a36Sopenharmony_ci}
40362306a36Sopenharmony_ci
40462306a36Sopenharmony_cistatic void hisi_i2c_configure_bus(struct hisi_i2c_controller *ctlr)
40562306a36Sopenharmony_ci{
40662306a36Sopenharmony_ci	u32 reg, sda_hold_cnt, speed_mode;
40762306a36Sopenharmony_ci
40862306a36Sopenharmony_ci	i2c_parse_fw_timings(ctlr->dev, &ctlr->t, true);
40962306a36Sopenharmony_ci	ctlr->spk_len = NSEC_TO_CYCLES(ctlr->t.digital_filter_width_ns, ctlr->clk_rate_khz);
41062306a36Sopenharmony_ci
41162306a36Sopenharmony_ci	switch (ctlr->t.bus_freq_hz) {
41262306a36Sopenharmony_ci	case I2C_MAX_FAST_MODE_FREQ:
41362306a36Sopenharmony_ci		speed_mode = HISI_I2C_FAST_SPEED_MODE;
41462306a36Sopenharmony_ci		hisi_i2c_set_scl(ctlr, 26, 76, HISI_I2C_FS_SCL_HCNT, HISI_I2C_FS_SCL_LCNT);
41562306a36Sopenharmony_ci		break;
41662306a36Sopenharmony_ci	case I2C_MAX_HIGH_SPEED_MODE_FREQ:
41762306a36Sopenharmony_ci		speed_mode = HISI_I2C_HIGH_SPEED_MODE;
41862306a36Sopenharmony_ci		hisi_i2c_set_scl(ctlr, 6, 22, HISI_I2C_HS_SCL_HCNT, HISI_I2C_HS_SCL_LCNT);
41962306a36Sopenharmony_ci		break;
42062306a36Sopenharmony_ci	case I2C_MAX_STANDARD_MODE_FREQ:
42162306a36Sopenharmony_ci	default:
42262306a36Sopenharmony_ci		speed_mode = HISI_I2C_STD_SPEED_MODE;
42362306a36Sopenharmony_ci
42462306a36Sopenharmony_ci		/* For default condition force the bus speed to standard mode. */
42562306a36Sopenharmony_ci		ctlr->t.bus_freq_hz = I2C_MAX_STANDARD_MODE_FREQ;
42662306a36Sopenharmony_ci		hisi_i2c_set_scl(ctlr, 40, 87, HISI_I2C_SS_SCL_HCNT, HISI_I2C_SS_SCL_LCNT);
42762306a36Sopenharmony_ci		break;
42862306a36Sopenharmony_ci	}
42962306a36Sopenharmony_ci
43062306a36Sopenharmony_ci	reg = readl(ctlr->iobase + HISI_I2C_FRAME_CTRL);
43162306a36Sopenharmony_ci	reg &= ~HISI_I2C_FRAME_CTRL_SPEED_MODE;
43262306a36Sopenharmony_ci	reg |= FIELD_PREP(HISI_I2C_FRAME_CTRL_SPEED_MODE, speed_mode);
43362306a36Sopenharmony_ci	writel(reg, ctlr->iobase + HISI_I2C_FRAME_CTRL);
43462306a36Sopenharmony_ci
43562306a36Sopenharmony_ci	sda_hold_cnt = NSEC_TO_CYCLES(ctlr->t.sda_hold_ns, ctlr->clk_rate_khz);
43662306a36Sopenharmony_ci
43762306a36Sopenharmony_ci	reg = FIELD_PREP(HISI_I2C_SDA_HOLD_TX, sda_hold_cnt);
43862306a36Sopenharmony_ci	writel(reg, ctlr->iobase + HISI_I2C_SDA_HOLD);
43962306a36Sopenharmony_ci
44062306a36Sopenharmony_ci	writel(ctlr->spk_len, ctlr->iobase + HISI_I2C_FS_SPK_LEN);
44162306a36Sopenharmony_ci
44262306a36Sopenharmony_ci	reg = FIELD_PREP(HISI_I2C_FIFO_RX_AF_THRESH, HISI_I2C_RX_F_AF_THRESH);
44362306a36Sopenharmony_ci	reg |= FIELD_PREP(HISI_I2C_FIFO_TX_AE_THRESH, HISI_I2C_TX_F_AE_THRESH);
44462306a36Sopenharmony_ci	writel(reg, ctlr->iobase + HISI_I2C_FIFO_CTRL);
44562306a36Sopenharmony_ci}
44662306a36Sopenharmony_ci
44762306a36Sopenharmony_cistatic int hisi_i2c_probe(struct platform_device *pdev)
44862306a36Sopenharmony_ci{
44962306a36Sopenharmony_ci	struct hisi_i2c_controller *ctlr;
45062306a36Sopenharmony_ci	struct device *dev = &pdev->dev;
45162306a36Sopenharmony_ci	struct i2c_adapter *adapter;
45262306a36Sopenharmony_ci	u64 clk_rate_hz;
45362306a36Sopenharmony_ci	u32 hw_version;
45462306a36Sopenharmony_ci	int ret;
45562306a36Sopenharmony_ci
45662306a36Sopenharmony_ci	ctlr = devm_kzalloc(dev, sizeof(*ctlr), GFP_KERNEL);
45762306a36Sopenharmony_ci	if (!ctlr)
45862306a36Sopenharmony_ci		return -ENOMEM;
45962306a36Sopenharmony_ci
46062306a36Sopenharmony_ci	ctlr->iobase = devm_platform_ioremap_resource(pdev, 0);
46162306a36Sopenharmony_ci	if (IS_ERR(ctlr->iobase))
46262306a36Sopenharmony_ci		return PTR_ERR(ctlr->iobase);
46362306a36Sopenharmony_ci
46462306a36Sopenharmony_ci	ctlr->irq = platform_get_irq(pdev, 0);
46562306a36Sopenharmony_ci	if (ctlr->irq < 0)
46662306a36Sopenharmony_ci		return ctlr->irq;
46762306a36Sopenharmony_ci
46862306a36Sopenharmony_ci	ctlr->dev = dev;
46962306a36Sopenharmony_ci
47062306a36Sopenharmony_ci	hisi_i2c_disable_int(ctlr, HISI_I2C_INT_ALL);
47162306a36Sopenharmony_ci
47262306a36Sopenharmony_ci	ret = devm_request_irq(dev, ctlr->irq, hisi_i2c_irq, 0, "hisi-i2c", ctlr);
47362306a36Sopenharmony_ci	if (ret)
47462306a36Sopenharmony_ci		return dev_err_probe(dev, ret, "failed to request irq handler\n");
47562306a36Sopenharmony_ci
47662306a36Sopenharmony_ci	ctlr->clk = devm_clk_get_optional_enabled(&pdev->dev, NULL);
47762306a36Sopenharmony_ci	if (IS_ERR_OR_NULL(ctlr->clk)) {
47862306a36Sopenharmony_ci		ret = device_property_read_u64(dev, "clk_rate", &clk_rate_hz);
47962306a36Sopenharmony_ci		if (ret)
48062306a36Sopenharmony_ci			return dev_err_probe(dev, ret, "failed to get clock frequency\n");
48162306a36Sopenharmony_ci	} else {
48262306a36Sopenharmony_ci		clk_rate_hz = clk_get_rate(ctlr->clk);
48362306a36Sopenharmony_ci	}
48462306a36Sopenharmony_ci
48562306a36Sopenharmony_ci	ctlr->clk_rate_khz = DIV_ROUND_UP_ULL(clk_rate_hz, HZ_PER_KHZ);
48662306a36Sopenharmony_ci
48762306a36Sopenharmony_ci	hisi_i2c_configure_bus(ctlr);
48862306a36Sopenharmony_ci
48962306a36Sopenharmony_ci	adapter = &ctlr->adapter;
49062306a36Sopenharmony_ci	snprintf(adapter->name, sizeof(adapter->name),
49162306a36Sopenharmony_ci		 "HiSilicon I2C Controller %s", dev_name(dev));
49262306a36Sopenharmony_ci	adapter->owner = THIS_MODULE;
49362306a36Sopenharmony_ci	adapter->algo = &hisi_i2c_algo;
49462306a36Sopenharmony_ci	adapter->dev.parent = dev;
49562306a36Sopenharmony_ci	i2c_set_adapdata(adapter, ctlr);
49662306a36Sopenharmony_ci
49762306a36Sopenharmony_ci	ret = devm_i2c_add_adapter(dev, adapter);
49862306a36Sopenharmony_ci	if (ret)
49962306a36Sopenharmony_ci		return ret;
50062306a36Sopenharmony_ci
50162306a36Sopenharmony_ci	hw_version = readl(ctlr->iobase + HISI_I2C_VERSION);
50262306a36Sopenharmony_ci	dev_info(ctlr->dev, "speed mode is %s. hw version 0x%x\n",
50362306a36Sopenharmony_ci		 i2c_freq_mode_string(ctlr->t.bus_freq_hz), hw_version);
50462306a36Sopenharmony_ci
50562306a36Sopenharmony_ci	return 0;
50662306a36Sopenharmony_ci}
50762306a36Sopenharmony_ci
50862306a36Sopenharmony_cistatic const struct acpi_device_id hisi_i2c_acpi_ids[] = {
50962306a36Sopenharmony_ci	{ "HISI03D1", 0 },
51062306a36Sopenharmony_ci	{ }
51162306a36Sopenharmony_ci};
51262306a36Sopenharmony_ciMODULE_DEVICE_TABLE(acpi, hisi_i2c_acpi_ids);
51362306a36Sopenharmony_ci
51462306a36Sopenharmony_cistatic const struct of_device_id hisi_i2c_dts_ids[] = {
51562306a36Sopenharmony_ci	{ .compatible = "hisilicon,ascend910-i2c", },
51662306a36Sopenharmony_ci	{ }
51762306a36Sopenharmony_ci};
51862306a36Sopenharmony_ciMODULE_DEVICE_TABLE(of, hisi_i2c_dts_ids);
51962306a36Sopenharmony_ci
52062306a36Sopenharmony_cistatic struct platform_driver hisi_i2c_driver = {
52162306a36Sopenharmony_ci	.probe		= hisi_i2c_probe,
52262306a36Sopenharmony_ci	.driver		= {
52362306a36Sopenharmony_ci		.name	= "hisi-i2c",
52462306a36Sopenharmony_ci		.acpi_match_table = hisi_i2c_acpi_ids,
52562306a36Sopenharmony_ci		.of_match_table = hisi_i2c_dts_ids,
52662306a36Sopenharmony_ci	},
52762306a36Sopenharmony_ci};
52862306a36Sopenharmony_cimodule_platform_driver(hisi_i2c_driver);
52962306a36Sopenharmony_ci
53062306a36Sopenharmony_ciMODULE_AUTHOR("Yicong Yang <yangyicong@hisilicon.com>");
53162306a36Sopenharmony_ciMODULE_DESCRIPTION("HiSilicon I2C Controller Driver");
53262306a36Sopenharmony_ciMODULE_LICENSE("GPL");
533