linux/drivers/i2c/busses/i2c-npcm7xx.c

// SPDX-License-Identifier: GPL-2.0
/*
 * Nuvoton NPCM7xx I2C Controller driver
 *
 * Copyright (C) 2020 Nuvoton Technologies [email protected]
 */
#include <linux/bitfield.h>
#include <linux/clk.h>
#include <linux/debugfs.h>
#include <linux/errno.h>
#include <linux/i2c.h>
#include <linux/interrupt.h>
#include <linux/iopoll.h>
#include <linux/irq.h>
#include <linux/jiffies.h>
#include <linux/kernel.h>
#include <linux/mfd/syscon.h>
#include <linux/module.h>
#include <linux/of.h>
#include <linux/platform_device.h>
#include <linux/regmap.h>

enum i2c_mode {};

/*
 * External I2C Interface driver xfer indication values, which indicate status
 * of the bus.
 */
enum i2c_state_ind {};

/*
 * Operation type values (used to define the operation currently running)
 * module is interrupt driven, on each interrupt the current operation is
 * checked to see if the module is currently reading or writing.
 */
enum i2c_oper {};

/* I2C Bank (module had 2 banks of registers) */
enum i2c_bank {};

/* Internal I2C states values (for the I2C module state machine). */
enum i2c_state {};

#if IS_ENABLED(CONFIG_I2C_SLAVE)
/* Module supports setting multiple own slave addresses */
enum i2c_addr {};
#endif

/* init register and default value required to enable module */
#define NPCM_I2CSEGCTL

/* Common regs */
#define NPCM_I2CSDA
#define NPCM_I2CST
#define NPCM_I2CCST
#define NPCM_I2CCTL1
#define NPCM_I2CADDR1
#define NPCM_I2CCTL2
#define NPCM_I2CADDR2
#define NPCM_I2CCTL3
#define NPCM_I2CCST2
#define NPCM_I2CCST3
#define I2C_VER

/* BANK 0 regs */
#define NPCM_I2CADDR3
#define NPCM_I2CADDR7
#define NPCM_I2CADDR4
#define NPCM_I2CADDR8
#define NPCM_I2CADDR5
#define NPCM_I2CADDR9
#define NPCM_I2CADDR6
#define NPCM_I2CADDR10
#define NPCM_I2CCTL4
#define NPCM_I2CCTL5
#define NPCM_I2CSCLLT
#define NPCM_I2CFIF_CTL
#define NPCM_I2CSCLHT

/* BANK 1 regs */
#define NPCM_I2CFIF_CTS
#define NPCM_I2CTXF_CTL
#define NPCM_I2CT_OUT
#define NPCM_I2CPEC
#define NPCM_I2CTXF_STS
#define NPCM_I2CRXF_STS
#define NPCM_I2CRXF_CTL

#if IS_ENABLED(CONFIG_I2C_SLAVE)
/*
 * npcm_i2caddr array:
 * The module supports having multiple own slave addresses.
 * Since the addr regs are sprinkled all over the address space,
 * use this array to get the address or each register.
 */
#define I2C_NUM_OWN_ADDR
#define I2C_NUM_OWN_ADDR_SUPPORTED

static const int npcm_i2caddr[I2C_NUM_OWN_ADDR] =;
#endif

/* NPCM_I2CST reg fields */
#define NPCM_I2CST_XMIT
#define NPCM_I2CST_MASTER
#define NPCM_I2CST_NMATCH
#define NPCM_I2CST_STASTR
#define NPCM_I2CST_NEGACK
#define NPCM_I2CST_BER
#define NPCM_I2CST_SDAST
#define NPCM_I2CST_SLVSTP

/* NPCM_I2CCST reg fields */
#define NPCM_I2CCST_BUSY
#define NPCM_I2CCST_BB
#define NPCM_I2CCST_MATCH
#define NPCM_I2CCST_GCMATCH
#define NPCM_I2CCST_TSDA
#define NPCM_I2CCST_TGSCL
#define NPCM_I2CCST_MATCHAF
#define NPCM_I2CCST_ARPMATCH

/* NPCM_I2CCTL1 reg fields */
#define NPCM_I2CCTL1_START
#define NPCM_I2CCTL1_STOP
#define NPCM_I2CCTL1_INTEN
#define NPCM_I2CCTL1_EOBINTE
#define NPCM_I2CCTL1_ACK
#define NPCM_I2CCTL1_GCMEN
#define NPCM_I2CCTL1_NMINTE
#define NPCM_I2CCTL1_STASTRE

