162306a36Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0
262306a36Sopenharmony_ci/*
362306a36Sopenharmony_ci * Copyright (C) 2012 FUJITSU SEMICONDUCTOR LIMITED
462306a36Sopenharmony_ci */
562306a36Sopenharmony_ci
662306a36Sopenharmony_ci#include <linux/acpi.h>
762306a36Sopenharmony_ci#include <linux/clk.h>
862306a36Sopenharmony_ci#include <linux/delay.h>
962306a36Sopenharmony_ci#include <linux/device.h>
1062306a36Sopenharmony_ci#include <linux/err.h>
1162306a36Sopenharmony_ci#include <linux/errno.h>
1262306a36Sopenharmony_ci#include <linux/i2c.h>
1362306a36Sopenharmony_ci#include <linux/interrupt.h>
1462306a36Sopenharmony_ci#include <linux/io.h>
1562306a36Sopenharmony_ci#include <linux/kernel.h>
1662306a36Sopenharmony_ci#include <linux/module.h>
1762306a36Sopenharmony_ci#include <linux/platform_device.h>
1862306a36Sopenharmony_ci#include <linux/sched.h>
1962306a36Sopenharmony_ci#include <linux/slab.h>
2062306a36Sopenharmony_ci#include <linux/spinlock.h>
2162306a36Sopenharmony_ci
2262306a36Sopenharmony_ci#define WAIT_PCLK(n, rate)	\
2362306a36Sopenharmony_ci	ndelay(DIV_ROUND_UP(DIV_ROUND_UP(1000000000, rate), n) + 10)
2462306a36Sopenharmony_ci
2562306a36Sopenharmony_ci/* I2C register address definitions */
2662306a36Sopenharmony_ci#define SYNQUACER_I2C_REG_BSR		(0x00 << 2) // Bus Status
2762306a36Sopenharmony_ci#define SYNQUACER_I2C_REG_BCR		(0x01 << 2) // Bus Control
2862306a36Sopenharmony_ci#define SYNQUACER_I2C_REG_CCR		(0x02 << 2) // Clock Control
2962306a36Sopenharmony_ci#define SYNQUACER_I2C_REG_ADR		(0x03 << 2) // Address
3062306a36Sopenharmony_ci#define SYNQUACER_I2C_REG_DAR		(0x04 << 2) // Data
3162306a36Sopenharmony_ci#define SYNQUACER_I2C_REG_CSR		(0x05 << 2) // Expansion CS
3262306a36Sopenharmony_ci#define SYNQUACER_I2C_REG_FSR		(0x06 << 2) // Bus Clock Freq
3362306a36Sopenharmony_ci#define SYNQUACER_I2C_REG_BC2R		(0x07 << 2) // Bus Control 2
3462306a36Sopenharmony_ci
3562306a36Sopenharmony_ci/* I2C register bit definitions */
3662306a36Sopenharmony_ci#define SYNQUACER_I2C_BSR_FBT		BIT(0)	// First Byte Transfer
3762306a36Sopenharmony_ci#define SYNQUACER_I2C_BSR_GCA		BIT(1)	// General Call Address
3862306a36Sopenharmony_ci#define SYNQUACER_I2C_BSR_AAS		BIT(2)	// Address as Slave
3962306a36Sopenharmony_ci#define SYNQUACER_I2C_BSR_TRX		BIT(3)	// Transfer/Receive
4062306a36Sopenharmony_ci#define SYNQUACER_I2C_BSR_LRB		BIT(4)	// Last Received Bit
4162306a36Sopenharmony_ci#define SYNQUACER_I2C_BSR_AL		BIT(5)	// Arbitration Lost
4262306a36Sopenharmony_ci#define SYNQUACER_I2C_BSR_RSC		BIT(6)	// Repeated Start Cond.
4362306a36Sopenharmony_ci#define SYNQUACER_I2C_BSR_BB		BIT(7)	// Bus Busy
4462306a36Sopenharmony_ci
4562306a36Sopenharmony_ci#define SYNQUACER_I2C_BCR_INT		BIT(0)	// Interrupt
4662306a36Sopenharmony_ci#define SYNQUACER_I2C_BCR_INTE		BIT(1)	// Interrupt Enable
4762306a36Sopenharmony_ci#define SYNQUACER_I2C_BCR_GCAA		BIT(2)	// Gen. Call Access Ack.
4862306a36Sopenharmony_ci#define SYNQUACER_I2C_BCR_ACK		BIT(3)	// Acknowledge
4962306a36Sopenharmony_ci#define SYNQUACER_I2C_BCR_MSS		BIT(4)	// Master Slave Select
5062306a36Sopenharmony_ci#define SYNQUACER_I2C_BCR_SCC		BIT(5)	// Start Condition Cont.
5162306a36Sopenharmony_ci#define SYNQUACER_I2C_BCR_BEIE		BIT(6)	// Bus Error Int Enable
5262306a36Sopenharmony_ci#define SYNQUACER_I2C_BCR_BER		BIT(7)	// Bus Error
5362306a36Sopenharmony_ci
5462306a36Sopenharmony_ci#define SYNQUACER_I2C_CCR_CS_MASK	(0x1f)	// CCR Clock Period Sel.
5562306a36Sopenharmony_ci#define SYNQUACER_I2C_CCR_EN		BIT(5)	// Enable
5662306a36Sopenharmony_ci#define SYNQUACER_I2C_CCR_FM		BIT(6)	// Speed Mode Select
5762306a36Sopenharmony_ci
5862306a36Sopenharmony_ci#define SYNQUACER_I2C_CSR_CS_MASK	(0x3f)	// CSR Clock Period Sel.
5962306a36Sopenharmony_ci
6062306a36Sopenharmony_ci#define SYNQUACER_I2C_BC2R_SCLL		BIT(0)	// SCL Low Drive
6162306a36Sopenharmony_ci#define SYNQUACER_I2C_BC2R_SDAL		BIT(1)	// SDA Low Drive
6262306a36Sopenharmony_ci#define SYNQUACER_I2C_BC2R_SCLS		BIT(4)	// SCL Status
6362306a36Sopenharmony_ci#define SYNQUACER_I2C_BC2R_SDAS		BIT(5)	// SDA Status
6462306a36Sopenharmony_ci
6562306a36Sopenharmony_ci/* PCLK frequency */
6662306a36Sopenharmony_ci#define SYNQUACER_I2C_BUS_CLK_FR(rate)	(((rate) / 20000000) + 1)
6762306a36Sopenharmony_ci
6862306a36Sopenharmony_ci/* STANDARD MODE frequency */
6962306a36Sopenharmony_ci#define SYNQUACER_I2C_CLK_MASTER_STD(rate)			\
7062306a36Sopenharmony_ci	DIV_ROUND_UP(DIV_ROUND_UP((rate), I2C_MAX_STANDARD_MODE_FREQ) - 2, 2)
7162306a36Sopenharmony_ci/* FAST MODE frequency */
7262306a36Sopenharmony_ci#define SYNQUACER_I2C_CLK_MASTER_FAST(rate)			\
7362306a36Sopenharmony_ci	DIV_ROUND_UP((DIV_ROUND_UP((rate), I2C_MAX_FAST_MODE_FREQ) - 2) * 2, 3)
7462306a36Sopenharmony_ci
7562306a36Sopenharmony_ci/* (clkrate <= 18000000) */
7662306a36Sopenharmony_ci/* calculate the value of CS bits in CCR register on standard mode */
7762306a36Sopenharmony_ci#define SYNQUACER_I2C_CCR_CS_STD_MAX_18M(rate)			\
7862306a36Sopenharmony_ci	   ((SYNQUACER_I2C_CLK_MASTER_STD(rate) - 65)		\
7962306a36Sopenharmony_ci					& SYNQUACER_I2C_CCR_CS_MASK)
8062306a36Sopenharmony_ci
8162306a36Sopenharmony_ci/* calculate the value of CS bits in CSR register on standard mode */
8262306a36Sopenharmony_ci#define SYNQUACER_I2C_CSR_CS_STD_MAX_18M(rate)		0x00
8362306a36Sopenharmony_ci
8462306a36Sopenharmony_ci/* calculate the value of CS bits in CCR register on fast mode */
8562306a36Sopenharmony_ci#define SYNQUACER_I2C_CCR_CS_FAST_MAX_18M(rate)			\
8662306a36Sopenharmony_ci	   ((SYNQUACER_I2C_CLK_MASTER_FAST(rate) - 1)		\
8762306a36Sopenharmony_ci					& SYNQUACER_I2C_CCR_CS_MASK)
8862306a36Sopenharmony_ci
8962306a36Sopenharmony_ci/* calculate the value of CS bits in CSR register on fast mode */
9062306a36Sopenharmony_ci#define SYNQUACER_I2C_CSR_CS_FAST_MAX_18M(rate)		0x00
9162306a36Sopenharmony_ci
9262306a36Sopenharmony_ci/* (clkrate > 18000000) */
9362306a36Sopenharmony_ci/* calculate the value of CS bits in CCR register on standard mode */
9462306a36Sopenharmony_ci#define SYNQUACER_I2C_CCR_CS_STD_MIN_18M(rate)			\
9562306a36Sopenharmony_ci	   ((SYNQUACER_I2C_CLK_MASTER_STD(rate) - 1)		\
9662306a36Sopenharmony_ci					& SYNQUACER_I2C_CCR_CS_MASK)
9762306a36Sopenharmony_ci
9862306a36Sopenharmony_ci/* calculate the value of CS bits in CSR register on standard mode */
9962306a36Sopenharmony_ci#define SYNQUACER_I2C_CSR_CS_STD_MIN_18M(rate)			\
10062306a36Sopenharmony_ci	   (((SYNQUACER_I2C_CLK_MASTER_STD(rate) - 1) >> 5)	\
10162306a36Sopenharmony_ci					& SYNQUACER_I2C_CSR_CS_MASK)
10262306a36Sopenharmony_ci
10362306a36Sopenharmony_ci/* calculate the value of CS bits in CCR register on fast mode */
10462306a36Sopenharmony_ci#define SYNQUACER_I2C_CCR_CS_FAST_MIN_18M(rate)			\
10562306a36Sopenharmony_ci	   ((SYNQUACER_I2C_CLK_MASTER_FAST(rate) - 1)		\
10662306a36Sopenharmony_ci					& SYNQUACER_I2C_CCR_CS_MASK)
10762306a36Sopenharmony_ci
10862306a36Sopenharmony_ci/* calculate the value of CS bits in CSR register on fast mode */
10962306a36Sopenharmony_ci#define SYNQUACER_I2C_CSR_CS_FAST_MIN_18M(rate)			\
11062306a36Sopenharmony_ci	   (((SYNQUACER_I2C_CLK_MASTER_FAST(rate) - 1) >> 5)	\
11162306a36Sopenharmony_ci					& SYNQUACER_I2C_CSR_CS_MASK)
11262306a36Sopenharmony_ci
11362306a36Sopenharmony_ci/* min I2C clock frequency 14M */
11462306a36Sopenharmony_ci#define SYNQUACER_I2C_MIN_CLK_RATE	(14 * 1000000)
11562306a36Sopenharmony_ci/* max I2C clock frequency 200M */
11662306a36Sopenharmony_ci#define SYNQUACER_I2C_MAX_CLK_RATE	(200 * 1000000)
11762306a36Sopenharmony_ci/* I2C clock frequency 18M */
11862306a36Sopenharmony_ci#define SYNQUACER_I2C_CLK_RATE_18M	(18 * 1000000)
11962306a36Sopenharmony_ci
12062306a36Sopenharmony_ci#define SYNQUACER_I2C_SPEED_FM		400	// Fast Mode
12162306a36Sopenharmony_ci#define SYNQUACER_I2C_SPEED_SM		100	// Standard Mode
12262306a36Sopenharmony_ci
12362306a36Sopenharmony_cienum i2c_state {
12462306a36Sopenharmony_ci	STATE_IDLE,
12562306a36Sopenharmony_ci	STATE_START,
12662306a36Sopenharmony_ci	STATE_READ,
12762306a36Sopenharmony_ci	STATE_WRITE
12862306a36Sopenharmony_ci};
12962306a36Sopenharmony_ci
13062306a36Sopenharmony_cistruct synquacer_i2c {
13162306a36Sopenharmony_ci	struct completion	completion;
13262306a36Sopenharmony_ci
13362306a36Sopenharmony_ci	struct i2c_msg		*msg;
13462306a36Sopenharmony_ci	u32			msg_num;
13562306a36Sopenharmony_ci	u32			msg_idx;
13662306a36Sopenharmony_ci	u32			msg_ptr;
13762306a36Sopenharmony_ci
13862306a36Sopenharmony_ci	int			irq;
13962306a36Sopenharmony_ci	struct device		*dev;
14062306a36Sopenharmony_ci	void __iomem		*base;
14162306a36Sopenharmony_ci	struct clk		*pclk;
14262306a36Sopenharmony_ci	u32			pclkrate;
14362306a36Sopenharmony_ci	u32			speed_khz;
14462306a36Sopenharmony_ci	u32			timeout_ms;
14562306a36Sopenharmony_ci	enum i2c_state		state;
14662306a36Sopenharmony_ci	struct i2c_adapter	adapter;
14762306a36Sopenharmony_ci};
14862306a36Sopenharmony_ci
14962306a36Sopenharmony_cistatic inline int is_lastmsg(struct synquacer_i2c *i2c)
15062306a36Sopenharmony_ci{
15162306a36Sopenharmony_ci	return i2c->msg_idx >= (i2c->msg_num - 1);
15262306a36Sopenharmony_ci}
15362306a36Sopenharmony_ci
15462306a36Sopenharmony_cistatic inline int is_msglast(struct synquacer_i2c *i2c)
15562306a36Sopenharmony_ci{
15662306a36Sopenharmony_ci	return i2c->msg_ptr == (i2c->msg->len - 1);
15762306a36Sopenharmony_ci}
15862306a36Sopenharmony_ci
15962306a36Sopenharmony_cistatic inline int is_msgend(struct synquacer_i2c *i2c)
16062306a36Sopenharmony_ci{
16162306a36Sopenharmony_ci	return i2c->msg_ptr >= i2c->msg->len;
16262306a36Sopenharmony_ci}
16362306a36Sopenharmony_ci
16462306a36Sopenharmony_cistatic inline unsigned long calc_timeout_ms(struct synquacer_i2c *i2c,
16562306a36Sopenharmony_ci					    struct i2c_msg *msgs,
16662306a36Sopenharmony_ci					    int num)
16762306a36Sopenharmony_ci{
16862306a36Sopenharmony_ci	unsigned long bit_count = 0;
16962306a36Sopenharmony_ci	int i;
17062306a36Sopenharmony_ci
17162306a36Sopenharmony_ci	for (i = 0; i < num; i++, msgs++)
17262306a36Sopenharmony_ci		bit_count += msgs->len;
17362306a36Sopenharmony_ci
17462306a36Sopenharmony_ci	return DIV_ROUND_UP((bit_count * 9 + num * 10) * 3, 200) + 10;
17562306a36Sopenharmony_ci}
17662306a36Sopenharmony_ci
17762306a36Sopenharmony_cistatic void synquacer_i2c_stop(struct synquacer_i2c *i2c, int ret)
17862306a36Sopenharmony_ci{
17962306a36Sopenharmony_ci	/*
18062306a36Sopenharmony_ci	 * clear IRQ (INT=0, BER=0)
18162306a36Sopenharmony_ci	 * set Stop Condition (MSS=0)
18262306a36Sopenharmony_ci	 * Interrupt Disable
18362306a36Sopenharmony_ci	 */
18462306a36Sopenharmony_ci	writeb(0, i2c->base + SYNQUACER_I2C_REG_BCR);
18562306a36Sopenharmony_ci
18662306a36Sopenharmony_ci	i2c->state = STATE_IDLE;
18762306a36Sopenharmony_ci
18862306a36Sopenharmony_ci	i2c->msg_ptr = 0;
18962306a36Sopenharmony_ci	i2c->msg = NULL;
19062306a36Sopenharmony_ci	i2c->msg_idx++;
19162306a36Sopenharmony_ci	i2c->msg_num = 0;
19262306a36Sopenharmony_ci	if (ret)
19362306a36Sopenharmony_ci		i2c->msg_idx = ret;
19462306a36Sopenharmony_ci
19562306a36Sopenharmony_ci	complete(&i2c->completion);
19662306a36Sopenharmony_ci}
19762306a36Sopenharmony_ci
19862306a36Sopenharmony_cistatic void synquacer_i2c_hw_init(struct synquacer_i2c *i2c)
19962306a36Sopenharmony_ci{
20062306a36Sopenharmony_ci	unsigned char ccr_cs, csr_cs;
20162306a36Sopenharmony_ci	u32 rt = i2c->pclkrate;
20262306a36Sopenharmony_ci
20362306a36Sopenharmony_ci	/* Set own Address */
20462306a36Sopenharmony_ci	writeb(0, i2c->base + SYNQUACER_I2C_REG_ADR);
20562306a36Sopenharmony_ci
20662306a36Sopenharmony_ci	/* Set PCLK frequency */
20762306a36Sopenharmony_ci	writeb(SYNQUACER_I2C_BUS_CLK_FR(i2c->pclkrate),
20862306a36Sopenharmony_ci	       i2c->base + SYNQUACER_I2C_REG_FSR);
20962306a36Sopenharmony_ci
21062306a36Sopenharmony_ci	switch (i2c->speed_khz) {
21162306a36Sopenharmony_ci	case SYNQUACER_I2C_SPEED_FM:
21262306a36Sopenharmony_ci		if (i2c->pclkrate <= SYNQUACER_I2C_CLK_RATE_18M) {
21362306a36Sopenharmony_ci			ccr_cs = SYNQUACER_I2C_CCR_CS_FAST_MAX_18M(rt);
21462306a36Sopenharmony_ci			csr_cs = SYNQUACER_I2C_CSR_CS_FAST_MAX_18M(rt);
21562306a36Sopenharmony_ci		} else {
21662306a36Sopenharmony_ci			ccr_cs = SYNQUACER_I2C_CCR_CS_FAST_MIN_18M(rt);
21762306a36Sopenharmony_ci			csr_cs = SYNQUACER_I2C_CSR_CS_FAST_MIN_18M(rt);
21862306a36Sopenharmony_ci		}
21962306a36Sopenharmony_ci
22062306a36Sopenharmony_ci		/* Set Clock and enable, Set fast mode */
22162306a36Sopenharmony_ci		writeb(ccr_cs | SYNQUACER_I2C_CCR_FM |
22262306a36Sopenharmony_ci		       SYNQUACER_I2C_CCR_EN,
22362306a36Sopenharmony_ci		       i2c->base + SYNQUACER_I2C_REG_CCR);
22462306a36Sopenharmony_ci		writeb(csr_cs, i2c->base + SYNQUACER_I2C_REG_CSR);
22562306a36Sopenharmony_ci		break;
22662306a36Sopenharmony_ci	case SYNQUACER_I2C_SPEED_SM:
22762306a36Sopenharmony_ci		if (i2c->pclkrate <= SYNQUACER_I2C_CLK_RATE_18M) {
22862306a36Sopenharmony_ci			ccr_cs = SYNQUACER_I2C_CCR_CS_STD_MAX_18M(rt);
22962306a36Sopenharmony_ci			csr_cs = SYNQUACER_I2C_CSR_CS_STD_MAX_18M(rt);
23062306a36Sopenharmony_ci		} else {
23162306a36Sopenharmony_ci			ccr_cs = SYNQUACER_I2C_CCR_CS_STD_MIN_18M(rt);
23262306a36Sopenharmony_ci			csr_cs = SYNQUACER_I2C_CSR_CS_STD_MIN_18M(rt);
23362306a36Sopenharmony_ci		}
23462306a36Sopenharmony_ci
23562306a36Sopenharmony_ci		/* Set Clock and enable, Set standard mode */
23662306a36Sopenharmony_ci		writeb(ccr_cs | SYNQUACER_I2C_CCR_EN,
23762306a36Sopenharmony_ci		      i2c->base + SYNQUACER_I2C_REG_CCR);
23862306a36Sopenharmony_ci		writeb(csr_cs, i2c->base + SYNQUACER_I2C_REG_CSR);
23962306a36Sopenharmony_ci		break;
24062306a36Sopenharmony_ci	default:
24162306a36Sopenharmony_ci		WARN_ON(1);
24262306a36Sopenharmony_ci	}
24362306a36Sopenharmony_ci
24462306a36Sopenharmony_ci	/* clear IRQ (INT=0, BER=0), Interrupt Disable */
24562306a36Sopenharmony_ci	writeb(0, i2c->base + SYNQUACER_I2C_REG_BCR);
24662306a36Sopenharmony_ci	writeb(0, i2c->base + SYNQUACER_I2C_REG_BC2R);
24762306a36Sopenharmony_ci}
24862306a36Sopenharmony_ci
24962306a36Sopenharmony_cistatic void synquacer_i2c_hw_reset(struct synquacer_i2c *i2c)
25062306a36Sopenharmony_ci{
25162306a36Sopenharmony_ci	/* Disable clock */
25262306a36Sopenharmony_ci	writeb(0, i2c->base + SYNQUACER_I2C_REG_CCR);
25362306a36Sopenharmony_ci	writeb(0, i2c->base + SYNQUACER_I2C_REG_CSR);
25462306a36Sopenharmony_ci
25562306a36Sopenharmony_ci	WAIT_PCLK(100, i2c->pclkrate);
25662306a36Sopenharmony_ci}
25762306a36Sopenharmony_ci
25862306a36Sopenharmony_cistatic int synquacer_i2c_master_start(struct synquacer_i2c *i2c,
25962306a36Sopenharmony_ci				      struct i2c_msg *pmsg)
26062306a36Sopenharmony_ci{
26162306a36Sopenharmony_ci	unsigned char bsr, bcr;
26262306a36Sopenharmony_ci
26362306a36Sopenharmony_ci	writeb(i2c_8bit_addr_from_msg(pmsg), i2c->base + SYNQUACER_I2C_REG_DAR);
26462306a36Sopenharmony_ci
26562306a36Sopenharmony_ci	dev_dbg(i2c->dev, "slave:0x%02x\n", pmsg->addr);
26662306a36Sopenharmony_ci
26762306a36Sopenharmony_ci	/* Generate Start Condition */
26862306a36Sopenharmony_ci	bsr = readb(i2c->base + SYNQUACER_I2C_REG_BSR);
26962306a36Sopenharmony_ci	bcr = readb(i2c->base + SYNQUACER_I2C_REG_BCR);
27062306a36Sopenharmony_ci	dev_dbg(i2c->dev, "bsr:0x%02x, bcr:0x%02x\n", bsr, bcr);
27162306a36Sopenharmony_ci
27262306a36Sopenharmony_ci	if ((bsr & SYNQUACER_I2C_BSR_BB) &&
27362306a36Sopenharmony_ci	    !(bcr & SYNQUACER_I2C_BCR_MSS)) {
27462306a36Sopenharmony_ci		dev_dbg(i2c->dev, "bus is busy");
27562306a36Sopenharmony_ci		return -EBUSY;
27662306a36Sopenharmony_ci	}
27762306a36Sopenharmony_ci
27862306a36Sopenharmony_ci	if (bsr & SYNQUACER_I2C_BSR_BB) { /* Bus is busy */
27962306a36Sopenharmony_ci		dev_dbg(i2c->dev, "Continuous Start");
28062306a36Sopenharmony_ci		writeb(bcr | SYNQUACER_I2C_BCR_SCC,
28162306a36Sopenharmony_ci		       i2c->base + SYNQUACER_I2C_REG_BCR);
28262306a36Sopenharmony_ci	} else {
28362306a36Sopenharmony_ci		if (bcr & SYNQUACER_I2C_BCR_MSS) {
28462306a36Sopenharmony_ci			dev_dbg(i2c->dev, "not in master mode");
28562306a36Sopenharmony_ci			return -EAGAIN;
28662306a36Sopenharmony_ci		}
28762306a36Sopenharmony_ci		dev_dbg(i2c->dev, "Start Condition");
28862306a36Sopenharmony_ci		/* Start Condition + Enable Interrupts */
28962306a36Sopenharmony_ci		writeb(bcr | SYNQUACER_I2C_BCR_MSS |
29062306a36Sopenharmony_ci		       SYNQUACER_I2C_BCR_INTE | SYNQUACER_I2C_BCR_BEIE,
29162306a36Sopenharmony_ci		       i2c->base + SYNQUACER_I2C_REG_BCR);
29262306a36Sopenharmony_ci	}
29362306a36Sopenharmony_ci
29462306a36Sopenharmony_ci	WAIT_PCLK(10, i2c->pclkrate);
29562306a36Sopenharmony_ci
29662306a36Sopenharmony_ci	/* get BSR & BCR registers */
29762306a36Sopenharmony_ci	bsr = readb(i2c->base + SYNQUACER_I2C_REG_BSR);
29862306a36Sopenharmony_ci	bcr = readb(i2c->base + SYNQUACER_I2C_REG_BCR);
29962306a36Sopenharmony_ci	dev_dbg(i2c->dev, "bsr:0x%02x, bcr:0x%02x\n", bsr, bcr);
30062306a36Sopenharmony_ci
30162306a36Sopenharmony_ci	if ((bsr & SYNQUACER_I2C_BSR_AL) ||
30262306a36Sopenharmony_ci	    !(bcr & SYNQUACER_I2C_BCR_MSS)) {
30362306a36Sopenharmony_ci		dev_dbg(i2c->dev, "arbitration lost\n");
30462306a36Sopenharmony_ci		return -EAGAIN;
30562306a36Sopenharmony_ci	}
30662306a36Sopenharmony_ci
30762306a36Sopenharmony_ci	return 0;
30862306a36Sopenharmony_ci}
30962306a36Sopenharmony_ci
31062306a36Sopenharmony_cistatic int synquacer_i2c_doxfer(struct synquacer_i2c *i2c,
31162306a36Sopenharmony_ci				struct i2c_msg *msgs, int num)
31262306a36Sopenharmony_ci{
31362306a36Sopenharmony_ci	unsigned char bsr;
31462306a36Sopenharmony_ci	unsigned long timeout;
31562306a36Sopenharmony_ci	int ret;
31662306a36Sopenharmony_ci
31762306a36Sopenharmony_ci	synquacer_i2c_hw_init(i2c);
31862306a36Sopenharmony_ci	bsr = readb(i2c->base + SYNQUACER_I2C_REG_BSR);
31962306a36Sopenharmony_ci	if (bsr & SYNQUACER_I2C_BSR_BB) {
32062306a36Sopenharmony_ci		dev_err(i2c->dev, "cannot get bus (bus busy)\n");
32162306a36Sopenharmony_ci		return -EBUSY;
32262306a36Sopenharmony_ci	}
32362306a36Sopenharmony_ci
32462306a36Sopenharmony_ci	reinit_completion(&i2c->completion);
32562306a36Sopenharmony_ci
32662306a36Sopenharmony_ci	i2c->msg = msgs;
32762306a36Sopenharmony_ci	i2c->msg_num = num;
32862306a36Sopenharmony_ci	i2c->msg_ptr = 0;
32962306a36Sopenharmony_ci	i2c->msg_idx = 0;
33062306a36Sopenharmony_ci	i2c->state = STATE_START;
33162306a36Sopenharmony_ci
33262306a36Sopenharmony_ci	ret = synquacer_i2c_master_start(i2c, i2c->msg);
33362306a36Sopenharmony_ci	if (ret < 0) {
33462306a36Sopenharmony_ci		dev_dbg(i2c->dev, "Address failed: (%d)\n", ret);
33562306a36Sopenharmony_ci		return ret;
33662306a36Sopenharmony_ci	}
33762306a36Sopenharmony_ci
33862306a36Sopenharmony_ci	timeout = wait_for_completion_timeout(&i2c->completion,
33962306a36Sopenharmony_ci					msecs_to_jiffies(i2c->timeout_ms));
34062306a36Sopenharmony_ci	if (timeout == 0) {
34162306a36Sopenharmony_ci		dev_dbg(i2c->dev, "timeout\n");
34262306a36Sopenharmony_ci		return -EAGAIN;
34362306a36Sopenharmony_ci	}
34462306a36Sopenharmony_ci
34562306a36Sopenharmony_ci	ret = i2c->msg_idx;
34662306a36Sopenharmony_ci	if (ret != num) {
34762306a36Sopenharmony_ci		dev_dbg(i2c->dev, "incomplete xfer (%d)\n", ret);
34862306a36Sopenharmony_ci		return -EAGAIN;
34962306a36Sopenharmony_ci	}
35062306a36Sopenharmony_ci
35162306a36Sopenharmony_ci	/* wait 2 clock periods to ensure the stop has been through the bus */
35262306a36Sopenharmony_ci	udelay(DIV_ROUND_UP(2 * 1000, i2c->speed_khz));
35362306a36Sopenharmony_ci
35462306a36Sopenharmony_ci	return ret;
35562306a36Sopenharmony_ci}
35662306a36Sopenharmony_ci
35762306a36Sopenharmony_cistatic irqreturn_t synquacer_i2c_isr(int irq, void *dev_id)
35862306a36Sopenharmony_ci{
35962306a36Sopenharmony_ci	struct synquacer_i2c *i2c = dev_id;
36062306a36Sopenharmony_ci
36162306a36Sopenharmony_ci	unsigned char byte;
36262306a36Sopenharmony_ci	unsigned char bsr, bcr;
36362306a36Sopenharmony_ci	int ret;
36462306a36Sopenharmony_ci
36562306a36Sopenharmony_ci	bcr = readb(i2c->base + SYNQUACER_I2C_REG_BCR);
36662306a36Sopenharmony_ci	bsr = readb(i2c->base + SYNQUACER_I2C_REG_BSR);
36762306a36Sopenharmony_ci	dev_dbg(i2c->dev, "bsr:0x%02x, bcr:0x%02x\n", bsr, bcr);
36862306a36Sopenharmony_ci
36962306a36Sopenharmony_ci	if (bcr & SYNQUACER_I2C_BCR_BER) {
37062306a36Sopenharmony_ci		dev_err(i2c->dev, "bus error\n");
37162306a36Sopenharmony_ci		synquacer_i2c_stop(i2c, -EAGAIN);
37262306a36Sopenharmony_ci		goto out;
37362306a36Sopenharmony_ci	}
37462306a36Sopenharmony_ci	if ((bsr & SYNQUACER_I2C_BSR_AL) ||
37562306a36Sopenharmony_ci	    !(bcr & SYNQUACER_I2C_BCR_MSS)) {
37662306a36Sopenharmony_ci		dev_dbg(i2c->dev, "arbitration lost\n");
37762306a36Sopenharmony_ci		synquacer_i2c_stop(i2c, -EAGAIN);
37862306a36Sopenharmony_ci		goto out;
37962306a36Sopenharmony_ci	}
38062306a36Sopenharmony_ci
38162306a36Sopenharmony_ci	switch (i2c->state) {
38262306a36Sopenharmony_ci	case STATE_START:
38362306a36Sopenharmony_ci		if (bsr & SYNQUACER_I2C_BSR_LRB) {
38462306a36Sopenharmony_ci			dev_dbg(i2c->dev, "ack was not received\n");
38562306a36Sopenharmony_ci			synquacer_i2c_stop(i2c, -EAGAIN);
38662306a36Sopenharmony_ci			goto out;
38762306a36Sopenharmony_ci		}
38862306a36Sopenharmony_ci
38962306a36Sopenharmony_ci		if (i2c->msg->flags & I2C_M_RD)
39062306a36Sopenharmony_ci			i2c->state = STATE_READ;
39162306a36Sopenharmony_ci		else
39262306a36Sopenharmony_ci			i2c->state = STATE_WRITE;
39362306a36Sopenharmony_ci
39462306a36Sopenharmony_ci		if (is_lastmsg(i2c) && i2c->msg->len == 0) {
39562306a36Sopenharmony_ci			synquacer_i2c_stop(i2c, 0);
39662306a36Sopenharmony_ci			goto out;
39762306a36Sopenharmony_ci		}
39862306a36Sopenharmony_ci
39962306a36Sopenharmony_ci		if (i2c->state == STATE_READ)
40062306a36Sopenharmony_ci			goto prepare_read;
40162306a36Sopenharmony_ci		fallthrough;
40262306a36Sopenharmony_ci
40362306a36Sopenharmony_ci	case STATE_WRITE:
40462306a36Sopenharmony_ci		if (bsr & SYNQUACER_I2C_BSR_LRB) {
40562306a36Sopenharmony_ci			dev_dbg(i2c->dev, "WRITE: No Ack\n");
40662306a36Sopenharmony_ci			synquacer_i2c_stop(i2c, -EAGAIN);
40762306a36Sopenharmony_ci			goto out;
40862306a36Sopenharmony_ci		}
40962306a36Sopenharmony_ci
41062306a36Sopenharmony_ci		if (!is_msgend(i2c)) {
41162306a36Sopenharmony_ci			writeb(i2c->msg->buf[i2c->msg_ptr++],
41262306a36Sopenharmony_ci			       i2c->base + SYNQUACER_I2C_REG_DAR);
41362306a36Sopenharmony_ci
41462306a36Sopenharmony_ci			/* clear IRQ, and continue */
41562306a36Sopenharmony_ci			writeb(SYNQUACER_I2C_BCR_BEIE |
41662306a36Sopenharmony_ci			       SYNQUACER_I2C_BCR_MSS |
41762306a36Sopenharmony_ci			       SYNQUACER_I2C_BCR_INTE,
41862306a36Sopenharmony_ci			       i2c->base + SYNQUACER_I2C_REG_BCR);
41962306a36Sopenharmony_ci			break;
42062306a36Sopenharmony_ci		}
42162306a36Sopenharmony_ci		if (is_lastmsg(i2c)) {
42262306a36Sopenharmony_ci			synquacer_i2c_stop(i2c, 0);
42362306a36Sopenharmony_ci			break;
42462306a36Sopenharmony_ci		}
42562306a36Sopenharmony_ci		dev_dbg(i2c->dev, "WRITE: Next Message\n");
42662306a36Sopenharmony_ci
42762306a36Sopenharmony_ci		i2c->msg_ptr = 0;
42862306a36Sopenharmony_ci		i2c->msg_idx++;
42962306a36Sopenharmony_ci		i2c->msg++;
43062306a36Sopenharmony_ci
43162306a36Sopenharmony_ci		/* send the new start */
43262306a36Sopenharmony_ci		ret = synquacer_i2c_master_start(i2c, i2c->msg);
43362306a36Sopenharmony_ci		if (ret < 0) {
43462306a36Sopenharmony_ci			dev_dbg(i2c->dev, "restart error (%d)\n", ret);
43562306a36Sopenharmony_ci			synquacer_i2c_stop(i2c, -EAGAIN);
43662306a36Sopenharmony_ci			break;
43762306a36Sopenharmony_ci		}
43862306a36Sopenharmony_ci		i2c->state = STATE_START;
43962306a36Sopenharmony_ci		break;
44062306a36Sopenharmony_ci
44162306a36Sopenharmony_ci	case STATE_READ:
44262306a36Sopenharmony_ci		byte = readb(i2c->base + SYNQUACER_I2C_REG_DAR);
44362306a36Sopenharmony_ci		if (!(bsr & SYNQUACER_I2C_BSR_FBT)) /* data */
44462306a36Sopenharmony_ci			i2c->msg->buf[i2c->msg_ptr++] = byte;
44562306a36Sopenharmony_ci		else /* address */
44662306a36Sopenharmony_ci			dev_dbg(i2c->dev, "address:0x%02x. ignore it.\n", byte);
44762306a36Sopenharmony_ci
44862306a36Sopenharmony_ciprepare_read:
44962306a36Sopenharmony_ci		if (is_msglast(i2c)) {
45062306a36Sopenharmony_ci			writeb(SYNQUACER_I2C_BCR_MSS |
45162306a36Sopenharmony_ci			       SYNQUACER_I2C_BCR_BEIE |
45262306a36Sopenharmony_ci			       SYNQUACER_I2C_BCR_INTE,
45362306a36Sopenharmony_ci			       i2c->base + SYNQUACER_I2C_REG_BCR);
45462306a36Sopenharmony_ci			break;
45562306a36Sopenharmony_ci		}
45662306a36Sopenharmony_ci		if (!is_msgend(i2c)) {
45762306a36Sopenharmony_ci			writeb(SYNQUACER_I2C_BCR_MSS |
45862306a36Sopenharmony_ci			       SYNQUACER_I2C_BCR_BEIE |
45962306a36Sopenharmony_ci			       SYNQUACER_I2C_BCR_INTE |
46062306a36Sopenharmony_ci			       SYNQUACER_I2C_BCR_ACK,
46162306a36Sopenharmony_ci			       i2c->base + SYNQUACER_I2C_REG_BCR);
46262306a36Sopenharmony_ci			break;
46362306a36Sopenharmony_ci		}
46462306a36Sopenharmony_ci		if (is_lastmsg(i2c)) {
46562306a36Sopenharmony_ci			/* last message, send stop and complete */
46662306a36Sopenharmony_ci			dev_dbg(i2c->dev, "READ: Send Stop\n");
46762306a36Sopenharmony_ci			synquacer_i2c_stop(i2c, 0);
46862306a36Sopenharmony_ci			break;
46962306a36Sopenharmony_ci		}
47062306a36Sopenharmony_ci		dev_dbg(i2c->dev, "READ: Next Transfer\n");
47162306a36Sopenharmony_ci
47262306a36Sopenharmony_ci		i2c->msg_ptr = 0;
47362306a36Sopenharmony_ci		i2c->msg_idx++;
47462306a36Sopenharmony_ci		i2c->msg++;
47562306a36Sopenharmony_ci
47662306a36Sopenharmony_ci		ret = synquacer_i2c_master_start(i2c, i2c->msg);
47762306a36Sopenharmony_ci		if (ret < 0) {
47862306a36Sopenharmony_ci			dev_dbg(i2c->dev, "restart error (%d)\n", ret);
47962306a36Sopenharmony_ci			synquacer_i2c_stop(i2c, -EAGAIN);
48062306a36Sopenharmony_ci		} else {
48162306a36Sopenharmony_ci			i2c->state = STATE_START;
48262306a36Sopenharmony_ci		}
48362306a36Sopenharmony_ci		break;
48462306a36Sopenharmony_ci	default:
48562306a36Sopenharmony_ci		dev_err(i2c->dev, "called in err STATE (%d)\n", i2c->state);
48662306a36Sopenharmony_ci		break;
48762306a36Sopenharmony_ci	}
48862306a36Sopenharmony_ci
48962306a36Sopenharmony_ciout:
49062306a36Sopenharmony_ci	WAIT_PCLK(10, i2c->pclkrate);
49162306a36Sopenharmony_ci	return IRQ_HANDLED;
49262306a36Sopenharmony_ci}
49362306a36Sopenharmony_ci
49462306a36Sopenharmony_cistatic int synquacer_i2c_xfer(struct i2c_adapter *adap, struct i2c_msg *msgs,
49562306a36Sopenharmony_ci			      int num)
49662306a36Sopenharmony_ci{
49762306a36Sopenharmony_ci	struct synquacer_i2c *i2c;
49862306a36Sopenharmony_ci	int retry;
49962306a36Sopenharmony_ci	int ret;
50062306a36Sopenharmony_ci
50162306a36Sopenharmony_ci	i2c = i2c_get_adapdata(adap);
50262306a36Sopenharmony_ci	i2c->timeout_ms = calc_timeout_ms(i2c, msgs, num);
50362306a36Sopenharmony_ci
50462306a36Sopenharmony_ci	dev_dbg(i2c->dev, "calculated timeout %d ms\n", i2c->timeout_ms);
50562306a36Sopenharmony_ci
50662306a36Sopenharmony_ci	for (retry = 0; retry <= adap->retries; retry++) {
50762306a36Sopenharmony_ci		ret = synquacer_i2c_doxfer(i2c, msgs, num);
50862306a36Sopenharmony_ci		if (ret != -EAGAIN)
50962306a36Sopenharmony_ci			return ret;
51062306a36Sopenharmony_ci
51162306a36Sopenharmony_ci		dev_dbg(i2c->dev, "Retrying transmission (%d)\n", retry);
51262306a36Sopenharmony_ci
51362306a36Sopenharmony_ci		synquacer_i2c_hw_reset(i2c);
51462306a36Sopenharmony_ci	}
51562306a36Sopenharmony_ci	return -EIO;
51662306a36Sopenharmony_ci}
51762306a36Sopenharmony_ci
51862306a36Sopenharmony_cistatic u32 synquacer_i2c_functionality(struct i2c_adapter *adap)
51962306a36Sopenharmony_ci{
52062306a36Sopenharmony_ci	return I2C_FUNC_I2C | I2C_FUNC_SMBUS_EMUL;
52162306a36Sopenharmony_ci}
52262306a36Sopenharmony_ci
52362306a36Sopenharmony_cistatic const struct i2c_algorithm synquacer_i2c_algo = {
52462306a36Sopenharmony_ci	.master_xfer	= synquacer_i2c_xfer,
52562306a36Sopenharmony_ci	.functionality	= synquacer_i2c_functionality,
52662306a36Sopenharmony_ci};
52762306a36Sopenharmony_ci
52862306a36Sopenharmony_cistatic const struct i2c_adapter synquacer_i2c_ops = {
52962306a36Sopenharmony_ci	.owner		= THIS_MODULE,
53062306a36Sopenharmony_ci	.name		= "synquacer_i2c-adapter",
53162306a36Sopenharmony_ci	.algo		= &synquacer_i2c_algo,
53262306a36Sopenharmony_ci	.retries	= 5,
53362306a36Sopenharmony_ci};
53462306a36Sopenharmony_ci
53562306a36Sopenharmony_cistatic int synquacer_i2c_probe(struct platform_device *pdev)
53662306a36Sopenharmony_ci{
53762306a36Sopenharmony_ci	struct synquacer_i2c *i2c;
53862306a36Sopenharmony_ci	u32 bus_speed;
53962306a36Sopenharmony_ci	int ret;
54062306a36Sopenharmony_ci
54162306a36Sopenharmony_ci	i2c = devm_kzalloc(&pdev->dev, sizeof(*i2c), GFP_KERNEL);
54262306a36Sopenharmony_ci	if (!i2c)
54362306a36Sopenharmony_ci		return -ENOMEM;
54462306a36Sopenharmony_ci
54562306a36Sopenharmony_ci	bus_speed = i2c_acpi_find_bus_speed(&pdev->dev);
54662306a36Sopenharmony_ci	if (!bus_speed)
54762306a36Sopenharmony_ci		device_property_read_u32(&pdev->dev, "clock-frequency",
54862306a36Sopenharmony_ci					 &bus_speed);
54962306a36Sopenharmony_ci
55062306a36Sopenharmony_ci	device_property_read_u32(&pdev->dev, "socionext,pclk-rate",
55162306a36Sopenharmony_ci				 &i2c->pclkrate);
55262306a36Sopenharmony_ci
55362306a36Sopenharmony_ci	i2c->pclk = devm_clk_get(&pdev->dev, "pclk");
55462306a36Sopenharmony_ci	if (PTR_ERR(i2c->pclk) == -EPROBE_DEFER)
55562306a36Sopenharmony_ci		return -EPROBE_DEFER;
55662306a36Sopenharmony_ci	if (!IS_ERR_OR_NULL(i2c->pclk)) {
55762306a36Sopenharmony_ci		dev_dbg(&pdev->dev, "clock source %p\n", i2c->pclk);
55862306a36Sopenharmony_ci
55962306a36Sopenharmony_ci		ret = clk_prepare_enable(i2c->pclk);
56062306a36Sopenharmony_ci		if (ret)
56162306a36Sopenharmony_ci			return dev_err_probe(&pdev->dev, ret, "failed to enable clock\n");
56262306a36Sopenharmony_ci		i2c->pclkrate = clk_get_rate(i2c->pclk);
56362306a36Sopenharmony_ci	}
56462306a36Sopenharmony_ci
56562306a36Sopenharmony_ci	if (i2c->pclkrate < SYNQUACER_I2C_MIN_CLK_RATE ||
56662306a36Sopenharmony_ci	    i2c->pclkrate > SYNQUACER_I2C_MAX_CLK_RATE)
56762306a36Sopenharmony_ci		return dev_err_probe(&pdev->dev, -EINVAL,
56862306a36Sopenharmony_ci				     "PCLK missing or out of range (%d)\n",
56962306a36Sopenharmony_ci				     i2c->pclkrate);
57062306a36Sopenharmony_ci
57162306a36Sopenharmony_ci	i2c->base = devm_platform_ioremap_resource(pdev, 0);
57262306a36Sopenharmony_ci	if (IS_ERR(i2c->base))
57362306a36Sopenharmony_ci		return PTR_ERR(i2c->base);
57462306a36Sopenharmony_ci
57562306a36Sopenharmony_ci	i2c->irq = platform_get_irq(pdev, 0);
57662306a36Sopenharmony_ci	if (i2c->irq < 0)
57762306a36Sopenharmony_ci		return i2c->irq;
57862306a36Sopenharmony_ci
57962306a36Sopenharmony_ci	ret = devm_request_irq(&pdev->dev, i2c->irq, synquacer_i2c_isr,
58062306a36Sopenharmony_ci			       0, dev_name(&pdev->dev), i2c);
58162306a36Sopenharmony_ci	if (ret < 0)
58262306a36Sopenharmony_ci		return dev_err_probe(&pdev->dev, ret, "cannot claim IRQ %d\n", i2c->irq);
58362306a36Sopenharmony_ci
58462306a36Sopenharmony_ci	i2c->state = STATE_IDLE;
58562306a36Sopenharmony_ci	i2c->dev = &pdev->dev;
58662306a36Sopenharmony_ci	i2c->adapter = synquacer_i2c_ops;
58762306a36Sopenharmony_ci	i2c_set_adapdata(&i2c->adapter, i2c);
58862306a36Sopenharmony_ci	i2c->adapter.dev.parent = &pdev->dev;
58962306a36Sopenharmony_ci	i2c->adapter.dev.of_node = pdev->dev.of_node;
59062306a36Sopenharmony_ci	ACPI_COMPANION_SET(&i2c->adapter.dev, ACPI_COMPANION(&pdev->dev));
59162306a36Sopenharmony_ci	i2c->adapter.nr = pdev->id;
59262306a36Sopenharmony_ci	init_completion(&i2c->completion);
59362306a36Sopenharmony_ci
59462306a36Sopenharmony_ci	if (bus_speed < I2C_MAX_FAST_MODE_FREQ)
59562306a36Sopenharmony_ci		i2c->speed_khz = SYNQUACER_I2C_SPEED_SM;
59662306a36Sopenharmony_ci	else
59762306a36Sopenharmony_ci		i2c->speed_khz = SYNQUACER_I2C_SPEED_FM;
59862306a36Sopenharmony_ci
59962306a36Sopenharmony_ci	synquacer_i2c_hw_init(i2c);
60062306a36Sopenharmony_ci
60162306a36Sopenharmony_ci	ret = i2c_add_numbered_adapter(&i2c->adapter);
60262306a36Sopenharmony_ci	if (ret)
60362306a36Sopenharmony_ci		return dev_err_probe(&pdev->dev, ret, "failed to add bus to i2c core\n");
60462306a36Sopenharmony_ci
60562306a36Sopenharmony_ci	platform_set_drvdata(pdev, i2c);
60662306a36Sopenharmony_ci
60762306a36Sopenharmony_ci	dev_info(&pdev->dev, "%s: synquacer_i2c adapter\n",
60862306a36Sopenharmony_ci		 dev_name(&i2c->adapter.dev));
60962306a36Sopenharmony_ci
61062306a36Sopenharmony_ci	return 0;
61162306a36Sopenharmony_ci}
61262306a36Sopenharmony_ci
61362306a36Sopenharmony_cistatic void synquacer_i2c_remove(struct platform_device *pdev)
61462306a36Sopenharmony_ci{
61562306a36Sopenharmony_ci	struct synquacer_i2c *i2c = platform_get_drvdata(pdev);
61662306a36Sopenharmony_ci
61762306a36Sopenharmony_ci	i2c_del_adapter(&i2c->adapter);
61862306a36Sopenharmony_ci	if (!IS_ERR(i2c->pclk))
61962306a36Sopenharmony_ci		clk_disable_unprepare(i2c->pclk);
62062306a36Sopenharmony_ci};
62162306a36Sopenharmony_ci
62262306a36Sopenharmony_cistatic const struct of_device_id synquacer_i2c_dt_ids[] __maybe_unused = {
62362306a36Sopenharmony_ci	{ .compatible = "socionext,synquacer-i2c" },
62462306a36Sopenharmony_ci	{ /* sentinel */ }
62562306a36Sopenharmony_ci};
62662306a36Sopenharmony_ciMODULE_DEVICE_TABLE(of, synquacer_i2c_dt_ids);
62762306a36Sopenharmony_ci
62862306a36Sopenharmony_ci#ifdef CONFIG_ACPI
62962306a36Sopenharmony_cistatic const struct acpi_device_id synquacer_i2c_acpi_ids[] = {
63062306a36Sopenharmony_ci	{ "SCX0003" },
63162306a36Sopenharmony_ci	{ /* sentinel */ }
63262306a36Sopenharmony_ci};
63362306a36Sopenharmony_ciMODULE_DEVICE_TABLE(acpi, synquacer_i2c_acpi_ids);
63462306a36Sopenharmony_ci#endif
63562306a36Sopenharmony_ci
63662306a36Sopenharmony_cistatic struct platform_driver synquacer_i2c_driver = {
63762306a36Sopenharmony_ci	.probe	= synquacer_i2c_probe,
63862306a36Sopenharmony_ci	.remove_new = synquacer_i2c_remove,
63962306a36Sopenharmony_ci	.driver	= {
64062306a36Sopenharmony_ci		.name = "synquacer_i2c",
64162306a36Sopenharmony_ci		.of_match_table = of_match_ptr(synquacer_i2c_dt_ids),
64262306a36Sopenharmony_ci		.acpi_match_table = ACPI_PTR(synquacer_i2c_acpi_ids),
64362306a36Sopenharmony_ci	},
64462306a36Sopenharmony_ci};
64562306a36Sopenharmony_cimodule_platform_driver(synquacer_i2c_driver);
64662306a36Sopenharmony_ci
64762306a36Sopenharmony_ciMODULE_AUTHOR("Fujitsu Semiconductor Ltd");
64862306a36Sopenharmony_ciMODULE_DESCRIPTION("Socionext SynQuacer I2C Driver");
64962306a36Sopenharmony_ciMODULE_LICENSE("GPL v2");
650