162306a36Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0-only
262306a36Sopenharmony_ci/*
362306a36Sopenharmony_ci * Copyright (C) 2009 ST-Ericsson SA
462306a36Sopenharmony_ci * Copyright (C) 2009 STMicroelectronics
562306a36Sopenharmony_ci *
662306a36Sopenharmony_ci * I2C master mode controller driver, used in Nomadik 8815
762306a36Sopenharmony_ci * and Ux500 platforms.
862306a36Sopenharmony_ci *
962306a36Sopenharmony_ci * Author: Srinidhi Kasagar <srinidhi.kasagar@stericsson.com>
1062306a36Sopenharmony_ci * Author: Sachin Verma <sachin.verma@st.com>
1162306a36Sopenharmony_ci */
1262306a36Sopenharmony_ci#include <linux/init.h>
1362306a36Sopenharmony_ci#include <linux/module.h>
1462306a36Sopenharmony_ci#include <linux/amba/bus.h>
1562306a36Sopenharmony_ci#include <linux/slab.h>
1662306a36Sopenharmony_ci#include <linux/interrupt.h>
1762306a36Sopenharmony_ci#include <linux/i2c.h>
1862306a36Sopenharmony_ci#include <linux/err.h>
1962306a36Sopenharmony_ci#include <linux/clk.h>
2062306a36Sopenharmony_ci#include <linux/io.h>
2162306a36Sopenharmony_ci#include <linux/pm_runtime.h>
2262306a36Sopenharmony_ci#include <linux/of.h>
2362306a36Sopenharmony_ci#include <linux/pinctrl/consumer.h>
2462306a36Sopenharmony_ci
2562306a36Sopenharmony_ci#define DRIVER_NAME "nmk-i2c"
2662306a36Sopenharmony_ci
2762306a36Sopenharmony_ci/* I2C Controller register offsets */
2862306a36Sopenharmony_ci#define I2C_CR		(0x000)
2962306a36Sopenharmony_ci#define I2C_SCR		(0x004)
3062306a36Sopenharmony_ci#define I2C_HSMCR	(0x008)
3162306a36Sopenharmony_ci#define I2C_MCR		(0x00C)
3262306a36Sopenharmony_ci#define I2C_TFR		(0x010)
3362306a36Sopenharmony_ci#define I2C_SR		(0x014)
3462306a36Sopenharmony_ci#define I2C_RFR		(0x018)
3562306a36Sopenharmony_ci#define I2C_TFTR	(0x01C)
3662306a36Sopenharmony_ci#define I2C_RFTR	(0x020)
3762306a36Sopenharmony_ci#define I2C_DMAR	(0x024)
3862306a36Sopenharmony_ci#define I2C_BRCR	(0x028)
3962306a36Sopenharmony_ci#define I2C_IMSCR	(0x02C)
4062306a36Sopenharmony_ci#define I2C_RISR	(0x030)
4162306a36Sopenharmony_ci#define I2C_MISR	(0x034)
4262306a36Sopenharmony_ci#define I2C_ICR		(0x038)
4362306a36Sopenharmony_ci
4462306a36Sopenharmony_ci/* Control registers */
4562306a36Sopenharmony_ci#define I2C_CR_PE		(0x1 << 0)	/* Peripheral Enable */
4662306a36Sopenharmony_ci#define I2C_CR_OM		(0x3 << 1)	/* Operating mode */
4762306a36Sopenharmony_ci#define I2C_CR_SAM		(0x1 << 3)	/* Slave addressing mode */
4862306a36Sopenharmony_ci#define I2C_CR_SM		(0x3 << 4)	/* Speed mode */
4962306a36Sopenharmony_ci#define I2C_CR_SGCM		(0x1 << 6)	/* Slave general call mode */
5062306a36Sopenharmony_ci#define I2C_CR_FTX		(0x1 << 7)	/* Flush Transmit */
5162306a36Sopenharmony_ci#define I2C_CR_FRX		(0x1 << 8)	/* Flush Receive */
5262306a36Sopenharmony_ci#define I2C_CR_DMA_TX_EN	(0x1 << 9)	/* DMA Tx enable */
5362306a36Sopenharmony_ci#define I2C_CR_DMA_RX_EN	(0x1 << 10)	/* DMA Rx Enable */
5462306a36Sopenharmony_ci#define I2C_CR_DMA_SLE		(0x1 << 11)	/* DMA sync. logic enable */
5562306a36Sopenharmony_ci#define I2C_CR_LM		(0x1 << 12)	/* Loopback mode */
5662306a36Sopenharmony_ci#define I2C_CR_FON		(0x3 << 13)	/* Filtering on */
5762306a36Sopenharmony_ci#define I2C_CR_FS		(0x3 << 15)	/* Force stop enable */
5862306a36Sopenharmony_ci
5962306a36Sopenharmony_ci/* Master controller (MCR) register */
6062306a36Sopenharmony_ci#define I2C_MCR_OP		(0x1 << 0)	/* Operation */
6162306a36Sopenharmony_ci#define I2C_MCR_A7		(0x7f << 1)	/* 7-bit address */
6262306a36Sopenharmony_ci#define I2C_MCR_EA10		(0x7 << 8)	/* 10-bit Extended address */
6362306a36Sopenharmony_ci#define I2C_MCR_SB		(0x1 << 11)	/* Extended address */
6462306a36Sopenharmony_ci#define I2C_MCR_AM		(0x3 << 12)	/* Address type */
6562306a36Sopenharmony_ci#define I2C_MCR_STOP		(0x1 << 14)	/* Stop condition */
6662306a36Sopenharmony_ci#define I2C_MCR_LENGTH		(0x7ff << 15)	/* Transaction length */
6762306a36Sopenharmony_ci
6862306a36Sopenharmony_ci/* Status register (SR) */
6962306a36Sopenharmony_ci#define I2C_SR_OP		(0x3 << 0)	/* Operation */
7062306a36Sopenharmony_ci#define I2C_SR_STATUS		(0x3 << 2)	/* controller status */
7162306a36Sopenharmony_ci#define I2C_SR_CAUSE		(0x7 << 4)	/* Abort cause */
7262306a36Sopenharmony_ci#define I2C_SR_TYPE		(0x3 << 7)	/* Receive type */
7362306a36Sopenharmony_ci#define I2C_SR_LENGTH		(0x7ff << 9)	/* Transfer length */
7462306a36Sopenharmony_ci
7562306a36Sopenharmony_ci/* Interrupt mask set/clear (IMSCR) bits */
7662306a36Sopenharmony_ci#define I2C_IT_TXFE		(0x1 << 0)
7762306a36Sopenharmony_ci#define I2C_IT_TXFNE		(0x1 << 1)
7862306a36Sopenharmony_ci#define I2C_IT_TXFF		(0x1 << 2)
7962306a36Sopenharmony_ci#define I2C_IT_TXFOVR		(0x1 << 3)
8062306a36Sopenharmony_ci#define I2C_IT_RXFE		(0x1 << 4)
8162306a36Sopenharmony_ci#define I2C_IT_RXFNF		(0x1 << 5)
8262306a36Sopenharmony_ci#define I2C_IT_RXFF		(0x1 << 6)
8362306a36Sopenharmony_ci#define I2C_IT_RFSR		(0x1 << 16)
8462306a36Sopenharmony_ci#define I2C_IT_RFSE		(0x1 << 17)
8562306a36Sopenharmony_ci#define I2C_IT_WTSR		(0x1 << 18)
8662306a36Sopenharmony_ci#define I2C_IT_MTD		(0x1 << 19)
8762306a36Sopenharmony_ci#define I2C_IT_STD		(0x1 << 20)
8862306a36Sopenharmony_ci#define I2C_IT_MAL		(0x1 << 24)
8962306a36Sopenharmony_ci#define I2C_IT_BERR		(0x1 << 25)
9062306a36Sopenharmony_ci#define I2C_IT_MTDWS		(0x1 << 28)
9162306a36Sopenharmony_ci
9262306a36Sopenharmony_ci#define GEN_MASK(val, mask, sb)  (((val) << (sb)) & (mask))
9362306a36Sopenharmony_ci
9462306a36Sopenharmony_ci/* some bits in ICR are reserved */
9562306a36Sopenharmony_ci#define I2C_CLEAR_ALL_INTS	0x131f007f
9662306a36Sopenharmony_ci
9762306a36Sopenharmony_ci/* first three msb bits are reserved */
9862306a36Sopenharmony_ci#define IRQ_MASK(mask)		(mask & 0x1fffffff)
9962306a36Sopenharmony_ci
10062306a36Sopenharmony_ci/* maximum threshold value */
10162306a36Sopenharmony_ci#define MAX_I2C_FIFO_THRESHOLD	15
10262306a36Sopenharmony_ci
10362306a36Sopenharmony_cienum i2c_freq_mode {
10462306a36Sopenharmony_ci	I2C_FREQ_MODE_STANDARD,		/* up to 100 Kb/s */
10562306a36Sopenharmony_ci	I2C_FREQ_MODE_FAST,		/* up to 400 Kb/s */
10662306a36Sopenharmony_ci	I2C_FREQ_MODE_HIGH_SPEED,	/* up to 3.4 Mb/s */
10762306a36Sopenharmony_ci	I2C_FREQ_MODE_FAST_PLUS,	/* up to 1 Mb/s */
10862306a36Sopenharmony_ci};
10962306a36Sopenharmony_ci
11062306a36Sopenharmony_ci/**
11162306a36Sopenharmony_ci * struct i2c_vendor_data - per-vendor variations
11262306a36Sopenharmony_ci * @has_mtdws: variant has the MTDWS bit
11362306a36Sopenharmony_ci * @fifodepth: variant FIFO depth
11462306a36Sopenharmony_ci */
11562306a36Sopenharmony_cistruct i2c_vendor_data {
11662306a36Sopenharmony_ci	bool has_mtdws;
11762306a36Sopenharmony_ci	u32 fifodepth;
11862306a36Sopenharmony_ci};
11962306a36Sopenharmony_ci
12062306a36Sopenharmony_cienum i2c_status {
12162306a36Sopenharmony_ci	I2C_NOP,
12262306a36Sopenharmony_ci	I2C_ON_GOING,
12362306a36Sopenharmony_ci	I2C_OK,
12462306a36Sopenharmony_ci	I2C_ABORT
12562306a36Sopenharmony_ci};
12662306a36Sopenharmony_ci
12762306a36Sopenharmony_ci/* operation */
12862306a36Sopenharmony_cienum i2c_operation {
12962306a36Sopenharmony_ci	I2C_NO_OPERATION = 0xff,
13062306a36Sopenharmony_ci	I2C_WRITE = 0x00,
13162306a36Sopenharmony_ci	I2C_READ = 0x01
13262306a36Sopenharmony_ci};
13362306a36Sopenharmony_ci
13462306a36Sopenharmony_ci/**
13562306a36Sopenharmony_ci * struct i2c_nmk_client - client specific data
13662306a36Sopenharmony_ci * @slave_adr: 7-bit slave address
13762306a36Sopenharmony_ci * @count: no. bytes to be transferred
13862306a36Sopenharmony_ci * @buffer: client data buffer
13962306a36Sopenharmony_ci * @xfer_bytes: bytes transferred till now
14062306a36Sopenharmony_ci * @operation: current I2C operation
14162306a36Sopenharmony_ci */
14262306a36Sopenharmony_cistruct i2c_nmk_client {
14362306a36Sopenharmony_ci	unsigned short		slave_adr;
14462306a36Sopenharmony_ci	unsigned long		count;
14562306a36Sopenharmony_ci	unsigned char		*buffer;
14662306a36Sopenharmony_ci	unsigned long		xfer_bytes;
14762306a36Sopenharmony_ci	enum i2c_operation	operation;
14862306a36Sopenharmony_ci};
14962306a36Sopenharmony_ci
15062306a36Sopenharmony_ci/**
15162306a36Sopenharmony_ci * struct nmk_i2c_dev - private data structure of the controller.
15262306a36Sopenharmony_ci * @vendor: vendor data for this variant.
15362306a36Sopenharmony_ci * @adev: parent amba device.
15462306a36Sopenharmony_ci * @adap: corresponding I2C adapter.
15562306a36Sopenharmony_ci * @irq: interrupt line for the controller.
15662306a36Sopenharmony_ci * @virtbase: virtual io memory area.
15762306a36Sopenharmony_ci * @clk: hardware i2c block clock.
15862306a36Sopenharmony_ci * @cli: holder of client specific data.
15962306a36Sopenharmony_ci * @clk_freq: clock frequency for the operation mode
16062306a36Sopenharmony_ci * @tft: Tx FIFO Threshold in bytes
16162306a36Sopenharmony_ci * @rft: Rx FIFO Threshold in bytes
16262306a36Sopenharmony_ci * @timeout: Slave response timeout (ms)
16362306a36Sopenharmony_ci * @sm: speed mode
16462306a36Sopenharmony_ci * @stop: stop condition.
16562306a36Sopenharmony_ci * @xfer_complete: acknowledge completion for a I2C message.
16662306a36Sopenharmony_ci * @result: controller propogated result.
16762306a36Sopenharmony_ci */
16862306a36Sopenharmony_cistruct nmk_i2c_dev {
16962306a36Sopenharmony_ci	struct i2c_vendor_data		*vendor;
17062306a36Sopenharmony_ci	struct amba_device		*adev;
17162306a36Sopenharmony_ci	struct i2c_adapter		adap;
17262306a36Sopenharmony_ci	int				irq;
17362306a36Sopenharmony_ci	void __iomem			*virtbase;
17462306a36Sopenharmony_ci	struct clk			*clk;
17562306a36Sopenharmony_ci	struct i2c_nmk_client		cli;
17662306a36Sopenharmony_ci	u32				clk_freq;
17762306a36Sopenharmony_ci	unsigned char			tft;
17862306a36Sopenharmony_ci	unsigned char			rft;
17962306a36Sopenharmony_ci	int				timeout;
18062306a36Sopenharmony_ci	enum i2c_freq_mode		sm;
18162306a36Sopenharmony_ci	int				stop;
18262306a36Sopenharmony_ci	struct completion		xfer_complete;
18362306a36Sopenharmony_ci	int				result;
18462306a36Sopenharmony_ci};
18562306a36Sopenharmony_ci
18662306a36Sopenharmony_ci/* controller's abort causes */
18762306a36Sopenharmony_cistatic const char *abort_causes[] = {
18862306a36Sopenharmony_ci	"no ack received after address transmission",
18962306a36Sopenharmony_ci	"no ack received during data phase",
19062306a36Sopenharmony_ci	"ack received after xmission of master code",
19162306a36Sopenharmony_ci	"master lost arbitration",
19262306a36Sopenharmony_ci	"slave restarts",
19362306a36Sopenharmony_ci	"slave reset",
19462306a36Sopenharmony_ci	"overflow, maxsize is 2047 bytes",
19562306a36Sopenharmony_ci};
19662306a36Sopenharmony_ci
19762306a36Sopenharmony_cistatic inline void i2c_set_bit(void __iomem *reg, u32 mask)
19862306a36Sopenharmony_ci{
19962306a36Sopenharmony_ci	writel(readl(reg) | mask, reg);
20062306a36Sopenharmony_ci}
20162306a36Sopenharmony_ci
20262306a36Sopenharmony_cistatic inline void i2c_clr_bit(void __iomem *reg, u32 mask)
20362306a36Sopenharmony_ci{
20462306a36Sopenharmony_ci	writel(readl(reg) & ~mask, reg);
20562306a36Sopenharmony_ci}
20662306a36Sopenharmony_ci
20762306a36Sopenharmony_ci/**
20862306a36Sopenharmony_ci * flush_i2c_fifo() - This function flushes the I2C FIFO
20962306a36Sopenharmony_ci * @dev: private data of I2C Driver
21062306a36Sopenharmony_ci *
21162306a36Sopenharmony_ci * This function flushes the I2C Tx and Rx FIFOs. It returns
21262306a36Sopenharmony_ci * 0 on successful flushing of FIFO
21362306a36Sopenharmony_ci */
21462306a36Sopenharmony_cistatic int flush_i2c_fifo(struct nmk_i2c_dev *dev)
21562306a36Sopenharmony_ci{
21662306a36Sopenharmony_ci#define LOOP_ATTEMPTS 10
21762306a36Sopenharmony_ci	int i;
21862306a36Sopenharmony_ci	unsigned long timeout;
21962306a36Sopenharmony_ci
22062306a36Sopenharmony_ci	/*
22162306a36Sopenharmony_ci	 * flush the transmit and receive FIFO. The flushing
22262306a36Sopenharmony_ci	 * operation takes several cycles before to be completed.
22362306a36Sopenharmony_ci	 * On the completion, the I2C internal logic clears these
22462306a36Sopenharmony_ci	 * bits, until then no one must access Tx, Rx FIFO and
22562306a36Sopenharmony_ci	 * should poll on these bits waiting for the completion.
22662306a36Sopenharmony_ci	 */
22762306a36Sopenharmony_ci	writel((I2C_CR_FTX | I2C_CR_FRX), dev->virtbase + I2C_CR);
22862306a36Sopenharmony_ci
22962306a36Sopenharmony_ci	for (i = 0; i < LOOP_ATTEMPTS; i++) {
23062306a36Sopenharmony_ci		timeout = jiffies + dev->adap.timeout;
23162306a36Sopenharmony_ci
23262306a36Sopenharmony_ci		while (!time_after(jiffies, timeout)) {
23362306a36Sopenharmony_ci			if ((readl(dev->virtbase + I2C_CR) &
23462306a36Sopenharmony_ci				(I2C_CR_FTX | I2C_CR_FRX)) == 0)
23562306a36Sopenharmony_ci					return 0;
23662306a36Sopenharmony_ci		}
23762306a36Sopenharmony_ci	}
23862306a36Sopenharmony_ci
23962306a36Sopenharmony_ci	dev_err(&dev->adev->dev,
24062306a36Sopenharmony_ci		"flushing operation timed out giving up after %d attempts",
24162306a36Sopenharmony_ci		LOOP_ATTEMPTS);
24262306a36Sopenharmony_ci
24362306a36Sopenharmony_ci	return -ETIMEDOUT;
24462306a36Sopenharmony_ci}
24562306a36Sopenharmony_ci
24662306a36Sopenharmony_ci/**
24762306a36Sopenharmony_ci * disable_all_interrupts() - Disable all interrupts of this I2c Bus
24862306a36Sopenharmony_ci * @dev: private data of I2C Driver
24962306a36Sopenharmony_ci */
25062306a36Sopenharmony_cistatic void disable_all_interrupts(struct nmk_i2c_dev *dev)
25162306a36Sopenharmony_ci{
25262306a36Sopenharmony_ci	u32 mask = IRQ_MASK(0);
25362306a36Sopenharmony_ci	writel(mask, dev->virtbase + I2C_IMSCR);
25462306a36Sopenharmony_ci}
25562306a36Sopenharmony_ci
25662306a36Sopenharmony_ci/**
25762306a36Sopenharmony_ci * clear_all_interrupts() - Clear all interrupts of I2C Controller
25862306a36Sopenharmony_ci * @dev: private data of I2C Driver
25962306a36Sopenharmony_ci */
26062306a36Sopenharmony_cistatic void clear_all_interrupts(struct nmk_i2c_dev *dev)
26162306a36Sopenharmony_ci{
26262306a36Sopenharmony_ci	u32 mask;
26362306a36Sopenharmony_ci	mask = IRQ_MASK(I2C_CLEAR_ALL_INTS);
26462306a36Sopenharmony_ci	writel(mask, dev->virtbase + I2C_ICR);
26562306a36Sopenharmony_ci}
26662306a36Sopenharmony_ci
26762306a36Sopenharmony_ci/**
26862306a36Sopenharmony_ci * init_hw() - initialize the I2C hardware
26962306a36Sopenharmony_ci * @dev: private data of I2C Driver
27062306a36Sopenharmony_ci */
27162306a36Sopenharmony_cistatic int init_hw(struct nmk_i2c_dev *dev)
27262306a36Sopenharmony_ci{
27362306a36Sopenharmony_ci	int stat;
27462306a36Sopenharmony_ci
27562306a36Sopenharmony_ci	stat = flush_i2c_fifo(dev);
27662306a36Sopenharmony_ci	if (stat)
27762306a36Sopenharmony_ci		goto exit;
27862306a36Sopenharmony_ci
27962306a36Sopenharmony_ci	/* disable the controller */
28062306a36Sopenharmony_ci	i2c_clr_bit(dev->virtbase + I2C_CR, I2C_CR_PE);
28162306a36Sopenharmony_ci
28262306a36Sopenharmony_ci	disable_all_interrupts(dev);
28362306a36Sopenharmony_ci
28462306a36Sopenharmony_ci	clear_all_interrupts(dev);
28562306a36Sopenharmony_ci
28662306a36Sopenharmony_ci	dev->cli.operation = I2C_NO_OPERATION;
28762306a36Sopenharmony_ci
28862306a36Sopenharmony_ciexit:
28962306a36Sopenharmony_ci	return stat;
29062306a36Sopenharmony_ci}
29162306a36Sopenharmony_ci
29262306a36Sopenharmony_ci/* enable peripheral, master mode operation */
29362306a36Sopenharmony_ci#define DEFAULT_I2C_REG_CR	((1 << 1) | I2C_CR_PE)
29462306a36Sopenharmony_ci
29562306a36Sopenharmony_ci/**
29662306a36Sopenharmony_ci * load_i2c_mcr_reg() - load the MCR register
29762306a36Sopenharmony_ci * @dev: private data of controller
29862306a36Sopenharmony_ci * @flags: message flags
29962306a36Sopenharmony_ci */
30062306a36Sopenharmony_cistatic u32 load_i2c_mcr_reg(struct nmk_i2c_dev *dev, u16 flags)
30162306a36Sopenharmony_ci{
30262306a36Sopenharmony_ci	u32 mcr = 0;
30362306a36Sopenharmony_ci	unsigned short slave_adr_3msb_bits;
30462306a36Sopenharmony_ci
30562306a36Sopenharmony_ci	mcr |= GEN_MASK(dev->cli.slave_adr, I2C_MCR_A7, 1);
30662306a36Sopenharmony_ci
30762306a36Sopenharmony_ci	if (unlikely(flags & I2C_M_TEN)) {
30862306a36Sopenharmony_ci		/* 10-bit address transaction */
30962306a36Sopenharmony_ci		mcr |= GEN_MASK(2, I2C_MCR_AM, 12);
31062306a36Sopenharmony_ci		/*
31162306a36Sopenharmony_ci		 * Get the top 3 bits.
31262306a36Sopenharmony_ci		 * EA10 represents extended address in MCR. This includes
31362306a36Sopenharmony_ci		 * the extension (MSB bits) of the 7 bit address loaded
31462306a36Sopenharmony_ci		 * in A7
31562306a36Sopenharmony_ci		 */
31662306a36Sopenharmony_ci		slave_adr_3msb_bits = (dev->cli.slave_adr >> 7) & 0x7;
31762306a36Sopenharmony_ci
31862306a36Sopenharmony_ci		mcr |= GEN_MASK(slave_adr_3msb_bits, I2C_MCR_EA10, 8);
31962306a36Sopenharmony_ci	} else {
32062306a36Sopenharmony_ci		/* 7-bit address transaction */
32162306a36Sopenharmony_ci		mcr |= GEN_MASK(1, I2C_MCR_AM, 12);
32262306a36Sopenharmony_ci	}
32362306a36Sopenharmony_ci
32462306a36Sopenharmony_ci	/* start byte procedure not applied */
32562306a36Sopenharmony_ci	mcr |= GEN_MASK(0, I2C_MCR_SB, 11);
32662306a36Sopenharmony_ci
32762306a36Sopenharmony_ci	/* check the operation, master read/write? */
32862306a36Sopenharmony_ci	if (dev->cli.operation == I2C_WRITE)
32962306a36Sopenharmony_ci		mcr |= GEN_MASK(I2C_WRITE, I2C_MCR_OP, 0);
33062306a36Sopenharmony_ci	else
33162306a36Sopenharmony_ci		mcr |= GEN_MASK(I2C_READ, I2C_MCR_OP, 0);
33262306a36Sopenharmony_ci
33362306a36Sopenharmony_ci	/* stop or repeated start? */
33462306a36Sopenharmony_ci	if (dev->stop)
33562306a36Sopenharmony_ci		mcr |= GEN_MASK(1, I2C_MCR_STOP, 14);
33662306a36Sopenharmony_ci	else
33762306a36Sopenharmony_ci		mcr &= ~(GEN_MASK(1, I2C_MCR_STOP, 14));
33862306a36Sopenharmony_ci
33962306a36Sopenharmony_ci	mcr |= GEN_MASK(dev->cli.count, I2C_MCR_LENGTH, 15);
34062306a36Sopenharmony_ci
34162306a36Sopenharmony_ci	return mcr;
34262306a36Sopenharmony_ci}
34362306a36Sopenharmony_ci
34462306a36Sopenharmony_ci/**
34562306a36Sopenharmony_ci * setup_i2c_controller() - setup the controller
34662306a36Sopenharmony_ci * @dev: private data of controller
34762306a36Sopenharmony_ci */
34862306a36Sopenharmony_cistatic void setup_i2c_controller(struct nmk_i2c_dev *dev)
34962306a36Sopenharmony_ci{
35062306a36Sopenharmony_ci	u32 brcr1, brcr2;
35162306a36Sopenharmony_ci	u32 i2c_clk, div;
35262306a36Sopenharmony_ci	u32 ns;
35362306a36Sopenharmony_ci	u16 slsu;
35462306a36Sopenharmony_ci
35562306a36Sopenharmony_ci	writel(0x0, dev->virtbase + I2C_CR);
35662306a36Sopenharmony_ci	writel(0x0, dev->virtbase + I2C_HSMCR);
35762306a36Sopenharmony_ci	writel(0x0, dev->virtbase + I2C_TFTR);
35862306a36Sopenharmony_ci	writel(0x0, dev->virtbase + I2C_RFTR);
35962306a36Sopenharmony_ci	writel(0x0, dev->virtbase + I2C_DMAR);
36062306a36Sopenharmony_ci
36162306a36Sopenharmony_ci	i2c_clk = clk_get_rate(dev->clk);
36262306a36Sopenharmony_ci
36362306a36Sopenharmony_ci	/*
36462306a36Sopenharmony_ci	 * set the slsu:
36562306a36Sopenharmony_ci	 *
36662306a36Sopenharmony_ci	 * slsu defines the data setup time after SCL clock
36762306a36Sopenharmony_ci	 * stretching in terms of i2c clk cycles + 1 (zero means
36862306a36Sopenharmony_ci	 * "wait one cycle"), the needed setup time for the three
36962306a36Sopenharmony_ci	 * modes are 250ns, 100ns, 10ns respectively.
37062306a36Sopenharmony_ci	 *
37162306a36Sopenharmony_ci	 * As the time for one cycle T in nanoseconds is
37262306a36Sopenharmony_ci	 * T = (1/f) * 1000000000 =>
37362306a36Sopenharmony_ci	 * slsu = cycles / (1000000000 / f) + 1
37462306a36Sopenharmony_ci	 */
37562306a36Sopenharmony_ci	ns = DIV_ROUND_UP_ULL(1000000000ULL, i2c_clk);
37662306a36Sopenharmony_ci	switch (dev->sm) {
37762306a36Sopenharmony_ci	case I2C_FREQ_MODE_FAST:
37862306a36Sopenharmony_ci	case I2C_FREQ_MODE_FAST_PLUS:
37962306a36Sopenharmony_ci		slsu = DIV_ROUND_UP(100, ns); /* Fast */
38062306a36Sopenharmony_ci		break;
38162306a36Sopenharmony_ci	case I2C_FREQ_MODE_HIGH_SPEED:
38262306a36Sopenharmony_ci		slsu = DIV_ROUND_UP(10, ns); /* High */
38362306a36Sopenharmony_ci		break;
38462306a36Sopenharmony_ci	case I2C_FREQ_MODE_STANDARD:
38562306a36Sopenharmony_ci	default:
38662306a36Sopenharmony_ci		slsu = DIV_ROUND_UP(250, ns); /* Standard */
38762306a36Sopenharmony_ci		break;
38862306a36Sopenharmony_ci	}
38962306a36Sopenharmony_ci	slsu += 1;
39062306a36Sopenharmony_ci
39162306a36Sopenharmony_ci	dev_dbg(&dev->adev->dev, "calculated SLSU = %04x\n", slsu);
39262306a36Sopenharmony_ci	writel(slsu << 16, dev->virtbase + I2C_SCR);
39362306a36Sopenharmony_ci
39462306a36Sopenharmony_ci	/*
39562306a36Sopenharmony_ci	 * The spec says, in case of std. mode the divider is
39662306a36Sopenharmony_ci	 * 2 whereas it is 3 for fast and fastplus mode of
39762306a36Sopenharmony_ci	 * operation. TODO - high speed support.
39862306a36Sopenharmony_ci	 */
39962306a36Sopenharmony_ci	div = (dev->clk_freq > I2C_MAX_STANDARD_MODE_FREQ) ? 3 : 2;
40062306a36Sopenharmony_ci
40162306a36Sopenharmony_ci	/*
40262306a36Sopenharmony_ci	 * generate the mask for baud rate counters. The controller
40362306a36Sopenharmony_ci	 * has two baud rate counters. One is used for High speed
40462306a36Sopenharmony_ci	 * operation, and the other is for std, fast mode, fast mode
40562306a36Sopenharmony_ci	 * plus operation. Currently we do not supprt high speed mode
40662306a36Sopenharmony_ci	 * so set brcr1 to 0.
40762306a36Sopenharmony_ci	 */
40862306a36Sopenharmony_ci	brcr1 = 0 << 16;
40962306a36Sopenharmony_ci	brcr2 = (i2c_clk/(dev->clk_freq * div)) & 0xffff;
41062306a36Sopenharmony_ci
41162306a36Sopenharmony_ci	/* set the baud rate counter register */
41262306a36Sopenharmony_ci	writel((brcr1 | brcr2), dev->virtbase + I2C_BRCR);
41362306a36Sopenharmony_ci
41462306a36Sopenharmony_ci	/*
41562306a36Sopenharmony_ci	 * set the speed mode. Currently we support
41662306a36Sopenharmony_ci	 * only standard and fast mode of operation
41762306a36Sopenharmony_ci	 * TODO - support for fast mode plus (up to 1Mb/s)
41862306a36Sopenharmony_ci	 * and high speed (up to 3.4 Mb/s)
41962306a36Sopenharmony_ci	 */
42062306a36Sopenharmony_ci	if (dev->sm > I2C_FREQ_MODE_FAST) {
42162306a36Sopenharmony_ci		dev_err(&dev->adev->dev,
42262306a36Sopenharmony_ci			"do not support this mode defaulting to std. mode\n");
42362306a36Sopenharmony_ci		brcr2 = i2c_clk / (I2C_MAX_STANDARD_MODE_FREQ * 2) & 0xffff;
42462306a36Sopenharmony_ci		writel((brcr1 | brcr2), dev->virtbase + I2C_BRCR);
42562306a36Sopenharmony_ci		writel(I2C_FREQ_MODE_STANDARD << 4,
42662306a36Sopenharmony_ci				dev->virtbase + I2C_CR);
42762306a36Sopenharmony_ci	}
42862306a36Sopenharmony_ci	writel(dev->sm << 4, dev->virtbase + I2C_CR);
42962306a36Sopenharmony_ci
43062306a36Sopenharmony_ci	/* set the Tx and Rx FIFO threshold */
43162306a36Sopenharmony_ci	writel(dev->tft, dev->virtbase + I2C_TFTR);
43262306a36Sopenharmony_ci	writel(dev->rft, dev->virtbase + I2C_RFTR);
43362306a36Sopenharmony_ci}
43462306a36Sopenharmony_ci
43562306a36Sopenharmony_ci/**
43662306a36Sopenharmony_ci * read_i2c() - Read from I2C client device
43762306a36Sopenharmony_ci * @dev: private data of I2C Driver
43862306a36Sopenharmony_ci * @flags: message flags
43962306a36Sopenharmony_ci *
44062306a36Sopenharmony_ci * This function reads from i2c client device when controller is in
44162306a36Sopenharmony_ci * master mode. There is a completion timeout. If there is no transfer
44262306a36Sopenharmony_ci * before timeout error is returned.
44362306a36Sopenharmony_ci */
44462306a36Sopenharmony_cistatic int read_i2c(struct nmk_i2c_dev *dev, u16 flags)
44562306a36Sopenharmony_ci{
44662306a36Sopenharmony_ci	int status = 0;
44762306a36Sopenharmony_ci	u32 mcr, irq_mask;
44862306a36Sopenharmony_ci	unsigned long timeout;
44962306a36Sopenharmony_ci
45062306a36Sopenharmony_ci	mcr = load_i2c_mcr_reg(dev, flags);
45162306a36Sopenharmony_ci	writel(mcr, dev->virtbase + I2C_MCR);
45262306a36Sopenharmony_ci
45362306a36Sopenharmony_ci	/* load the current CR value */
45462306a36Sopenharmony_ci	writel(readl(dev->virtbase + I2C_CR) | DEFAULT_I2C_REG_CR,
45562306a36Sopenharmony_ci			dev->virtbase + I2C_CR);
45662306a36Sopenharmony_ci
45762306a36Sopenharmony_ci	/* enable the controller */
45862306a36Sopenharmony_ci	i2c_set_bit(dev->virtbase + I2C_CR, I2C_CR_PE);
45962306a36Sopenharmony_ci
46062306a36Sopenharmony_ci	init_completion(&dev->xfer_complete);
46162306a36Sopenharmony_ci
46262306a36Sopenharmony_ci	/* enable interrupts by setting the mask */
46362306a36Sopenharmony_ci	irq_mask = (I2C_IT_RXFNF | I2C_IT_RXFF |
46462306a36Sopenharmony_ci			I2C_IT_MAL | I2C_IT_BERR);
46562306a36Sopenharmony_ci
46662306a36Sopenharmony_ci	if (dev->stop || !dev->vendor->has_mtdws)
46762306a36Sopenharmony_ci		irq_mask |= I2C_IT_MTD;
46862306a36Sopenharmony_ci	else
46962306a36Sopenharmony_ci		irq_mask |= I2C_IT_MTDWS;
47062306a36Sopenharmony_ci
47162306a36Sopenharmony_ci	irq_mask = I2C_CLEAR_ALL_INTS & IRQ_MASK(irq_mask);
47262306a36Sopenharmony_ci
47362306a36Sopenharmony_ci	writel(readl(dev->virtbase + I2C_IMSCR) | irq_mask,
47462306a36Sopenharmony_ci			dev->virtbase + I2C_IMSCR);
47562306a36Sopenharmony_ci
47662306a36Sopenharmony_ci	timeout = wait_for_completion_timeout(
47762306a36Sopenharmony_ci		&dev->xfer_complete, dev->adap.timeout);
47862306a36Sopenharmony_ci
47962306a36Sopenharmony_ci	if (timeout == 0) {
48062306a36Sopenharmony_ci		/* Controller timed out */
48162306a36Sopenharmony_ci		dev_err(&dev->adev->dev, "read from slave 0x%x timed out\n",
48262306a36Sopenharmony_ci				dev->cli.slave_adr);
48362306a36Sopenharmony_ci		status = -ETIMEDOUT;
48462306a36Sopenharmony_ci	}
48562306a36Sopenharmony_ci	return status;
48662306a36Sopenharmony_ci}
48762306a36Sopenharmony_ci
48862306a36Sopenharmony_cistatic void fill_tx_fifo(struct nmk_i2c_dev *dev, int no_bytes)
48962306a36Sopenharmony_ci{
49062306a36Sopenharmony_ci	int count;
49162306a36Sopenharmony_ci
49262306a36Sopenharmony_ci	for (count = (no_bytes - 2);
49362306a36Sopenharmony_ci			(count > 0) &&
49462306a36Sopenharmony_ci			(dev->cli.count != 0);
49562306a36Sopenharmony_ci			count--) {
49662306a36Sopenharmony_ci		/* write to the Tx FIFO */
49762306a36Sopenharmony_ci		writeb(*dev->cli.buffer,
49862306a36Sopenharmony_ci			dev->virtbase + I2C_TFR);
49962306a36Sopenharmony_ci		dev->cli.buffer++;
50062306a36Sopenharmony_ci		dev->cli.count--;
50162306a36Sopenharmony_ci		dev->cli.xfer_bytes++;
50262306a36Sopenharmony_ci	}
50362306a36Sopenharmony_ci
50462306a36Sopenharmony_ci}
50562306a36Sopenharmony_ci
50662306a36Sopenharmony_ci/**
50762306a36Sopenharmony_ci * write_i2c() - Write data to I2C client.
50862306a36Sopenharmony_ci * @dev: private data of I2C Driver
50962306a36Sopenharmony_ci * @flags: message flags
51062306a36Sopenharmony_ci *
51162306a36Sopenharmony_ci * This function writes data to I2C client
51262306a36Sopenharmony_ci */
51362306a36Sopenharmony_cistatic int write_i2c(struct nmk_i2c_dev *dev, u16 flags)
51462306a36Sopenharmony_ci{
51562306a36Sopenharmony_ci	u32 status = 0;
51662306a36Sopenharmony_ci	u32 mcr, irq_mask;
51762306a36Sopenharmony_ci	unsigned long timeout;
51862306a36Sopenharmony_ci
51962306a36Sopenharmony_ci	mcr = load_i2c_mcr_reg(dev, flags);
52062306a36Sopenharmony_ci
52162306a36Sopenharmony_ci	writel(mcr, dev->virtbase + I2C_MCR);
52262306a36Sopenharmony_ci
52362306a36Sopenharmony_ci	/* load the current CR value */
52462306a36Sopenharmony_ci	writel(readl(dev->virtbase + I2C_CR) | DEFAULT_I2C_REG_CR,
52562306a36Sopenharmony_ci			dev->virtbase + I2C_CR);
52662306a36Sopenharmony_ci
52762306a36Sopenharmony_ci	/* enable the controller */
52862306a36Sopenharmony_ci	i2c_set_bit(dev->virtbase + I2C_CR, I2C_CR_PE);
52962306a36Sopenharmony_ci
53062306a36Sopenharmony_ci	init_completion(&dev->xfer_complete);
53162306a36Sopenharmony_ci
53262306a36Sopenharmony_ci	/* enable interrupts by settings the masks */
53362306a36Sopenharmony_ci	irq_mask = (I2C_IT_TXFOVR | I2C_IT_MAL | I2C_IT_BERR);
53462306a36Sopenharmony_ci
53562306a36Sopenharmony_ci	/* Fill the TX FIFO with transmit data */
53662306a36Sopenharmony_ci	fill_tx_fifo(dev, MAX_I2C_FIFO_THRESHOLD);
53762306a36Sopenharmony_ci
53862306a36Sopenharmony_ci	if (dev->cli.count != 0)
53962306a36Sopenharmony_ci		irq_mask |= I2C_IT_TXFNE;
54062306a36Sopenharmony_ci
54162306a36Sopenharmony_ci	/*
54262306a36Sopenharmony_ci	 * check if we want to transfer a single or multiple bytes, if so
54362306a36Sopenharmony_ci	 * set the MTDWS bit (Master Transaction Done Without Stop)
54462306a36Sopenharmony_ci	 * to start repeated start operation
54562306a36Sopenharmony_ci	 */
54662306a36Sopenharmony_ci	if (dev->stop || !dev->vendor->has_mtdws)
54762306a36Sopenharmony_ci		irq_mask |= I2C_IT_MTD;
54862306a36Sopenharmony_ci	else
54962306a36Sopenharmony_ci		irq_mask |= I2C_IT_MTDWS;
55062306a36Sopenharmony_ci
55162306a36Sopenharmony_ci	irq_mask = I2C_CLEAR_ALL_INTS & IRQ_MASK(irq_mask);
55262306a36Sopenharmony_ci
55362306a36Sopenharmony_ci	writel(readl(dev->virtbase + I2C_IMSCR) | irq_mask,
55462306a36Sopenharmony_ci			dev->virtbase + I2C_IMSCR);
55562306a36Sopenharmony_ci
55662306a36Sopenharmony_ci	timeout = wait_for_completion_timeout(
55762306a36Sopenharmony_ci		&dev->xfer_complete, dev->adap.timeout);
55862306a36Sopenharmony_ci
55962306a36Sopenharmony_ci	if (timeout == 0) {
56062306a36Sopenharmony_ci		/* Controller timed out */
56162306a36Sopenharmony_ci		dev_err(&dev->adev->dev, "write to slave 0x%x timed out\n",
56262306a36Sopenharmony_ci				dev->cli.slave_adr);
56362306a36Sopenharmony_ci		status = -ETIMEDOUT;
56462306a36Sopenharmony_ci	}
56562306a36Sopenharmony_ci
56662306a36Sopenharmony_ci	return status;
56762306a36Sopenharmony_ci}
56862306a36Sopenharmony_ci
56962306a36Sopenharmony_ci/**
57062306a36Sopenharmony_ci * nmk_i2c_xfer_one() - transmit a single I2C message
57162306a36Sopenharmony_ci * @dev: device with a message encoded into it
57262306a36Sopenharmony_ci * @flags: message flags
57362306a36Sopenharmony_ci */
57462306a36Sopenharmony_cistatic int nmk_i2c_xfer_one(struct nmk_i2c_dev *dev, u16 flags)
57562306a36Sopenharmony_ci{
57662306a36Sopenharmony_ci	int status;
57762306a36Sopenharmony_ci
57862306a36Sopenharmony_ci	if (flags & I2C_M_RD) {
57962306a36Sopenharmony_ci		/* read operation */
58062306a36Sopenharmony_ci		dev->cli.operation = I2C_READ;
58162306a36Sopenharmony_ci		status = read_i2c(dev, flags);
58262306a36Sopenharmony_ci	} else {
58362306a36Sopenharmony_ci		/* write operation */
58462306a36Sopenharmony_ci		dev->cli.operation = I2C_WRITE;
58562306a36Sopenharmony_ci		status = write_i2c(dev, flags);
58662306a36Sopenharmony_ci	}
58762306a36Sopenharmony_ci
58862306a36Sopenharmony_ci	if (status || (dev->result)) {
58962306a36Sopenharmony_ci		u32 i2c_sr;
59062306a36Sopenharmony_ci		u32 cause;
59162306a36Sopenharmony_ci
59262306a36Sopenharmony_ci		i2c_sr = readl(dev->virtbase + I2C_SR);
59362306a36Sopenharmony_ci		/*
59462306a36Sopenharmony_ci		 * Check if the controller I2C operation status
59562306a36Sopenharmony_ci		 * is set to ABORT(11b).
59662306a36Sopenharmony_ci		 */
59762306a36Sopenharmony_ci		if (((i2c_sr >> 2) & 0x3) == 0x3) {
59862306a36Sopenharmony_ci			/* get the abort cause */
59962306a36Sopenharmony_ci			cause =	(i2c_sr >> 4) & 0x7;
60062306a36Sopenharmony_ci			dev_err(&dev->adev->dev, "%s\n",
60162306a36Sopenharmony_ci				cause >= ARRAY_SIZE(abort_causes) ?
60262306a36Sopenharmony_ci				"unknown reason" :
60362306a36Sopenharmony_ci				abort_causes[cause]);
60462306a36Sopenharmony_ci		}
60562306a36Sopenharmony_ci
60662306a36Sopenharmony_ci		(void) init_hw(dev);
60762306a36Sopenharmony_ci
60862306a36Sopenharmony_ci		status = status ? status : dev->result;
60962306a36Sopenharmony_ci	}
61062306a36Sopenharmony_ci
61162306a36Sopenharmony_ci	return status;
61262306a36Sopenharmony_ci}
61362306a36Sopenharmony_ci
61462306a36Sopenharmony_ci/**
61562306a36Sopenharmony_ci * nmk_i2c_xfer() - I2C transfer function used by kernel framework
61662306a36Sopenharmony_ci * @i2c_adap: Adapter pointer to the controller
61762306a36Sopenharmony_ci * @msgs: Pointer to data to be written.
61862306a36Sopenharmony_ci * @num_msgs: Number of messages to be executed
61962306a36Sopenharmony_ci *
62062306a36Sopenharmony_ci * This is the function called by the generic kernel i2c_transfer()
62162306a36Sopenharmony_ci * or i2c_smbus...() API calls. Note that this code is protected by the
62262306a36Sopenharmony_ci * semaphore set in the kernel i2c_transfer() function.
62362306a36Sopenharmony_ci *
62462306a36Sopenharmony_ci * NOTE:
62562306a36Sopenharmony_ci * READ TRANSFER : We impose a restriction of the first message to be the
62662306a36Sopenharmony_ci *		index message for any read transaction.
62762306a36Sopenharmony_ci *		- a no index is coded as '0',
62862306a36Sopenharmony_ci *		- 2byte big endian index is coded as '3'
62962306a36Sopenharmony_ci *		!!! msg[0].buf holds the actual index.
63062306a36Sopenharmony_ci *		This is compatible with generic messages of smbus emulator
63162306a36Sopenharmony_ci *		that send a one byte index.
63262306a36Sopenharmony_ci *		eg. a I2C transation to read 2 bytes from index 0
63362306a36Sopenharmony_ci *			idx = 0;
63462306a36Sopenharmony_ci *			msg[0].addr = client->addr;
63562306a36Sopenharmony_ci *			msg[0].flags = 0x0;
63662306a36Sopenharmony_ci *			msg[0].len = 1;
63762306a36Sopenharmony_ci *			msg[0].buf = &idx;
63862306a36Sopenharmony_ci *
63962306a36Sopenharmony_ci *			msg[1].addr = client->addr;
64062306a36Sopenharmony_ci *			msg[1].flags = I2C_M_RD;
64162306a36Sopenharmony_ci *			msg[1].len = 2;
64262306a36Sopenharmony_ci *			msg[1].buf = rd_buff
64362306a36Sopenharmony_ci *			i2c_transfer(adap, msg, 2);
64462306a36Sopenharmony_ci *
64562306a36Sopenharmony_ci * WRITE TRANSFER : The I2C standard interface interprets all data as payload.
64662306a36Sopenharmony_ci *		If you want to emulate an SMBUS write transaction put the
64762306a36Sopenharmony_ci *		index as first byte(or first and second) in the payload.
64862306a36Sopenharmony_ci *		eg. a I2C transation to write 2 bytes from index 1
64962306a36Sopenharmony_ci *			wr_buff[0] = 0x1;
65062306a36Sopenharmony_ci *			wr_buff[1] = 0x23;
65162306a36Sopenharmony_ci *			wr_buff[2] = 0x46;
65262306a36Sopenharmony_ci *			msg[0].flags = 0x0;
65362306a36Sopenharmony_ci *			msg[0].len = 3;
65462306a36Sopenharmony_ci *			msg[0].buf = wr_buff;
65562306a36Sopenharmony_ci *			i2c_transfer(adap, msg, 1);
65662306a36Sopenharmony_ci *
65762306a36Sopenharmony_ci * To read or write a block of data (multiple bytes) using SMBUS emulation
65862306a36Sopenharmony_ci * please use the i2c_smbus_read_i2c_block_data()
65962306a36Sopenharmony_ci * or i2c_smbus_write_i2c_block_data() API
66062306a36Sopenharmony_ci */
66162306a36Sopenharmony_cistatic int nmk_i2c_xfer(struct i2c_adapter *i2c_adap,
66262306a36Sopenharmony_ci		struct i2c_msg msgs[], int num_msgs)
66362306a36Sopenharmony_ci{
66462306a36Sopenharmony_ci	int status = 0;
66562306a36Sopenharmony_ci	int i;
66662306a36Sopenharmony_ci	struct nmk_i2c_dev *dev = i2c_get_adapdata(i2c_adap);
66762306a36Sopenharmony_ci	int j;
66862306a36Sopenharmony_ci
66962306a36Sopenharmony_ci	pm_runtime_get_sync(&dev->adev->dev);
67062306a36Sopenharmony_ci
67162306a36Sopenharmony_ci	/* Attempt three times to send the message queue */
67262306a36Sopenharmony_ci	for (j = 0; j < 3; j++) {
67362306a36Sopenharmony_ci		/* setup the i2c controller */
67462306a36Sopenharmony_ci		setup_i2c_controller(dev);
67562306a36Sopenharmony_ci
67662306a36Sopenharmony_ci		for (i = 0; i < num_msgs; i++) {
67762306a36Sopenharmony_ci			dev->cli.slave_adr	= msgs[i].addr;
67862306a36Sopenharmony_ci			dev->cli.buffer		= msgs[i].buf;
67962306a36Sopenharmony_ci			dev->cli.count		= msgs[i].len;
68062306a36Sopenharmony_ci			dev->stop = (i < (num_msgs - 1)) ? 0 : 1;
68162306a36Sopenharmony_ci			dev->result = 0;
68262306a36Sopenharmony_ci
68362306a36Sopenharmony_ci			status = nmk_i2c_xfer_one(dev, msgs[i].flags);
68462306a36Sopenharmony_ci			if (status != 0)
68562306a36Sopenharmony_ci				break;
68662306a36Sopenharmony_ci		}
68762306a36Sopenharmony_ci		if (status == 0)
68862306a36Sopenharmony_ci			break;
68962306a36Sopenharmony_ci	}
69062306a36Sopenharmony_ci
69162306a36Sopenharmony_ci	pm_runtime_put_sync(&dev->adev->dev);
69262306a36Sopenharmony_ci
69362306a36Sopenharmony_ci	/* return the no. messages processed */
69462306a36Sopenharmony_ci	if (status)
69562306a36Sopenharmony_ci		return status;
69662306a36Sopenharmony_ci	else
69762306a36Sopenharmony_ci		return num_msgs;
69862306a36Sopenharmony_ci}
69962306a36Sopenharmony_ci
70062306a36Sopenharmony_ci/**
70162306a36Sopenharmony_ci * disable_interrupts() - disable the interrupts
70262306a36Sopenharmony_ci * @dev: private data of controller
70362306a36Sopenharmony_ci * @irq: interrupt number
70462306a36Sopenharmony_ci */
70562306a36Sopenharmony_cistatic int disable_interrupts(struct nmk_i2c_dev *dev, u32 irq)
70662306a36Sopenharmony_ci{
70762306a36Sopenharmony_ci	irq = IRQ_MASK(irq);
70862306a36Sopenharmony_ci	writel(readl(dev->virtbase + I2C_IMSCR) & ~(I2C_CLEAR_ALL_INTS & irq),
70962306a36Sopenharmony_ci			dev->virtbase + I2C_IMSCR);
71062306a36Sopenharmony_ci	return 0;
71162306a36Sopenharmony_ci}
71262306a36Sopenharmony_ci
71362306a36Sopenharmony_ci/**
71462306a36Sopenharmony_ci * i2c_irq_handler() - interrupt routine
71562306a36Sopenharmony_ci * @irq: interrupt number
71662306a36Sopenharmony_ci * @arg: data passed to the handler
71762306a36Sopenharmony_ci *
71862306a36Sopenharmony_ci * This is the interrupt handler for the i2c driver. Currently
71962306a36Sopenharmony_ci * it handles the major interrupts like Rx & Tx FIFO management
72062306a36Sopenharmony_ci * interrupts, master transaction interrupts, arbitration and
72162306a36Sopenharmony_ci * bus error interrupts. The rest of the interrupts are treated as
72262306a36Sopenharmony_ci * unhandled.
72362306a36Sopenharmony_ci */
72462306a36Sopenharmony_cistatic irqreturn_t i2c_irq_handler(int irq, void *arg)
72562306a36Sopenharmony_ci{
72662306a36Sopenharmony_ci	struct nmk_i2c_dev *dev = arg;
72762306a36Sopenharmony_ci	u32 tft, rft;
72862306a36Sopenharmony_ci	u32 count;
72962306a36Sopenharmony_ci	u32 misr, src;
73062306a36Sopenharmony_ci
73162306a36Sopenharmony_ci	/* load Tx FIFO and Rx FIFO threshold values */
73262306a36Sopenharmony_ci	tft = readl(dev->virtbase + I2C_TFTR);
73362306a36Sopenharmony_ci	rft = readl(dev->virtbase + I2C_RFTR);
73462306a36Sopenharmony_ci
73562306a36Sopenharmony_ci	/* read interrupt status register */
73662306a36Sopenharmony_ci	misr = readl(dev->virtbase + I2C_MISR);
73762306a36Sopenharmony_ci
73862306a36Sopenharmony_ci	src = __ffs(misr);
73962306a36Sopenharmony_ci	switch ((1 << src)) {
74062306a36Sopenharmony_ci
74162306a36Sopenharmony_ci	/* Transmit FIFO nearly empty interrupt */
74262306a36Sopenharmony_ci	case I2C_IT_TXFNE:
74362306a36Sopenharmony_ci	{
74462306a36Sopenharmony_ci		if (dev->cli.operation == I2C_READ) {
74562306a36Sopenharmony_ci			/*
74662306a36Sopenharmony_ci			 * in read operation why do we care for writing?
74762306a36Sopenharmony_ci			 * so disable the Transmit FIFO interrupt
74862306a36Sopenharmony_ci			 */
74962306a36Sopenharmony_ci			disable_interrupts(dev, I2C_IT_TXFNE);
75062306a36Sopenharmony_ci		} else {
75162306a36Sopenharmony_ci			fill_tx_fifo(dev, (MAX_I2C_FIFO_THRESHOLD - tft));
75262306a36Sopenharmony_ci			/*
75362306a36Sopenharmony_ci			 * if done, close the transfer by disabling the
75462306a36Sopenharmony_ci			 * corresponding TXFNE interrupt
75562306a36Sopenharmony_ci			 */
75662306a36Sopenharmony_ci			if (dev->cli.count == 0)
75762306a36Sopenharmony_ci				disable_interrupts(dev,	I2C_IT_TXFNE);
75862306a36Sopenharmony_ci		}
75962306a36Sopenharmony_ci	}
76062306a36Sopenharmony_ci	break;
76162306a36Sopenharmony_ci
76262306a36Sopenharmony_ci	/*
76362306a36Sopenharmony_ci	 * Rx FIFO nearly full interrupt.
76462306a36Sopenharmony_ci	 * This is set when the numer of entries in Rx FIFO is
76562306a36Sopenharmony_ci	 * greater or equal than the threshold value programmed
76662306a36Sopenharmony_ci	 * in RFT
76762306a36Sopenharmony_ci	 */
76862306a36Sopenharmony_ci	case I2C_IT_RXFNF:
76962306a36Sopenharmony_ci		for (count = rft; count > 0; count--) {
77062306a36Sopenharmony_ci			/* Read the Rx FIFO */
77162306a36Sopenharmony_ci			*dev->cli.buffer = readb(dev->virtbase + I2C_RFR);
77262306a36Sopenharmony_ci			dev->cli.buffer++;
77362306a36Sopenharmony_ci		}
77462306a36Sopenharmony_ci		dev->cli.count -= rft;
77562306a36Sopenharmony_ci		dev->cli.xfer_bytes += rft;
77662306a36Sopenharmony_ci		break;
77762306a36Sopenharmony_ci
77862306a36Sopenharmony_ci	/* Rx FIFO full */
77962306a36Sopenharmony_ci	case I2C_IT_RXFF:
78062306a36Sopenharmony_ci		for (count = MAX_I2C_FIFO_THRESHOLD; count > 0; count--) {
78162306a36Sopenharmony_ci			*dev->cli.buffer = readb(dev->virtbase + I2C_RFR);
78262306a36Sopenharmony_ci			dev->cli.buffer++;
78362306a36Sopenharmony_ci		}
78462306a36Sopenharmony_ci		dev->cli.count -= MAX_I2C_FIFO_THRESHOLD;
78562306a36Sopenharmony_ci		dev->cli.xfer_bytes += MAX_I2C_FIFO_THRESHOLD;
78662306a36Sopenharmony_ci		break;
78762306a36Sopenharmony_ci
78862306a36Sopenharmony_ci	/* Master Transaction Done with/without stop */
78962306a36Sopenharmony_ci	case I2C_IT_MTD:
79062306a36Sopenharmony_ci	case I2C_IT_MTDWS:
79162306a36Sopenharmony_ci		if (dev->cli.operation == I2C_READ) {
79262306a36Sopenharmony_ci			while (!(readl(dev->virtbase + I2C_RISR)
79362306a36Sopenharmony_ci				 & I2C_IT_RXFE)) {
79462306a36Sopenharmony_ci				if (dev->cli.count == 0)
79562306a36Sopenharmony_ci					break;
79662306a36Sopenharmony_ci				*dev->cli.buffer =
79762306a36Sopenharmony_ci					readb(dev->virtbase + I2C_RFR);
79862306a36Sopenharmony_ci				dev->cli.buffer++;
79962306a36Sopenharmony_ci				dev->cli.count--;
80062306a36Sopenharmony_ci				dev->cli.xfer_bytes++;
80162306a36Sopenharmony_ci			}
80262306a36Sopenharmony_ci		}
80362306a36Sopenharmony_ci
80462306a36Sopenharmony_ci		disable_all_interrupts(dev);
80562306a36Sopenharmony_ci		clear_all_interrupts(dev);
80662306a36Sopenharmony_ci
80762306a36Sopenharmony_ci		if (dev->cli.count) {
80862306a36Sopenharmony_ci			dev->result = -EIO;
80962306a36Sopenharmony_ci			dev_err(&dev->adev->dev,
81062306a36Sopenharmony_ci				"%lu bytes still remain to be xfered\n",
81162306a36Sopenharmony_ci				dev->cli.count);
81262306a36Sopenharmony_ci			(void) init_hw(dev);
81362306a36Sopenharmony_ci		}
81462306a36Sopenharmony_ci		complete(&dev->xfer_complete);
81562306a36Sopenharmony_ci
81662306a36Sopenharmony_ci		break;
81762306a36Sopenharmony_ci
81862306a36Sopenharmony_ci	/* Master Arbitration lost interrupt */
81962306a36Sopenharmony_ci	case I2C_IT_MAL:
82062306a36Sopenharmony_ci		dev->result = -EIO;
82162306a36Sopenharmony_ci		(void) init_hw(dev);
82262306a36Sopenharmony_ci
82362306a36Sopenharmony_ci		i2c_set_bit(dev->virtbase + I2C_ICR, I2C_IT_MAL);
82462306a36Sopenharmony_ci		complete(&dev->xfer_complete);
82562306a36Sopenharmony_ci
82662306a36Sopenharmony_ci		break;
82762306a36Sopenharmony_ci
82862306a36Sopenharmony_ci	/*
82962306a36Sopenharmony_ci	 * Bus Error interrupt.
83062306a36Sopenharmony_ci	 * This happens when an unexpected start/stop condition occurs
83162306a36Sopenharmony_ci	 * during the transaction.
83262306a36Sopenharmony_ci	 */
83362306a36Sopenharmony_ci	case I2C_IT_BERR:
83462306a36Sopenharmony_ci		dev->result = -EIO;
83562306a36Sopenharmony_ci		/* get the status */
83662306a36Sopenharmony_ci		if (((readl(dev->virtbase + I2C_SR) >> 2) & 0x3) == I2C_ABORT)
83762306a36Sopenharmony_ci			(void) init_hw(dev);
83862306a36Sopenharmony_ci
83962306a36Sopenharmony_ci		i2c_set_bit(dev->virtbase + I2C_ICR, I2C_IT_BERR);
84062306a36Sopenharmony_ci		complete(&dev->xfer_complete);
84162306a36Sopenharmony_ci
84262306a36Sopenharmony_ci		break;
84362306a36Sopenharmony_ci
84462306a36Sopenharmony_ci	/*
84562306a36Sopenharmony_ci	 * Tx FIFO overrun interrupt.
84662306a36Sopenharmony_ci	 * This is set when a write operation in Tx FIFO is performed and
84762306a36Sopenharmony_ci	 * the Tx FIFO is full.
84862306a36Sopenharmony_ci	 */
84962306a36Sopenharmony_ci	case I2C_IT_TXFOVR:
85062306a36Sopenharmony_ci		dev->result = -EIO;
85162306a36Sopenharmony_ci		(void) init_hw(dev);
85262306a36Sopenharmony_ci
85362306a36Sopenharmony_ci		dev_err(&dev->adev->dev, "Tx Fifo Over run\n");
85462306a36Sopenharmony_ci		complete(&dev->xfer_complete);
85562306a36Sopenharmony_ci
85662306a36Sopenharmony_ci		break;
85762306a36Sopenharmony_ci
85862306a36Sopenharmony_ci	/* unhandled interrupts by this driver - TODO*/
85962306a36Sopenharmony_ci	case I2C_IT_TXFE:
86062306a36Sopenharmony_ci	case I2C_IT_TXFF:
86162306a36Sopenharmony_ci	case I2C_IT_RXFE:
86262306a36Sopenharmony_ci	case I2C_IT_RFSR:
86362306a36Sopenharmony_ci	case I2C_IT_RFSE:
86462306a36Sopenharmony_ci	case I2C_IT_WTSR:
86562306a36Sopenharmony_ci	case I2C_IT_STD:
86662306a36Sopenharmony_ci		dev_err(&dev->adev->dev, "unhandled Interrupt\n");
86762306a36Sopenharmony_ci		break;
86862306a36Sopenharmony_ci	default:
86962306a36Sopenharmony_ci		dev_err(&dev->adev->dev, "spurious Interrupt..\n");
87062306a36Sopenharmony_ci		break;
87162306a36Sopenharmony_ci	}
87262306a36Sopenharmony_ci
87362306a36Sopenharmony_ci	return IRQ_HANDLED;
87462306a36Sopenharmony_ci}
87562306a36Sopenharmony_ci
87662306a36Sopenharmony_cistatic int nmk_i2c_suspend_late(struct device *dev)
87762306a36Sopenharmony_ci{
87862306a36Sopenharmony_ci	int ret;
87962306a36Sopenharmony_ci
88062306a36Sopenharmony_ci	ret = pm_runtime_force_suspend(dev);
88162306a36Sopenharmony_ci	if (ret)
88262306a36Sopenharmony_ci		return ret;
88362306a36Sopenharmony_ci
88462306a36Sopenharmony_ci	pinctrl_pm_select_sleep_state(dev);
88562306a36Sopenharmony_ci	return 0;
88662306a36Sopenharmony_ci}
88762306a36Sopenharmony_ci
88862306a36Sopenharmony_cistatic int nmk_i2c_resume_early(struct device *dev)
88962306a36Sopenharmony_ci{
89062306a36Sopenharmony_ci	return pm_runtime_force_resume(dev);
89162306a36Sopenharmony_ci}
89262306a36Sopenharmony_ci
89362306a36Sopenharmony_cistatic int nmk_i2c_runtime_suspend(struct device *dev)
89462306a36Sopenharmony_ci{
89562306a36Sopenharmony_ci	struct amba_device *adev = to_amba_device(dev);
89662306a36Sopenharmony_ci	struct nmk_i2c_dev *nmk_i2c = amba_get_drvdata(adev);
89762306a36Sopenharmony_ci
89862306a36Sopenharmony_ci	clk_disable_unprepare(nmk_i2c->clk);
89962306a36Sopenharmony_ci	pinctrl_pm_select_idle_state(dev);
90062306a36Sopenharmony_ci	return 0;
90162306a36Sopenharmony_ci}
90262306a36Sopenharmony_ci
90362306a36Sopenharmony_cistatic int nmk_i2c_runtime_resume(struct device *dev)
90462306a36Sopenharmony_ci{
90562306a36Sopenharmony_ci	struct amba_device *adev = to_amba_device(dev);
90662306a36Sopenharmony_ci	struct nmk_i2c_dev *nmk_i2c = amba_get_drvdata(adev);
90762306a36Sopenharmony_ci	int ret;
90862306a36Sopenharmony_ci
90962306a36Sopenharmony_ci	ret = clk_prepare_enable(nmk_i2c->clk);
91062306a36Sopenharmony_ci	if (ret) {
91162306a36Sopenharmony_ci		dev_err(dev, "can't prepare_enable clock\n");
91262306a36Sopenharmony_ci		return ret;
91362306a36Sopenharmony_ci	}
91462306a36Sopenharmony_ci
91562306a36Sopenharmony_ci	pinctrl_pm_select_default_state(dev);
91662306a36Sopenharmony_ci
91762306a36Sopenharmony_ci	ret = init_hw(nmk_i2c);
91862306a36Sopenharmony_ci	if (ret) {
91962306a36Sopenharmony_ci		clk_disable_unprepare(nmk_i2c->clk);
92062306a36Sopenharmony_ci		pinctrl_pm_select_idle_state(dev);
92162306a36Sopenharmony_ci	}
92262306a36Sopenharmony_ci
92362306a36Sopenharmony_ci	return ret;
92462306a36Sopenharmony_ci}
92562306a36Sopenharmony_ci
92662306a36Sopenharmony_cistatic const struct dev_pm_ops nmk_i2c_pm = {
92762306a36Sopenharmony_ci	LATE_SYSTEM_SLEEP_PM_OPS(nmk_i2c_suspend_late, nmk_i2c_resume_early)
92862306a36Sopenharmony_ci	RUNTIME_PM_OPS(nmk_i2c_runtime_suspend, nmk_i2c_runtime_resume, NULL)
92962306a36Sopenharmony_ci};
93062306a36Sopenharmony_ci
93162306a36Sopenharmony_cistatic unsigned int nmk_i2c_functionality(struct i2c_adapter *adap)
93262306a36Sopenharmony_ci{
93362306a36Sopenharmony_ci	return I2C_FUNC_I2C | I2C_FUNC_SMBUS_EMUL | I2C_FUNC_10BIT_ADDR;
93462306a36Sopenharmony_ci}
93562306a36Sopenharmony_ci
93662306a36Sopenharmony_cistatic const struct i2c_algorithm nmk_i2c_algo = {
93762306a36Sopenharmony_ci	.master_xfer	= nmk_i2c_xfer,
93862306a36Sopenharmony_ci	.functionality	= nmk_i2c_functionality
93962306a36Sopenharmony_ci};
94062306a36Sopenharmony_ci
94162306a36Sopenharmony_cistatic void nmk_i2c_of_probe(struct device_node *np,
94262306a36Sopenharmony_ci			     struct nmk_i2c_dev *nmk)
94362306a36Sopenharmony_ci{
94462306a36Sopenharmony_ci	/* Default to 100 kHz if no frequency is given in the node */
94562306a36Sopenharmony_ci	if (of_property_read_u32(np, "clock-frequency", &nmk->clk_freq))
94662306a36Sopenharmony_ci		nmk->clk_freq = I2C_MAX_STANDARD_MODE_FREQ;
94762306a36Sopenharmony_ci
94862306a36Sopenharmony_ci	/* This driver only supports 'standard' and 'fast' modes of operation. */
94962306a36Sopenharmony_ci	if (nmk->clk_freq <= I2C_MAX_STANDARD_MODE_FREQ)
95062306a36Sopenharmony_ci		nmk->sm = I2C_FREQ_MODE_STANDARD;
95162306a36Sopenharmony_ci	else
95262306a36Sopenharmony_ci		nmk->sm = I2C_FREQ_MODE_FAST;
95362306a36Sopenharmony_ci	nmk->tft = 1; /* Tx FIFO threshold */
95462306a36Sopenharmony_ci	nmk->rft = 8; /* Rx FIFO threshold */
95562306a36Sopenharmony_ci	nmk->timeout = 200; /* Slave response timeout(ms) */
95662306a36Sopenharmony_ci}
95762306a36Sopenharmony_ci
95862306a36Sopenharmony_cistatic int nmk_i2c_probe(struct amba_device *adev, const struct amba_id *id)
95962306a36Sopenharmony_ci{
96062306a36Sopenharmony_ci	int ret = 0;
96162306a36Sopenharmony_ci	struct device_node *np = adev->dev.of_node;
96262306a36Sopenharmony_ci	struct nmk_i2c_dev	*dev;
96362306a36Sopenharmony_ci	struct i2c_adapter *adap;
96462306a36Sopenharmony_ci	struct i2c_vendor_data *vendor = id->data;
96562306a36Sopenharmony_ci	u32 max_fifo_threshold = (vendor->fifodepth / 2) - 1;
96662306a36Sopenharmony_ci
96762306a36Sopenharmony_ci	dev = devm_kzalloc(&adev->dev, sizeof(*dev), GFP_KERNEL);
96862306a36Sopenharmony_ci	if (!dev)
96962306a36Sopenharmony_ci		return -ENOMEM;
97062306a36Sopenharmony_ci
97162306a36Sopenharmony_ci	dev->vendor = vendor;
97262306a36Sopenharmony_ci	dev->adev = adev;
97362306a36Sopenharmony_ci	nmk_i2c_of_probe(np, dev);
97462306a36Sopenharmony_ci
97562306a36Sopenharmony_ci	if (dev->tft > max_fifo_threshold) {
97662306a36Sopenharmony_ci		dev_warn(&adev->dev, "requested TX FIFO threshold %u, adjusted down to %u\n",
97762306a36Sopenharmony_ci			 dev->tft, max_fifo_threshold);
97862306a36Sopenharmony_ci		dev->tft = max_fifo_threshold;
97962306a36Sopenharmony_ci	}
98062306a36Sopenharmony_ci
98162306a36Sopenharmony_ci	if (dev->rft > max_fifo_threshold) {
98262306a36Sopenharmony_ci		dev_warn(&adev->dev, "requested RX FIFO threshold %u, adjusted down to %u\n",
98362306a36Sopenharmony_ci			dev->rft, max_fifo_threshold);
98462306a36Sopenharmony_ci		dev->rft = max_fifo_threshold;
98562306a36Sopenharmony_ci	}
98662306a36Sopenharmony_ci
98762306a36Sopenharmony_ci	amba_set_drvdata(adev, dev);
98862306a36Sopenharmony_ci
98962306a36Sopenharmony_ci	dev->virtbase = devm_ioremap(&adev->dev, adev->res.start,
99062306a36Sopenharmony_ci				resource_size(&adev->res));
99162306a36Sopenharmony_ci	if (!dev->virtbase)
99262306a36Sopenharmony_ci		return -ENOMEM;
99362306a36Sopenharmony_ci
99462306a36Sopenharmony_ci	dev->irq = adev->irq[0];
99562306a36Sopenharmony_ci	ret = devm_request_irq(&adev->dev, dev->irq, i2c_irq_handler, 0,
99662306a36Sopenharmony_ci				DRIVER_NAME, dev);
99762306a36Sopenharmony_ci	if (ret)
99862306a36Sopenharmony_ci		return dev_err_probe(&adev->dev, ret,
99962306a36Sopenharmony_ci				     "cannot claim the irq %d\n", dev->irq);
100062306a36Sopenharmony_ci
100162306a36Sopenharmony_ci	dev->clk = devm_clk_get_enabled(&adev->dev, NULL);
100262306a36Sopenharmony_ci	if (IS_ERR(dev->clk))
100362306a36Sopenharmony_ci		return dev_err_probe(&adev->dev, PTR_ERR(dev->clk),
100462306a36Sopenharmony_ci				     "could enable i2c clock\n");
100562306a36Sopenharmony_ci
100662306a36Sopenharmony_ci	init_hw(dev);
100762306a36Sopenharmony_ci
100862306a36Sopenharmony_ci	adap = &dev->adap;
100962306a36Sopenharmony_ci	adap->dev.of_node = np;
101062306a36Sopenharmony_ci	adap->dev.parent = &adev->dev;
101162306a36Sopenharmony_ci	adap->owner = THIS_MODULE;
101262306a36Sopenharmony_ci	adap->class = I2C_CLASS_DEPRECATED;
101362306a36Sopenharmony_ci	adap->algo = &nmk_i2c_algo;
101462306a36Sopenharmony_ci	adap->timeout = msecs_to_jiffies(dev->timeout);
101562306a36Sopenharmony_ci	snprintf(adap->name, sizeof(adap->name),
101662306a36Sopenharmony_ci		 "Nomadik I2C at %pR", &adev->res);
101762306a36Sopenharmony_ci
101862306a36Sopenharmony_ci	i2c_set_adapdata(adap, dev);
101962306a36Sopenharmony_ci
102062306a36Sopenharmony_ci	dev_info(&adev->dev,
102162306a36Sopenharmony_ci		 "initialize %s on virtual base %p\n",
102262306a36Sopenharmony_ci		 adap->name, dev->virtbase);
102362306a36Sopenharmony_ci
102462306a36Sopenharmony_ci	ret = i2c_add_adapter(adap);
102562306a36Sopenharmony_ci	if (ret)
102662306a36Sopenharmony_ci		return ret;
102762306a36Sopenharmony_ci
102862306a36Sopenharmony_ci	pm_runtime_put(&adev->dev);
102962306a36Sopenharmony_ci
103062306a36Sopenharmony_ci	return 0;
103162306a36Sopenharmony_ci}
103262306a36Sopenharmony_ci
103362306a36Sopenharmony_cistatic void nmk_i2c_remove(struct amba_device *adev)
103462306a36Sopenharmony_ci{
103562306a36Sopenharmony_ci	struct nmk_i2c_dev *dev = amba_get_drvdata(adev);
103662306a36Sopenharmony_ci
103762306a36Sopenharmony_ci	i2c_del_adapter(&dev->adap);
103862306a36Sopenharmony_ci	flush_i2c_fifo(dev);
103962306a36Sopenharmony_ci	disable_all_interrupts(dev);
104062306a36Sopenharmony_ci	clear_all_interrupts(dev);
104162306a36Sopenharmony_ci	/* disable the controller */
104262306a36Sopenharmony_ci	i2c_clr_bit(dev->virtbase + I2C_CR, I2C_CR_PE);
104362306a36Sopenharmony_ci}
104462306a36Sopenharmony_ci
104562306a36Sopenharmony_cistatic struct i2c_vendor_data vendor_stn8815 = {
104662306a36Sopenharmony_ci	.has_mtdws = false,
104762306a36Sopenharmony_ci	.fifodepth = 16, /* Guessed from TFTR/RFTR = 7 */
104862306a36Sopenharmony_ci};
104962306a36Sopenharmony_ci
105062306a36Sopenharmony_cistatic struct i2c_vendor_data vendor_db8500 = {
105162306a36Sopenharmony_ci	.has_mtdws = true,
105262306a36Sopenharmony_ci	.fifodepth = 32, /* Guessed from TFTR/RFTR = 15 */
105362306a36Sopenharmony_ci};
105462306a36Sopenharmony_ci
105562306a36Sopenharmony_cistatic const struct amba_id nmk_i2c_ids[] = {
105662306a36Sopenharmony_ci	{
105762306a36Sopenharmony_ci		.id	= 0x00180024,
105862306a36Sopenharmony_ci		.mask	= 0x00ffffff,
105962306a36Sopenharmony_ci		.data	= &vendor_stn8815,
106062306a36Sopenharmony_ci	},
106162306a36Sopenharmony_ci	{
106262306a36Sopenharmony_ci		.id	= 0x00380024,
106362306a36Sopenharmony_ci		.mask	= 0x00ffffff,
106462306a36Sopenharmony_ci		.data	= &vendor_db8500,
106562306a36Sopenharmony_ci	},
106662306a36Sopenharmony_ci	{},
106762306a36Sopenharmony_ci};
106862306a36Sopenharmony_ci
106962306a36Sopenharmony_ciMODULE_DEVICE_TABLE(amba, nmk_i2c_ids);
107062306a36Sopenharmony_ci
107162306a36Sopenharmony_cistatic struct amba_driver nmk_i2c_driver = {
107262306a36Sopenharmony_ci	.drv = {
107362306a36Sopenharmony_ci		.owner = THIS_MODULE,
107462306a36Sopenharmony_ci		.name = DRIVER_NAME,
107562306a36Sopenharmony_ci		.pm = pm_ptr(&nmk_i2c_pm),
107662306a36Sopenharmony_ci	},
107762306a36Sopenharmony_ci	.id_table = nmk_i2c_ids,
107862306a36Sopenharmony_ci	.probe = nmk_i2c_probe,
107962306a36Sopenharmony_ci	.remove = nmk_i2c_remove,
108062306a36Sopenharmony_ci};
108162306a36Sopenharmony_ci
108262306a36Sopenharmony_cistatic int __init nmk_i2c_init(void)
108362306a36Sopenharmony_ci{
108462306a36Sopenharmony_ci	return amba_driver_register(&nmk_i2c_driver);
108562306a36Sopenharmony_ci}
108662306a36Sopenharmony_ci
108762306a36Sopenharmony_cistatic void __exit nmk_i2c_exit(void)
108862306a36Sopenharmony_ci{
108962306a36Sopenharmony_ci	amba_driver_unregister(&nmk_i2c_driver);
109062306a36Sopenharmony_ci}
109162306a36Sopenharmony_ci
109262306a36Sopenharmony_cisubsys_initcall(nmk_i2c_init);
109362306a36Sopenharmony_cimodule_exit(nmk_i2c_exit);
109462306a36Sopenharmony_ci
109562306a36Sopenharmony_ciMODULE_AUTHOR("Sachin Verma");
109662306a36Sopenharmony_ciMODULE_AUTHOR("Srinidhi KASAGAR");
109762306a36Sopenharmony_ciMODULE_DESCRIPTION("Nomadik/Ux500 I2C driver");
109862306a36Sopenharmony_ciMODULE_LICENSE("GPL");
1099