/* RW1S fields (inside a RW reg): */
#define NPCM_I2CCTL1_RWS

/* npcm_i2caddr reg fields */
#define NPCM_I2CADDR_A
#define NPCM_I2CADDR_SAEN

/* NPCM_I2CCTL2 reg fields */
#define I2CCTL2_ENABLE
#define I2CCTL2_SCLFRQ6_0

/* NPCM_I2CCTL3 reg fields */
#define I2CCTL3_SCLFRQ8_7
#define I2CCTL3_ARPMEN
#define I2CCTL3_IDL_START
#define I2CCTL3_400K_MODE
#define I2CCTL3_BNK_SEL
#define I2CCTL3_SDA_LVL
#define I2CCTL3_SCL_LVL

/* NPCM_I2CCST2 reg fields */
#define NPCM_I2CCST2_MATCHA1F
#define NPCM_I2CCST2_MATCHA2F
#define NPCM_I2CCST2_MATCHA3F
#define NPCM_I2CCST2_MATCHA4F
#define NPCM_I2CCST2_MATCHA5F
#define NPCM_I2CCST2_MATCHA6F
#define NPCM_I2CCST2_MATCHA7F
#define NPCM_I2CCST2_INTSTS

/* NPCM_I2CCST3 reg fields */
#define NPCM_I2CCST3_MATCHA8F
#define NPCM_I2CCST3_MATCHA9F
#define NPCM_I2CCST3_MATCHA10F
#define NPCM_I2CCST3_EO_BUSY

/* NPCM_I2CCTL4 reg fields */
#define I2CCTL4_HLDT
#define I2CCTL4_LVL_WE

/* NPCM_I2CCTL5 reg fields */
#define I2CCTL5_DBNCT

/* NPCM_I2CFIF_CTS reg fields */
#define NPCM_I2CFIF_CTS_RXF_TXE
#define NPCM_I2CFIF_CTS_RFTE_IE
#define NPCM_I2CFIF_CTS_CLR_FIFO
#define NPCM_I2CFIF_CTS_SLVRSTR

/* NPCM_I2CTXF_CTL reg field */
#define NPCM_I2CTXF_CTL_THR_TXIE

/* NPCM_I2CT_OUT reg fields */
#define NPCM_I2CT_OUT_TO_CKDIV
#define NPCM_I2CT_OUT_T_OUTIE
#define NPCM_I2CT_OUT_T_OUTST

/* NPCM_I2CTXF_STS reg fields */
#define NPCM_I2CTXF_STS_TX_THST

/* NPCM_I2CRXF_STS reg fields */
#define NPCM_I2CRXF_STS_RX_THST

/* NPCM_I2CFIF_CTL reg fields */
#define NPCM_I2CFIF_CTL_FIFO_EN

/* NPCM_I2CRXF_CTL reg fields */
#define NPCM_I2CRXF_CTL_THR_RXIE

#define MAX_I2C_HW_FIFO_SIZE

/* I2C_VER reg fields */
#define I2C_VER_VERSION
#define I2C_VER_FIFO_EN

/* stall/stuck timeout in us */
#define DEFAULT_STALL_COUNT

/* SCLFRQ field position */
#define SCLFRQ_0_TO_6
#define SCLFRQ_7_TO_8

/* supported clk settings. values in Hz. */
#define I2C_FREQ_MIN_HZ
#define I2C_FREQ_MAX_HZ

struct npcm_i2c_data {};

static const struct npcm_i2c_data npxm7xx_i2c_data =;

static const struct npcm_i2c_data npxm8xx_i2c_data =;

/* Status of one I2C module */
struct npcm_i2c {};

static inline void npcm_i2c_select_bank(struct npcm_i2c *bus,
					enum i2c_bank bank)
{}

static void npcm_i2c_init_params(struct npcm_i2c *bus)
{}

static inline void npcm_i2c_wr_byte(struct npcm_i2c *bus, u8 data)
{}

static inline u8 npcm_i2c_rd_byte(struct npcm_i2c *bus)
{}

static int npcm_i2c_get_SCL(struct i2c_adapter *_adap)
{}

static int npcm_i2c_get_SDA(struct i2c_adapter *_adap)
{}

