/* SPDX-License-Identifier: GPL-2.0-only
 *
 * Copyright (c) 2022-2023 Qualcomm Innovation Center, Inc. All rights reserved.
 */

#ifndef _I2C_SLAVE_H_
#define _I2C_SLAVE_H_

#define I2C_S_DEVICE_ADDR		0x00
#define I2C_S_IRQ_STATUS		0x08
#define I2C_S_IRQ_CLR			0x0C
#define I2C_S_IRQ_EN			0x10
#define I2C_S_IRQ_FORCE			0x14
#define I2C_S_CONFIG			0x18
#define I2C_S_CONTROL			0x1C
#define I2C_S_FIFOS_STATUS		0x20
#define I2C_S_TX_FIFO			0x24
#define I2C_S_RX_FIFO			0x28
#define I2C_S_CORE_VERSION		0x2C
#define I2C_S_CHAR_DATA0		0x30
#define I2C_S_CHAR_DATA1		0x34
#define I2C_S_CHAR_CFG			0x38
#define I2C_S_DEBUG_REG1		0x3C
#define I2C_S_DEBUG_REG2		0x40
#define I2C_S_SW_RESET_REG		0x4C
#define I2C_S_CLK_LOW_TIMEOUT		0x50
#define I2C_S_CLK_RELEASE_DELAY_CNT_VAL	0x54
#define I2C_S_SDA_HOLD_CNT_VAL		0x58
#define SMBALERT_REG			0x5C
#define SMBALERT_STATUS_REG		0x60
#define SMBALERT_PEC_REG		0x64

/* I2C Slave CONFIG reg fields */
#define CORE_EN				(BIT(0))
#define GCA_SUPPORTED			(BIT(3))

/* I2C Slave CONTROL reg fields */
#define CLEAR_RX_FIFO			(BIT(0))
#define CLEAR_TX_FIFO			(BIT(1))
#define NACK				(BIT(2))
#define ACK_RESUME			(BIT(3))

/* I2C Slave SW RESET reg fields */
#define SW_RESET			(BIT(0))

/* I2C Slave CLK_LOW_TIMEOUT reg fields */
#define TIMER_MODE			(BIT(30))

#define SLAVE_ADDR			0x30
#define I2C_SLAVE_MAX_MSG_SIZE		32
#define I2C_SLAVE_BYTE_DATA		1
#define I2C_SLAVE_WORD_DATA		2
#define APPS_PROC_TO_I2C_SLAVE_VOTE	1190000

/* Dev node for poll function */
#define I2C_SLAVE_DEV			"i2c-poll"

#define I2C_SLAVE_ERR(log_ctx, print, dev, x...) \
	do { \
		ipc_log_string(log_ctx, x); \
		if (print) { \
			if (dev) \
				dev_err((dev), x); \
			else \
				pr_err(x); \
			if (dev) \
				i2c_slave_trace_log(dev, x); \
		} \
	} while (0)

#define I2C_SLAVE_DBG(log_ctx, print, dev, x...) \
	do { \
		ipc_log_string(log_ctx, x); \
		if (print) { \
			if (dev) \
				dev_info((dev), x); \
			else \
				pr_debug(x); \
			if (dev) \
				i2c_slave_trace_log(dev, x); \
		} \
	} while (0)

/* I2C_S_IRQ_STATUS fields */
enum i2c_slave_irq_status {
	STOP_DETECTED = 0,
	RX_FIFO_FULL,
	TX_FIFO_EMPTY,
	RX_DATA_AVAIL,
	CLOCK_LOW_TIMEOUT,
	STRCH_WR,
	STRCH_RD,
	GCA_DETECTED,
	ERR_CONDITION,
	RESTART_DETECTED,
	SMBALERT_ARA_DONE,
	SMBALERT_LOST_ARB,
	ALL_IRQ = 0xFFF
};

static const char * const irq_log[] = {
	[STOP_DETECTED] =       "Stop bit detected ",
	[RX_FIFO_FULL] =        "Rx FIFO Full",
	[TX_FIFO_EMPTY] =       "Tx FIFO empty",
	[RX_DATA_AVAIL] =       "Rx data available",
	[CLOCK_LOW_TIMEOUT] =   "Timeout happended",
	[STRCH_WR] =            "clock stretching during WR (Rx) phase",
	[STRCH_RD] =            "clock stretch during RD (Tx) phase.",
	[GCA_DETECTED] =        "General Call address detcted",
	[ERR_CONDITION] =       "Error condition: unexpected Start / Stop bits",
	[RESTART_DETECTED] =    "Repeated start bit detected",
	[SMBALERT_ARA_DONE] =   "ARA/SMBAlert done",
	[SMBALERT_LOST_ARB] =   "SLAVE arbitration lost",
};

/**
 * i2c_slave: Represent an I2C slave device
 * @client: Handle to slave device
 * @dev: Driver model device node for the slave.
 * @cdev: cdev struct to dev node
 * @base: pointer to HW register base address
 * @adapter: manages the bus segment hosting this I2C device
 * @ipcl: pointer to IPC log
 * @ahb_clk: Pointer to AHB Clock structure
 * @xo_clk: Pointer to XO Clock structure
 * @slave_addr: I2C slave address
 * @rx_count: RX data count
 * @rx_msg_buf: RX Data buffer
 * @tx_count: TX data count
 * @tx_msg_buf: TX Data buffer
 * @irq: IRQ generated by i2c slave
 * @icc_path: ICC path structure.
 * @bw: ICB bandwidth.
 * @readq: waitqueue for rx data.
 */
struct i2c_slave {
	struct i2c_client	*client;
	struct device		*dev;
	struct cdev		cdev;
	void __iomem		*base;
	struct i2c_adapter	adap;
	void			*ipcl;
	struct clk		*ahb_clk;
	struct clk		*xo_clk;
	int			slave_addr;
	u8			rx_count;
	u8			rx_msg_buf[I2C_SLAVE_MAX_MSG_SIZE];
	u8			tx_count;
	u8			*tx_msg_buf;
	int			irq;
	struct icc_path		*icc_path;
	unsigned int		bw;
	wait_queue_head_t	readq;
};
#endif /* _I2C_SLAVE_H_ */
