18c2ecf20Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0
28c2ecf20Sopenharmony_ci/*
38c2ecf20Sopenharmony_ci * Nuvoton NPCM7xx I2C Controller driver
48c2ecf20Sopenharmony_ci *
58c2ecf20Sopenharmony_ci * Copyright (C) 2020 Nuvoton Technologies tali.perry@nuvoton.com
68c2ecf20Sopenharmony_ci */
78c2ecf20Sopenharmony_ci#include <linux/bitfield.h>
88c2ecf20Sopenharmony_ci#include <linux/clk.h>
98c2ecf20Sopenharmony_ci#include <linux/debugfs.h>
108c2ecf20Sopenharmony_ci#include <linux/errno.h>
118c2ecf20Sopenharmony_ci#include <linux/i2c.h>
128c2ecf20Sopenharmony_ci#include <linux/interrupt.h>
138c2ecf20Sopenharmony_ci#include <linux/iopoll.h>
148c2ecf20Sopenharmony_ci#include <linux/irq.h>
158c2ecf20Sopenharmony_ci#include <linux/jiffies.h>
168c2ecf20Sopenharmony_ci#include <linux/kernel.h>
178c2ecf20Sopenharmony_ci#include <linux/mfd/syscon.h>
188c2ecf20Sopenharmony_ci#include <linux/module.h>
198c2ecf20Sopenharmony_ci#include <linux/of.h>
208c2ecf20Sopenharmony_ci#include <linux/platform_device.h>
218c2ecf20Sopenharmony_ci#include <linux/regmap.h>
228c2ecf20Sopenharmony_ci
238c2ecf20Sopenharmony_cienum i2c_mode {
248c2ecf20Sopenharmony_ci	I2C_MASTER,
258c2ecf20Sopenharmony_ci	I2C_SLAVE,
268c2ecf20Sopenharmony_ci};
278c2ecf20Sopenharmony_ci
288c2ecf20Sopenharmony_ci/*
298c2ecf20Sopenharmony_ci * External I2C Interface driver xfer indication values, which indicate status
308c2ecf20Sopenharmony_ci * of the bus.
318c2ecf20Sopenharmony_ci */
328c2ecf20Sopenharmony_cienum i2c_state_ind {
338c2ecf20Sopenharmony_ci	I2C_NO_STATUS_IND = 0,
348c2ecf20Sopenharmony_ci	I2C_SLAVE_RCV_IND,
358c2ecf20Sopenharmony_ci	I2C_SLAVE_XMIT_IND,
368c2ecf20Sopenharmony_ci	I2C_SLAVE_XMIT_MISSING_DATA_IND,
378c2ecf20Sopenharmony_ci	I2C_SLAVE_RESTART_IND,
388c2ecf20Sopenharmony_ci	I2C_SLAVE_DONE_IND,
398c2ecf20Sopenharmony_ci	I2C_MASTER_DONE_IND,
408c2ecf20Sopenharmony_ci	I2C_NACK_IND,
418c2ecf20Sopenharmony_ci	I2C_BUS_ERR_IND,
428c2ecf20Sopenharmony_ci	I2C_WAKE_UP_IND,
438c2ecf20Sopenharmony_ci	I2C_BLOCK_BYTES_ERR_IND,
448c2ecf20Sopenharmony_ci	I2C_SLAVE_RCV_MISSING_DATA_IND,
458c2ecf20Sopenharmony_ci};
468c2ecf20Sopenharmony_ci
478c2ecf20Sopenharmony_ci/*
488c2ecf20Sopenharmony_ci * Operation type values (used to define the operation currently running)
498c2ecf20Sopenharmony_ci * module is interrupt driven, on each interrupt the current operation is
508c2ecf20Sopenharmony_ci * checked to see if the module is currently reading or writing.
518c2ecf20Sopenharmony_ci */
528c2ecf20Sopenharmony_cienum i2c_oper {
538c2ecf20Sopenharmony_ci	I2C_NO_OPER = 0,
548c2ecf20Sopenharmony_ci	I2C_WRITE_OPER,
558c2ecf20Sopenharmony_ci	I2C_READ_OPER,
568c2ecf20Sopenharmony_ci};
578c2ecf20Sopenharmony_ci
588c2ecf20Sopenharmony_ci/* I2C Bank (module had 2 banks of registers) */
598c2ecf20Sopenharmony_cienum i2c_bank {
608c2ecf20Sopenharmony_ci	I2C_BANK_0 = 0,
618c2ecf20Sopenharmony_ci	I2C_BANK_1,
628c2ecf20Sopenharmony_ci};
638c2ecf20Sopenharmony_ci
648c2ecf20Sopenharmony_ci/* Internal I2C states values (for the I2C module state machine). */
658c2ecf20Sopenharmony_cienum i2c_state {
668c2ecf20Sopenharmony_ci	I2C_DISABLE = 0,
678c2ecf20Sopenharmony_ci	I2C_IDLE,
688c2ecf20Sopenharmony_ci	I2C_MASTER_START,
698c2ecf20Sopenharmony_ci	I2C_SLAVE_MATCH,
708c2ecf20Sopenharmony_ci	I2C_OPER_STARTED,
718c2ecf20Sopenharmony_ci	I2C_STOP_PENDING,
728c2ecf20Sopenharmony_ci};
738c2ecf20Sopenharmony_ci
748c2ecf20Sopenharmony_ci#if IS_ENABLED(CONFIG_I2C_SLAVE)
758c2ecf20Sopenharmony_ci/* Module supports setting multiple own slave addresses */
768c2ecf20Sopenharmony_cienum i2c_addr {
778c2ecf20Sopenharmony_ci	I2C_SLAVE_ADDR1 = 0,
788c2ecf20Sopenharmony_ci	I2C_SLAVE_ADDR2,
798c2ecf20Sopenharmony_ci	I2C_SLAVE_ADDR3,
808c2ecf20Sopenharmony_ci	I2C_SLAVE_ADDR4,
818c2ecf20Sopenharmony_ci	I2C_SLAVE_ADDR5,
828c2ecf20Sopenharmony_ci	I2C_SLAVE_ADDR6,
838c2ecf20Sopenharmony_ci	I2C_SLAVE_ADDR7,
848c2ecf20Sopenharmony_ci	I2C_SLAVE_ADDR8,
858c2ecf20Sopenharmony_ci	I2C_SLAVE_ADDR9,
868c2ecf20Sopenharmony_ci	I2C_SLAVE_ADDR10,
878c2ecf20Sopenharmony_ci	I2C_GC_ADDR,
888c2ecf20Sopenharmony_ci	I2C_ARP_ADDR,
898c2ecf20Sopenharmony_ci};
908c2ecf20Sopenharmony_ci#endif
918c2ecf20Sopenharmony_ci
928c2ecf20Sopenharmony_ci/* init register and default value required to enable module */
938c2ecf20Sopenharmony_ci#define NPCM_I2CSEGCTL			0xE4
948c2ecf20Sopenharmony_ci#define NPCM_I2CSEGCTL_INIT_VAL		0x0333F000
958c2ecf20Sopenharmony_ci
968c2ecf20Sopenharmony_ci/* Common regs */
978c2ecf20Sopenharmony_ci#define NPCM_I2CSDA			0x00
988c2ecf20Sopenharmony_ci#define NPCM_I2CST			0x02
998c2ecf20Sopenharmony_ci#define NPCM_I2CCST			0x04
1008c2ecf20Sopenharmony_ci#define NPCM_I2CCTL1			0x06
1018c2ecf20Sopenharmony_ci#define NPCM_I2CADDR1			0x08
1028c2ecf20Sopenharmony_ci#define NPCM_I2CCTL2			0x0A
1038c2ecf20Sopenharmony_ci#define NPCM_I2CADDR2			0x0C
1048c2ecf20Sopenharmony_ci#define NPCM_I2CCTL3			0x0E
1058c2ecf20Sopenharmony_ci#define NPCM_I2CCST2			0x18
1068c2ecf20Sopenharmony_ci#define NPCM_I2CCST3			0x19
1078c2ecf20Sopenharmony_ci#define I2C_VER				0x1F
1088c2ecf20Sopenharmony_ci
1098c2ecf20Sopenharmony_ci/*BANK0 regs*/
1108c2ecf20Sopenharmony_ci#define NPCM_I2CADDR3			0x10
1118c2ecf20Sopenharmony_ci#define NPCM_I2CADDR7			0x11
1128c2ecf20Sopenharmony_ci#define NPCM_I2CADDR4			0x12
1138c2ecf20Sopenharmony_ci#define NPCM_I2CADDR8			0x13
1148c2ecf20Sopenharmony_ci#define NPCM_I2CADDR5			0x14
1158c2ecf20Sopenharmony_ci#define NPCM_I2CADDR9			0x15
1168c2ecf20Sopenharmony_ci#define NPCM_I2CADDR6			0x16
1178c2ecf20Sopenharmony_ci#define NPCM_I2CADDR10			0x17
1188c2ecf20Sopenharmony_ci
1198c2ecf20Sopenharmony_ci#if IS_ENABLED(CONFIG_I2C_SLAVE)
1208c2ecf20Sopenharmony_ci/*
1218c2ecf20Sopenharmony_ci * npcm_i2caddr array:
1228c2ecf20Sopenharmony_ci * The module supports having multiple own slave addresses.
1238c2ecf20Sopenharmony_ci * Since the addr regs are sprinkled all over the address space,
1248c2ecf20Sopenharmony_ci * use this array to get the address or each register.
1258c2ecf20Sopenharmony_ci */
1268c2ecf20Sopenharmony_ci#define I2C_NUM_OWN_ADDR 2
1278c2ecf20Sopenharmony_ci#define I2C_NUM_OWN_ADDR_SUPPORTED 2
1288c2ecf20Sopenharmony_ci
1298c2ecf20Sopenharmony_cistatic const int npcm_i2caddr[I2C_NUM_OWN_ADDR] = {
1308c2ecf20Sopenharmony_ci	NPCM_I2CADDR1, NPCM_I2CADDR2,
1318c2ecf20Sopenharmony_ci};
1328c2ecf20Sopenharmony_ci#endif
1338c2ecf20Sopenharmony_ci
1348c2ecf20Sopenharmony_ci#define NPCM_I2CCTL4			0x1A
1358c2ecf20Sopenharmony_ci#define NPCM_I2CCTL5			0x1B
1368c2ecf20Sopenharmony_ci#define NPCM_I2CSCLLT			0x1C /* SCL Low Time */
1378c2ecf20Sopenharmony_ci#define NPCM_I2CFIF_CTL			0x1D /* FIFO Control */
1388c2ecf20Sopenharmony_ci#define NPCM_I2CSCLHT			0x1E /* SCL High Time */
1398c2ecf20Sopenharmony_ci
1408c2ecf20Sopenharmony_ci/* BANK 1 regs */
1418c2ecf20Sopenharmony_ci#define NPCM_I2CFIF_CTS			0x10 /* Both FIFOs Control and Status */
1428c2ecf20Sopenharmony_ci#define NPCM_I2CTXF_CTL			0x12 /* Tx-FIFO Control */
1438c2ecf20Sopenharmony_ci#define NPCM_I2CT_OUT			0x14 /* Bus T.O. */
1448c2ecf20Sopenharmony_ci#define NPCM_I2CPEC			0x16 /* PEC Data */
1458c2ecf20Sopenharmony_ci#define NPCM_I2CTXF_STS			0x1A /* Tx-FIFO Status */
1468c2ecf20Sopenharmony_ci#define NPCM_I2CRXF_STS			0x1C /* Rx-FIFO Status */
1478c2ecf20Sopenharmony_ci#define NPCM_I2CRXF_CTL			0x1E /* Rx-FIFO Control */
1488c2ecf20Sopenharmony_ci
1498c2ecf20Sopenharmony_ci/* NPCM_I2CST reg fields */
1508c2ecf20Sopenharmony_ci#define NPCM_I2CST_XMIT			BIT(0)
1518c2ecf20Sopenharmony_ci#define NPCM_I2CST_MASTER		BIT(1)
1528c2ecf20Sopenharmony_ci#define NPCM_I2CST_NMATCH		BIT(2)
1538c2ecf20Sopenharmony_ci#define NPCM_I2CST_STASTR		BIT(3)
1548c2ecf20Sopenharmony_ci#define NPCM_I2CST_NEGACK		BIT(4)
1558c2ecf20Sopenharmony_ci#define NPCM_I2CST_BER			BIT(5)
1568c2ecf20Sopenharmony_ci#define NPCM_I2CST_SDAST		BIT(6)
1578c2ecf20Sopenharmony_ci#define NPCM_I2CST_SLVSTP		BIT(7)
1588c2ecf20Sopenharmony_ci
1598c2ecf20Sopenharmony_ci/* NPCM_I2CCST reg fields */
1608c2ecf20Sopenharmony_ci#define NPCM_I2CCST_BUSY		BIT(0)
1618c2ecf20Sopenharmony_ci#define NPCM_I2CCST_BB			BIT(1)
1628c2ecf20Sopenharmony_ci#define NPCM_I2CCST_MATCH		BIT(2)
1638c2ecf20Sopenharmony_ci#define NPCM_I2CCST_GCMATCH		BIT(3)
1648c2ecf20Sopenharmony_ci#define NPCM_I2CCST_TSDA		BIT(4)
1658c2ecf20Sopenharmony_ci#define NPCM_I2CCST_TGSCL		BIT(5)
1668c2ecf20Sopenharmony_ci#define NPCM_I2CCST_MATCHAF		BIT(6)
1678c2ecf20Sopenharmony_ci#define NPCM_I2CCST_ARPMATCH		BIT(7)
1688c2ecf20Sopenharmony_ci
1698c2ecf20Sopenharmony_ci/* NPCM_I2CCTL1 reg fields */
1708c2ecf20Sopenharmony_ci#define NPCM_I2CCTL1_START		BIT(0)
1718c2ecf20Sopenharmony_ci#define NPCM_I2CCTL1_STOP		BIT(1)
1728c2ecf20Sopenharmony_ci#define NPCM_I2CCTL1_INTEN		BIT(2)
1738c2ecf20Sopenharmony_ci#define NPCM_I2CCTL1_EOBINTE		BIT(3)
1748c2ecf20Sopenharmony_ci#define NPCM_I2CCTL1_ACK		BIT(4)
1758c2ecf20Sopenharmony_ci#define NPCM_I2CCTL1_GCMEN		BIT(5)
1768c2ecf20Sopenharmony_ci#define NPCM_I2CCTL1_NMINTE		BIT(6)
1778c2ecf20Sopenharmony_ci#define NPCM_I2CCTL1_STASTRE		BIT(7)
1788c2ecf20Sopenharmony_ci
1798c2ecf20Sopenharmony_ci/* RW1S fields (inside a RW reg): */
1808c2ecf20Sopenharmony_ci#define NPCM_I2CCTL1_RWS   \
1818c2ecf20Sopenharmony_ci	(NPCM_I2CCTL1_START | NPCM_I2CCTL1_STOP | NPCM_I2CCTL1_ACK)
1828c2ecf20Sopenharmony_ci
1838c2ecf20Sopenharmony_ci/* npcm_i2caddr reg fields */
1848c2ecf20Sopenharmony_ci#define NPCM_I2CADDR_A			GENMASK(6, 0)
1858c2ecf20Sopenharmony_ci#define NPCM_I2CADDR_SAEN		BIT(7)
1868c2ecf20Sopenharmony_ci
1878c2ecf20Sopenharmony_ci/* NPCM_I2CCTL2 reg fields */
1888c2ecf20Sopenharmony_ci#define I2CCTL2_ENABLE			BIT(0)
1898c2ecf20Sopenharmony_ci#define I2CCTL2_SCLFRQ6_0		GENMASK(7, 1)
1908c2ecf20Sopenharmony_ci
1918c2ecf20Sopenharmony_ci/* NPCM_I2CCTL3 reg fields */
1928c2ecf20Sopenharmony_ci#define I2CCTL3_SCLFRQ8_7		GENMASK(1, 0)
1938c2ecf20Sopenharmony_ci#define I2CCTL3_ARPMEN			BIT(2)
1948c2ecf20Sopenharmony_ci#define I2CCTL3_IDL_START		BIT(3)
1958c2ecf20Sopenharmony_ci#define I2CCTL3_400K_MODE		BIT(4)
1968c2ecf20Sopenharmony_ci#define I2CCTL3_BNK_SEL			BIT(5)
1978c2ecf20Sopenharmony_ci#define I2CCTL3_SDA_LVL			BIT(6)
1988c2ecf20Sopenharmony_ci#define I2CCTL3_SCL_LVL			BIT(7)
1998c2ecf20Sopenharmony_ci
2008c2ecf20Sopenharmony_ci/* NPCM_I2CCST2 reg fields */
2018c2ecf20Sopenharmony_ci#define NPCM_I2CCST2_MATCHA1F		BIT(0)
2028c2ecf20Sopenharmony_ci#define NPCM_I2CCST2_MATCHA2F		BIT(1)
2038c2ecf20Sopenharmony_ci#define NPCM_I2CCST2_MATCHA3F		BIT(2)
2048c2ecf20Sopenharmony_ci#define NPCM_I2CCST2_MATCHA4F		BIT(3)
2058c2ecf20Sopenharmony_ci#define NPCM_I2CCST2_MATCHA5F		BIT(4)
2068c2ecf20Sopenharmony_ci#define NPCM_I2CCST2_MATCHA6F		BIT(5)
2078c2ecf20Sopenharmony_ci#define NPCM_I2CCST2_MATCHA7F		BIT(5)
2088c2ecf20Sopenharmony_ci#define NPCM_I2CCST2_INTSTS		BIT(7)
2098c2ecf20Sopenharmony_ci
2108c2ecf20Sopenharmony_ci/* NPCM_I2CCST3 reg fields */
2118c2ecf20Sopenharmony_ci#define NPCM_I2CCST3_MATCHA8F		BIT(0)
2128c2ecf20Sopenharmony_ci#define NPCM_I2CCST3_MATCHA9F		BIT(1)
2138c2ecf20Sopenharmony_ci#define NPCM_I2CCST3_MATCHA10F		BIT(2)
2148c2ecf20Sopenharmony_ci#define NPCM_I2CCST3_EO_BUSY		BIT(7)
2158c2ecf20Sopenharmony_ci
2168c2ecf20Sopenharmony_ci/* NPCM_I2CCTL4 reg fields */
2178c2ecf20Sopenharmony_ci#define I2CCTL4_HLDT			GENMASK(5, 0)
2188c2ecf20Sopenharmony_ci#define I2CCTL4_LVL_WE			BIT(7)
2198c2ecf20Sopenharmony_ci
2208c2ecf20Sopenharmony_ci/* NPCM_I2CCTL5 reg fields */
2218c2ecf20Sopenharmony_ci#define I2CCTL5_DBNCT			GENMASK(3, 0)
2228c2ecf20Sopenharmony_ci
2238c2ecf20Sopenharmony_ci/* NPCM_I2CFIF_CTS reg fields */
2248c2ecf20Sopenharmony_ci#define NPCM_I2CFIF_CTS_RXF_TXE		BIT(1)
2258c2ecf20Sopenharmony_ci#define NPCM_I2CFIF_CTS_RFTE_IE		BIT(3)
2268c2ecf20Sopenharmony_ci#define NPCM_I2CFIF_CTS_CLR_FIFO	BIT(6)
2278c2ecf20Sopenharmony_ci#define NPCM_I2CFIF_CTS_SLVRSTR		BIT(7)
2288c2ecf20Sopenharmony_ci
2298c2ecf20Sopenharmony_ci/* NPCM_I2CTXF_CTL reg fields */
2308c2ecf20Sopenharmony_ci#define NPCM_I2CTXF_CTL_TX_THR		GENMASK(4, 0)
2318c2ecf20Sopenharmony_ci#define NPCM_I2CTXF_CTL_THR_TXIE	BIT(6)
2328c2ecf20Sopenharmony_ci
2338c2ecf20Sopenharmony_ci/* NPCM_I2CT_OUT reg fields */
2348c2ecf20Sopenharmony_ci#define NPCM_I2CT_OUT_TO_CKDIV		GENMASK(5, 0)
2358c2ecf20Sopenharmony_ci#define NPCM_I2CT_OUT_T_OUTIE		BIT(6)
2368c2ecf20Sopenharmony_ci#define NPCM_I2CT_OUT_T_OUTST		BIT(7)
2378c2ecf20Sopenharmony_ci
2388c2ecf20Sopenharmony_ci/* NPCM_I2CTXF_STS reg fields */
2398c2ecf20Sopenharmony_ci#define NPCM_I2CTXF_STS_TX_BYTES	GENMASK(4, 0)
2408c2ecf20Sopenharmony_ci#define NPCM_I2CTXF_STS_TX_THST		BIT(6)
2418c2ecf20Sopenharmony_ci
2428c2ecf20Sopenharmony_ci/* NPCM_I2CRXF_STS reg fields */
2438c2ecf20Sopenharmony_ci#define NPCM_I2CRXF_STS_RX_BYTES	GENMASK(4, 0)
2448c2ecf20Sopenharmony_ci#define NPCM_I2CRXF_STS_RX_THST		BIT(6)
2458c2ecf20Sopenharmony_ci
2468c2ecf20Sopenharmony_ci/* NPCM_I2CFIF_CTL reg fields */
2478c2ecf20Sopenharmony_ci#define NPCM_I2CFIF_CTL_FIFO_EN		BIT(4)
2488c2ecf20Sopenharmony_ci
2498c2ecf20Sopenharmony_ci/* NPCM_I2CRXF_CTL reg fields */
2508c2ecf20Sopenharmony_ci#define NPCM_I2CRXF_CTL_RX_THR		GENMASK(4, 0)
2518c2ecf20Sopenharmony_ci#define NPCM_I2CRXF_CTL_LAST_PEC	BIT(5)
2528c2ecf20Sopenharmony_ci#define NPCM_I2CRXF_CTL_THR_RXIE	BIT(6)
2538c2ecf20Sopenharmony_ci
2548c2ecf20Sopenharmony_ci#define I2C_HW_FIFO_SIZE		16
2558c2ecf20Sopenharmony_ci
2568c2ecf20Sopenharmony_ci/* I2C_VER reg fields */
2578c2ecf20Sopenharmony_ci#define I2C_VER_VERSION			GENMASK(6, 0)
2588c2ecf20Sopenharmony_ci#define I2C_VER_FIFO_EN			BIT(7)
2598c2ecf20Sopenharmony_ci
2608c2ecf20Sopenharmony_ci/* stall/stuck timeout in us */
2618c2ecf20Sopenharmony_ci#define DEFAULT_STALL_COUNT		25
2628c2ecf20Sopenharmony_ci
2638c2ecf20Sopenharmony_ci/* SCLFRQ field position */
2648c2ecf20Sopenharmony_ci#define SCLFRQ_0_TO_6			GENMASK(6, 0)
2658c2ecf20Sopenharmony_ci#define SCLFRQ_7_TO_8			GENMASK(8, 7)
2668c2ecf20Sopenharmony_ci
2678c2ecf20Sopenharmony_ci/* supported clk settings. values in Hz. */
2688c2ecf20Sopenharmony_ci#define I2C_FREQ_MIN_HZ			10000
2698c2ecf20Sopenharmony_ci#define I2C_FREQ_MAX_HZ			I2C_MAX_FAST_MODE_PLUS_FREQ
2708c2ecf20Sopenharmony_ci
2718c2ecf20Sopenharmony_ci/* Status of one I2C module */
2728c2ecf20Sopenharmony_cistruct npcm_i2c {
2738c2ecf20Sopenharmony_ci	struct i2c_adapter adap;
2748c2ecf20Sopenharmony_ci	struct device *dev;
2758c2ecf20Sopenharmony_ci	unsigned char __iomem *reg;
2768c2ecf20Sopenharmony_ci	spinlock_t lock;   /* IRQ synchronization */
2778c2ecf20Sopenharmony_ci	struct completion cmd_complete;
2788c2ecf20Sopenharmony_ci	int cmd_err;
2798c2ecf20Sopenharmony_ci	struct i2c_msg *msgs;
2808c2ecf20Sopenharmony_ci	int msgs_num;
2818c2ecf20Sopenharmony_ci	int num;
2828c2ecf20Sopenharmony_ci	u32 apb_clk;
2838c2ecf20Sopenharmony_ci	struct i2c_bus_recovery_info rinfo;
2848c2ecf20Sopenharmony_ci	enum i2c_state state;
2858c2ecf20Sopenharmony_ci	enum i2c_oper operation;
2868c2ecf20Sopenharmony_ci	enum i2c_mode master_or_slave;
2878c2ecf20Sopenharmony_ci	enum i2c_state_ind stop_ind;
2888c2ecf20Sopenharmony_ci	u8 dest_addr;
2898c2ecf20Sopenharmony_ci	u8 *rd_buf;
2908c2ecf20Sopenharmony_ci	u16 rd_size;
2918c2ecf20Sopenharmony_ci	u16 rd_ind;
2928c2ecf20Sopenharmony_ci	u8 *wr_buf;
2938c2ecf20Sopenharmony_ci	u16 wr_size;
2948c2ecf20Sopenharmony_ci	u16 wr_ind;
2958c2ecf20Sopenharmony_ci	bool fifo_use;
2968c2ecf20Sopenharmony_ci	u16 PEC_mask; /* PEC bit mask per slave address */
2978c2ecf20Sopenharmony_ci	bool PEC_use;
2988c2ecf20Sopenharmony_ci	bool read_block_use;
2998c2ecf20Sopenharmony_ci	unsigned long int_time_stamp;
3008c2ecf20Sopenharmony_ci	unsigned long bus_freq; /* in Hz */
3018c2ecf20Sopenharmony_ci#if IS_ENABLED(CONFIG_I2C_SLAVE)
3028c2ecf20Sopenharmony_ci	u8 own_slave_addr;
3038c2ecf20Sopenharmony_ci	struct i2c_client *slave;
3048c2ecf20Sopenharmony_ci	int slv_rd_size;
3058c2ecf20Sopenharmony_ci	int slv_rd_ind;
3068c2ecf20Sopenharmony_ci	int slv_wr_size;
3078c2ecf20Sopenharmony_ci	int slv_wr_ind;
3088c2ecf20Sopenharmony_ci	u8 slv_rd_buf[I2C_HW_FIFO_SIZE];
3098c2ecf20Sopenharmony_ci	u8 slv_wr_buf[I2C_HW_FIFO_SIZE];
3108c2ecf20Sopenharmony_ci#endif
3118c2ecf20Sopenharmony_ci	struct dentry *debugfs; /* debugfs device directory */
3128c2ecf20Sopenharmony_ci	u64 ber_cnt;
3138c2ecf20Sopenharmony_ci	u64 rec_succ_cnt;
3148c2ecf20Sopenharmony_ci	u64 rec_fail_cnt;
3158c2ecf20Sopenharmony_ci	u64 nack_cnt;
3168c2ecf20Sopenharmony_ci	u64 timeout_cnt;
3178c2ecf20Sopenharmony_ci};
3188c2ecf20Sopenharmony_ci
3198c2ecf20Sopenharmony_cistatic inline void npcm_i2c_select_bank(struct npcm_i2c *bus,
3208c2ecf20Sopenharmony_ci					enum i2c_bank bank)
3218c2ecf20Sopenharmony_ci{
3228c2ecf20Sopenharmony_ci	u8 i2cctl3 = ioread8(bus->reg + NPCM_I2CCTL3);
3238c2ecf20Sopenharmony_ci
3248c2ecf20Sopenharmony_ci	if (bank == I2C_BANK_0)
3258c2ecf20Sopenharmony_ci		i2cctl3 = i2cctl3 & ~I2CCTL3_BNK_SEL;
3268c2ecf20Sopenharmony_ci	else
3278c2ecf20Sopenharmony_ci		i2cctl3 = i2cctl3 | I2CCTL3_BNK_SEL;
3288c2ecf20Sopenharmony_ci	iowrite8(i2cctl3, bus->reg + NPCM_I2CCTL3);
3298c2ecf20Sopenharmony_ci}
3308c2ecf20Sopenharmony_ci
3318c2ecf20Sopenharmony_cistatic void npcm_i2c_init_params(struct npcm_i2c *bus)
3328c2ecf20Sopenharmony_ci{
3338c2ecf20Sopenharmony_ci	bus->stop_ind = I2C_NO_STATUS_IND;
3348c2ecf20Sopenharmony_ci	bus->rd_size = 0;
3358c2ecf20Sopenharmony_ci	bus->wr_size = 0;
3368c2ecf20Sopenharmony_ci	bus->rd_ind = 0;
3378c2ecf20Sopenharmony_ci	bus->wr_ind = 0;
3388c2ecf20Sopenharmony_ci	bus->read_block_use = false;
3398c2ecf20Sopenharmony_ci	bus->int_time_stamp = 0;
3408c2ecf20Sopenharmony_ci	bus->PEC_use = false;
3418c2ecf20Sopenharmony_ci	bus->PEC_mask = 0;
3428c2ecf20Sopenharmony_ci#if IS_ENABLED(CONFIG_I2C_SLAVE)
3438c2ecf20Sopenharmony_ci	if (bus->slave)
3448c2ecf20Sopenharmony_ci		bus->master_or_slave = I2C_SLAVE;
3458c2ecf20Sopenharmony_ci#endif
3468c2ecf20Sopenharmony_ci}
3478c2ecf20Sopenharmony_ci
3488c2ecf20Sopenharmony_cistatic inline void npcm_i2c_wr_byte(struct npcm_i2c *bus, u8 data)
3498c2ecf20Sopenharmony_ci{
3508c2ecf20Sopenharmony_ci	iowrite8(data, bus->reg + NPCM_I2CSDA);
3518c2ecf20Sopenharmony_ci}
3528c2ecf20Sopenharmony_ci
3538c2ecf20Sopenharmony_cistatic inline u8 npcm_i2c_rd_byte(struct npcm_i2c *bus)
3548c2ecf20Sopenharmony_ci{
3558c2ecf20Sopenharmony_ci	return ioread8(bus->reg + NPCM_I2CSDA);
3568c2ecf20Sopenharmony_ci}
3578c2ecf20Sopenharmony_ci
3588c2ecf20Sopenharmony_cistatic int npcm_i2c_get_SCL(struct i2c_adapter *_adap)
3598c2ecf20Sopenharmony_ci{
3608c2ecf20Sopenharmony_ci	struct npcm_i2c *bus = container_of(_adap, struct npcm_i2c, adap);
3618c2ecf20Sopenharmony_ci
3628c2ecf20Sopenharmony_ci	return !!(I2CCTL3_SCL_LVL & ioread8(bus->reg + NPCM_I2CCTL3));
3638c2ecf20Sopenharmony_ci}
3648c2ecf20Sopenharmony_ci
3658c2ecf20Sopenharmony_cistatic int npcm_i2c_get_SDA(struct i2c_adapter *_adap)
3668c2ecf20Sopenharmony_ci{
3678c2ecf20Sopenharmony_ci	struct npcm_i2c *bus = container_of(_adap, struct npcm_i2c, adap);
3688c2ecf20Sopenharmony_ci
3698c2ecf20Sopenharmony_ci	return !!(I2CCTL3_SDA_LVL & ioread8(bus->reg + NPCM_I2CCTL3));
3708c2ecf20Sopenharmony_ci}
3718c2ecf20Sopenharmony_ci
3728c2ecf20Sopenharmony_cistatic inline u16 npcm_i2c_get_index(struct npcm_i2c *bus)
3738c2ecf20Sopenharmony_ci{
3748c2ecf20Sopenharmony_ci	if (bus->operation == I2C_READ_OPER)
3758c2ecf20Sopenharmony_ci		return bus->rd_ind;
3768c2ecf20Sopenharmony_ci	if (bus->operation == I2C_WRITE_OPER)
3778c2ecf20Sopenharmony_ci		return bus->wr_ind;
3788c2ecf20Sopenharmony_ci	return 0;
3798c2ecf20Sopenharmony_ci}
3808c2ecf20Sopenharmony_ci
3818c2ecf20Sopenharmony_ci/* quick protocol (just address) */
3828c2ecf20Sopenharmony_cistatic inline bool npcm_i2c_is_quick(struct npcm_i2c *bus)
3838c2ecf20Sopenharmony_ci{
3848c2ecf20Sopenharmony_ci	return bus->wr_size == 0 && bus->rd_size == 0;
3858c2ecf20Sopenharmony_ci}
3868c2ecf20Sopenharmony_ci
3878c2ecf20Sopenharmony_cistatic void npcm_i2c_disable(struct npcm_i2c *bus)
3888c2ecf20Sopenharmony_ci{
3898c2ecf20Sopenharmony_ci	u8 i2cctl2;
3908c2ecf20Sopenharmony_ci
3918c2ecf20Sopenharmony_ci#if IS_ENABLED(CONFIG_I2C_SLAVE)
3928c2ecf20Sopenharmony_ci	int i;
3938c2ecf20Sopenharmony_ci
3948c2ecf20Sopenharmony_ci	/* Slave addresses removal */
3958c2ecf20Sopenharmony_ci	for (i = I2C_SLAVE_ADDR1; i < I2C_NUM_OWN_ADDR_SUPPORTED; i++)
3968c2ecf20Sopenharmony_ci		iowrite8(0, bus->reg + npcm_i2caddr[i]);
3978c2ecf20Sopenharmony_ci
3988c2ecf20Sopenharmony_ci#endif
3998c2ecf20Sopenharmony_ci	/* Disable module */
4008c2ecf20Sopenharmony_ci	i2cctl2 = ioread8(bus->reg + NPCM_I2CCTL2);
4018c2ecf20Sopenharmony_ci	i2cctl2 = i2cctl2 & ~I2CCTL2_ENABLE;
4028c2ecf20Sopenharmony_ci	iowrite8(i2cctl2, bus->reg + NPCM_I2CCTL2);
4038c2ecf20Sopenharmony_ci
4048c2ecf20Sopenharmony_ci	bus->state = I2C_DISABLE;
4058c2ecf20Sopenharmony_ci}
4068c2ecf20Sopenharmony_ci
4078c2ecf20Sopenharmony_cistatic void npcm_i2c_enable(struct npcm_i2c *bus)
4088c2ecf20Sopenharmony_ci{
4098c2ecf20Sopenharmony_ci	u8 i2cctl2 = ioread8(bus->reg + NPCM_I2CCTL2);
4108c2ecf20Sopenharmony_ci
4118c2ecf20Sopenharmony_ci	i2cctl2 = i2cctl2 | I2CCTL2_ENABLE;
4128c2ecf20Sopenharmony_ci	iowrite8(i2cctl2, bus->reg + NPCM_I2CCTL2);
4138c2ecf20Sopenharmony_ci	bus->state = I2C_IDLE;
4148c2ecf20Sopenharmony_ci}
4158c2ecf20Sopenharmony_ci
4168c2ecf20Sopenharmony_ci/* enable\disable end of busy (EOB) interrupts */
4178c2ecf20Sopenharmony_cistatic inline void npcm_i2c_eob_int(struct npcm_i2c *bus, bool enable)
4188c2ecf20Sopenharmony_ci{
4198c2ecf20Sopenharmony_ci	u8 val;
4208c2ecf20Sopenharmony_ci
4218c2ecf20Sopenharmony_ci	/* Clear EO_BUSY pending bit: */
4228c2ecf20Sopenharmony_ci	val = ioread8(bus->reg + NPCM_I2CCST3);
4238c2ecf20Sopenharmony_ci	val = val | NPCM_I2CCST3_EO_BUSY;
4248c2ecf20Sopenharmony_ci	iowrite8(val, bus->reg + NPCM_I2CCST3);
4258c2ecf20Sopenharmony_ci
4268c2ecf20Sopenharmony_ci	val = ioread8(bus->reg + NPCM_I2CCTL1);
4278c2ecf20Sopenharmony_ci	val &= ~NPCM_I2CCTL1_RWS;
4288c2ecf20Sopenharmony_ci	if (enable)
4298c2ecf20Sopenharmony_ci		val |= NPCM_I2CCTL1_EOBINTE;
4308c2ecf20Sopenharmony_ci	else
4318c2ecf20Sopenharmony_ci		val &= ~NPCM_I2CCTL1_EOBINTE;
4328c2ecf20Sopenharmony_ci	iowrite8(val, bus->reg + NPCM_I2CCTL1);
4338c2ecf20Sopenharmony_ci}
4348c2ecf20Sopenharmony_ci
4358c2ecf20Sopenharmony_cistatic inline bool npcm_i2c_tx_fifo_empty(struct npcm_i2c *bus)
4368c2ecf20Sopenharmony_ci{
4378c2ecf20Sopenharmony_ci	u8 tx_fifo_sts;
4388c2ecf20Sopenharmony_ci
4398c2ecf20Sopenharmony_ci	tx_fifo_sts = ioread8(bus->reg + NPCM_I2CTXF_STS);
4408c2ecf20Sopenharmony_ci	/* check if TX FIFO is not empty */
4418c2ecf20Sopenharmony_ci	if ((tx_fifo_sts & NPCM_I2CTXF_STS_TX_BYTES) == 0)
4428c2ecf20Sopenharmony_ci		return false;
4438c2ecf20Sopenharmony_ci
4448c2ecf20Sopenharmony_ci	/* check if TX FIFO status bit is set: */
4458c2ecf20Sopenharmony_ci	return !!FIELD_GET(NPCM_I2CTXF_STS_TX_THST, tx_fifo_sts);
4468c2ecf20Sopenharmony_ci}
4478c2ecf20Sopenharmony_ci
4488c2ecf20Sopenharmony_cistatic inline bool npcm_i2c_rx_fifo_full(struct npcm_i2c *bus)
4498c2ecf20Sopenharmony_ci{
4508c2ecf20Sopenharmony_ci	u8 rx_fifo_sts;
4518c2ecf20Sopenharmony_ci
4528c2ecf20Sopenharmony_ci	rx_fifo_sts = ioread8(bus->reg + NPCM_I2CRXF_STS);
4538c2ecf20Sopenharmony_ci	/* check if RX FIFO is not empty: */
4548c2ecf20Sopenharmony_ci	if ((rx_fifo_sts & NPCM_I2CRXF_STS_RX_BYTES) == 0)
4558c2ecf20Sopenharmony_ci		return false;
4568c2ecf20Sopenharmony_ci
4578c2ecf20Sopenharmony_ci	/* check if rx fifo full status is set: */
4588c2ecf20Sopenharmony_ci	return !!FIELD_GET(NPCM_I2CRXF_STS_RX_THST, rx_fifo_sts);
4598c2ecf20Sopenharmony_ci}
4608c2ecf20Sopenharmony_ci
4618c2ecf20Sopenharmony_cistatic inline void npcm_i2c_clear_fifo_int(struct npcm_i2c *bus)
4628c2ecf20Sopenharmony_ci{
4638c2ecf20Sopenharmony_ci	u8 val;
4648c2ecf20Sopenharmony_ci
4658c2ecf20Sopenharmony_ci	val = ioread8(bus->reg + NPCM_I2CFIF_CTS);
4668c2ecf20Sopenharmony_ci	val = (val & NPCM_I2CFIF_CTS_SLVRSTR) | NPCM_I2CFIF_CTS_RXF_TXE;
4678c2ecf20Sopenharmony_ci	iowrite8(val, bus->reg + NPCM_I2CFIF_CTS);
4688c2ecf20Sopenharmony_ci}
4698c2ecf20Sopenharmony_ci
4708c2ecf20Sopenharmony_cistatic inline void npcm_i2c_clear_tx_fifo(struct npcm_i2c *bus)
4718c2ecf20Sopenharmony_ci{
4728c2ecf20Sopenharmony_ci	u8 val;
4738c2ecf20Sopenharmony_ci
4748c2ecf20Sopenharmony_ci	val = ioread8(bus->reg + NPCM_I2CTXF_STS);
4758c2ecf20Sopenharmony_ci	val = val | NPCM_I2CTXF_STS_TX_THST;
4768c2ecf20Sopenharmony_ci	iowrite8(val, bus->reg + NPCM_I2CTXF_STS);
4778c2ecf20Sopenharmony_ci}
4788c2ecf20Sopenharmony_ci
4798c2ecf20Sopenharmony_cistatic inline void npcm_i2c_clear_rx_fifo(struct npcm_i2c *bus)
4808c2ecf20Sopenharmony_ci{
4818c2ecf20Sopenharmony_ci	u8 val;
4828c2ecf20Sopenharmony_ci
4838c2ecf20Sopenharmony_ci	val = ioread8(bus->reg + NPCM_I2CRXF_STS);
4848c2ecf20Sopenharmony_ci	val = val | NPCM_I2CRXF_STS_RX_THST;
4858c2ecf20Sopenharmony_ci	iowrite8(val, bus->reg + NPCM_I2CRXF_STS);
4868c2ecf20Sopenharmony_ci}
4878c2ecf20Sopenharmony_ci
4888c2ecf20Sopenharmony_cistatic void npcm_i2c_int_enable(struct npcm_i2c *bus, bool enable)
4898c2ecf20Sopenharmony_ci{
4908c2ecf20Sopenharmony_ci	u8 val;
4918c2ecf20Sopenharmony_ci
4928c2ecf20Sopenharmony_ci	val = ioread8(bus->reg + NPCM_I2CCTL1);
4938c2ecf20Sopenharmony_ci	val &= ~NPCM_I2CCTL1_RWS;
4948c2ecf20Sopenharmony_ci	if (enable)
4958c2ecf20Sopenharmony_ci		val |= NPCM_I2CCTL1_INTEN;
4968c2ecf20Sopenharmony_ci	else
4978c2ecf20Sopenharmony_ci		val &= ~NPCM_I2CCTL1_INTEN;
4988c2ecf20Sopenharmony_ci	iowrite8(val, bus->reg + NPCM_I2CCTL1);
4998c2ecf20Sopenharmony_ci}
5008c2ecf20Sopenharmony_ci
5018c2ecf20Sopenharmony_cistatic inline void npcm_i2c_master_start(struct npcm_i2c *bus)
5028c2ecf20Sopenharmony_ci{
5038c2ecf20Sopenharmony_ci	u8 val;
5048c2ecf20Sopenharmony_ci
5058c2ecf20Sopenharmony_ci	val = ioread8(bus->reg + NPCM_I2CCTL1);
5068c2ecf20Sopenharmony_ci	val &= ~(NPCM_I2CCTL1_STOP | NPCM_I2CCTL1_ACK);
5078c2ecf20Sopenharmony_ci	val |= NPCM_I2CCTL1_START;
5088c2ecf20Sopenharmony_ci	iowrite8(val, bus->reg + NPCM_I2CCTL1);
5098c2ecf20Sopenharmony_ci}
5108c2ecf20Sopenharmony_ci
5118c2ecf20Sopenharmony_cistatic inline void npcm_i2c_master_stop(struct npcm_i2c *bus)
5128c2ecf20Sopenharmony_ci{
5138c2ecf20Sopenharmony_ci	u8 val;
5148c2ecf20Sopenharmony_ci
5158c2ecf20Sopenharmony_ci	/*
5168c2ecf20Sopenharmony_ci	 * override HW issue: I2C may fail to supply stop condition in Master
5178c2ecf20Sopenharmony_ci	 * Write operation.
5188c2ecf20Sopenharmony_ci	 * Need to delay at least 5 us from the last int, before issueing a stop
5198c2ecf20Sopenharmony_ci	 */
5208c2ecf20Sopenharmony_ci	udelay(10); /* function called from interrupt, can't sleep */
5218c2ecf20Sopenharmony_ci	val = ioread8(bus->reg + NPCM_I2CCTL1);
5228c2ecf20Sopenharmony_ci	val &= ~(NPCM_I2CCTL1_START | NPCM_I2CCTL1_ACK);
5238c2ecf20Sopenharmony_ci	val |= NPCM_I2CCTL1_STOP;
5248c2ecf20Sopenharmony_ci	iowrite8(val, bus->reg + NPCM_I2CCTL1);
5258c2ecf20Sopenharmony_ci
5268c2ecf20Sopenharmony_ci	if (!bus->fifo_use)
5278c2ecf20Sopenharmony_ci		return;
5288c2ecf20Sopenharmony_ci
5298c2ecf20Sopenharmony_ci	npcm_i2c_select_bank(bus, I2C_BANK_1);
5308c2ecf20Sopenharmony_ci
5318c2ecf20Sopenharmony_ci	if (bus->operation == I2C_READ_OPER)
5328c2ecf20Sopenharmony_ci		npcm_i2c_clear_rx_fifo(bus);
5338c2ecf20Sopenharmony_ci	else
5348c2ecf20Sopenharmony_ci		npcm_i2c_clear_tx_fifo(bus);
5358c2ecf20Sopenharmony_ci	npcm_i2c_clear_fifo_int(bus);
5368c2ecf20Sopenharmony_ci	iowrite8(0, bus->reg + NPCM_I2CTXF_CTL);
5378c2ecf20Sopenharmony_ci}
5388c2ecf20Sopenharmony_ci
5398c2ecf20Sopenharmony_cistatic inline void npcm_i2c_stall_after_start(struct npcm_i2c *bus, bool stall)
5408c2ecf20Sopenharmony_ci{
5418c2ecf20Sopenharmony_ci	u8 val;
5428c2ecf20Sopenharmony_ci
5438c2ecf20Sopenharmony_ci	val = ioread8(bus->reg + NPCM_I2CCTL1);
5448c2ecf20Sopenharmony_ci	val &= ~NPCM_I2CCTL1_RWS;
5458c2ecf20Sopenharmony_ci	if (stall)
5468c2ecf20Sopenharmony_ci		val |= NPCM_I2CCTL1_STASTRE;
5478c2ecf20Sopenharmony_ci	else
5488c2ecf20Sopenharmony_ci		val &= ~NPCM_I2CCTL1_STASTRE;
5498c2ecf20Sopenharmony_ci	iowrite8(val, bus->reg + NPCM_I2CCTL1);
5508c2ecf20Sopenharmony_ci}
5518c2ecf20Sopenharmony_ci
5528c2ecf20Sopenharmony_cistatic inline void npcm_i2c_nack(struct npcm_i2c *bus)
5538c2ecf20Sopenharmony_ci{
5548c2ecf20Sopenharmony_ci	u8 val;
5558c2ecf20Sopenharmony_ci
5568c2ecf20Sopenharmony_ci	val = ioread8(bus->reg + NPCM_I2CCTL1);
5578c2ecf20Sopenharmony_ci	val &= ~(NPCM_I2CCTL1_STOP | NPCM_I2CCTL1_START);
5588c2ecf20Sopenharmony_ci	val |= NPCM_I2CCTL1_ACK;
5598c2ecf20Sopenharmony_ci	iowrite8(val, bus->reg + NPCM_I2CCTL1);
5608c2ecf20Sopenharmony_ci}
5618c2ecf20Sopenharmony_ci
5628c2ecf20Sopenharmony_cistatic inline void npcm_i2c_clear_master_status(struct npcm_i2c *bus)
5638c2ecf20Sopenharmony_ci{
5648c2ecf20Sopenharmony_ci	u8 val;
5658c2ecf20Sopenharmony_ci
5668c2ecf20Sopenharmony_ci	/* Clear NEGACK, STASTR and BER bits */
5678c2ecf20Sopenharmony_ci	val = NPCM_I2CST_BER | NPCM_I2CST_NEGACK | NPCM_I2CST_STASTR;
5688c2ecf20Sopenharmony_ci	iowrite8(val, bus->reg + NPCM_I2CST);
5698c2ecf20Sopenharmony_ci}
5708c2ecf20Sopenharmony_ci
5718c2ecf20Sopenharmony_ci#if IS_ENABLED(CONFIG_I2C_SLAVE)
5728c2ecf20Sopenharmony_cistatic void npcm_i2c_slave_int_enable(struct npcm_i2c *bus, bool enable)
5738c2ecf20Sopenharmony_ci{
5748c2ecf20Sopenharmony_ci	u8 i2cctl1;
5758c2ecf20Sopenharmony_ci
5768c2ecf20Sopenharmony_ci	/* enable interrupt on slave match: */
5778c2ecf20Sopenharmony_ci	i2cctl1 = ioread8(bus->reg + NPCM_I2CCTL1);
5788c2ecf20Sopenharmony_ci	i2cctl1 &= ~NPCM_I2CCTL1_RWS;
5798c2ecf20Sopenharmony_ci	if (enable)
5808c2ecf20Sopenharmony_ci		i2cctl1 |= NPCM_I2CCTL1_NMINTE;
5818c2ecf20Sopenharmony_ci	else
5828c2ecf20Sopenharmony_ci		i2cctl1 &= ~NPCM_I2CCTL1_NMINTE;
5838c2ecf20Sopenharmony_ci	iowrite8(i2cctl1, bus->reg + NPCM_I2CCTL1);
5848c2ecf20Sopenharmony_ci}
5858c2ecf20Sopenharmony_ci
5868c2ecf20Sopenharmony_cistatic int npcm_i2c_slave_enable(struct npcm_i2c *bus, enum i2c_addr addr_type,
5878c2ecf20Sopenharmony_ci				 u8 addr, bool enable)
5888c2ecf20Sopenharmony_ci{
5898c2ecf20Sopenharmony_ci	u8 i2cctl1;
5908c2ecf20Sopenharmony_ci	u8 i2cctl3;
5918c2ecf20Sopenharmony_ci	u8 sa_reg;
5928c2ecf20Sopenharmony_ci
5938c2ecf20Sopenharmony_ci	sa_reg = (addr & 0x7F) | FIELD_PREP(NPCM_I2CADDR_SAEN, enable);
5948c2ecf20Sopenharmony_ci	if (addr_type == I2C_GC_ADDR) {
5958c2ecf20Sopenharmony_ci		i2cctl1 = ioread8(bus->reg + NPCM_I2CCTL1);
5968c2ecf20Sopenharmony_ci		if (enable)
5978c2ecf20Sopenharmony_ci			i2cctl1 |= NPCM_I2CCTL1_GCMEN;
5988c2ecf20Sopenharmony_ci		else
5998c2ecf20Sopenharmony_ci			i2cctl1 &= ~NPCM_I2CCTL1_GCMEN;
6008c2ecf20Sopenharmony_ci		iowrite8(i2cctl1, bus->reg + NPCM_I2CCTL1);
6018c2ecf20Sopenharmony_ci		return 0;
6028c2ecf20Sopenharmony_ci	} else if (addr_type == I2C_ARP_ADDR) {
6038c2ecf20Sopenharmony_ci		i2cctl3 = ioread8(bus->reg + NPCM_I2CCTL3);
6048c2ecf20Sopenharmony_ci		if (enable)
6058c2ecf20Sopenharmony_ci			i2cctl3 |= I2CCTL3_ARPMEN;
6068c2ecf20Sopenharmony_ci		else
6078c2ecf20Sopenharmony_ci			i2cctl3 &= ~I2CCTL3_ARPMEN;
6088c2ecf20Sopenharmony_ci		iowrite8(i2cctl3, bus->reg + NPCM_I2CCTL3);
6098c2ecf20Sopenharmony_ci		return 0;
6108c2ecf20Sopenharmony_ci	}
6118c2ecf20Sopenharmony_ci	if (addr_type > I2C_SLAVE_ADDR2 && addr_type <= I2C_SLAVE_ADDR10)
6128c2ecf20Sopenharmony_ci		dev_err(bus->dev, "try to enable more than 2 SA not supported\n");
6138c2ecf20Sopenharmony_ci
6148c2ecf20Sopenharmony_ci	if (addr_type >= I2C_ARP_ADDR)
6158c2ecf20Sopenharmony_ci		return -EFAULT;
6168c2ecf20Sopenharmony_ci
6178c2ecf20Sopenharmony_ci	/* Set and enable the address */
6188c2ecf20Sopenharmony_ci	iowrite8(sa_reg, bus->reg + npcm_i2caddr[addr_type]);
6198c2ecf20Sopenharmony_ci	npcm_i2c_slave_int_enable(bus, enable);
6208c2ecf20Sopenharmony_ci
6218c2ecf20Sopenharmony_ci	return 0;
6228c2ecf20Sopenharmony_ci}
6238c2ecf20Sopenharmony_ci#endif
6248c2ecf20Sopenharmony_ci
6258c2ecf20Sopenharmony_cistatic void npcm_i2c_reset(struct npcm_i2c *bus)
6268c2ecf20Sopenharmony_ci{
6278c2ecf20Sopenharmony_ci	/*
6288c2ecf20Sopenharmony_ci	 * Save I2CCTL1 relevant bits. It is being cleared when the module
6298c2ecf20Sopenharmony_ci	 *  is disabled.
6308c2ecf20Sopenharmony_ci	 */
6318c2ecf20Sopenharmony_ci	u8 i2cctl1;
6328c2ecf20Sopenharmony_ci#if IS_ENABLED(CONFIG_I2C_SLAVE)
6338c2ecf20Sopenharmony_ci	u8 addr;
6348c2ecf20Sopenharmony_ci#endif
6358c2ecf20Sopenharmony_ci
6368c2ecf20Sopenharmony_ci	i2cctl1 = ioread8(bus->reg + NPCM_I2CCTL1);
6378c2ecf20Sopenharmony_ci
6388c2ecf20Sopenharmony_ci	npcm_i2c_disable(bus);
6398c2ecf20Sopenharmony_ci	npcm_i2c_enable(bus);
6408c2ecf20Sopenharmony_ci
6418c2ecf20Sopenharmony_ci	/* Restore NPCM_I2CCTL1 Status */
6428c2ecf20Sopenharmony_ci	i2cctl1 &= ~NPCM_I2CCTL1_RWS;
6438c2ecf20Sopenharmony_ci	iowrite8(i2cctl1, bus->reg + NPCM_I2CCTL1);
6448c2ecf20Sopenharmony_ci
6458c2ecf20Sopenharmony_ci	/* Clear BB (BUS BUSY) bit */
6468c2ecf20Sopenharmony_ci	iowrite8(NPCM_I2CCST_BB, bus->reg + NPCM_I2CCST);
6478c2ecf20Sopenharmony_ci	iowrite8(0xFF, bus->reg + NPCM_I2CST);
6488c2ecf20Sopenharmony_ci
6498c2ecf20Sopenharmony_ci	/* Clear and disable EOB */
6508c2ecf20Sopenharmony_ci	npcm_i2c_eob_int(bus, false);
6518c2ecf20Sopenharmony_ci
6528c2ecf20Sopenharmony_ci	/* Clear all fifo bits: */
6538c2ecf20Sopenharmony_ci	iowrite8(NPCM_I2CFIF_CTS_CLR_FIFO, bus->reg + NPCM_I2CFIF_CTS);
6548c2ecf20Sopenharmony_ci
6558c2ecf20Sopenharmony_ci#if IS_ENABLED(CONFIG_I2C_SLAVE)
6568c2ecf20Sopenharmony_ci	if (bus->slave) {
6578c2ecf20Sopenharmony_ci		addr = bus->slave->addr;
6588c2ecf20Sopenharmony_ci		npcm_i2c_slave_enable(bus, I2C_SLAVE_ADDR1, addr, true);
6598c2ecf20Sopenharmony_ci	}
6608c2ecf20Sopenharmony_ci#endif
6618c2ecf20Sopenharmony_ci
6628c2ecf20Sopenharmony_ci	/* clear status bits for spurious interrupts */
6638c2ecf20Sopenharmony_ci	npcm_i2c_clear_master_status(bus);
6648c2ecf20Sopenharmony_ci
6658c2ecf20Sopenharmony_ci	bus->state = I2C_IDLE;
6668c2ecf20Sopenharmony_ci}
6678c2ecf20Sopenharmony_ci
6688c2ecf20Sopenharmony_cistatic inline bool npcm_i2c_is_master(struct npcm_i2c *bus)
6698c2ecf20Sopenharmony_ci{
6708c2ecf20Sopenharmony_ci	return !!FIELD_GET(NPCM_I2CST_MASTER, ioread8(bus->reg + NPCM_I2CST));
6718c2ecf20Sopenharmony_ci}
6728c2ecf20Sopenharmony_ci
6738c2ecf20Sopenharmony_cistatic void npcm_i2c_callback(struct npcm_i2c *bus,
6748c2ecf20Sopenharmony_ci			      enum i2c_state_ind op_status, u16 info)
6758c2ecf20Sopenharmony_ci{
6768c2ecf20Sopenharmony_ci	struct i2c_msg *msgs;
6778c2ecf20Sopenharmony_ci	int msgs_num;
6788c2ecf20Sopenharmony_ci	bool do_complete = false;
6798c2ecf20Sopenharmony_ci
6808c2ecf20Sopenharmony_ci	msgs = bus->msgs;
6818c2ecf20Sopenharmony_ci	msgs_num = bus->msgs_num;
6828c2ecf20Sopenharmony_ci	/*
6838c2ecf20Sopenharmony_ci	 * check that transaction was not timed-out, and msgs still
6848c2ecf20Sopenharmony_ci	 * holds a valid value.
6858c2ecf20Sopenharmony_ci	 */
6868c2ecf20Sopenharmony_ci	if (!msgs)
6878c2ecf20Sopenharmony_ci		return;
6888c2ecf20Sopenharmony_ci
6898c2ecf20Sopenharmony_ci	if (completion_done(&bus->cmd_complete))
6908c2ecf20Sopenharmony_ci		return;
6918c2ecf20Sopenharmony_ci
6928c2ecf20Sopenharmony_ci	switch (op_status) {
6938c2ecf20Sopenharmony_ci	case I2C_MASTER_DONE_IND:
6948c2ecf20Sopenharmony_ci		bus->cmd_err = bus->msgs_num;
6958c2ecf20Sopenharmony_ci		fallthrough;
6968c2ecf20Sopenharmony_ci	case I2C_BLOCK_BYTES_ERR_IND:
6978c2ecf20Sopenharmony_ci		/* Master tx finished and all transmit bytes were sent */
6988c2ecf20Sopenharmony_ci		if (bus->msgs) {
6998c2ecf20Sopenharmony_ci			if (msgs[0].flags & I2C_M_RD)
7008c2ecf20Sopenharmony_ci				msgs[0].len = info;
7018c2ecf20Sopenharmony_ci			else if (msgs_num == 2 &&
7028c2ecf20Sopenharmony_ci				 msgs[1].flags & I2C_M_RD)
7038c2ecf20Sopenharmony_ci				msgs[1].len = info;
7048c2ecf20Sopenharmony_ci		}
7058c2ecf20Sopenharmony_ci		do_complete = true;
7068c2ecf20Sopenharmony_ci		break;
7078c2ecf20Sopenharmony_ci	case I2C_NACK_IND:
7088c2ecf20Sopenharmony_ci		/* MASTER transmit got a NACK before tx all bytes */
7098c2ecf20Sopenharmony_ci		bus->cmd_err = -ENXIO;
7108c2ecf20Sopenharmony_ci		do_complete = true;
7118c2ecf20Sopenharmony_ci		break;
7128c2ecf20Sopenharmony_ci	case I2C_BUS_ERR_IND:
7138c2ecf20Sopenharmony_ci		/* Bus error */
7148c2ecf20Sopenharmony_ci		bus->cmd_err = -EAGAIN;
7158c2ecf20Sopenharmony_ci		do_complete = true;
7168c2ecf20Sopenharmony_ci		break;
7178c2ecf20Sopenharmony_ci	case I2C_WAKE_UP_IND:
7188c2ecf20Sopenharmony_ci		/* I2C wake up */
7198c2ecf20Sopenharmony_ci		break;
7208c2ecf20Sopenharmony_ci	default:
7218c2ecf20Sopenharmony_ci		break;
7228c2ecf20Sopenharmony_ci	}
7238c2ecf20Sopenharmony_ci
7248c2ecf20Sopenharmony_ci	bus->operation = I2C_NO_OPER;
7258c2ecf20Sopenharmony_ci#if IS_ENABLED(CONFIG_I2C_SLAVE)
7268c2ecf20Sopenharmony_ci	if (bus->slave)
7278c2ecf20Sopenharmony_ci		bus->master_or_slave = I2C_SLAVE;
7288c2ecf20Sopenharmony_ci#endif
7298c2ecf20Sopenharmony_ci	if (do_complete)
7308c2ecf20Sopenharmony_ci		complete(&bus->cmd_complete);
7318c2ecf20Sopenharmony_ci}
7328c2ecf20Sopenharmony_ci
7338c2ecf20Sopenharmony_cistatic u8 npcm_i2c_fifo_usage(struct npcm_i2c *bus)
7348c2ecf20Sopenharmony_ci{
7358c2ecf20Sopenharmony_ci	if (bus->operation == I2C_WRITE_OPER)
7368c2ecf20Sopenharmony_ci		return FIELD_GET(NPCM_I2CTXF_STS_TX_BYTES,
7378c2ecf20Sopenharmony_ci				 ioread8(bus->reg + NPCM_I2CTXF_STS));
7388c2ecf20Sopenharmony_ci	if (bus->operation == I2C_READ_OPER)
7398c2ecf20Sopenharmony_ci		return FIELD_GET(NPCM_I2CRXF_STS_RX_BYTES,
7408c2ecf20Sopenharmony_ci				 ioread8(bus->reg + NPCM_I2CRXF_STS));
7418c2ecf20Sopenharmony_ci	return 0;
7428c2ecf20Sopenharmony_ci}
7438c2ecf20Sopenharmony_ci
7448c2ecf20Sopenharmony_cistatic void npcm_i2c_write_to_fifo_master(struct npcm_i2c *bus, u16 max_bytes)
7458c2ecf20Sopenharmony_ci{
7468c2ecf20Sopenharmony_ci	u8 size_free_fifo;
7478c2ecf20Sopenharmony_ci
7488c2ecf20Sopenharmony_ci	/*
7498c2ecf20Sopenharmony_ci	 * Fill the FIFO, while the FIFO is not full and there are more bytes
7508c2ecf20Sopenharmony_ci	 * to write
7518c2ecf20Sopenharmony_ci	 */
7528c2ecf20Sopenharmony_ci	size_free_fifo = I2C_HW_FIFO_SIZE - npcm_i2c_fifo_usage(bus);
7538c2ecf20Sopenharmony_ci	while (max_bytes-- && size_free_fifo) {
7548c2ecf20Sopenharmony_ci		if (bus->wr_ind < bus->wr_size)
7558c2ecf20Sopenharmony_ci			npcm_i2c_wr_byte(bus, bus->wr_buf[bus->wr_ind++]);
7568c2ecf20Sopenharmony_ci		else
7578c2ecf20Sopenharmony_ci			npcm_i2c_wr_byte(bus, 0xFF);
7588c2ecf20Sopenharmony_ci		size_free_fifo = I2C_HW_FIFO_SIZE - npcm_i2c_fifo_usage(bus);
7598c2ecf20Sopenharmony_ci	}
7608c2ecf20Sopenharmony_ci}
7618c2ecf20Sopenharmony_ci
7628c2ecf20Sopenharmony_ci/*
7638c2ecf20Sopenharmony_ci * npcm_i2c_set_fifo:
7648c2ecf20Sopenharmony_ci * configure the FIFO before using it. If nread is -1 RX FIFO will not be
7658c2ecf20Sopenharmony_ci * configured. same for nwrite
7668c2ecf20Sopenharmony_ci */
7678c2ecf20Sopenharmony_cistatic void npcm_i2c_set_fifo(struct npcm_i2c *bus, int nread, int nwrite)
7688c2ecf20Sopenharmony_ci{
7698c2ecf20Sopenharmony_ci	u8 rxf_ctl = 0;
7708c2ecf20Sopenharmony_ci
7718c2ecf20Sopenharmony_ci	if (!bus->fifo_use)
7728c2ecf20Sopenharmony_ci		return;
7738c2ecf20Sopenharmony_ci	npcm_i2c_select_bank(bus, I2C_BANK_1);
7748c2ecf20Sopenharmony_ci	npcm_i2c_clear_tx_fifo(bus);
7758c2ecf20Sopenharmony_ci	npcm_i2c_clear_rx_fifo(bus);
7768c2ecf20Sopenharmony_ci
7778c2ecf20Sopenharmony_ci	/* configure RX FIFO */
7788c2ecf20Sopenharmony_ci	if (nread > 0) {
7798c2ecf20Sopenharmony_ci		rxf_ctl = min_t(int, nread, I2C_HW_FIFO_SIZE);
7808c2ecf20Sopenharmony_ci
7818c2ecf20Sopenharmony_ci		/* set LAST bit. if LAST is set next FIFO packet is nacked */
7828c2ecf20Sopenharmony_ci		if (nread <= I2C_HW_FIFO_SIZE)
7838c2ecf20Sopenharmony_ci			rxf_ctl |= NPCM_I2CRXF_CTL_LAST_PEC;
7848c2ecf20Sopenharmony_ci
7858c2ecf20Sopenharmony_ci		/*
7868c2ecf20Sopenharmony_ci		 * if we are about to read the first byte in blk rd mode,
7878c2ecf20Sopenharmony_ci		 * don't NACK it. If slave returns zero size HW can't NACK
7888c2ecf20Sopenharmony_ci		 * it immidiattly, it will read extra byte and then NACK.
7898c2ecf20Sopenharmony_ci		 */
7908c2ecf20Sopenharmony_ci		if (bus->rd_ind == 0 && bus->read_block_use) {
7918c2ecf20Sopenharmony_ci			/* set fifo to read one byte, no last: */
7928c2ecf20Sopenharmony_ci			rxf_ctl = 1;
7938c2ecf20Sopenharmony_ci		}
7948c2ecf20Sopenharmony_ci
7958c2ecf20Sopenharmony_ci		/* set fifo size: */
7968c2ecf20Sopenharmony_ci		iowrite8(rxf_ctl, bus->reg + NPCM_I2CRXF_CTL);
7978c2ecf20Sopenharmony_ci	}
7988c2ecf20Sopenharmony_ci
7998c2ecf20Sopenharmony_ci	/* configure TX FIFO */
8008c2ecf20Sopenharmony_ci	if (nwrite > 0) {
8018c2ecf20Sopenharmony_ci		if (nwrite > I2C_HW_FIFO_SIZE)
8028c2ecf20Sopenharmony_ci			/* data to send is more then FIFO size. */
8038c2ecf20Sopenharmony_ci			iowrite8(I2C_HW_FIFO_SIZE, bus->reg + NPCM_I2CTXF_CTL);
8048c2ecf20Sopenharmony_ci		else
8058c2ecf20Sopenharmony_ci			iowrite8(nwrite, bus->reg + NPCM_I2CTXF_CTL);
8068c2ecf20Sopenharmony_ci
8078c2ecf20Sopenharmony_ci		npcm_i2c_clear_tx_fifo(bus);
8088c2ecf20Sopenharmony_ci	}
8098c2ecf20Sopenharmony_ci}
8108c2ecf20Sopenharmony_ci
8118c2ecf20Sopenharmony_cistatic void npcm_i2c_read_fifo(struct npcm_i2c *bus, u8 bytes_in_fifo)
8128c2ecf20Sopenharmony_ci{
8138c2ecf20Sopenharmony_ci	u8 data;
8148c2ecf20Sopenharmony_ci
8158c2ecf20Sopenharmony_ci	while (bytes_in_fifo--) {
8168c2ecf20Sopenharmony_ci		data = npcm_i2c_rd_byte(bus);
8178c2ecf20Sopenharmony_ci		if (bus->rd_ind < bus->rd_size)
8188c2ecf20Sopenharmony_ci			bus->rd_buf[bus->rd_ind++] = data;
8198c2ecf20Sopenharmony_ci	}
8208c2ecf20Sopenharmony_ci}
8218c2ecf20Sopenharmony_ci
8228c2ecf20Sopenharmony_cistatic void npcm_i2c_master_abort(struct npcm_i2c *bus)
8238c2ecf20Sopenharmony_ci{
8248c2ecf20Sopenharmony_ci	/* Only current master is allowed to issue a stop condition */
8258c2ecf20Sopenharmony_ci	if (!npcm_i2c_is_master(bus))
8268c2ecf20Sopenharmony_ci		return;
8278c2ecf20Sopenharmony_ci
8288c2ecf20Sopenharmony_ci	npcm_i2c_eob_int(bus, true);
8298c2ecf20Sopenharmony_ci	npcm_i2c_master_stop(bus);
8308c2ecf20Sopenharmony_ci	npcm_i2c_clear_master_status(bus);
8318c2ecf20Sopenharmony_ci}
8328c2ecf20Sopenharmony_ci
8338c2ecf20Sopenharmony_ci#if IS_ENABLED(CONFIG_I2C_SLAVE)
8348c2ecf20Sopenharmony_cistatic u8 npcm_i2c_get_slave_addr(struct npcm_i2c *bus, enum i2c_addr addr_type)
8358c2ecf20Sopenharmony_ci{
8368c2ecf20Sopenharmony_ci	u8 slave_add;
8378c2ecf20Sopenharmony_ci
8388c2ecf20Sopenharmony_ci	if (addr_type > I2C_SLAVE_ADDR2 && addr_type <= I2C_SLAVE_ADDR10)
8398c2ecf20Sopenharmony_ci		dev_err(bus->dev, "get slave: try to use more than 2 SA not supported\n");
8408c2ecf20Sopenharmony_ci
8418c2ecf20Sopenharmony_ci	slave_add = ioread8(bus->reg + npcm_i2caddr[(int)addr_type]);
8428c2ecf20Sopenharmony_ci
8438c2ecf20Sopenharmony_ci	return slave_add;
8448c2ecf20Sopenharmony_ci}
8458c2ecf20Sopenharmony_ci
8468c2ecf20Sopenharmony_cistatic int npcm_i2c_remove_slave_addr(struct npcm_i2c *bus, u8 slave_add)
8478c2ecf20Sopenharmony_ci{
8488c2ecf20Sopenharmony_ci	int i;
8498c2ecf20Sopenharmony_ci
8508c2ecf20Sopenharmony_ci	/* Set the enable bit */
8518c2ecf20Sopenharmony_ci	slave_add |= 0x80;
8528c2ecf20Sopenharmony_ci
8538c2ecf20Sopenharmony_ci	for (i = I2C_SLAVE_ADDR1; i < I2C_NUM_OWN_ADDR_SUPPORTED; i++) {
8548c2ecf20Sopenharmony_ci		if (ioread8(bus->reg + npcm_i2caddr[i]) == slave_add)
8558c2ecf20Sopenharmony_ci			iowrite8(0, bus->reg + npcm_i2caddr[i]);
8568c2ecf20Sopenharmony_ci	}
8578c2ecf20Sopenharmony_ci
8588c2ecf20Sopenharmony_ci	return 0;
8598c2ecf20Sopenharmony_ci}
8608c2ecf20Sopenharmony_ci
8618c2ecf20Sopenharmony_cistatic void npcm_i2c_write_fifo_slave(struct npcm_i2c *bus, u16 max_bytes)
8628c2ecf20Sopenharmony_ci{
8638c2ecf20Sopenharmony_ci	/*
8648c2ecf20Sopenharmony_ci	 * Fill the FIFO, while the FIFO is not full and there are more bytes
8658c2ecf20Sopenharmony_ci	 * to write
8668c2ecf20Sopenharmony_ci	 */
8678c2ecf20Sopenharmony_ci	npcm_i2c_clear_fifo_int(bus);
8688c2ecf20Sopenharmony_ci	npcm_i2c_clear_tx_fifo(bus);
8698c2ecf20Sopenharmony_ci	iowrite8(0, bus->reg + NPCM_I2CTXF_CTL);
8708c2ecf20Sopenharmony_ci	while (max_bytes-- && I2C_HW_FIFO_SIZE != npcm_i2c_fifo_usage(bus)) {
8718c2ecf20Sopenharmony_ci		if (bus->slv_wr_size <= 0)
8728c2ecf20Sopenharmony_ci			break;
8738c2ecf20Sopenharmony_ci		bus->slv_wr_ind = bus->slv_wr_ind % I2C_HW_FIFO_SIZE;
8748c2ecf20Sopenharmony_ci		npcm_i2c_wr_byte(bus, bus->slv_wr_buf[bus->slv_wr_ind]);
8758c2ecf20Sopenharmony_ci		bus->slv_wr_ind++;
8768c2ecf20Sopenharmony_ci		bus->slv_wr_ind = bus->slv_wr_ind % I2C_HW_FIFO_SIZE;
8778c2ecf20Sopenharmony_ci		bus->slv_wr_size--;
8788c2ecf20Sopenharmony_ci	}
8798c2ecf20Sopenharmony_ci}
8808c2ecf20Sopenharmony_ci
8818c2ecf20Sopenharmony_cistatic void npcm_i2c_read_fifo_slave(struct npcm_i2c *bus, u8 bytes_in_fifo)
8828c2ecf20Sopenharmony_ci{
8838c2ecf20Sopenharmony_ci	u8 data;
8848c2ecf20Sopenharmony_ci
8858c2ecf20Sopenharmony_ci	if (!bus->slave)
8868c2ecf20Sopenharmony_ci		return;
8878c2ecf20Sopenharmony_ci
8888c2ecf20Sopenharmony_ci	while (bytes_in_fifo--) {
8898c2ecf20Sopenharmony_ci		data = npcm_i2c_rd_byte(bus);
8908c2ecf20Sopenharmony_ci
8918c2ecf20Sopenharmony_ci		bus->slv_rd_ind = bus->slv_rd_ind % I2C_HW_FIFO_SIZE;
8928c2ecf20Sopenharmony_ci		bus->slv_rd_buf[bus->slv_rd_ind] = data;
8938c2ecf20Sopenharmony_ci		bus->slv_rd_ind++;
8948c2ecf20Sopenharmony_ci
8958c2ecf20Sopenharmony_ci		/* 1st byte is length in block protocol: */
8968c2ecf20Sopenharmony_ci		if (bus->slv_rd_ind == 1 && bus->read_block_use)
8978c2ecf20Sopenharmony_ci			bus->slv_rd_size = data + bus->PEC_use + 1;
8988c2ecf20Sopenharmony_ci	}
8998c2ecf20Sopenharmony_ci}
9008c2ecf20Sopenharmony_ci
9018c2ecf20Sopenharmony_cistatic int npcm_i2c_slave_get_wr_buf(struct npcm_i2c *bus)
9028c2ecf20Sopenharmony_ci{
9038c2ecf20Sopenharmony_ci	int i;
9048c2ecf20Sopenharmony_ci	u8 value;
9058c2ecf20Sopenharmony_ci	int ind;
9068c2ecf20Sopenharmony_ci	int ret = bus->slv_wr_ind;
9078c2ecf20Sopenharmony_ci
9088c2ecf20Sopenharmony_ci	/* fill a cyclic buffer */
9098c2ecf20Sopenharmony_ci	for (i = 0; i < I2C_HW_FIFO_SIZE; i++) {
9108c2ecf20Sopenharmony_ci		if (bus->slv_wr_size >= I2C_HW_FIFO_SIZE)
9118c2ecf20Sopenharmony_ci			break;
9128c2ecf20Sopenharmony_ci		if (bus->state == I2C_SLAVE_MATCH) {
9138c2ecf20Sopenharmony_ci			i2c_slave_event(bus->slave, I2C_SLAVE_READ_REQUESTED, &value);
9148c2ecf20Sopenharmony_ci			bus->state = I2C_OPER_STARTED;
9158c2ecf20Sopenharmony_ci		} else {
9168c2ecf20Sopenharmony_ci			i2c_slave_event(bus->slave, I2C_SLAVE_READ_PROCESSED, &value);
9178c2ecf20Sopenharmony_ci		}
9188c2ecf20Sopenharmony_ci		ind = (bus->slv_wr_ind + bus->slv_wr_size) % I2C_HW_FIFO_SIZE;
9198c2ecf20Sopenharmony_ci		bus->slv_wr_buf[ind] = value;
9208c2ecf20Sopenharmony_ci		bus->slv_wr_size++;
9218c2ecf20Sopenharmony_ci	}
9228c2ecf20Sopenharmony_ci	return I2C_HW_FIFO_SIZE - ret;
9238c2ecf20Sopenharmony_ci}
9248c2ecf20Sopenharmony_ci
9258c2ecf20Sopenharmony_cistatic void npcm_i2c_slave_send_rd_buf(struct npcm_i2c *bus)
9268c2ecf20Sopenharmony_ci{
9278c2ecf20Sopenharmony_ci	int i;
9288c2ecf20Sopenharmony_ci
9298c2ecf20Sopenharmony_ci	for (i = 0; i < bus->slv_rd_ind; i++)
9308c2ecf20Sopenharmony_ci		i2c_slave_event(bus->slave, I2C_SLAVE_WRITE_RECEIVED,
9318c2ecf20Sopenharmony_ci				&bus->slv_rd_buf[i]);
9328c2ecf20Sopenharmony_ci	/*
9338c2ecf20Sopenharmony_ci	 * once we send bytes up, need to reset the counter of the wr buf
9348c2ecf20Sopenharmony_ci	 * got data from master (new offset in device), ignore wr fifo:
9358c2ecf20Sopenharmony_ci	 */
9368c2ecf20Sopenharmony_ci	if (bus->slv_rd_ind) {
9378c2ecf20Sopenharmony_ci		bus->slv_wr_size = 0;
9388c2ecf20Sopenharmony_ci		bus->slv_wr_ind = 0;
9398c2ecf20Sopenharmony_ci	}
9408c2ecf20Sopenharmony_ci
9418c2ecf20Sopenharmony_ci	bus->slv_rd_ind = 0;
9428c2ecf20Sopenharmony_ci	bus->slv_rd_size = bus->adap.quirks->max_read_len;
9438c2ecf20Sopenharmony_ci
9448c2ecf20Sopenharmony_ci	npcm_i2c_clear_fifo_int(bus);
9458c2ecf20Sopenharmony_ci	npcm_i2c_clear_rx_fifo(bus);
9468c2ecf20Sopenharmony_ci}
9478c2ecf20Sopenharmony_ci
9488c2ecf20Sopenharmony_cistatic void npcm_i2c_slave_receive(struct npcm_i2c *bus, u16 nread,
9498c2ecf20Sopenharmony_ci				   u8 *read_data)
9508c2ecf20Sopenharmony_ci{
9518c2ecf20Sopenharmony_ci	bus->state = I2C_OPER_STARTED;
9528c2ecf20Sopenharmony_ci	bus->operation = I2C_READ_OPER;
9538c2ecf20Sopenharmony_ci	bus->slv_rd_size = nread;
9548c2ecf20Sopenharmony_ci	bus->slv_rd_ind = 0;
9558c2ecf20Sopenharmony_ci
9568c2ecf20Sopenharmony_ci	iowrite8(0, bus->reg + NPCM_I2CTXF_CTL);
9578c2ecf20Sopenharmony_ci	iowrite8(I2C_HW_FIFO_SIZE, bus->reg + NPCM_I2CRXF_CTL);
9588c2ecf20Sopenharmony_ci	npcm_i2c_clear_tx_fifo(bus);
9598c2ecf20Sopenharmony_ci	npcm_i2c_clear_rx_fifo(bus);
9608c2ecf20Sopenharmony_ci}
9618c2ecf20Sopenharmony_ci
9628c2ecf20Sopenharmony_cistatic void npcm_i2c_slave_xmit(struct npcm_i2c *bus, u16 nwrite,
9638c2ecf20Sopenharmony_ci				u8 *write_data)
9648c2ecf20Sopenharmony_ci{
9658c2ecf20Sopenharmony_ci	if (nwrite == 0)
9668c2ecf20Sopenharmony_ci		return;
9678c2ecf20Sopenharmony_ci
9688c2ecf20Sopenharmony_ci	bus->operation = I2C_WRITE_OPER;
9698c2ecf20Sopenharmony_ci
9708c2ecf20Sopenharmony_ci	/* get the next buffer */
9718c2ecf20Sopenharmony_ci	npcm_i2c_slave_get_wr_buf(bus);
9728c2ecf20Sopenharmony_ci	npcm_i2c_write_fifo_slave(bus, nwrite);
9738c2ecf20Sopenharmony_ci}
9748c2ecf20Sopenharmony_ci
9758c2ecf20Sopenharmony_ci/*
9768c2ecf20Sopenharmony_ci * npcm_i2c_slave_wr_buf_sync:
9778c2ecf20Sopenharmony_ci * currently slave IF only supports single byte operations.
9788c2ecf20Sopenharmony_ci * in order to utilyze the npcm HW FIFO, the driver will ask for 16 bytes
9798c2ecf20Sopenharmony_ci * at a time, pack them in buffer, and then transmit them all together
9808c2ecf20Sopenharmony_ci * to the FIFO and onward to the bus.
9818c2ecf20Sopenharmony_ci * NACK on read will be once reached to bus->adap->quirks->max_read_len.
9828c2ecf20Sopenharmony_ci * sending a NACK wherever the backend requests for it is not supported.
9838c2ecf20Sopenharmony_ci * the next two functions allow reading to local buffer before writing it all
9848c2ecf20Sopenharmony_ci * to the HW FIFO.
9858c2ecf20Sopenharmony_ci */
9868c2ecf20Sopenharmony_cistatic void npcm_i2c_slave_wr_buf_sync(struct npcm_i2c *bus)
9878c2ecf20Sopenharmony_ci{
9888c2ecf20Sopenharmony_ci	int left_in_fifo;
9898c2ecf20Sopenharmony_ci
9908c2ecf20Sopenharmony_ci	left_in_fifo = FIELD_GET(NPCM_I2CTXF_STS_TX_BYTES,
9918c2ecf20Sopenharmony_ci				 ioread8(bus->reg + NPCM_I2CTXF_STS));
9928c2ecf20Sopenharmony_ci
9938c2ecf20Sopenharmony_ci	/* fifo already full: */
9948c2ecf20Sopenharmony_ci	if (left_in_fifo >= I2C_HW_FIFO_SIZE ||
9958c2ecf20Sopenharmony_ci	    bus->slv_wr_size >= I2C_HW_FIFO_SIZE)
9968c2ecf20Sopenharmony_ci		return;
9978c2ecf20Sopenharmony_ci
9988c2ecf20Sopenharmony_ci	/* update the wr fifo index back to the untransmitted bytes: */
9998c2ecf20Sopenharmony_ci	bus->slv_wr_ind = bus->slv_wr_ind - left_in_fifo;
10008c2ecf20Sopenharmony_ci	bus->slv_wr_size = bus->slv_wr_size + left_in_fifo;
10018c2ecf20Sopenharmony_ci
10028c2ecf20Sopenharmony_ci	if (bus->slv_wr_ind < 0)
10038c2ecf20Sopenharmony_ci		bus->slv_wr_ind += I2C_HW_FIFO_SIZE;
10048c2ecf20Sopenharmony_ci}
10058c2ecf20Sopenharmony_ci
10068c2ecf20Sopenharmony_cistatic void npcm_i2c_slave_rd_wr(struct npcm_i2c *bus)
10078c2ecf20Sopenharmony_ci{
10088c2ecf20Sopenharmony_ci	if (NPCM_I2CST_XMIT & ioread8(bus->reg + NPCM_I2CST)) {
10098c2ecf20Sopenharmony_ci		/*
10108c2ecf20Sopenharmony_ci		 * Slave got an address match with direction bit 1 so it should
10118c2ecf20Sopenharmony_ci		 * transmit data. Write till the master will NACK
10128c2ecf20Sopenharmony_ci		 */
10138c2ecf20Sopenharmony_ci		bus->operation = I2C_WRITE_OPER;
10148c2ecf20Sopenharmony_ci		npcm_i2c_slave_xmit(bus, bus->adap.quirks->max_write_len,
10158c2ecf20Sopenharmony_ci				    bus->slv_wr_buf);
10168c2ecf20Sopenharmony_ci	} else {
10178c2ecf20Sopenharmony_ci		/*
10188c2ecf20Sopenharmony_ci		 * Slave got an address match with direction bit 0 so it should
10198c2ecf20Sopenharmony_ci		 * receive data.
10208c2ecf20Sopenharmony_ci		 * this module does not support saying no to bytes.
10218c2ecf20Sopenharmony_ci		 * it will always ACK.
10228c2ecf20Sopenharmony_ci		 */
10238c2ecf20Sopenharmony_ci		bus->operation = I2C_READ_OPER;
10248c2ecf20Sopenharmony_ci		npcm_i2c_read_fifo_slave(bus, npcm_i2c_fifo_usage(bus));
10258c2ecf20Sopenharmony_ci		bus->stop_ind = I2C_SLAVE_RCV_IND;
10268c2ecf20Sopenharmony_ci		npcm_i2c_slave_send_rd_buf(bus);
10278c2ecf20Sopenharmony_ci		npcm_i2c_slave_receive(bus, bus->adap.quirks->max_read_len,
10288c2ecf20Sopenharmony_ci				       bus->slv_rd_buf);
10298c2ecf20Sopenharmony_ci	}
10308c2ecf20Sopenharmony_ci}
10318c2ecf20Sopenharmony_ci
10328c2ecf20Sopenharmony_cistatic irqreturn_t npcm_i2c_int_slave_handler(struct npcm_i2c *bus)
10338c2ecf20Sopenharmony_ci{
10348c2ecf20Sopenharmony_ci	u8 val;
10358c2ecf20Sopenharmony_ci	irqreturn_t ret = IRQ_NONE;
10368c2ecf20Sopenharmony_ci	u8 i2cst = ioread8(bus->reg + NPCM_I2CST);
10378c2ecf20Sopenharmony_ci
10388c2ecf20Sopenharmony_ci	/* Slave: A NACK has occurred */
10398c2ecf20Sopenharmony_ci	if (NPCM_I2CST_NEGACK & i2cst) {
10408c2ecf20Sopenharmony_ci		bus->stop_ind = I2C_NACK_IND;
10418c2ecf20Sopenharmony_ci		npcm_i2c_slave_wr_buf_sync(bus);
10428c2ecf20Sopenharmony_ci		if (bus->fifo_use)
10438c2ecf20Sopenharmony_ci			/* clear the FIFO */
10448c2ecf20Sopenharmony_ci			iowrite8(NPCM_I2CFIF_CTS_CLR_FIFO,
10458c2ecf20Sopenharmony_ci				 bus->reg + NPCM_I2CFIF_CTS);
10468c2ecf20Sopenharmony_ci
10478c2ecf20Sopenharmony_ci		/* In slave write, NACK is OK, otherwise it is a problem */
10488c2ecf20Sopenharmony_ci		bus->stop_ind = I2C_NO_STATUS_IND;
10498c2ecf20Sopenharmony_ci		bus->operation = I2C_NO_OPER;
10508c2ecf20Sopenharmony_ci		bus->own_slave_addr = 0xFF;
10518c2ecf20Sopenharmony_ci
10528c2ecf20Sopenharmony_ci		/*
10538c2ecf20Sopenharmony_ci		 * Slave has to wait for STOP to decide this is the end
10548c2ecf20Sopenharmony_ci		 * of the transaction. tx is not yet considered as done
10558c2ecf20Sopenharmony_ci		 */
10568c2ecf20Sopenharmony_ci		iowrite8(NPCM_I2CST_NEGACK, bus->reg + NPCM_I2CST);
10578c2ecf20Sopenharmony_ci
10588c2ecf20Sopenharmony_ci		ret = IRQ_HANDLED;
10598c2ecf20Sopenharmony_ci	}
10608c2ecf20Sopenharmony_ci
10618c2ecf20Sopenharmony_ci	/* Slave mode: a Bus Error (BER) has been identified */
10628c2ecf20Sopenharmony_ci	if (NPCM_I2CST_BER & i2cst) {
10638c2ecf20Sopenharmony_ci		/*
10648c2ecf20Sopenharmony_ci		 * Check whether bus arbitration or Start or Stop during data
10658c2ecf20Sopenharmony_ci		 * xfer bus arbitration problem should not result in recovery
10668c2ecf20Sopenharmony_ci		 */
10678c2ecf20Sopenharmony_ci		bus->stop_ind = I2C_BUS_ERR_IND;
10688c2ecf20Sopenharmony_ci
10698c2ecf20Sopenharmony_ci		/* wait for bus busy before clear fifo */
10708c2ecf20Sopenharmony_ci		iowrite8(NPCM_I2CFIF_CTS_CLR_FIFO, bus->reg + NPCM_I2CFIF_CTS);
10718c2ecf20Sopenharmony_ci
10728c2ecf20Sopenharmony_ci		bus->state = I2C_IDLE;
10738c2ecf20Sopenharmony_ci
10748c2ecf20Sopenharmony_ci		/*
10758c2ecf20Sopenharmony_ci		 * in BER case we might get 2 interrupts: one for slave one for
10768c2ecf20Sopenharmony_ci		 * master ( for a channel which is master\slave switching)
10778c2ecf20Sopenharmony_ci		 */
10788c2ecf20Sopenharmony_ci		if (completion_done(&bus->cmd_complete) == false) {
10798c2ecf20Sopenharmony_ci			bus->cmd_err = -EIO;
10808c2ecf20Sopenharmony_ci			complete(&bus->cmd_complete);
10818c2ecf20Sopenharmony_ci		}
10828c2ecf20Sopenharmony_ci		bus->own_slave_addr = 0xFF;
10838c2ecf20Sopenharmony_ci		iowrite8(NPCM_I2CST_BER, bus->reg + NPCM_I2CST);
10848c2ecf20Sopenharmony_ci		ret = IRQ_HANDLED;
10858c2ecf20Sopenharmony_ci	}
10868c2ecf20Sopenharmony_ci
10878c2ecf20Sopenharmony_ci	/* A Slave Stop Condition has been identified */
10888c2ecf20Sopenharmony_ci	if (NPCM_I2CST_SLVSTP & i2cst) {
10898c2ecf20Sopenharmony_ci		u8 bytes_in_fifo = npcm_i2c_fifo_usage(bus);
10908c2ecf20Sopenharmony_ci
10918c2ecf20Sopenharmony_ci		bus->stop_ind = I2C_SLAVE_DONE_IND;
10928c2ecf20Sopenharmony_ci
10938c2ecf20Sopenharmony_ci		if (bus->operation == I2C_READ_OPER)
10948c2ecf20Sopenharmony_ci			npcm_i2c_read_fifo_slave(bus, bytes_in_fifo);
10958c2ecf20Sopenharmony_ci
10968c2ecf20Sopenharmony_ci		/* if the buffer is empty nothing will be sent */
10978c2ecf20Sopenharmony_ci		npcm_i2c_slave_send_rd_buf(bus);
10988c2ecf20Sopenharmony_ci
10998c2ecf20Sopenharmony_ci		/* Slave done transmitting or receiving */
11008c2ecf20Sopenharmony_ci		bus->stop_ind = I2C_NO_STATUS_IND;
11018c2ecf20Sopenharmony_ci
11028c2ecf20Sopenharmony_ci		/*
11038c2ecf20Sopenharmony_ci		 * Note, just because we got here, it doesn't mean we through
11048c2ecf20Sopenharmony_ci		 * away the wr buffer.
11058c2ecf20Sopenharmony_ci		 * we keep it until the next received offset.
11068c2ecf20Sopenharmony_ci		 */
11078c2ecf20Sopenharmony_ci		bus->operation = I2C_NO_OPER;
11088c2ecf20Sopenharmony_ci		bus->own_slave_addr = 0xFF;
11098c2ecf20Sopenharmony_ci		i2c_slave_event(bus->slave, I2C_SLAVE_STOP, 0);
11108c2ecf20Sopenharmony_ci		iowrite8(NPCM_I2CST_SLVSTP, bus->reg + NPCM_I2CST);
11118c2ecf20Sopenharmony_ci		if (bus->fifo_use) {
11128c2ecf20Sopenharmony_ci			npcm_i2c_clear_fifo_int(bus);
11138c2ecf20Sopenharmony_ci			npcm_i2c_clear_rx_fifo(bus);
11148c2ecf20Sopenharmony_ci			npcm_i2c_clear_tx_fifo(bus);
11158c2ecf20Sopenharmony_ci
11168c2ecf20Sopenharmony_ci			iowrite8(NPCM_I2CFIF_CTS_CLR_FIFO,
11178c2ecf20Sopenharmony_ci				 bus->reg + NPCM_I2CFIF_CTS);
11188c2ecf20Sopenharmony_ci		}
11198c2ecf20Sopenharmony_ci		bus->state = I2C_IDLE;
11208c2ecf20Sopenharmony_ci		ret = IRQ_HANDLED;
11218c2ecf20Sopenharmony_ci	}
11228c2ecf20Sopenharmony_ci
11238c2ecf20Sopenharmony_ci	/* restart condition occurred and Rx-FIFO was not empty */
11248c2ecf20Sopenharmony_ci	if (bus->fifo_use && FIELD_GET(NPCM_I2CFIF_CTS_SLVRSTR,
11258c2ecf20Sopenharmony_ci				       ioread8(bus->reg + NPCM_I2CFIF_CTS))) {
11268c2ecf20Sopenharmony_ci		bus->stop_ind = I2C_SLAVE_RESTART_IND;
11278c2ecf20Sopenharmony_ci		bus->master_or_slave = I2C_SLAVE;
11288c2ecf20Sopenharmony_ci		if (bus->operation == I2C_READ_OPER)
11298c2ecf20Sopenharmony_ci			npcm_i2c_read_fifo_slave(bus, npcm_i2c_fifo_usage(bus));
11308c2ecf20Sopenharmony_ci		bus->operation = I2C_WRITE_OPER;
11318c2ecf20Sopenharmony_ci		iowrite8(0, bus->reg + NPCM_I2CRXF_CTL);
11328c2ecf20Sopenharmony_ci		val = NPCM_I2CFIF_CTS_CLR_FIFO | NPCM_I2CFIF_CTS_SLVRSTR |
11338c2ecf20Sopenharmony_ci		      NPCM_I2CFIF_CTS_RXF_TXE;
11348c2ecf20Sopenharmony_ci		iowrite8(val, bus->reg + NPCM_I2CFIF_CTS);
11358c2ecf20Sopenharmony_ci		npcm_i2c_slave_rd_wr(bus);
11368c2ecf20Sopenharmony_ci		ret = IRQ_HANDLED;
11378c2ecf20Sopenharmony_ci	}
11388c2ecf20Sopenharmony_ci
11398c2ecf20Sopenharmony_ci	/* A Slave Address Match has been identified */
11408c2ecf20Sopenharmony_ci	if (NPCM_I2CST_NMATCH & i2cst) {
11418c2ecf20Sopenharmony_ci		u8 info = 0;
11428c2ecf20Sopenharmony_ci
11438c2ecf20Sopenharmony_ci		/* Address match automatically implies slave mode */
11448c2ecf20Sopenharmony_ci		bus->master_or_slave = I2C_SLAVE;
11458c2ecf20Sopenharmony_ci		npcm_i2c_clear_fifo_int(bus);
11468c2ecf20Sopenharmony_ci		npcm_i2c_clear_rx_fifo(bus);
11478c2ecf20Sopenharmony_ci		npcm_i2c_clear_tx_fifo(bus);
11488c2ecf20Sopenharmony_ci		iowrite8(0, bus->reg + NPCM_I2CTXF_CTL);
11498c2ecf20Sopenharmony_ci		iowrite8(I2C_HW_FIFO_SIZE, bus->reg + NPCM_I2CRXF_CTL);
11508c2ecf20Sopenharmony_ci		if (NPCM_I2CST_XMIT & i2cst) {
11518c2ecf20Sopenharmony_ci			bus->operation = I2C_WRITE_OPER;
11528c2ecf20Sopenharmony_ci		} else {
11538c2ecf20Sopenharmony_ci			i2c_slave_event(bus->slave, I2C_SLAVE_WRITE_REQUESTED,
11548c2ecf20Sopenharmony_ci					&info);
11558c2ecf20Sopenharmony_ci			bus->operation = I2C_READ_OPER;
11568c2ecf20Sopenharmony_ci		}
11578c2ecf20Sopenharmony_ci		if (bus->own_slave_addr == 0xFF) {
11588c2ecf20Sopenharmony_ci			/* Check which type of address match */
11598c2ecf20Sopenharmony_ci			val = ioread8(bus->reg + NPCM_I2CCST);
11608c2ecf20Sopenharmony_ci			if (NPCM_I2CCST_MATCH & val) {
11618c2ecf20Sopenharmony_ci				u16 addr;
11628c2ecf20Sopenharmony_ci				enum i2c_addr eaddr;
11638c2ecf20Sopenharmony_ci				u8 i2ccst2;
11648c2ecf20Sopenharmony_ci				u8 i2ccst3;
11658c2ecf20Sopenharmony_ci
11668c2ecf20Sopenharmony_ci				i2ccst3 = ioread8(bus->reg + NPCM_I2CCST3);
11678c2ecf20Sopenharmony_ci				i2ccst2 = ioread8(bus->reg + NPCM_I2CCST2);
11688c2ecf20Sopenharmony_ci
11698c2ecf20Sopenharmony_ci				/*
11708c2ecf20Sopenharmony_ci				 * the i2c module can response to 10 own SA.
11718c2ecf20Sopenharmony_ci				 * check which one was addressed by the master.
11728c2ecf20Sopenharmony_ci				 * repond to the first one.
11738c2ecf20Sopenharmony_ci				 */
11748c2ecf20Sopenharmony_ci				addr = ((i2ccst3 & 0x07) << 7) |
11758c2ecf20Sopenharmony_ci					(i2ccst2 & 0x7F);
11768c2ecf20Sopenharmony_ci				info = ffs(addr);
11778c2ecf20Sopenharmony_ci				eaddr = (enum i2c_addr)info;
11788c2ecf20Sopenharmony_ci				addr = npcm_i2c_get_slave_addr(bus, eaddr);
11798c2ecf20Sopenharmony_ci				addr &= 0x7F;
11808c2ecf20Sopenharmony_ci				bus->own_slave_addr = addr;
11818c2ecf20Sopenharmony_ci				if (bus->PEC_mask & BIT(info))
11828c2ecf20Sopenharmony_ci					bus->PEC_use = true;
11838c2ecf20Sopenharmony_ci				else
11848c2ecf20Sopenharmony_ci					bus->PEC_use = false;
11858c2ecf20Sopenharmony_ci			} else {
11868c2ecf20Sopenharmony_ci				if (NPCM_I2CCST_GCMATCH & val)
11878c2ecf20Sopenharmony_ci					bus->own_slave_addr = 0;
11888c2ecf20Sopenharmony_ci				if (NPCM_I2CCST_ARPMATCH & val)
11898c2ecf20Sopenharmony_ci					bus->own_slave_addr = 0x61;
11908c2ecf20Sopenharmony_ci			}
11918c2ecf20Sopenharmony_ci		} else {
11928c2ecf20Sopenharmony_ci			/*
11938c2ecf20Sopenharmony_ci			 *  Slave match can happen in two options:
11948c2ecf20Sopenharmony_ci			 *  1. Start, SA, read (slave read without further ado)
11958c2ecf20Sopenharmony_ci			 *  2. Start, SA, read, data, restart, SA, read,  ...
11968c2ecf20Sopenharmony_ci			 *     (slave read in fragmented mode)
11978c2ecf20Sopenharmony_ci			 *  3. Start, SA, write, data, restart, SA, read, ..
11988c2ecf20Sopenharmony_ci			 *     (regular write-read mode)
11998c2ecf20Sopenharmony_ci			 */
12008c2ecf20Sopenharmony_ci			if ((bus->state == I2C_OPER_STARTED &&
12018c2ecf20Sopenharmony_ci			     bus->operation == I2C_READ_OPER &&
12028c2ecf20Sopenharmony_ci			     bus->stop_ind == I2C_SLAVE_XMIT_IND) ||
12038c2ecf20Sopenharmony_ci			     bus->stop_ind == I2C_SLAVE_RCV_IND) {
12048c2ecf20Sopenharmony_ci				/* slave tx after slave rx w/o STOP */
12058c2ecf20Sopenharmony_ci				bus->stop_ind = I2C_SLAVE_RESTART_IND;
12068c2ecf20Sopenharmony_ci			}
12078c2ecf20Sopenharmony_ci		}
12088c2ecf20Sopenharmony_ci
12098c2ecf20Sopenharmony_ci		if (NPCM_I2CST_XMIT & i2cst)
12108c2ecf20Sopenharmony_ci			bus->stop_ind = I2C_SLAVE_XMIT_IND;
12118c2ecf20Sopenharmony_ci		else
12128c2ecf20Sopenharmony_ci			bus->stop_ind = I2C_SLAVE_RCV_IND;
12138c2ecf20Sopenharmony_ci		bus->state = I2C_SLAVE_MATCH;
12148c2ecf20Sopenharmony_ci		npcm_i2c_slave_rd_wr(bus);
12158c2ecf20Sopenharmony_ci		iowrite8(NPCM_I2CST_NMATCH, bus->reg + NPCM_I2CST);
12168c2ecf20Sopenharmony_ci		ret = IRQ_HANDLED;
12178c2ecf20Sopenharmony_ci	}
12188c2ecf20Sopenharmony_ci
12198c2ecf20Sopenharmony_ci	/* Slave SDA status is set - tx or rx */
12208c2ecf20Sopenharmony_ci	if ((NPCM_I2CST_SDAST & i2cst) ||
12218c2ecf20Sopenharmony_ci	    (bus->fifo_use &&
12228c2ecf20Sopenharmony_ci	    (npcm_i2c_tx_fifo_empty(bus) || npcm_i2c_rx_fifo_full(bus)))) {
12238c2ecf20Sopenharmony_ci		npcm_i2c_slave_rd_wr(bus);
12248c2ecf20Sopenharmony_ci		iowrite8(NPCM_I2CST_SDAST, bus->reg + NPCM_I2CST);
12258c2ecf20Sopenharmony_ci		ret = IRQ_HANDLED;
12268c2ecf20Sopenharmony_ci	} /* SDAST */
12278c2ecf20Sopenharmony_ci
12288c2ecf20Sopenharmony_ci	/*
12298c2ecf20Sopenharmony_ci	 * if irq is not one of the above, make sure EOB is disabled and all
12308c2ecf20Sopenharmony_ci	 * status bits are cleared.
12318c2ecf20Sopenharmony_ci	 */
12328c2ecf20Sopenharmony_ci	if (ret == IRQ_NONE) {
12338c2ecf20Sopenharmony_ci		npcm_i2c_eob_int(bus, false);
12348c2ecf20Sopenharmony_ci		npcm_i2c_clear_master_status(bus);
12358c2ecf20Sopenharmony_ci	}
12368c2ecf20Sopenharmony_ci
12378c2ecf20Sopenharmony_ci	return IRQ_HANDLED;
12388c2ecf20Sopenharmony_ci}
12398c2ecf20Sopenharmony_ci
12408c2ecf20Sopenharmony_cistatic int npcm_i2c_reg_slave(struct i2c_client *client)
12418c2ecf20Sopenharmony_ci{
12428c2ecf20Sopenharmony_ci	unsigned long lock_flags;
12438c2ecf20Sopenharmony_ci	struct npcm_i2c *bus = i2c_get_adapdata(client->adapter);
12448c2ecf20Sopenharmony_ci
12458c2ecf20Sopenharmony_ci	bus->slave = client;
12468c2ecf20Sopenharmony_ci
12478c2ecf20Sopenharmony_ci	if (!bus->slave)
12488c2ecf20Sopenharmony_ci		return -EINVAL;
12498c2ecf20Sopenharmony_ci
12508c2ecf20Sopenharmony_ci	if (client->flags & I2C_CLIENT_TEN)
12518c2ecf20Sopenharmony_ci		return -EAFNOSUPPORT;
12528c2ecf20Sopenharmony_ci
12538c2ecf20Sopenharmony_ci	spin_lock_irqsave(&bus->lock, lock_flags);
12548c2ecf20Sopenharmony_ci
12558c2ecf20Sopenharmony_ci	npcm_i2c_init_params(bus);
12568c2ecf20Sopenharmony_ci	bus->slv_rd_size = 0;
12578c2ecf20Sopenharmony_ci	bus->slv_wr_size = 0;
12588c2ecf20Sopenharmony_ci	bus->slv_rd_ind = 0;
12598c2ecf20Sopenharmony_ci	bus->slv_wr_ind = 0;
12608c2ecf20Sopenharmony_ci	if (client->flags & I2C_CLIENT_PEC)
12618c2ecf20Sopenharmony_ci		bus->PEC_use = true;
12628c2ecf20Sopenharmony_ci
12638c2ecf20Sopenharmony_ci	dev_info(bus->dev, "i2c%d register slave SA=0x%x, PEC=%d\n", bus->num,
12648c2ecf20Sopenharmony_ci		 client->addr, bus->PEC_use);
12658c2ecf20Sopenharmony_ci
12668c2ecf20Sopenharmony_ci	npcm_i2c_slave_enable(bus, I2C_SLAVE_ADDR1, client->addr, true);
12678c2ecf20Sopenharmony_ci	npcm_i2c_clear_fifo_int(bus);
12688c2ecf20Sopenharmony_ci	npcm_i2c_clear_rx_fifo(bus);
12698c2ecf20Sopenharmony_ci	npcm_i2c_clear_tx_fifo(bus);
12708c2ecf20Sopenharmony_ci	npcm_i2c_slave_int_enable(bus, true);
12718c2ecf20Sopenharmony_ci
12728c2ecf20Sopenharmony_ci	spin_unlock_irqrestore(&bus->lock, lock_flags);
12738c2ecf20Sopenharmony_ci	return 0;
12748c2ecf20Sopenharmony_ci}
12758c2ecf20Sopenharmony_ci
12768c2ecf20Sopenharmony_cistatic int npcm_i2c_unreg_slave(struct i2c_client *client)
12778c2ecf20Sopenharmony_ci{
12788c2ecf20Sopenharmony_ci	struct npcm_i2c *bus = client->adapter->algo_data;
12798c2ecf20Sopenharmony_ci	unsigned long lock_flags;
12808c2ecf20Sopenharmony_ci
12818c2ecf20Sopenharmony_ci	spin_lock_irqsave(&bus->lock, lock_flags);
12828c2ecf20Sopenharmony_ci	if (!bus->slave) {
12838c2ecf20Sopenharmony_ci		spin_unlock_irqrestore(&bus->lock, lock_flags);
12848c2ecf20Sopenharmony_ci		return -EINVAL;
12858c2ecf20Sopenharmony_ci	}
12868c2ecf20Sopenharmony_ci	npcm_i2c_slave_int_enable(bus, false);
12878c2ecf20Sopenharmony_ci	npcm_i2c_remove_slave_addr(bus, client->addr);
12888c2ecf20Sopenharmony_ci	bus->slave = NULL;
12898c2ecf20Sopenharmony_ci	spin_unlock_irqrestore(&bus->lock, lock_flags);
12908c2ecf20Sopenharmony_ci	return 0;
12918c2ecf20Sopenharmony_ci}
12928c2ecf20Sopenharmony_ci#endif /* CONFIG_I2C_SLAVE */
12938c2ecf20Sopenharmony_ci
12948c2ecf20Sopenharmony_cistatic void npcm_i2c_master_fifo_read(struct npcm_i2c *bus)
12958c2ecf20Sopenharmony_ci{
12968c2ecf20Sopenharmony_ci	int rcount;
12978c2ecf20Sopenharmony_ci	int fifo_bytes;
12988c2ecf20Sopenharmony_ci	enum i2c_state_ind ind = I2C_MASTER_DONE_IND;
12998c2ecf20Sopenharmony_ci
13008c2ecf20Sopenharmony_ci	fifo_bytes = npcm_i2c_fifo_usage(bus);
13018c2ecf20Sopenharmony_ci	rcount = bus->rd_size - bus->rd_ind;
13028c2ecf20Sopenharmony_ci
13038c2ecf20Sopenharmony_ci	/*
13048c2ecf20Sopenharmony_ci	 * In order not to change the RX_TRH during transaction (we found that
13058c2ecf20Sopenharmony_ci	 * this might be problematic if it takes too much time to read the FIFO)
13068c2ecf20Sopenharmony_ci	 * we read the data in the following way. If the number of bytes to
13078c2ecf20Sopenharmony_ci	 * read == FIFO Size + C (where C < FIFO Size)then first read C bytes
13088c2ecf20Sopenharmony_ci	 * and in the next int we read rest of the data.
13098c2ecf20Sopenharmony_ci	 */
13108c2ecf20Sopenharmony_ci	if (rcount < (2 * I2C_HW_FIFO_SIZE) && rcount > I2C_HW_FIFO_SIZE)
13118c2ecf20Sopenharmony_ci		fifo_bytes = rcount - I2C_HW_FIFO_SIZE;
13128c2ecf20Sopenharmony_ci
13138c2ecf20Sopenharmony_ci	if (rcount <= fifo_bytes) {
13148c2ecf20Sopenharmony_ci		/* last bytes are about to be read - end of tx */
13158c2ecf20Sopenharmony_ci		bus->state = I2C_STOP_PENDING;
13168c2ecf20Sopenharmony_ci		bus->stop_ind = ind;
13178c2ecf20Sopenharmony_ci		npcm_i2c_eob_int(bus, true);
13188c2ecf20Sopenharmony_ci		/* Stop should be set before reading last byte. */
13198c2ecf20Sopenharmony_ci		npcm_i2c_master_stop(bus);
13208c2ecf20Sopenharmony_ci		npcm_i2c_read_fifo(bus, fifo_bytes);
13218c2ecf20Sopenharmony_ci	} else {
13228c2ecf20Sopenharmony_ci		npcm_i2c_read_fifo(bus, fifo_bytes);
13238c2ecf20Sopenharmony_ci		rcount = bus->rd_size - bus->rd_ind;
13248c2ecf20Sopenharmony_ci		npcm_i2c_set_fifo(bus, rcount, -1);
13258c2ecf20Sopenharmony_ci	}
13268c2ecf20Sopenharmony_ci}
13278c2ecf20Sopenharmony_ci
13288c2ecf20Sopenharmony_cistatic void npcm_i2c_irq_master_handler_write(struct npcm_i2c *bus)
13298c2ecf20Sopenharmony_ci{
13308c2ecf20Sopenharmony_ci	u16 wcount;
13318c2ecf20Sopenharmony_ci
13328c2ecf20Sopenharmony_ci	if (bus->fifo_use)
13338c2ecf20Sopenharmony_ci		npcm_i2c_clear_tx_fifo(bus); /* clear the TX fifo status bit */
13348c2ecf20Sopenharmony_ci
13358c2ecf20Sopenharmony_ci	/* Master write operation - last byte handling */
13368c2ecf20Sopenharmony_ci	if (bus->wr_ind == bus->wr_size) {
13378c2ecf20Sopenharmony_ci		if (bus->fifo_use && npcm_i2c_fifo_usage(bus) > 0)
13388c2ecf20Sopenharmony_ci			/*
13398c2ecf20Sopenharmony_ci			 * No more bytes to send (to add to the FIFO),
13408c2ecf20Sopenharmony_ci			 * however the FIFO is not empty yet. It is
13418c2ecf20Sopenharmony_ci			 * still in the middle of tx. Currently there's nothing
13428c2ecf20Sopenharmony_ci			 * to do except for waiting to the end of the tx
13438c2ecf20Sopenharmony_ci			 * We will get an int when the FIFO will get empty.
13448c2ecf20Sopenharmony_ci			 */
13458c2ecf20Sopenharmony_ci			return;
13468c2ecf20Sopenharmony_ci
13478c2ecf20Sopenharmony_ci		if (bus->rd_size == 0) {
13488c2ecf20Sopenharmony_ci			/* all bytes have been written, in wr only operation */
13498c2ecf20Sopenharmony_ci			npcm_i2c_eob_int(bus, true);
13508c2ecf20Sopenharmony_ci			bus->state = I2C_STOP_PENDING;
13518c2ecf20Sopenharmony_ci			bus->stop_ind = I2C_MASTER_DONE_IND;
13528c2ecf20Sopenharmony_ci			npcm_i2c_master_stop(bus);
13538c2ecf20Sopenharmony_ci			/* Clear SDA Status bit (by writing dummy byte) */
13548c2ecf20Sopenharmony_ci			npcm_i2c_wr_byte(bus, 0xFF);
13558c2ecf20Sopenharmony_ci
13568c2ecf20Sopenharmony_ci		} else {
13578c2ecf20Sopenharmony_ci			/* last write-byte written on previous int - restart */
13588c2ecf20Sopenharmony_ci			npcm_i2c_set_fifo(bus, bus->rd_size, -1);
13598c2ecf20Sopenharmony_ci			/* Generate repeated start upon next write to SDA */
13608c2ecf20Sopenharmony_ci			npcm_i2c_master_start(bus);
13618c2ecf20Sopenharmony_ci
13628c2ecf20Sopenharmony_ci			/*
13638c2ecf20Sopenharmony_ci			 * Receiving one byte only - stall after successful
13648c2ecf20Sopenharmony_ci			 * completion of send address byte. If we NACK here, and
13658c2ecf20Sopenharmony_ci			 * slave doesn't ACK the address, we might
13668c2ecf20Sopenharmony_ci			 * unintentionally NACK the next multi-byte read.
13678c2ecf20Sopenharmony_ci			 */
13688c2ecf20Sopenharmony_ci			if (bus->rd_size == 1)
13698c2ecf20Sopenharmony_ci				npcm_i2c_stall_after_start(bus, true);
13708c2ecf20Sopenharmony_ci
13718c2ecf20Sopenharmony_ci			/* Next int will occur on read */
13728c2ecf20Sopenharmony_ci			bus->operation = I2C_READ_OPER;
13738c2ecf20Sopenharmony_ci			/* send the slave address in read direction */
13748c2ecf20Sopenharmony_ci			npcm_i2c_wr_byte(bus, bus->dest_addr | 0x1);
13758c2ecf20Sopenharmony_ci		}
13768c2ecf20Sopenharmony_ci	} else {
13778c2ecf20Sopenharmony_ci		/* write next byte not last byte and not slave address */
13788c2ecf20Sopenharmony_ci		if (!bus->fifo_use || bus->wr_size == 1) {
13798c2ecf20Sopenharmony_ci			npcm_i2c_wr_byte(bus, bus->wr_buf[bus->wr_ind++]);
13808c2ecf20Sopenharmony_ci		} else {
13818c2ecf20Sopenharmony_ci			wcount = bus->wr_size - bus->wr_ind;
13828c2ecf20Sopenharmony_ci			npcm_i2c_set_fifo(bus, -1, wcount);
13838c2ecf20Sopenharmony_ci			if (wcount)
13848c2ecf20Sopenharmony_ci				npcm_i2c_write_to_fifo_master(bus, wcount);
13858c2ecf20Sopenharmony_ci		}
13868c2ecf20Sopenharmony_ci	}
13878c2ecf20Sopenharmony_ci}
13888c2ecf20Sopenharmony_ci
13898c2ecf20Sopenharmony_cistatic void npcm_i2c_irq_master_handler_read(struct npcm_i2c *bus)
13908c2ecf20Sopenharmony_ci{
13918c2ecf20Sopenharmony_ci	u16 block_extra_bytes_size;
13928c2ecf20Sopenharmony_ci	u8 data;
13938c2ecf20Sopenharmony_ci
13948c2ecf20Sopenharmony_ci	/* added bytes to the packet: */
13958c2ecf20Sopenharmony_ci	block_extra_bytes_size = bus->read_block_use + bus->PEC_use;
13968c2ecf20Sopenharmony_ci
13978c2ecf20Sopenharmony_ci	/*
13988c2ecf20Sopenharmony_ci	 * Perform master read, distinguishing between last byte and the rest of
13998c2ecf20Sopenharmony_ci	 * the bytes. The last byte should be read when the clock is stopped
14008c2ecf20Sopenharmony_ci	 */
14018c2ecf20Sopenharmony_ci	if (bus->rd_ind == 0) { /* first byte handling: */
14028c2ecf20Sopenharmony_ci		if (bus->read_block_use) {
14038c2ecf20Sopenharmony_ci			/* first byte in block protocol is the size: */
14048c2ecf20Sopenharmony_ci			data = npcm_i2c_rd_byte(bus);
14058c2ecf20Sopenharmony_ci			data = clamp_val(data, 1, I2C_SMBUS_BLOCK_MAX);
14068c2ecf20Sopenharmony_ci			bus->rd_size = data + block_extra_bytes_size;
14078c2ecf20Sopenharmony_ci			bus->rd_buf[bus->rd_ind++] = data;
14088c2ecf20Sopenharmony_ci
14098c2ecf20Sopenharmony_ci			/* clear RX FIFO interrupt status: */
14108c2ecf20Sopenharmony_ci			if (bus->fifo_use) {
14118c2ecf20Sopenharmony_ci				data = ioread8(bus->reg + NPCM_I2CFIF_CTS);
14128c2ecf20Sopenharmony_ci				data = data | NPCM_I2CFIF_CTS_RXF_TXE;
14138c2ecf20Sopenharmony_ci				iowrite8(data, bus->reg + NPCM_I2CFIF_CTS);
14148c2ecf20Sopenharmony_ci			}
14158c2ecf20Sopenharmony_ci
14168c2ecf20Sopenharmony_ci			npcm_i2c_set_fifo(bus, bus->rd_size - 1, -1);
14178c2ecf20Sopenharmony_ci			npcm_i2c_stall_after_start(bus, false);
14188c2ecf20Sopenharmony_ci		} else {
14198c2ecf20Sopenharmony_ci			npcm_i2c_clear_tx_fifo(bus);
14208c2ecf20Sopenharmony_ci			npcm_i2c_master_fifo_read(bus);
14218c2ecf20Sopenharmony_ci		}
14228c2ecf20Sopenharmony_ci	} else {
14238c2ecf20Sopenharmony_ci		if (bus->rd_size == block_extra_bytes_size &&
14248c2ecf20Sopenharmony_ci		    bus->read_block_use) {
14258c2ecf20Sopenharmony_ci			bus->state = I2C_STOP_PENDING;
14268c2ecf20Sopenharmony_ci			bus->stop_ind = I2C_BLOCK_BYTES_ERR_IND;
14278c2ecf20Sopenharmony_ci			bus->cmd_err = -EIO;
14288c2ecf20Sopenharmony_ci			npcm_i2c_eob_int(bus, true);
14298c2ecf20Sopenharmony_ci			npcm_i2c_master_stop(bus);
14308c2ecf20Sopenharmony_ci			npcm_i2c_read_fifo(bus, npcm_i2c_fifo_usage(bus));
14318c2ecf20Sopenharmony_ci		} else {
14328c2ecf20Sopenharmony_ci			npcm_i2c_master_fifo_read(bus);
14338c2ecf20Sopenharmony_ci		}
14348c2ecf20Sopenharmony_ci	}
14358c2ecf20Sopenharmony_ci}
14368c2ecf20Sopenharmony_ci
14378c2ecf20Sopenharmony_cistatic void npcm_i2c_irq_handle_nmatch(struct npcm_i2c *bus)
14388c2ecf20Sopenharmony_ci{
14398c2ecf20Sopenharmony_ci	iowrite8(NPCM_I2CST_NMATCH, bus->reg + NPCM_I2CST);
14408c2ecf20Sopenharmony_ci	npcm_i2c_nack(bus);
14418c2ecf20Sopenharmony_ci	bus->stop_ind = I2C_BUS_ERR_IND;
14428c2ecf20Sopenharmony_ci	npcm_i2c_callback(bus, bus->stop_ind, npcm_i2c_get_index(bus));
14438c2ecf20Sopenharmony_ci}
14448c2ecf20Sopenharmony_ci
14458c2ecf20Sopenharmony_ci/* A NACK has occurred */
14468c2ecf20Sopenharmony_cistatic void npcm_i2c_irq_handle_nack(struct npcm_i2c *bus)
14478c2ecf20Sopenharmony_ci{
14488c2ecf20Sopenharmony_ci	u8 val;
14498c2ecf20Sopenharmony_ci
14508c2ecf20Sopenharmony_ci	if (bus->nack_cnt < ULLONG_MAX)
14518c2ecf20Sopenharmony_ci		bus->nack_cnt++;
14528c2ecf20Sopenharmony_ci
14538c2ecf20Sopenharmony_ci	if (bus->fifo_use) {
14548c2ecf20Sopenharmony_ci		/*
14558c2ecf20Sopenharmony_ci		 * if there are still untransmitted bytes in TX FIFO
14568c2ecf20Sopenharmony_ci		 * reduce them from wr_ind
14578c2ecf20Sopenharmony_ci		 */
14588c2ecf20Sopenharmony_ci		if (bus->operation == I2C_WRITE_OPER)
14598c2ecf20Sopenharmony_ci			bus->wr_ind -= npcm_i2c_fifo_usage(bus);
14608c2ecf20Sopenharmony_ci
14618c2ecf20Sopenharmony_ci		/* clear the FIFO */
14628c2ecf20Sopenharmony_ci		iowrite8(NPCM_I2CFIF_CTS_CLR_FIFO, bus->reg + NPCM_I2CFIF_CTS);
14638c2ecf20Sopenharmony_ci	}
14648c2ecf20Sopenharmony_ci
14658c2ecf20Sopenharmony_ci	/* In master write operation, got unexpected NACK */
14668c2ecf20Sopenharmony_ci	bus->stop_ind = I2C_NACK_IND;
14678c2ecf20Sopenharmony_ci	/* Only current master is allowed to issue Stop Condition */
14688c2ecf20Sopenharmony_ci	if (npcm_i2c_is_master(bus)) {
14698c2ecf20Sopenharmony_ci		/* stopping in the middle */
14708c2ecf20Sopenharmony_ci		npcm_i2c_eob_int(bus, false);
14718c2ecf20Sopenharmony_ci		npcm_i2c_master_stop(bus);
14728c2ecf20Sopenharmony_ci
14738c2ecf20Sopenharmony_ci		/* Clear SDA Status bit (by reading dummy byte) */
14748c2ecf20Sopenharmony_ci		npcm_i2c_rd_byte(bus);
14758c2ecf20Sopenharmony_ci
14768c2ecf20Sopenharmony_ci		/*
14778c2ecf20Sopenharmony_ci		 * The bus is released from stall only after the SW clears
14788c2ecf20Sopenharmony_ci		 * NEGACK bit. Then a Stop condition is sent.
14798c2ecf20Sopenharmony_ci		 */
14808c2ecf20Sopenharmony_ci		npcm_i2c_clear_master_status(bus);
14818c2ecf20Sopenharmony_ci		readx_poll_timeout_atomic(ioread8, bus->reg + NPCM_I2CCST, val,
14828c2ecf20Sopenharmony_ci					  !(val & NPCM_I2CCST_BUSY), 10, 200);
14838c2ecf20Sopenharmony_ci		/* verify no status bits are still set after bus is released */
14848c2ecf20Sopenharmony_ci		npcm_i2c_clear_master_status(bus);
14858c2ecf20Sopenharmony_ci	}
14868c2ecf20Sopenharmony_ci	bus->state = I2C_IDLE;
14878c2ecf20Sopenharmony_ci
14888c2ecf20Sopenharmony_ci	/*
14898c2ecf20Sopenharmony_ci	 * In Master mode, NACK should be cleared only after STOP.
14908c2ecf20Sopenharmony_ci	 * In such case, the bus is released from stall only after the
14918c2ecf20Sopenharmony_ci	 * software clears NACK bit. Then a Stop condition is sent.
14928c2ecf20Sopenharmony_ci	 */
14938c2ecf20Sopenharmony_ci	npcm_i2c_callback(bus, bus->stop_ind, bus->wr_ind);
14948c2ecf20Sopenharmony_ci}
14958c2ecf20Sopenharmony_ci
14968c2ecf20Sopenharmony_ci	/* Master mode: a Bus Error has been identified */
14978c2ecf20Sopenharmony_cistatic void npcm_i2c_irq_handle_ber(struct npcm_i2c *bus)
14988c2ecf20Sopenharmony_ci{
14998c2ecf20Sopenharmony_ci	if (bus->ber_cnt < ULLONG_MAX)
15008c2ecf20Sopenharmony_ci		bus->ber_cnt++;
15018c2ecf20Sopenharmony_ci	bus->stop_ind = I2C_BUS_ERR_IND;
15028c2ecf20Sopenharmony_ci	if (npcm_i2c_is_master(bus)) {
15038c2ecf20Sopenharmony_ci		npcm_i2c_master_abort(bus);
15048c2ecf20Sopenharmony_ci	} else {
15058c2ecf20Sopenharmony_ci		npcm_i2c_clear_master_status(bus);
15068c2ecf20Sopenharmony_ci
15078c2ecf20Sopenharmony_ci		/* Clear BB (BUS BUSY) bit */
15088c2ecf20Sopenharmony_ci		iowrite8(NPCM_I2CCST_BB, bus->reg + NPCM_I2CCST);
15098c2ecf20Sopenharmony_ci
15108c2ecf20Sopenharmony_ci		bus->cmd_err = -EAGAIN;
15118c2ecf20Sopenharmony_ci		npcm_i2c_callback(bus, bus->stop_ind, npcm_i2c_get_index(bus));
15128c2ecf20Sopenharmony_ci	}
15138c2ecf20Sopenharmony_ci	bus->state = I2C_IDLE;
15148c2ecf20Sopenharmony_ci}
15158c2ecf20Sopenharmony_ci
15168c2ecf20Sopenharmony_ci	/* EOB: a master End Of Busy (meaning STOP completed) */
15178c2ecf20Sopenharmony_cistatic void npcm_i2c_irq_handle_eob(struct npcm_i2c *bus)
15188c2ecf20Sopenharmony_ci{
15198c2ecf20Sopenharmony_ci	npcm_i2c_eob_int(bus, false);
15208c2ecf20Sopenharmony_ci	bus->state = I2C_IDLE;
15218c2ecf20Sopenharmony_ci	npcm_i2c_callback(bus, bus->stop_ind, bus->rd_ind);
15228c2ecf20Sopenharmony_ci}
15238c2ecf20Sopenharmony_ci
15248c2ecf20Sopenharmony_ci/* Address sent and requested stall occurred (Master mode) */
15258c2ecf20Sopenharmony_cistatic void npcm_i2c_irq_handle_stall_after_start(struct npcm_i2c *bus)
15268c2ecf20Sopenharmony_ci{
15278c2ecf20Sopenharmony_ci	if (npcm_i2c_is_quick(bus)) {
15288c2ecf20Sopenharmony_ci		bus->state = I2C_STOP_PENDING;
15298c2ecf20Sopenharmony_ci		bus->stop_ind = I2C_MASTER_DONE_IND;
15308c2ecf20Sopenharmony_ci		npcm_i2c_eob_int(bus, true);
15318c2ecf20Sopenharmony_ci		npcm_i2c_master_stop(bus);
15328c2ecf20Sopenharmony_ci	} else if ((bus->rd_size == 1) && !bus->read_block_use) {
15338c2ecf20Sopenharmony_ci		/*
15348c2ecf20Sopenharmony_ci		 * Receiving one byte only - set NACK after ensuring
15358c2ecf20Sopenharmony_ci		 * slave ACKed the address byte.
15368c2ecf20Sopenharmony_ci		 */
15378c2ecf20Sopenharmony_ci		npcm_i2c_nack(bus);
15388c2ecf20Sopenharmony_ci	}
15398c2ecf20Sopenharmony_ci
15408c2ecf20Sopenharmony_ci	/* Reset stall-after-address-byte */
15418c2ecf20Sopenharmony_ci	npcm_i2c_stall_after_start(bus, false);
15428c2ecf20Sopenharmony_ci
15438c2ecf20Sopenharmony_ci	/* Clear stall only after setting STOP */
15448c2ecf20Sopenharmony_ci	iowrite8(NPCM_I2CST_STASTR, bus->reg + NPCM_I2CST);
15458c2ecf20Sopenharmony_ci}
15468c2ecf20Sopenharmony_ci
15478c2ecf20Sopenharmony_ci/* SDA status is set - TX or RX, master */
15488c2ecf20Sopenharmony_cistatic void npcm_i2c_irq_handle_sda(struct npcm_i2c *bus, u8 i2cst)
15498c2ecf20Sopenharmony_ci{
15508c2ecf20Sopenharmony_ci	u8 fif_cts;
15518c2ecf20Sopenharmony_ci
15528c2ecf20Sopenharmony_ci	if (!npcm_i2c_is_master(bus))
15538c2ecf20Sopenharmony_ci		return;
15548c2ecf20Sopenharmony_ci
15558c2ecf20Sopenharmony_ci	if (bus->state == I2C_IDLE) {
15568c2ecf20Sopenharmony_ci		bus->stop_ind = I2C_WAKE_UP_IND;
15578c2ecf20Sopenharmony_ci
15588c2ecf20Sopenharmony_ci		if (npcm_i2c_is_quick(bus) || bus->read_block_use)
15598c2ecf20Sopenharmony_ci			/*
15608c2ecf20Sopenharmony_ci			 * Need to stall after successful
15618c2ecf20Sopenharmony_ci			 * completion of sending address byte
15628c2ecf20Sopenharmony_ci			 */
15638c2ecf20Sopenharmony_ci			npcm_i2c_stall_after_start(bus, true);
15648c2ecf20Sopenharmony_ci		else
15658c2ecf20Sopenharmony_ci			npcm_i2c_stall_after_start(bus, false);
15668c2ecf20Sopenharmony_ci
15678c2ecf20Sopenharmony_ci		/*
15688c2ecf20Sopenharmony_ci		 * Receiving one byte only - stall after successful completion
15698c2ecf20Sopenharmony_ci		 * of sending address byte If we NACK here, and slave doesn't
15708c2ecf20Sopenharmony_ci		 * ACK the address, we might unintentionally NACK the next
15718c2ecf20Sopenharmony_ci		 * multi-byte read
15728c2ecf20Sopenharmony_ci		 */
15738c2ecf20Sopenharmony_ci		if (bus->wr_size == 0 && bus->rd_size == 1)
15748c2ecf20Sopenharmony_ci			npcm_i2c_stall_after_start(bus, true);
15758c2ecf20Sopenharmony_ci
15768c2ecf20Sopenharmony_ci		/* Initiate I2C master tx */
15778c2ecf20Sopenharmony_ci
15788c2ecf20Sopenharmony_ci		/* select bank 1 for FIFO regs */
15798c2ecf20Sopenharmony_ci		npcm_i2c_select_bank(bus, I2C_BANK_1);
15808c2ecf20Sopenharmony_ci
15818c2ecf20Sopenharmony_ci		fif_cts = ioread8(bus->reg + NPCM_I2CFIF_CTS);
15828c2ecf20Sopenharmony_ci		fif_cts = fif_cts & ~NPCM_I2CFIF_CTS_SLVRSTR;
15838c2ecf20Sopenharmony_ci
15848c2ecf20Sopenharmony_ci		/* clear FIFO and relevant status bits. */
15858c2ecf20Sopenharmony_ci		fif_cts = fif_cts | NPCM_I2CFIF_CTS_CLR_FIFO;
15868c2ecf20Sopenharmony_ci		iowrite8(fif_cts, bus->reg + NPCM_I2CFIF_CTS);
15878c2ecf20Sopenharmony_ci
15888c2ecf20Sopenharmony_ci		/* re-enable */
15898c2ecf20Sopenharmony_ci		fif_cts = fif_cts | NPCM_I2CFIF_CTS_RXF_TXE;
15908c2ecf20Sopenharmony_ci		iowrite8(fif_cts, bus->reg + NPCM_I2CFIF_CTS);
15918c2ecf20Sopenharmony_ci
15928c2ecf20Sopenharmony_ci		/*
15938c2ecf20Sopenharmony_ci		 * Configure the FIFO threshold:
15948c2ecf20Sopenharmony_ci		 * according to the needed # of bytes to read.
15958c2ecf20Sopenharmony_ci		 * Note: due to HW limitation can't config the rx fifo before it
15968c2ecf20Sopenharmony_ci		 * got and ACK on the restart. LAST bit will not be reset unless
15978c2ecf20Sopenharmony_ci		 * RX completed. It will stay set on the next tx.
15988c2ecf20Sopenharmony_ci		 */
15998c2ecf20Sopenharmony_ci		if (bus->wr_size)
16008c2ecf20Sopenharmony_ci			npcm_i2c_set_fifo(bus, -1, bus->wr_size);
16018c2ecf20Sopenharmony_ci		else
16028c2ecf20Sopenharmony_ci			npcm_i2c_set_fifo(bus, bus->rd_size, -1);
16038c2ecf20Sopenharmony_ci
16048c2ecf20Sopenharmony_ci		bus->state = I2C_OPER_STARTED;
16058c2ecf20Sopenharmony_ci
16068c2ecf20Sopenharmony_ci		if (npcm_i2c_is_quick(bus) || bus->wr_size)
16078c2ecf20Sopenharmony_ci			npcm_i2c_wr_byte(bus, bus->dest_addr);
16088c2ecf20Sopenharmony_ci		else
16098c2ecf20Sopenharmony_ci			npcm_i2c_wr_byte(bus, bus->dest_addr | BIT(0));
16108c2ecf20Sopenharmony_ci	/* SDA interrupt, after start\restart */
16118c2ecf20Sopenharmony_ci	} else {
16128c2ecf20Sopenharmony_ci		if (NPCM_I2CST_XMIT & i2cst) {
16138c2ecf20Sopenharmony_ci			bus->operation = I2C_WRITE_OPER;
16148c2ecf20Sopenharmony_ci			npcm_i2c_irq_master_handler_write(bus);
16158c2ecf20Sopenharmony_ci		} else {
16168c2ecf20Sopenharmony_ci			bus->operation = I2C_READ_OPER;
16178c2ecf20Sopenharmony_ci			npcm_i2c_irq_master_handler_read(bus);
16188c2ecf20Sopenharmony_ci		}
16198c2ecf20Sopenharmony_ci	}
16208c2ecf20Sopenharmony_ci}
16218c2ecf20Sopenharmony_ci
16228c2ecf20Sopenharmony_cistatic int npcm_i2c_int_master_handler(struct npcm_i2c *bus)
16238c2ecf20Sopenharmony_ci{
16248c2ecf20Sopenharmony_ci	u8 i2cst;
16258c2ecf20Sopenharmony_ci	int ret = -EIO;
16268c2ecf20Sopenharmony_ci
16278c2ecf20Sopenharmony_ci	i2cst = ioread8(bus->reg + NPCM_I2CST);
16288c2ecf20Sopenharmony_ci
16298c2ecf20Sopenharmony_ci	if (FIELD_GET(NPCM_I2CST_NMATCH, i2cst)) {
16308c2ecf20Sopenharmony_ci		npcm_i2c_irq_handle_nmatch(bus);
16318c2ecf20Sopenharmony_ci		return 0;
16328c2ecf20Sopenharmony_ci	}
16338c2ecf20Sopenharmony_ci	/* A NACK has occurred */
16348c2ecf20Sopenharmony_ci	if (FIELD_GET(NPCM_I2CST_NEGACK, i2cst)) {
16358c2ecf20Sopenharmony_ci		npcm_i2c_irq_handle_nack(bus);
16368c2ecf20Sopenharmony_ci		return 0;
16378c2ecf20Sopenharmony_ci	}
16388c2ecf20Sopenharmony_ci
16398c2ecf20Sopenharmony_ci	/* Master mode: a Bus Error has been identified */
16408c2ecf20Sopenharmony_ci	if (FIELD_GET(NPCM_I2CST_BER, i2cst)) {
16418c2ecf20Sopenharmony_ci		npcm_i2c_irq_handle_ber(bus);
16428c2ecf20Sopenharmony_ci		return 0;
16438c2ecf20Sopenharmony_ci	}
16448c2ecf20Sopenharmony_ci
16458c2ecf20Sopenharmony_ci	/* EOB: a master End Of Busy (meaning STOP completed) */
16468c2ecf20Sopenharmony_ci	if ((FIELD_GET(NPCM_I2CCTL1_EOBINTE,
16478c2ecf20Sopenharmony_ci		       ioread8(bus->reg + NPCM_I2CCTL1)) == 1) &&
16488c2ecf20Sopenharmony_ci	    (FIELD_GET(NPCM_I2CCST3_EO_BUSY,
16498c2ecf20Sopenharmony_ci		       ioread8(bus->reg + NPCM_I2CCST3)))) {
16508c2ecf20Sopenharmony_ci		npcm_i2c_irq_handle_eob(bus);
16518c2ecf20Sopenharmony_ci		return 0;
16528c2ecf20Sopenharmony_ci	}
16538c2ecf20Sopenharmony_ci
16548c2ecf20Sopenharmony_ci	/* Address sent and requested stall occurred (Master mode) */
16558c2ecf20Sopenharmony_ci	if (FIELD_GET(NPCM_I2CST_STASTR, i2cst)) {
16568c2ecf20Sopenharmony_ci		npcm_i2c_irq_handle_stall_after_start(bus);
16578c2ecf20Sopenharmony_ci		ret = 0;
16588c2ecf20Sopenharmony_ci	}
16598c2ecf20Sopenharmony_ci
16608c2ecf20Sopenharmony_ci	/* SDA status is set - TX or RX, master */
16618c2ecf20Sopenharmony_ci	if (FIELD_GET(NPCM_I2CST_SDAST, i2cst) ||
16628c2ecf20Sopenharmony_ci	    (bus->fifo_use &&
16638c2ecf20Sopenharmony_ci	    (npcm_i2c_tx_fifo_empty(bus) || npcm_i2c_rx_fifo_full(bus)))) {
16648c2ecf20Sopenharmony_ci		npcm_i2c_irq_handle_sda(bus, i2cst);
16658c2ecf20Sopenharmony_ci		ret = 0;
16668c2ecf20Sopenharmony_ci	}
16678c2ecf20Sopenharmony_ci
16688c2ecf20Sopenharmony_ci	return ret;
16698c2ecf20Sopenharmony_ci}
16708c2ecf20Sopenharmony_ci
16718c2ecf20Sopenharmony_ci/* recovery using TGCLK functionality of the module */
16728c2ecf20Sopenharmony_cistatic int npcm_i2c_recovery_tgclk(struct i2c_adapter *_adap)
16738c2ecf20Sopenharmony_ci{
16748c2ecf20Sopenharmony_ci	u8               val;
16758c2ecf20Sopenharmony_ci	u8               fif_cts;
16768c2ecf20Sopenharmony_ci	bool             done = false;
16778c2ecf20Sopenharmony_ci	int              status = -ENOTRECOVERABLE;
16788c2ecf20Sopenharmony_ci	struct npcm_i2c *bus = container_of(_adap, struct npcm_i2c, adap);
16798c2ecf20Sopenharmony_ci	/* Allow 3 bytes (27 toggles) to be read from the slave: */
16808c2ecf20Sopenharmony_ci	int              iter = 27;
16818c2ecf20Sopenharmony_ci
16828c2ecf20Sopenharmony_ci	if ((npcm_i2c_get_SDA(_adap) == 1) && (npcm_i2c_get_SCL(_adap) == 1)) {
16838c2ecf20Sopenharmony_ci		dev_dbg(bus->dev, "bus%d-0x%x recovery skipped, bus not stuck",
16848c2ecf20Sopenharmony_ci			bus->num, bus->dest_addr);
16858c2ecf20Sopenharmony_ci		npcm_i2c_reset(bus);
16868c2ecf20Sopenharmony_ci		return 0;
16878c2ecf20Sopenharmony_ci	}
16888c2ecf20Sopenharmony_ci
16898c2ecf20Sopenharmony_ci	npcm_i2c_int_enable(bus, false);
16908c2ecf20Sopenharmony_ci	npcm_i2c_disable(bus);
16918c2ecf20Sopenharmony_ci	npcm_i2c_enable(bus);
16928c2ecf20Sopenharmony_ci	iowrite8(NPCM_I2CCST_BB, bus->reg + NPCM_I2CCST);
16938c2ecf20Sopenharmony_ci	npcm_i2c_clear_tx_fifo(bus);
16948c2ecf20Sopenharmony_ci	npcm_i2c_clear_rx_fifo(bus);
16958c2ecf20Sopenharmony_ci	iowrite8(0, bus->reg + NPCM_I2CRXF_CTL);
16968c2ecf20Sopenharmony_ci	iowrite8(0, bus->reg + NPCM_I2CTXF_CTL);
16978c2ecf20Sopenharmony_ci	npcm_i2c_stall_after_start(bus, false);
16988c2ecf20Sopenharmony_ci
16998c2ecf20Sopenharmony_ci	/* select bank 1 for FIFO regs */
17008c2ecf20Sopenharmony_ci	npcm_i2c_select_bank(bus, I2C_BANK_1);
17018c2ecf20Sopenharmony_ci
17028c2ecf20Sopenharmony_ci	/* clear FIFO and relevant status bits. */
17038c2ecf20Sopenharmony_ci	fif_cts = ioread8(bus->reg + NPCM_I2CFIF_CTS);
17048c2ecf20Sopenharmony_ci	fif_cts &= ~NPCM_I2CFIF_CTS_SLVRSTR;
17058c2ecf20Sopenharmony_ci	fif_cts |= NPCM_I2CFIF_CTS_CLR_FIFO;
17068c2ecf20Sopenharmony_ci	iowrite8(fif_cts, bus->reg + NPCM_I2CFIF_CTS);
17078c2ecf20Sopenharmony_ci	npcm_i2c_set_fifo(bus, -1, 0);
17088c2ecf20Sopenharmony_ci
17098c2ecf20Sopenharmony_ci	/* Repeat the following sequence until SDA is released */
17108c2ecf20Sopenharmony_ci	do {
17118c2ecf20Sopenharmony_ci		/* Issue a single SCL toggle */
17128c2ecf20Sopenharmony_ci		iowrite8(NPCM_I2CCST_TGSCL, bus->reg + NPCM_I2CCST);
17138c2ecf20Sopenharmony_ci		usleep_range(20, 30);
17148c2ecf20Sopenharmony_ci		/* If SDA line is inactive (high), stop */
17158c2ecf20Sopenharmony_ci		if (npcm_i2c_get_SDA(_adap)) {
17168c2ecf20Sopenharmony_ci			done = true;
17178c2ecf20Sopenharmony_ci			status = 0;
17188c2ecf20Sopenharmony_ci		}
17198c2ecf20Sopenharmony_ci	} while (!done && iter--);
17208c2ecf20Sopenharmony_ci
17218c2ecf20Sopenharmony_ci	/* If SDA line is released: send start-addr-stop, to re-sync. */
17228c2ecf20Sopenharmony_ci	if (npcm_i2c_get_SDA(_adap)) {
17238c2ecf20Sopenharmony_ci		/* Send an address byte in write direction: */
17248c2ecf20Sopenharmony_ci		npcm_i2c_wr_byte(bus, bus->dest_addr);
17258c2ecf20Sopenharmony_ci		npcm_i2c_master_start(bus);
17268c2ecf20Sopenharmony_ci		/* Wait until START condition is sent */
17278c2ecf20Sopenharmony_ci		status = readx_poll_timeout(npcm_i2c_get_SCL, _adap, val, !val,
17288c2ecf20Sopenharmony_ci					    20, 200);
17298c2ecf20Sopenharmony_ci		/* If START condition was sent */
17308c2ecf20Sopenharmony_ci		if (npcm_i2c_is_master(bus) > 0) {
17318c2ecf20Sopenharmony_ci			usleep_range(20, 30);
17328c2ecf20Sopenharmony_ci			npcm_i2c_master_stop(bus);
17338c2ecf20Sopenharmony_ci			usleep_range(200, 500);
17348c2ecf20Sopenharmony_ci		}
17358c2ecf20Sopenharmony_ci	}
17368c2ecf20Sopenharmony_ci	npcm_i2c_reset(bus);
17378c2ecf20Sopenharmony_ci	npcm_i2c_int_enable(bus, true);
17388c2ecf20Sopenharmony_ci
17398c2ecf20Sopenharmony_ci	if ((npcm_i2c_get_SDA(_adap) == 1) && (npcm_i2c_get_SCL(_adap) == 1))
17408c2ecf20Sopenharmony_ci		status = 0;
17418c2ecf20Sopenharmony_ci	else
17428c2ecf20Sopenharmony_ci		status = -ENOTRECOVERABLE;
17438c2ecf20Sopenharmony_ci	if (status) {
17448c2ecf20Sopenharmony_ci		if (bus->rec_fail_cnt < ULLONG_MAX)
17458c2ecf20Sopenharmony_ci			bus->rec_fail_cnt++;
17468c2ecf20Sopenharmony_ci	} else {
17478c2ecf20Sopenharmony_ci		if (bus->rec_succ_cnt < ULLONG_MAX)
17488c2ecf20Sopenharmony_ci			bus->rec_succ_cnt++;
17498c2ecf20Sopenharmony_ci	}
17508c2ecf20Sopenharmony_ci	return status;
17518c2ecf20Sopenharmony_ci}
17528c2ecf20Sopenharmony_ci
17538c2ecf20Sopenharmony_ci/* recovery using bit banging functionality of the module */
17548c2ecf20Sopenharmony_cistatic void npcm_i2c_recovery_init(struct i2c_adapter *_adap)
17558c2ecf20Sopenharmony_ci{
17568c2ecf20Sopenharmony_ci	struct npcm_i2c *bus = container_of(_adap, struct npcm_i2c, adap);
17578c2ecf20Sopenharmony_ci	struct i2c_bus_recovery_info *rinfo = &bus->rinfo;
17588c2ecf20Sopenharmony_ci
17598c2ecf20Sopenharmony_ci	rinfo->recover_bus = npcm_i2c_recovery_tgclk;
17608c2ecf20Sopenharmony_ci
17618c2ecf20Sopenharmony_ci	/*
17628c2ecf20Sopenharmony_ci	 * npcm i2c HW allows direct reading of SCL and SDA.
17638c2ecf20Sopenharmony_ci	 * However, it does not support setting SCL and SDA directly.
17648c2ecf20Sopenharmony_ci	 * The recovery function can togle SCL when SDA is low (but not set)
17658c2ecf20Sopenharmony_ci	 * Getter functions used internally, and can be used externaly.
17668c2ecf20Sopenharmony_ci	 */
17678c2ecf20Sopenharmony_ci	rinfo->get_scl = npcm_i2c_get_SCL;
17688c2ecf20Sopenharmony_ci	rinfo->get_sda = npcm_i2c_get_SDA;
17698c2ecf20Sopenharmony_ci	_adap->bus_recovery_info = rinfo;
17708c2ecf20Sopenharmony_ci}
17718c2ecf20Sopenharmony_ci
17728c2ecf20Sopenharmony_ci/* SCLFRQ min/max field values */
17738c2ecf20Sopenharmony_ci#define SCLFRQ_MIN  10
17748c2ecf20Sopenharmony_ci#define SCLFRQ_MAX  511
17758c2ecf20Sopenharmony_ci#define clk_coef(freq, mul)	DIV_ROUND_UP((freq) * (mul), 1000000)
17768c2ecf20Sopenharmony_ci
17778c2ecf20Sopenharmony_ci/*
17788c2ecf20Sopenharmony_ci * npcm_i2c_init_clk: init HW timing parameters.
17798c2ecf20Sopenharmony_ci * NPCM7XX i2c module timing parameters are depenent on module core clk (APB)
17808c2ecf20Sopenharmony_ci * and bus frequency.
17818c2ecf20Sopenharmony_ci * 100kHz bus requires tSCL = 4 * SCLFRQ * tCLK. LT and HT are simetric.
17828c2ecf20Sopenharmony_ci * 400kHz bus requires assymetric HT and LT. A different equation is recomended
17838c2ecf20Sopenharmony_ci * by the HW designer, given core clock range (equations in comments below).
17848c2ecf20Sopenharmony_ci *
17858c2ecf20Sopenharmony_ci */
17868c2ecf20Sopenharmony_cistatic int npcm_i2c_init_clk(struct npcm_i2c *bus, u32 bus_freq_hz)
17878c2ecf20Sopenharmony_ci{
17888c2ecf20Sopenharmony_ci	u32  k1 = 0;
17898c2ecf20Sopenharmony_ci	u32  k2 = 0;
17908c2ecf20Sopenharmony_ci	u8   dbnct = 0;
17918c2ecf20Sopenharmony_ci	u32  sclfrq = 0;
17928c2ecf20Sopenharmony_ci	u8   hldt = 7;
17938c2ecf20Sopenharmony_ci	u8   fast_mode = 0;
17948c2ecf20Sopenharmony_ci	u32  src_clk_khz;
17958c2ecf20Sopenharmony_ci	u32  bus_freq_khz;
17968c2ecf20Sopenharmony_ci
17978c2ecf20Sopenharmony_ci	src_clk_khz = bus->apb_clk / 1000;
17988c2ecf20Sopenharmony_ci	bus_freq_khz = bus_freq_hz / 1000;
17998c2ecf20Sopenharmony_ci	bus->bus_freq = bus_freq_hz;
18008c2ecf20Sopenharmony_ci
18018c2ecf20Sopenharmony_ci	/* 100KHz and below: */
18028c2ecf20Sopenharmony_ci	if (bus_freq_hz <= I2C_MAX_STANDARD_MODE_FREQ) {
18038c2ecf20Sopenharmony_ci		sclfrq = src_clk_khz / (bus_freq_khz * 4);
18048c2ecf20Sopenharmony_ci
18058c2ecf20Sopenharmony_ci		if (sclfrq < SCLFRQ_MIN || sclfrq > SCLFRQ_MAX)
18068c2ecf20Sopenharmony_ci			return -EDOM;
18078c2ecf20Sopenharmony_ci
18088c2ecf20Sopenharmony_ci		if (src_clk_khz >= 40000)
18098c2ecf20Sopenharmony_ci			hldt = 17;
18108c2ecf20Sopenharmony_ci		else if (src_clk_khz >= 12500)
18118c2ecf20Sopenharmony_ci			hldt = 15;
18128c2ecf20Sopenharmony_ci		else
18138c2ecf20Sopenharmony_ci			hldt = 7;
18148c2ecf20Sopenharmony_ci	}
18158c2ecf20Sopenharmony_ci
18168c2ecf20Sopenharmony_ci	/* 400KHz: */
18178c2ecf20Sopenharmony_ci	else if (bus_freq_hz <= I2C_MAX_FAST_MODE_FREQ) {
18188c2ecf20Sopenharmony_ci		sclfrq = 0;
18198c2ecf20Sopenharmony_ci		fast_mode = I2CCTL3_400K_MODE;
18208c2ecf20Sopenharmony_ci
18218c2ecf20Sopenharmony_ci		if (src_clk_khz < 7500)
18228c2ecf20Sopenharmony_ci			/* 400KHZ cannot be supported for core clock < 7.5MHz */
18238c2ecf20Sopenharmony_ci			return -EDOM;
18248c2ecf20Sopenharmony_ci
18258c2ecf20Sopenharmony_ci		else if (src_clk_khz >= 50000) {
18268c2ecf20Sopenharmony_ci			k1 = 80;
18278c2ecf20Sopenharmony_ci			k2 = 48;
18288c2ecf20Sopenharmony_ci			hldt = 12;
18298c2ecf20Sopenharmony_ci			dbnct = 7;
18308c2ecf20Sopenharmony_ci		}
18318c2ecf20Sopenharmony_ci
18328c2ecf20Sopenharmony_ci		/* Master or Slave with frequency > 25MHz */
18338c2ecf20Sopenharmony_ci		else if (src_clk_khz > 25000) {
18348c2ecf20Sopenharmony_ci			hldt = clk_coef(src_clk_khz, 300) + 7;
18358c2ecf20Sopenharmony_ci			k1 = clk_coef(src_clk_khz, 1600);
18368c2ecf20Sopenharmony_ci			k2 = clk_coef(src_clk_khz, 900);
18378c2ecf20Sopenharmony_ci		}
18388c2ecf20Sopenharmony_ci	}
18398c2ecf20Sopenharmony_ci
18408c2ecf20Sopenharmony_ci	/* 1MHz: */
18418c2ecf20Sopenharmony_ci	else if (bus_freq_hz <= I2C_MAX_FAST_MODE_PLUS_FREQ) {
18428c2ecf20Sopenharmony_ci		sclfrq = 0;
18438c2ecf20Sopenharmony_ci		fast_mode = I2CCTL3_400K_MODE;
18448c2ecf20Sopenharmony_ci
18458c2ecf20Sopenharmony_ci		/* 1MHZ cannot be supported for core clock < 24 MHz */
18468c2ecf20Sopenharmony_ci		if (src_clk_khz < 24000)
18478c2ecf20Sopenharmony_ci			return -EDOM;
18488c2ecf20Sopenharmony_ci
18498c2ecf20Sopenharmony_ci		k1 = clk_coef(src_clk_khz, 620);
18508c2ecf20Sopenharmony_ci		k2 = clk_coef(src_clk_khz, 380);
18518c2ecf20Sopenharmony_ci
18528c2ecf20Sopenharmony_ci		/* Core clk > 40 MHz */
18538c2ecf20Sopenharmony_ci		if (src_clk_khz > 40000) {
18548c2ecf20Sopenharmony_ci			/*
18558c2ecf20Sopenharmony_ci			 * Set HLDT:
18568c2ecf20Sopenharmony_ci			 * SDA hold time:  (HLDT-7) * T(CLK) >= 120
18578c2ecf20Sopenharmony_ci			 * HLDT = 120/T(CLK) + 7 = 120 * FREQ(CLK) + 7
18588c2ecf20Sopenharmony_ci			 */
18598c2ecf20Sopenharmony_ci			hldt = clk_coef(src_clk_khz, 120) + 7;
18608c2ecf20Sopenharmony_ci		} else {
18618c2ecf20Sopenharmony_ci			hldt = 7;
18628c2ecf20Sopenharmony_ci			dbnct = 2;
18638c2ecf20Sopenharmony_ci		}
18648c2ecf20Sopenharmony_ci	}
18658c2ecf20Sopenharmony_ci
18668c2ecf20Sopenharmony_ci	/* Frequency larger than 1 MHz is not supported */
18678c2ecf20Sopenharmony_ci	else
18688c2ecf20Sopenharmony_ci		return -EINVAL;
18698c2ecf20Sopenharmony_ci
18708c2ecf20Sopenharmony_ci	if (bus_freq_hz >= I2C_MAX_FAST_MODE_FREQ) {
18718c2ecf20Sopenharmony_ci		k1 = round_up(k1, 2);
18728c2ecf20Sopenharmony_ci		k2 = round_up(k2 + 1, 2);
18738c2ecf20Sopenharmony_ci		if (k1 < SCLFRQ_MIN || k1 > SCLFRQ_MAX ||
18748c2ecf20Sopenharmony_ci		    k2 < SCLFRQ_MIN || k2 > SCLFRQ_MAX)
18758c2ecf20Sopenharmony_ci			return -EDOM;
18768c2ecf20Sopenharmony_ci	}
18778c2ecf20Sopenharmony_ci
18788c2ecf20Sopenharmony_ci	/* write sclfrq value. bits [6:0] are in I2CCTL2 reg */
18798c2ecf20Sopenharmony_ci	iowrite8(FIELD_PREP(I2CCTL2_SCLFRQ6_0, sclfrq & 0x7F),
18808c2ecf20Sopenharmony_ci		 bus->reg + NPCM_I2CCTL2);
18818c2ecf20Sopenharmony_ci
18828c2ecf20Sopenharmony_ci	/* bits [8:7] are in I2CCTL3 reg */
18838c2ecf20Sopenharmony_ci	iowrite8(fast_mode | FIELD_PREP(I2CCTL3_SCLFRQ8_7, (sclfrq >> 7) & 0x3),
18848c2ecf20Sopenharmony_ci		 bus->reg + NPCM_I2CCTL3);
18858c2ecf20Sopenharmony_ci
18868c2ecf20Sopenharmony_ci	/* Select Bank 0 to access NPCM_I2CCTL4/NPCM_I2CCTL5 */
18878c2ecf20Sopenharmony_ci	npcm_i2c_select_bank(bus, I2C_BANK_0);
18888c2ecf20Sopenharmony_ci
18898c2ecf20Sopenharmony_ci	if (bus_freq_hz >= I2C_MAX_FAST_MODE_FREQ) {
18908c2ecf20Sopenharmony_ci		/*
18918c2ecf20Sopenharmony_ci		 * Set SCL Low/High Time:
18928c2ecf20Sopenharmony_ci		 * k1 = 2 * SCLLT7-0 -> Low Time  = k1 / 2
18938c2ecf20Sopenharmony_ci		 * k2 = 2 * SCLLT7-0 -> High Time = k2 / 2
18948c2ecf20Sopenharmony_ci		 */
18958c2ecf20Sopenharmony_ci		iowrite8(k1 / 2, bus->reg + NPCM_I2CSCLLT);
18968c2ecf20Sopenharmony_ci		iowrite8(k2 / 2, bus->reg + NPCM_I2CSCLHT);
18978c2ecf20Sopenharmony_ci
18988c2ecf20Sopenharmony_ci		iowrite8(dbnct, bus->reg + NPCM_I2CCTL5);
18998c2ecf20Sopenharmony_ci	}
19008c2ecf20Sopenharmony_ci
19018c2ecf20Sopenharmony_ci	iowrite8(hldt, bus->reg + NPCM_I2CCTL4);
19028c2ecf20Sopenharmony_ci
19038c2ecf20Sopenharmony_ci	/* Return to Bank 1, and stay there by default: */
19048c2ecf20Sopenharmony_ci	npcm_i2c_select_bank(bus, I2C_BANK_1);
19058c2ecf20Sopenharmony_ci
19068c2ecf20Sopenharmony_ci	return 0;
19078c2ecf20Sopenharmony_ci}
19088c2ecf20Sopenharmony_ci
19098c2ecf20Sopenharmony_cistatic int npcm_i2c_init_module(struct npcm_i2c *bus, enum i2c_mode mode,
19108c2ecf20Sopenharmony_ci				u32 bus_freq_hz)
19118c2ecf20Sopenharmony_ci{
19128c2ecf20Sopenharmony_ci	u8 val;
19138c2ecf20Sopenharmony_ci	int ret;
19148c2ecf20Sopenharmony_ci
19158c2ecf20Sopenharmony_ci	/* Check whether module already enabled or frequency is out of bounds */
19168c2ecf20Sopenharmony_ci	if ((bus->state != I2C_DISABLE && bus->state != I2C_IDLE) ||
19178c2ecf20Sopenharmony_ci	    bus_freq_hz < I2C_FREQ_MIN_HZ || bus_freq_hz > I2C_FREQ_MAX_HZ)
19188c2ecf20Sopenharmony_ci		return -EINVAL;
19198c2ecf20Sopenharmony_ci
19208c2ecf20Sopenharmony_ci	npcm_i2c_int_enable(bus, false);
19218c2ecf20Sopenharmony_ci	npcm_i2c_disable(bus);
19228c2ecf20Sopenharmony_ci
19238c2ecf20Sopenharmony_ci	/* Configure FIFO mode : */
19248c2ecf20Sopenharmony_ci	if (FIELD_GET(I2C_VER_FIFO_EN, ioread8(bus->reg + I2C_VER))) {
19258c2ecf20Sopenharmony_ci		bus->fifo_use = true;
19268c2ecf20Sopenharmony_ci		npcm_i2c_select_bank(bus, I2C_BANK_0);
19278c2ecf20Sopenharmony_ci		val = ioread8(bus->reg + NPCM_I2CFIF_CTL);
19288c2ecf20Sopenharmony_ci		val |= NPCM_I2CFIF_CTL_FIFO_EN;
19298c2ecf20Sopenharmony_ci		iowrite8(val, bus->reg + NPCM_I2CFIF_CTL);
19308c2ecf20Sopenharmony_ci		npcm_i2c_select_bank(bus, I2C_BANK_1);
19318c2ecf20Sopenharmony_ci	} else {
19328c2ecf20Sopenharmony_ci		bus->fifo_use = false;
19338c2ecf20Sopenharmony_ci	}
19348c2ecf20Sopenharmony_ci
19358c2ecf20Sopenharmony_ci	/* Configure I2C module clock frequency */
19368c2ecf20Sopenharmony_ci	ret = npcm_i2c_init_clk(bus, bus_freq_hz);
19378c2ecf20Sopenharmony_ci	if (ret) {
19388c2ecf20Sopenharmony_ci		dev_err(bus->dev, "npcm_i2c_init_clk failed\n");
19398c2ecf20Sopenharmony_ci		return ret;
19408c2ecf20Sopenharmony_ci	}
19418c2ecf20Sopenharmony_ci
19428c2ecf20Sopenharmony_ci	/* Enable module (before configuring CTL1) */
19438c2ecf20Sopenharmony_ci	npcm_i2c_enable(bus);
19448c2ecf20Sopenharmony_ci	bus->state = I2C_IDLE;
19458c2ecf20Sopenharmony_ci	val = ioread8(bus->reg + NPCM_I2CCTL1);
19468c2ecf20Sopenharmony_ci	val = (val | NPCM_I2CCTL1_NMINTE) & ~NPCM_I2CCTL1_RWS;
19478c2ecf20Sopenharmony_ci	iowrite8(val, bus->reg + NPCM_I2CCTL1);
19488c2ecf20Sopenharmony_ci
19498c2ecf20Sopenharmony_ci	npcm_i2c_reset(bus);
19508c2ecf20Sopenharmony_ci
19518c2ecf20Sopenharmony_ci	/* check HW is OK: SDA and SCL should be high at this point. */
19528c2ecf20Sopenharmony_ci	if ((npcm_i2c_get_SDA(&bus->adap) == 0) || (npcm_i2c_get_SCL(&bus->adap) == 0)) {
19538c2ecf20Sopenharmony_ci		dev_err(bus->dev, "I2C%d init fail: lines are low\n", bus->num);
19548c2ecf20Sopenharmony_ci		dev_err(bus->dev, "SDA=%d SCL=%d\n", npcm_i2c_get_SDA(&bus->adap),
19558c2ecf20Sopenharmony_ci			npcm_i2c_get_SCL(&bus->adap));
19568c2ecf20Sopenharmony_ci		return -ENXIO;
19578c2ecf20Sopenharmony_ci	}
19588c2ecf20Sopenharmony_ci
19598c2ecf20Sopenharmony_ci	npcm_i2c_int_enable(bus, true);
19608c2ecf20Sopenharmony_ci	return 0;
19618c2ecf20Sopenharmony_ci}
19628c2ecf20Sopenharmony_ci
19638c2ecf20Sopenharmony_cistatic int __npcm_i2c_init(struct npcm_i2c *bus, struct platform_device *pdev)
19648c2ecf20Sopenharmony_ci{
19658c2ecf20Sopenharmony_ci	u32 clk_freq_hz;
19668c2ecf20Sopenharmony_ci	int ret;
19678c2ecf20Sopenharmony_ci
19688c2ecf20Sopenharmony_ci	/* Initialize the internal data structures */
19698c2ecf20Sopenharmony_ci	bus->state = I2C_DISABLE;
19708c2ecf20Sopenharmony_ci	bus->master_or_slave = I2C_SLAVE;
19718c2ecf20Sopenharmony_ci	bus->int_time_stamp = 0;
19728c2ecf20Sopenharmony_ci#if IS_ENABLED(CONFIG_I2C_SLAVE)
19738c2ecf20Sopenharmony_ci	bus->slave = NULL;
19748c2ecf20Sopenharmony_ci#endif
19758c2ecf20Sopenharmony_ci
19768c2ecf20Sopenharmony_ci	ret = device_property_read_u32(&pdev->dev, "clock-frequency",
19778c2ecf20Sopenharmony_ci				       &clk_freq_hz);
19788c2ecf20Sopenharmony_ci	if (ret) {
19798c2ecf20Sopenharmony_ci		dev_info(&pdev->dev, "Could not read clock-frequency property");
19808c2ecf20Sopenharmony_ci		clk_freq_hz = I2C_MAX_STANDARD_MODE_FREQ;
19818c2ecf20Sopenharmony_ci	}
19828c2ecf20Sopenharmony_ci
19838c2ecf20Sopenharmony_ci	ret = npcm_i2c_init_module(bus, I2C_MASTER, clk_freq_hz);
19848c2ecf20Sopenharmony_ci	if (ret) {
19858c2ecf20Sopenharmony_ci		dev_err(&pdev->dev, "npcm_i2c_init_module failed\n");
19868c2ecf20Sopenharmony_ci		return ret;
19878c2ecf20Sopenharmony_ci	}
19888c2ecf20Sopenharmony_ci
19898c2ecf20Sopenharmony_ci	return 0;
19908c2ecf20Sopenharmony_ci}
19918c2ecf20Sopenharmony_ci
19928c2ecf20Sopenharmony_cistatic irqreturn_t npcm_i2c_bus_irq(int irq, void *dev_id)
19938c2ecf20Sopenharmony_ci{
19948c2ecf20Sopenharmony_ci	struct npcm_i2c *bus = dev_id;
19958c2ecf20Sopenharmony_ci
19968c2ecf20Sopenharmony_ci	if (npcm_i2c_is_master(bus))
19978c2ecf20Sopenharmony_ci		bus->master_or_slave = I2C_MASTER;
19988c2ecf20Sopenharmony_ci
19998c2ecf20Sopenharmony_ci	if (bus->master_or_slave == I2C_MASTER) {
20008c2ecf20Sopenharmony_ci		bus->int_time_stamp = jiffies;
20018c2ecf20Sopenharmony_ci		if (!npcm_i2c_int_master_handler(bus))
20028c2ecf20Sopenharmony_ci			return IRQ_HANDLED;
20038c2ecf20Sopenharmony_ci	}
20048c2ecf20Sopenharmony_ci#if IS_ENABLED(CONFIG_I2C_SLAVE)
20058c2ecf20Sopenharmony_ci	if (bus->slave) {
20068c2ecf20Sopenharmony_ci		bus->master_or_slave = I2C_SLAVE;
20078c2ecf20Sopenharmony_ci		if (npcm_i2c_int_slave_handler(bus))
20088c2ecf20Sopenharmony_ci			return IRQ_HANDLED;
20098c2ecf20Sopenharmony_ci	}
20108c2ecf20Sopenharmony_ci#endif
20118c2ecf20Sopenharmony_ci	/* clear status bits for spurious interrupts */
20128c2ecf20Sopenharmony_ci	npcm_i2c_clear_master_status(bus);
20138c2ecf20Sopenharmony_ci
20148c2ecf20Sopenharmony_ci	return IRQ_HANDLED;
20158c2ecf20Sopenharmony_ci}
20168c2ecf20Sopenharmony_ci
20178c2ecf20Sopenharmony_cistatic bool npcm_i2c_master_start_xmit(struct npcm_i2c *bus,
20188c2ecf20Sopenharmony_ci				       u8 slave_addr, u16 nwrite, u16 nread,
20198c2ecf20Sopenharmony_ci				       u8 *write_data, u8 *read_data,
20208c2ecf20Sopenharmony_ci				       bool use_PEC, bool use_read_block)
20218c2ecf20Sopenharmony_ci{
20228c2ecf20Sopenharmony_ci	if (bus->state != I2C_IDLE) {
20238c2ecf20Sopenharmony_ci		bus->cmd_err = -EBUSY;
20248c2ecf20Sopenharmony_ci		return false;
20258c2ecf20Sopenharmony_ci	}
20268c2ecf20Sopenharmony_ci	bus->dest_addr = slave_addr << 1;
20278c2ecf20Sopenharmony_ci	bus->wr_buf = write_data;
20288c2ecf20Sopenharmony_ci	bus->wr_size = nwrite;
20298c2ecf20Sopenharmony_ci	bus->wr_ind = 0;
20308c2ecf20Sopenharmony_ci	bus->rd_buf = read_data;
20318c2ecf20Sopenharmony_ci	bus->rd_size = nread;
20328c2ecf20Sopenharmony_ci	bus->rd_ind = 0;
20338c2ecf20Sopenharmony_ci	bus->PEC_use = 0;
20348c2ecf20Sopenharmony_ci
20358c2ecf20Sopenharmony_ci	/* for tx PEC is appended to buffer from i2c IF. PEC flag is ignored */
20368c2ecf20Sopenharmony_ci	if (nread)
20378c2ecf20Sopenharmony_ci		bus->PEC_use = use_PEC;
20388c2ecf20Sopenharmony_ci
20398c2ecf20Sopenharmony_ci	bus->read_block_use = use_read_block;
20408c2ecf20Sopenharmony_ci	if (nread && !nwrite)
20418c2ecf20Sopenharmony_ci		bus->operation = I2C_READ_OPER;
20428c2ecf20Sopenharmony_ci	else
20438c2ecf20Sopenharmony_ci		bus->operation = I2C_WRITE_OPER;
20448c2ecf20Sopenharmony_ci	if (bus->fifo_use) {
20458c2ecf20Sopenharmony_ci		u8 i2cfif_cts;
20468c2ecf20Sopenharmony_ci
20478c2ecf20Sopenharmony_ci		npcm_i2c_select_bank(bus, I2C_BANK_1);
20488c2ecf20Sopenharmony_ci		/* clear FIFO and relevant status bits. */
20498c2ecf20Sopenharmony_ci		i2cfif_cts = ioread8(bus->reg + NPCM_I2CFIF_CTS);
20508c2ecf20Sopenharmony_ci		i2cfif_cts &= ~NPCM_I2CFIF_CTS_SLVRSTR;
20518c2ecf20Sopenharmony_ci		i2cfif_cts |= NPCM_I2CFIF_CTS_CLR_FIFO;
20528c2ecf20Sopenharmony_ci		iowrite8(i2cfif_cts, bus->reg + NPCM_I2CFIF_CTS);
20538c2ecf20Sopenharmony_ci	}
20548c2ecf20Sopenharmony_ci
20558c2ecf20Sopenharmony_ci	bus->state = I2C_IDLE;
20568c2ecf20Sopenharmony_ci	npcm_i2c_stall_after_start(bus, true);
20578c2ecf20Sopenharmony_ci	npcm_i2c_master_start(bus);
20588c2ecf20Sopenharmony_ci	return true;
20598c2ecf20Sopenharmony_ci}
20608c2ecf20Sopenharmony_ci
20618c2ecf20Sopenharmony_cistatic int npcm_i2c_master_xfer(struct i2c_adapter *adap, struct i2c_msg *msgs,
20628c2ecf20Sopenharmony_ci				int num)
20638c2ecf20Sopenharmony_ci{
20648c2ecf20Sopenharmony_ci	struct npcm_i2c *bus = container_of(adap, struct npcm_i2c, adap);
20658c2ecf20Sopenharmony_ci	struct i2c_msg *msg0, *msg1;
20668c2ecf20Sopenharmony_ci	unsigned long time_left, flags;
20678c2ecf20Sopenharmony_ci	u16 nwrite, nread;
20688c2ecf20Sopenharmony_ci	u8 *write_data, *read_data;
20698c2ecf20Sopenharmony_ci	u8 slave_addr;
20708c2ecf20Sopenharmony_ci	unsigned long timeout;
20718c2ecf20Sopenharmony_ci	bool read_block = false;
20728c2ecf20Sopenharmony_ci	bool read_PEC = false;
20738c2ecf20Sopenharmony_ci	u8 bus_busy;
20748c2ecf20Sopenharmony_ci	unsigned long timeout_usec;
20758c2ecf20Sopenharmony_ci
20768c2ecf20Sopenharmony_ci	if (bus->state == I2C_DISABLE) {
20778c2ecf20Sopenharmony_ci		dev_err(bus->dev, "I2C%d module is disabled", bus->num);
20788c2ecf20Sopenharmony_ci		return -EINVAL;
20798c2ecf20Sopenharmony_ci	}
20808c2ecf20Sopenharmony_ci
20818c2ecf20Sopenharmony_ci	msg0 = &msgs[0];
20828c2ecf20Sopenharmony_ci	slave_addr = msg0->addr;
20838c2ecf20Sopenharmony_ci	if (msg0->flags & I2C_M_RD) { /* read */
20848c2ecf20Sopenharmony_ci		nwrite = 0;
20858c2ecf20Sopenharmony_ci		write_data = NULL;
20868c2ecf20Sopenharmony_ci		read_data = msg0->buf;
20878c2ecf20Sopenharmony_ci		if (msg0->flags & I2C_M_RECV_LEN) {
20888c2ecf20Sopenharmony_ci			nread = 1;
20898c2ecf20Sopenharmony_ci			read_block = true;
20908c2ecf20Sopenharmony_ci			if (msg0->flags & I2C_CLIENT_PEC)
20918c2ecf20Sopenharmony_ci				read_PEC = true;
20928c2ecf20Sopenharmony_ci		} else {
20938c2ecf20Sopenharmony_ci			nread = msg0->len;
20948c2ecf20Sopenharmony_ci		}
20958c2ecf20Sopenharmony_ci	} else { /* write */
20968c2ecf20Sopenharmony_ci		nwrite = msg0->len;
20978c2ecf20Sopenharmony_ci		write_data = msg0->buf;
20988c2ecf20Sopenharmony_ci		nread = 0;
20998c2ecf20Sopenharmony_ci		read_data = NULL;
21008c2ecf20Sopenharmony_ci		if (num == 2) {
21018c2ecf20Sopenharmony_ci			msg1 = &msgs[1];
21028c2ecf20Sopenharmony_ci			read_data = msg1->buf;
21038c2ecf20Sopenharmony_ci			if (msg1->flags & I2C_M_RECV_LEN) {
21048c2ecf20Sopenharmony_ci				nread = 1;
21058c2ecf20Sopenharmony_ci				read_block = true;
21068c2ecf20Sopenharmony_ci				if (msg1->flags & I2C_CLIENT_PEC)
21078c2ecf20Sopenharmony_ci					read_PEC = true;
21088c2ecf20Sopenharmony_ci			} else {
21098c2ecf20Sopenharmony_ci				nread = msg1->len;
21108c2ecf20Sopenharmony_ci				read_block = false;
21118c2ecf20Sopenharmony_ci			}
21128c2ecf20Sopenharmony_ci		}
21138c2ecf20Sopenharmony_ci	}
21148c2ecf20Sopenharmony_ci
21158c2ecf20Sopenharmony_ci	/*
21168c2ecf20Sopenharmony_ci	 * Adaptive TimeOut: estimated time in usec + 100% margin:
21178c2ecf20Sopenharmony_ci	 * 2: double the timeout for clock stretching case
21188c2ecf20Sopenharmony_ci	 * 9: bits per transaction (including the ack/nack)
21198c2ecf20Sopenharmony_ci	 */
21208c2ecf20Sopenharmony_ci	timeout_usec = (2 * 9 * USEC_PER_SEC / bus->bus_freq) * (2 + nread + nwrite);
21218c2ecf20Sopenharmony_ci	timeout = max_t(unsigned long, bus->adap.timeout, usecs_to_jiffies(timeout_usec));
21228c2ecf20Sopenharmony_ci	if (nwrite >= 32 * 1024 || nread >= 32 * 1024) {
21238c2ecf20Sopenharmony_ci		dev_err(bus->dev, "i2c%d buffer too big\n", bus->num);
21248c2ecf20Sopenharmony_ci		return -EINVAL;
21258c2ecf20Sopenharmony_ci	}
21268c2ecf20Sopenharmony_ci
21278c2ecf20Sopenharmony_ci	time_left = jiffies + timeout + 1;
21288c2ecf20Sopenharmony_ci	do {
21298c2ecf20Sopenharmony_ci		/*
21308c2ecf20Sopenharmony_ci		 * we must clear slave address immediately when the bus is not
21318c2ecf20Sopenharmony_ci		 * busy, so we spinlock it, but we don't keep the lock for the
21328c2ecf20Sopenharmony_ci		 * entire while since it is too long.
21338c2ecf20Sopenharmony_ci		 */
21348c2ecf20Sopenharmony_ci		spin_lock_irqsave(&bus->lock, flags);
21358c2ecf20Sopenharmony_ci		bus_busy = ioread8(bus->reg + NPCM_I2CCST) & NPCM_I2CCST_BB;
21368c2ecf20Sopenharmony_ci#if IS_ENABLED(CONFIG_I2C_SLAVE)
21378c2ecf20Sopenharmony_ci		if (!bus_busy && bus->slave)
21388c2ecf20Sopenharmony_ci			iowrite8((bus->slave->addr & 0x7F),
21398c2ecf20Sopenharmony_ci				 bus->reg + NPCM_I2CADDR1);
21408c2ecf20Sopenharmony_ci#endif
21418c2ecf20Sopenharmony_ci		spin_unlock_irqrestore(&bus->lock, flags);
21428c2ecf20Sopenharmony_ci
21438c2ecf20Sopenharmony_ci	} while (time_is_after_jiffies(time_left) && bus_busy);
21448c2ecf20Sopenharmony_ci
21458c2ecf20Sopenharmony_ci	if (bus_busy) {
21468c2ecf20Sopenharmony_ci		iowrite8(NPCM_I2CCST_BB, bus->reg + NPCM_I2CCST);
21478c2ecf20Sopenharmony_ci		npcm_i2c_reset(bus);
21488c2ecf20Sopenharmony_ci		i2c_recover_bus(adap);
21498c2ecf20Sopenharmony_ci		return -EAGAIN;
21508c2ecf20Sopenharmony_ci	}
21518c2ecf20Sopenharmony_ci
21528c2ecf20Sopenharmony_ci	npcm_i2c_init_params(bus);
21538c2ecf20Sopenharmony_ci	bus->dest_addr = slave_addr;
21548c2ecf20Sopenharmony_ci	bus->msgs = msgs;
21558c2ecf20Sopenharmony_ci	bus->msgs_num = num;
21568c2ecf20Sopenharmony_ci	bus->cmd_err = 0;
21578c2ecf20Sopenharmony_ci	bus->read_block_use = read_block;
21588c2ecf20Sopenharmony_ci
21598c2ecf20Sopenharmony_ci	reinit_completion(&bus->cmd_complete);
21608c2ecf20Sopenharmony_ci
21618c2ecf20Sopenharmony_ci	npcm_i2c_int_enable(bus, true);
21628c2ecf20Sopenharmony_ci
21638c2ecf20Sopenharmony_ci	if (npcm_i2c_master_start_xmit(bus, slave_addr, nwrite, nread,
21648c2ecf20Sopenharmony_ci				       write_data, read_data, read_PEC,
21658c2ecf20Sopenharmony_ci				       read_block)) {
21668c2ecf20Sopenharmony_ci		time_left = wait_for_completion_timeout(&bus->cmd_complete,
21678c2ecf20Sopenharmony_ci							timeout);
21688c2ecf20Sopenharmony_ci
21698c2ecf20Sopenharmony_ci		if (time_left == 0) {
21708c2ecf20Sopenharmony_ci			if (bus->timeout_cnt < ULLONG_MAX)
21718c2ecf20Sopenharmony_ci				bus->timeout_cnt++;
21728c2ecf20Sopenharmony_ci			if (bus->master_or_slave == I2C_MASTER) {
21738c2ecf20Sopenharmony_ci				i2c_recover_bus(adap);
21748c2ecf20Sopenharmony_ci				bus->cmd_err = -EIO;
21758c2ecf20Sopenharmony_ci				bus->state = I2C_IDLE;
21768c2ecf20Sopenharmony_ci			}
21778c2ecf20Sopenharmony_ci		}
21788c2ecf20Sopenharmony_ci	}
21798c2ecf20Sopenharmony_ci
21808c2ecf20Sopenharmony_ci	/* if there was BER, check if need to recover the bus: */
21818c2ecf20Sopenharmony_ci	if (bus->cmd_err == -EAGAIN)
21828c2ecf20Sopenharmony_ci		bus->cmd_err = i2c_recover_bus(adap);
21838c2ecf20Sopenharmony_ci
21848c2ecf20Sopenharmony_ci	/*
21858c2ecf20Sopenharmony_ci	 * After any type of error, check if LAST bit is still set,
21868c2ecf20Sopenharmony_ci	 * due to a HW issue.
21878c2ecf20Sopenharmony_ci	 * It cannot be cleared without resetting the module.
21888c2ecf20Sopenharmony_ci	 */
21898c2ecf20Sopenharmony_ci	else if (bus->cmd_err &&
21908c2ecf20Sopenharmony_ci		 (NPCM_I2CRXF_CTL_LAST_PEC & ioread8(bus->reg + NPCM_I2CRXF_CTL)))
21918c2ecf20Sopenharmony_ci		npcm_i2c_reset(bus);
21928c2ecf20Sopenharmony_ci
21938c2ecf20Sopenharmony_ci	/* after any xfer, successful or not, stall and EOB must be disabled */
21948c2ecf20Sopenharmony_ci	npcm_i2c_stall_after_start(bus, false);
21958c2ecf20Sopenharmony_ci	npcm_i2c_eob_int(bus, false);
21968c2ecf20Sopenharmony_ci
21978c2ecf20Sopenharmony_ci#if IS_ENABLED(CONFIG_I2C_SLAVE)
21988c2ecf20Sopenharmony_ci	/* reenable slave if it was enabled */
21998c2ecf20Sopenharmony_ci	if (bus->slave)
22008c2ecf20Sopenharmony_ci		iowrite8((bus->slave->addr & 0x7F) | NPCM_I2CADDR_SAEN,
22018c2ecf20Sopenharmony_ci			 bus->reg + NPCM_I2CADDR1);
22028c2ecf20Sopenharmony_ci#else
22038c2ecf20Sopenharmony_ci	npcm_i2c_int_enable(bus, false);
22048c2ecf20Sopenharmony_ci#endif
22058c2ecf20Sopenharmony_ci	return bus->cmd_err;
22068c2ecf20Sopenharmony_ci}
22078c2ecf20Sopenharmony_ci
22088c2ecf20Sopenharmony_cistatic u32 npcm_i2c_functionality(struct i2c_adapter *adap)
22098c2ecf20Sopenharmony_ci{
22108c2ecf20Sopenharmony_ci	return I2C_FUNC_I2C |
22118c2ecf20Sopenharmony_ci	       I2C_FUNC_SMBUS_EMUL |
22128c2ecf20Sopenharmony_ci	       I2C_FUNC_SMBUS_BLOCK_DATA |
22138c2ecf20Sopenharmony_ci	       I2C_FUNC_SMBUS_PEC |
22148c2ecf20Sopenharmony_ci	       I2C_FUNC_SLAVE;
22158c2ecf20Sopenharmony_ci}
22168c2ecf20Sopenharmony_ci
22178c2ecf20Sopenharmony_cistatic const struct i2c_adapter_quirks npcm_i2c_quirks = {
22188c2ecf20Sopenharmony_ci	.max_read_len = 32768,
22198c2ecf20Sopenharmony_ci	.max_write_len = 32768,
22208c2ecf20Sopenharmony_ci	.flags = I2C_AQ_COMB_WRITE_THEN_READ,
22218c2ecf20Sopenharmony_ci};
22228c2ecf20Sopenharmony_ci
22238c2ecf20Sopenharmony_cistatic const struct i2c_algorithm npcm_i2c_algo = {
22248c2ecf20Sopenharmony_ci	.master_xfer = npcm_i2c_master_xfer,
22258c2ecf20Sopenharmony_ci	.functionality = npcm_i2c_functionality,
22268c2ecf20Sopenharmony_ci#if IS_ENABLED(CONFIG_I2C_SLAVE)
22278c2ecf20Sopenharmony_ci	.reg_slave	= npcm_i2c_reg_slave,
22288c2ecf20Sopenharmony_ci	.unreg_slave	= npcm_i2c_unreg_slave,
22298c2ecf20Sopenharmony_ci#endif
22308c2ecf20Sopenharmony_ci};
22318c2ecf20Sopenharmony_ci
22328c2ecf20Sopenharmony_ci/* i2c debugfs directory: used to keep health monitor of i2c devices */
22338c2ecf20Sopenharmony_cistatic struct dentry *npcm_i2c_debugfs_dir;
22348c2ecf20Sopenharmony_ci
22358c2ecf20Sopenharmony_cistatic void npcm_i2c_init_debugfs(struct platform_device *pdev,
22368c2ecf20Sopenharmony_ci				  struct npcm_i2c *bus)
22378c2ecf20Sopenharmony_ci{
22388c2ecf20Sopenharmony_ci	struct dentry *d;
22398c2ecf20Sopenharmony_ci
22408c2ecf20Sopenharmony_ci	if (!npcm_i2c_debugfs_dir)
22418c2ecf20Sopenharmony_ci		return;
22428c2ecf20Sopenharmony_ci	d = debugfs_create_dir(dev_name(&pdev->dev), npcm_i2c_debugfs_dir);
22438c2ecf20Sopenharmony_ci	if (IS_ERR_OR_NULL(d))
22448c2ecf20Sopenharmony_ci		return;
22458c2ecf20Sopenharmony_ci	debugfs_create_u64("ber_cnt", 0444, d, &bus->ber_cnt);
22468c2ecf20Sopenharmony_ci	debugfs_create_u64("nack_cnt", 0444, d, &bus->nack_cnt);
22478c2ecf20Sopenharmony_ci	debugfs_create_u64("rec_succ_cnt", 0444, d, &bus->rec_succ_cnt);
22488c2ecf20Sopenharmony_ci	debugfs_create_u64("rec_fail_cnt", 0444, d, &bus->rec_fail_cnt);
22498c2ecf20Sopenharmony_ci	debugfs_create_u64("timeout_cnt", 0444, d, &bus->timeout_cnt);
22508c2ecf20Sopenharmony_ci
22518c2ecf20Sopenharmony_ci	bus->debugfs = d;
22528c2ecf20Sopenharmony_ci}
22538c2ecf20Sopenharmony_ci
22548c2ecf20Sopenharmony_cistatic int npcm_i2c_probe_bus(struct platform_device *pdev)
22558c2ecf20Sopenharmony_ci{
22568c2ecf20Sopenharmony_ci	struct npcm_i2c *bus;
22578c2ecf20Sopenharmony_ci	struct i2c_adapter *adap;
22588c2ecf20Sopenharmony_ci	struct clk *i2c_clk;
22598c2ecf20Sopenharmony_ci	static struct regmap *gcr_regmap;
22608c2ecf20Sopenharmony_ci	static struct regmap *clk_regmap;
22618c2ecf20Sopenharmony_ci	int irq;
22628c2ecf20Sopenharmony_ci	int ret;
22638c2ecf20Sopenharmony_ci
22648c2ecf20Sopenharmony_ci	bus = devm_kzalloc(&pdev->dev, sizeof(*bus), GFP_KERNEL);
22658c2ecf20Sopenharmony_ci	if (!bus)
22668c2ecf20Sopenharmony_ci		return -ENOMEM;
22678c2ecf20Sopenharmony_ci
22688c2ecf20Sopenharmony_ci	bus->dev = &pdev->dev;
22698c2ecf20Sopenharmony_ci
22708c2ecf20Sopenharmony_ci	bus->num = of_alias_get_id(pdev->dev.of_node, "i2c");
22718c2ecf20Sopenharmony_ci	/* core clk must be acquired to calculate module timing settings */
22728c2ecf20Sopenharmony_ci	i2c_clk = devm_clk_get(&pdev->dev, NULL);
22738c2ecf20Sopenharmony_ci	if (IS_ERR(i2c_clk))
22748c2ecf20Sopenharmony_ci		return PTR_ERR(i2c_clk);
22758c2ecf20Sopenharmony_ci	bus->apb_clk = clk_get_rate(i2c_clk);
22768c2ecf20Sopenharmony_ci
22778c2ecf20Sopenharmony_ci	gcr_regmap = syscon_regmap_lookup_by_compatible("nuvoton,npcm750-gcr");
22788c2ecf20Sopenharmony_ci	if (IS_ERR(gcr_regmap))
22798c2ecf20Sopenharmony_ci		return PTR_ERR(gcr_regmap);
22808c2ecf20Sopenharmony_ci	regmap_write(gcr_regmap, NPCM_I2CSEGCTL, NPCM_I2CSEGCTL_INIT_VAL);
22818c2ecf20Sopenharmony_ci
22828c2ecf20Sopenharmony_ci	clk_regmap = syscon_regmap_lookup_by_compatible("nuvoton,npcm750-clk");
22838c2ecf20Sopenharmony_ci	if (IS_ERR(clk_regmap))
22848c2ecf20Sopenharmony_ci		return PTR_ERR(clk_regmap);
22858c2ecf20Sopenharmony_ci
22868c2ecf20Sopenharmony_ci	bus->reg = devm_platform_ioremap_resource(pdev, 0);
22878c2ecf20Sopenharmony_ci	if (IS_ERR(bus->reg))
22888c2ecf20Sopenharmony_ci		return PTR_ERR(bus->reg);
22898c2ecf20Sopenharmony_ci
22908c2ecf20Sopenharmony_ci	spin_lock_init(&bus->lock);
22918c2ecf20Sopenharmony_ci	init_completion(&bus->cmd_complete);
22928c2ecf20Sopenharmony_ci
22938c2ecf20Sopenharmony_ci	adap = &bus->adap;
22948c2ecf20Sopenharmony_ci	adap->owner = THIS_MODULE;
22958c2ecf20Sopenharmony_ci	adap->retries = 3;
22968c2ecf20Sopenharmony_ci	adap->timeout = msecs_to_jiffies(35);
22978c2ecf20Sopenharmony_ci	adap->algo = &npcm_i2c_algo;
22988c2ecf20Sopenharmony_ci	adap->quirks = &npcm_i2c_quirks;
22998c2ecf20Sopenharmony_ci	adap->algo_data = bus;
23008c2ecf20Sopenharmony_ci	adap->dev.parent = &pdev->dev;
23018c2ecf20Sopenharmony_ci	adap->dev.of_node = pdev->dev.of_node;
23028c2ecf20Sopenharmony_ci	adap->nr = pdev->id;
23038c2ecf20Sopenharmony_ci
23048c2ecf20Sopenharmony_ci	irq = platform_get_irq(pdev, 0);
23058c2ecf20Sopenharmony_ci	if (irq < 0)
23068c2ecf20Sopenharmony_ci		return irq;
23078c2ecf20Sopenharmony_ci
23088c2ecf20Sopenharmony_ci	ret = devm_request_irq(bus->dev, irq, npcm_i2c_bus_irq, 0,
23098c2ecf20Sopenharmony_ci			       dev_name(bus->dev), bus);
23108c2ecf20Sopenharmony_ci	if (ret)
23118c2ecf20Sopenharmony_ci		return ret;
23128c2ecf20Sopenharmony_ci
23138c2ecf20Sopenharmony_ci	ret = __npcm_i2c_init(bus, pdev);
23148c2ecf20Sopenharmony_ci	if (ret)
23158c2ecf20Sopenharmony_ci		return ret;
23168c2ecf20Sopenharmony_ci
23178c2ecf20Sopenharmony_ci	npcm_i2c_recovery_init(adap);
23188c2ecf20Sopenharmony_ci
23198c2ecf20Sopenharmony_ci	i2c_set_adapdata(adap, bus);
23208c2ecf20Sopenharmony_ci
23218c2ecf20Sopenharmony_ci	snprintf(bus->adap.name, sizeof(bus->adap.name), "npcm_i2c_%d",
23228c2ecf20Sopenharmony_ci		 bus->num);
23238c2ecf20Sopenharmony_ci	ret = i2c_add_numbered_adapter(&bus->adap);
23248c2ecf20Sopenharmony_ci	if (ret)
23258c2ecf20Sopenharmony_ci		return ret;
23268c2ecf20Sopenharmony_ci
23278c2ecf20Sopenharmony_ci	platform_set_drvdata(pdev, bus);
23288c2ecf20Sopenharmony_ci	npcm_i2c_init_debugfs(pdev, bus);
23298c2ecf20Sopenharmony_ci	return 0;
23308c2ecf20Sopenharmony_ci}
23318c2ecf20Sopenharmony_ci
23328c2ecf20Sopenharmony_cistatic int npcm_i2c_remove_bus(struct platform_device *pdev)
23338c2ecf20Sopenharmony_ci{
23348c2ecf20Sopenharmony_ci	unsigned long lock_flags;
23358c2ecf20Sopenharmony_ci	struct npcm_i2c *bus = platform_get_drvdata(pdev);
23368c2ecf20Sopenharmony_ci
23378c2ecf20Sopenharmony_ci	debugfs_remove_recursive(bus->debugfs);
23388c2ecf20Sopenharmony_ci	spin_lock_irqsave(&bus->lock, lock_flags);
23398c2ecf20Sopenharmony_ci	npcm_i2c_disable(bus);
23408c2ecf20Sopenharmony_ci	spin_unlock_irqrestore(&bus->lock, lock_flags);
23418c2ecf20Sopenharmony_ci	i2c_del_adapter(&bus->adap);
23428c2ecf20Sopenharmony_ci	return 0;
23438c2ecf20Sopenharmony_ci}
23448c2ecf20Sopenharmony_ci
23458c2ecf20Sopenharmony_cistatic const struct of_device_id npcm_i2c_bus_of_table[] = {
23468c2ecf20Sopenharmony_ci	{ .compatible = "nuvoton,npcm750-i2c", },
23478c2ecf20Sopenharmony_ci	{}
23488c2ecf20Sopenharmony_ci};
23498c2ecf20Sopenharmony_ciMODULE_DEVICE_TABLE(of, npcm_i2c_bus_of_table);
23508c2ecf20Sopenharmony_ci
23518c2ecf20Sopenharmony_cistatic struct platform_driver npcm_i2c_bus_driver = {
23528c2ecf20Sopenharmony_ci	.probe = npcm_i2c_probe_bus,
23538c2ecf20Sopenharmony_ci	.remove = npcm_i2c_remove_bus,
23548c2ecf20Sopenharmony_ci	.driver = {
23558c2ecf20Sopenharmony_ci		.name = "nuvoton-i2c",
23568c2ecf20Sopenharmony_ci		.of_match_table = npcm_i2c_bus_of_table,
23578c2ecf20Sopenharmony_ci	}
23588c2ecf20Sopenharmony_ci};
23598c2ecf20Sopenharmony_ci
23608c2ecf20Sopenharmony_cistatic int __init npcm_i2c_init(void)
23618c2ecf20Sopenharmony_ci{
23628c2ecf20Sopenharmony_ci	int ret;
23638c2ecf20Sopenharmony_ci
23648c2ecf20Sopenharmony_ci	npcm_i2c_debugfs_dir = debugfs_create_dir("npcm_i2c", NULL);
23658c2ecf20Sopenharmony_ci
23668c2ecf20Sopenharmony_ci	ret = platform_driver_register(&npcm_i2c_bus_driver);
23678c2ecf20Sopenharmony_ci	if (ret) {
23688c2ecf20Sopenharmony_ci		debugfs_remove_recursive(npcm_i2c_debugfs_dir);
23698c2ecf20Sopenharmony_ci		return ret;
23708c2ecf20Sopenharmony_ci	}
23718c2ecf20Sopenharmony_ci
23728c2ecf20Sopenharmony_ci	return 0;
23738c2ecf20Sopenharmony_ci}
23748c2ecf20Sopenharmony_cimodule_init(npcm_i2c_init);
23758c2ecf20Sopenharmony_ci
23768c2ecf20Sopenharmony_cistatic void __exit npcm_i2c_exit(void)
23778c2ecf20Sopenharmony_ci{
23788c2ecf20Sopenharmony_ci	platform_driver_unregister(&npcm_i2c_bus_driver);
23798c2ecf20Sopenharmony_ci	debugfs_remove_recursive(npcm_i2c_debugfs_dir);
23808c2ecf20Sopenharmony_ci}
23818c2ecf20Sopenharmony_cimodule_exit(npcm_i2c_exit);
23828c2ecf20Sopenharmony_ci
23838c2ecf20Sopenharmony_ciMODULE_AUTHOR("Avi Fishman <avi.fishman@gmail.com>");
23848c2ecf20Sopenharmony_ciMODULE_AUTHOR("Tali Perry <tali.perry@nuvoton.com>");
23858c2ecf20Sopenharmony_ciMODULE_AUTHOR("Tyrone Ting <kfting@nuvoton.com>");
23868c2ecf20Sopenharmony_ciMODULE_DESCRIPTION("Nuvoton I2C Bus Driver");
23878c2ecf20Sopenharmony_ciMODULE_LICENSE("GPL v2");
2388