static inline u16 npcm_i2c_get_index(struct npcm_i2c *bus)
{}

/* quick protocol (just address) */
static inline bool npcm_i2c_is_quick(struct npcm_i2c *bus)
{}

static void npcm_i2c_disable(struct npcm_i2c *bus)
{}

static void npcm_i2c_enable(struct npcm_i2c *bus)
{}

/* enable\disable end of busy (EOB) interrupts */
static inline void npcm_i2c_eob_int(struct npcm_i2c *bus, bool enable)
{}

static inline bool npcm_i2c_tx_fifo_empty(struct npcm_i2c *bus)
{}

static inline bool npcm_i2c_rx_fifo_full(struct npcm_i2c *bus)
{}

static inline void npcm_i2c_clear_fifo_int(struct npcm_i2c *bus)
{}

static inline void npcm_i2c_clear_tx_fifo(struct npcm_i2c *bus)
{}

static inline void npcm_i2c_clear_rx_fifo(struct npcm_i2c *bus)
{}

static void npcm_i2c_int_enable(struct npcm_i2c *bus, bool enable)
{}

static inline void npcm_i2c_master_start(struct npcm_i2c *bus)
{}

static inline void npcm_i2c_master_stop(struct npcm_i2c *bus)
{}

static inline void npcm_i2c_stall_after_start(struct npcm_i2c *bus, bool stall)
{}

static inline void npcm_i2c_nack(struct npcm_i2c *bus)
{}

static inline void npcm_i2c_clear_master_status(struct npcm_i2c *bus)
{}

#if IS_ENABLED(CONFIG_I2C_SLAVE)
static void npcm_i2c_slave_int_enable(struct npcm_i2c *bus, bool enable)
{}

static int npcm_i2c_slave_enable(struct npcm_i2c *bus, enum i2c_addr addr_type,
				 u8 addr, bool enable)
{}
#endif

static void npcm_i2c_reset(struct npcm_i2c *bus)
{}

static inline bool npcm_i2c_is_master(struct npcm_i2c *bus)
{}

static void npcm_i2c_callback(struct npcm_i2c *bus,
			      enum i2c_state_ind op_status, u16 info)
{}

static u8 npcm_i2c_fifo_usage(struct npcm_i2c *bus)
{}

static void npcm_i2c_write_to_fifo_master(struct npcm_i2c *bus, u16 max_bytes)
{}

/*
 * npcm_i2c_set_fifo:
 * configure the FIFO before using it. If nread is -1 RX FIFO will not be
 * configured. same for nwrite
 */
static void npcm_i2c_set_fifo(struct npcm_i2c *bus, int nread, int nwrite)
{}

static void npcm_i2c_read_fifo(struct npcm_i2c *bus, u8 bytes_in_fifo)
{}

static void npcm_i2c_master_abort(struct npcm_i2c *bus)
{}

#if IS_ENABLED(CONFIG_I2C_SLAVE)
static u8 npcm_i2c_get_slave_addr(struct npcm_i2c *bus, enum i2c_addr addr_type)
{}

static int npcm_i2c_remove_slave_addr(struct npcm_i2c *bus, u8 slave_add)
{}

static void npcm_i2c_write_fifo_slave(struct npcm_i2c *bus, u16 max_bytes)
{}

static void npcm_i2c_read_fifo_slave(struct npcm_i2c *bus, u8 bytes_in_fifo)
{}

static int npcm_i2c_slave_get_wr_buf(struct npcm_i2c *bus)
{}

static void npcm_i2c_slave_send_rd_buf(struct npcm_i2c *bus)
{}

static void npcm_i2c_slave_receive(struct npcm_i2c *bus, u16 nread,
				   u8 *read_data)
{}

static void npcm_i2c_slave_xmit(struct npcm_i2c *bus, u16 nwrite,
				u8 *write_data)
{}

/*
 * npcm_i2c_slave_wr_buf_sync:
 * currently slave IF only supports single byte operations.
 * in order to utilize the npcm HW FIFO, the driver will ask for 16 bytes
 * at a time, pack them in buffer, and then transmit them all together
 * to the FIFO and onward to the bus.
 * NACK on read will be once reached to bus->adap->quirks->max_read_len.
 * sending a NACK wherever the backend requests for it is not supported.
 * the next two functions allow reading to local buffer before writing it all
 * to the HW FIFO.
 */
static void npcm_i2c_slave_wr_buf_sync(struct npcm_i2c *bus)
{}

static void npcm_i2c_slave_rd_wr(struct npcm_i2c *bus)
{}

static irqreturn_t npcm_i2c_int_slave_handler(struct npcm_i2c *bus)
{}

static int npcm_i2c_reg_slave(struct i2c_client *client)
{}

static int npcm_i2c_unreg_slave(struct i2c_client *client)
{}
#endif /* CONFIG_I2C_SLAVE */

static void npcm_i2c_master_fifo_read(struct npcm_i2c *bus)
{}

static void npcm_i2c_irq_master_handler_write(struct npcm_i2c *bus)
{}

static void npcm_i2c_irq_master_handler_read(struct npcm_i2c *bus)
{}

static void npcm_i2c_irq_handle_nmatch(struct npcm_i2c *bus)
{}

/* A NACK has occurred */
static void npcm_i2c_irq_handle_nack(struct npcm_i2c *bus)
{}

	/* Master mode: a Bus Error has been identified */
static void npcm_i2c_irq_handle_ber(struct npcm_i2c *bus)
{}

	/* EOB: a master End Of Busy (meaning STOP completed) */
static void npcm_i2c_irq_handle_eob(struct npcm_i2c *bus)
{}

/* Address sent and requested stall occurred (Master mode) */
static void npcm_i2c_irq_handle_stall_after_start(struct npcm_i2c *bus)
{}

/* SDA status is set - TX or RX, master */
static void npcm_i2c_irq_handle_sda(struct npcm_i2c *bus, u8 i2cst)
{}

static int npcm_i2c_int_master_handler(struct npcm_i2c *bus)
{}

/* recovery using TGCLK functionality of the module */
static int npcm_i2c_recovery_tgclk(struct i2c_adapter *_adap)
{}

/* recovery using bit banging functionality of the module */
static void npcm_i2c_recovery_init(struct i2c_adapter *_adap)
{}

/* SCLFRQ min/max field values */
#define SCLFRQ_MIN
#define SCLFRQ_MAX
#define clk_coef(freq, mul)

/*
 * npcm_i2c_init_clk: init HW timing parameters.
 * NPCM7XX i2c module timing parameters are dependent on module core clk (APB)
 * and bus frequency.
 * 100kHz bus requires tSCL = 4 * SCLFRQ * tCLK. LT and HT are symmetric.
 * 400kHz bus requires asymmetric HT and LT. A different equation is recommended
 * by the HW designer, given core clock range (equations in comments below).
 *
 */
static int npcm_i2c_init_clk(struct npcm_i2c *bus, u32 bus_freq_hz)
{}

static int npcm_i2c_init_module(struct npcm_i2c *bus, enum i2c_mode mode,
				u32 bus_freq_hz)
{}

static int __npcm_i2c_init(struct npcm_i2c *bus, struct platform_device *pdev)
{}

static irqreturn_t npcm_i2c_bus_irq(int irq, void *dev_id)
{}

static bool npcm_i2c_master_start_xmit(struct npcm_i2c *bus,
				       u8 slave_addr, u16 nwrite, u16 nread,
				       u8 *write_data, u8 *read_data,
				       bool use_PEC, bool use_read_block)
{}

static int npcm_i2c_master_xfer(struct i2c_adapter *adap, struct i2c_msg *msgs,
				int num)
{}

static u32 npcm_i2c_functionality(struct i2c_adapter *adap)
{}

static const struct i2c_adapter_quirks npcm_i2c_quirks =;

static const struct i2c_algorithm npcm_i2c_algo =;

static void npcm_i2c_init_debugfs(struct platform_device *pdev,
				  struct npcm_i2c *bus)
{}

static int npcm_i2c_probe_bus(struct platform_device *pdev)
{}

static void npcm_i2c_remove_bus(struct platform_device *pdev)
{}

static const struct of_device_id npcm_i2c_bus_of_table[] =;
MODULE_DEVICE_TABLE(of, npcm_i2c_bus_of_table);

static struct platform_driver npcm_i2c_bus_driver =;

module_platform_driver();

MODULE_AUTHOR();
MODULE_AUTHOR();
MODULE_AUTHOR();
MODULE_DESCRIPTION();
MODULE_LICENSE();