All of lore.kernel.org
 help / color / mirror / Atom feed
From: Brendan Higgins <brendanhiggins-hpIqsD4AKlfQT0dZR+AlfA@public.gmane.org>
To: Tali Perry <tali.perry1-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org>
Cc: robh+dt-DgEjT+Ai2ygdnm+yROfE0A@public.gmane.org,
	mark.rutland-5wv7dgnIgG8@public.gmane.org,
	yuenn-hpIqsD4AKlfQT0dZR+AlfA@public.gmane.org,
	venture-hpIqsD4AKlfQT0dZR+AlfA@public.gmane.org,
	benjaminfair-hpIqsD4AKlfQT0dZR+AlfA@public.gmane.org,
	avifishman70-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org,
	joel-U3u1mxZcP9KHXe+LvDLADg@public.gmane.org,
	tmaimon77-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org,
	wsa-z923LK4zBo2bacvFa/9K2g@public.gmane.org,
	syniurge-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org,
	linux-i2c-u79uwXL29TY76Z2rM5mHXA@public.gmane.org,
	openbmc-uLR06cmDAlY/bJ5BZ2RsiQ@public.gmane.org,
	devicetree-u79uwXL29TY76Z2rM5mHXA@public.gmane.org,
	linux-kernel-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
Subject: Re: [PATCH v7 2/2] i2c: npcm: Add Nuvoton NPCM I2C controller driver
Date: Tue, 25 Feb 2020 12:01:04 -0800	[thread overview]
Message-ID: <20200225200104.GA105722@google.com> (raw)
In-Reply-To: <20191121095350.158689-3-tali.perry1-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org>

On Thu, Nov 21, 2019 at 11:53:50AM +0200, Tali Perry wrote:
> Add Nuvoton NPCM BMC i2c controller driver.
> 
> Signed-off-by: Tali Perry <tali.perry1-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org>
> ---
>  drivers/i2c/busses/Kconfig       |   11 +
>  drivers/i2c/busses/Makefile      |    1 +
>  drivers/i2c/busses/i2c-npcm7xx.c | 2485 ++++++++++++++++++++++++++++++
>  3 files changed, 2497 insertions(+)
>  create mode 100644 drivers/i2c/busses/i2c-npcm7xx.c
> 
> diff --git a/drivers/i2c/busses/Kconfig b/drivers/i2c/busses/Kconfig
> index 146ce40d8e0a..9091b93aaf90 100644
> --- a/drivers/i2c/busses/Kconfig
> +++ b/drivers/i2c/busses/Kconfig
> @@ -786,6 +786,17 @@ config I2C_NOMADIK
>  	  I2C interface from ST-Ericsson's Nomadik and Ux500 architectures,
>  	  as well as the STA2X11 PCIe I/O HUB.
>  
> +config I2C_NPCM7XX
> +	tristate "Nuvoton I2C Controller"
> +	depends on ARCH_NPCM7XX

This should also depend on "|| COMPILE_TEST"

> +	select I2C_SLAVE

Personally, I would prefer if this was optional, but it's up to you.

> +	help
> +	  If you say yes to this option, support will be included for the
> +	  Nuvoton I2C controller.

Might want to elaborate about the capabilities of the driver/hardware.

> +	  This driver can also be built as a module.  If so, the module
> +	  will be called i2c-npcm7xx.

Probably unnecessary; this follows the pattern that most other I2C
drivers do.

>  config I2C_OCORES
>  	tristate "OpenCores I2C Controller"
>  	help
> diff --git a/drivers/i2c/busses/Makefile b/drivers/i2c/busses/Makefile
> index 3ab8aebc39c9..4af59a806f3c 100644
> --- a/drivers/i2c/busses/Makefile
> +++ b/drivers/i2c/busses/Makefile
> @@ -81,6 +81,7 @@ obj-$(CONFIG_I2C_MT7621)	+= i2c-mt7621.o
>  obj-$(CONFIG_I2C_MV64XXX)	+= i2c-mv64xxx.o
>  obj-$(CONFIG_I2C_MXS)		+= i2c-mxs.o
>  obj-$(CONFIG_I2C_NOMADIK)	+= i2c-nomadik.o
> +obj-$(CONFIG_I2C_NPCM7XX)	+= i2c-npcm7xx.o
>  obj-$(CONFIG_I2C_OCORES)	+= i2c-ocores.o
>  obj-$(CONFIG_I2C_OMAP)		+= i2c-omap.o
>  obj-$(CONFIG_I2C_OWL)		+= i2c-owl.o
> diff --git a/drivers/i2c/busses/i2c-npcm7xx.c b/drivers/i2c/busses/i2c-npcm7xx.c
> new file mode 100644
> index 000000000000..ce9699d56835
> --- /dev/null
> +++ b/drivers/i2c/busses/i2c-npcm7xx.c
> @@ -0,0 +1,2485 @@
> +// SPDX-License-Identifier: GPL-2.0
> +/*
> + * Nuvoton NPCM7xx SMB Controller driver
> + *
> + * Copyright (C) 2018 Nuvoton Technologies tali.perry-KrzQf0k3Iz9BDgjK7y7TUQ@public.gmane.org

You should update the date.

> + */
> +#include <linux/bitfield.h>
> +#include <linux/clk.h>
> +#include <linux/errno.h>
> +#include <linux/i2c.h>
> +#include <linux/interrupt.h>
> +#include <linux/irq.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>
> +#include <linux/jiffies.h>
> +
> +#define I2C_VERSION "0.1.0"

nit: You only use this macro in one place. I think it would be clearer
to just use the raw string there.

> +
> +enum smb_mode {
> +	SMB_SLAVE = 1,
> +	SMB_MASTER
> +};

Please use proper namespacing.

> +/*
> + * External SMB Interface driver xfer indication values, which indicate status
> + * of the bus.
> + */
> +enum smb_state_ind {
> +	SMB_NO_STATUS_IND = 0,
> +	SMB_SLAVE_RCV_IND = 1,
> +	SMB_SLAVE_XMIT_IND = 2,
> +	SMB_SLAVE_XMIT_MISSING_DATA_IND = 3,
> +	SMB_SLAVE_RESTART_IND = 4,
> +	SMB_SLAVE_DONE_IND = 5,
> +	SMB_MASTER_DONE_IND = 6,
> +	SMB_NACK_IND = 8,
> +	SMB_BUS_ERR_IND = 9,
> +	SMB_WAKE_UP_IND = 10,
> +	SMB_BLOCK_BYTES_ERR_IND = 12,
> +	SMB_SLAVE_RCV_MISSING_DATA_IND = 14,
> +};
> +
> +// SMBus Operation type values
> +enum smb_oper {
> +	SMB_NO_OPER = 0,
> +	SMB_WRITE_OPER = 1,
> +	SMB_READ_OPER = 2
> +};
> +
> +// SMBus Bank (FIFO mode)
> +enum smb_bank {
> +	SMB_BANK_0 = 0,
> +	SMB_BANK_1 = 1
> +};
> +
> +// Internal SMB states values (for the SMB module state machine).
> +enum smb_state {
> +	SMB_DISABLE = 0,
> +	SMB_IDLE,
> +	SMB_MASTER_START,
> +	SMB_SLAVE_MATCH,
> +	SMB_OPER_STARTED,
> +	SMB_STOP_PENDING
> +};
> +
> +// Module supports setting multiple own slave addresses
> +enum smb_addr {
> +	SMB_SLAVE_ADDR1 = 0,
> +	SMB_SLAVE_ADDR2,
> +	SMB_SLAVE_ADDR3,
> +	SMB_SLAVE_ADDR4,
> +	SMB_SLAVE_ADDR5,
> +	SMB_SLAVE_ADDR6,
> +	SMB_SLAVE_ADDR7,
> +	SMB_SLAVE_ADDR8,
> +	SMB_SLAVE_ADDR9,
> +	SMB_SLAVE_ADDR10,
> +	SMB_GC_ADDR,
> +	SMB_ARP_ADDR
> +};
> +
> +// global regs
> +static struct regmap *gcr_regmap;
> +static struct regmap *clk_regmap;

It's generally best to avoid global variables.

> +#define NPCM_I2CSEGCTL  0xE4
> +#define I2CSEGCTL_VAL	0x0333F000

What is this value? It doesn't look like a register offset.

> +// Common regs
> +#define NPCM_SMBSDA			0x000
> +#define NPCM_SMBST			0x002
> +#define NPCM_SMBCST			0x004
> +#define NPCM_SMBCTL1			0x006
> +#define NPCM_SMBADDR1			0x008
> +#define NPCM_SMBCTL2			0x00A
> +#define NPCM_SMBADDR2			0x00C
> +#define NPCM_SMBCTL3			0x00E
> +#define NPCM_SMBCST2			0x018
> +#define NPCM_SMBCST3			0x019
> +#define SMB_VER				0x01F

nit: I am guessing these are not 12 bit values. Can you use just two digits?

> +// BANK 0 regs
> +#define NPCM_SMBADDR3			0x010
> +#define NPCM_SMBADDR7			0x011
> +#define NPCM_SMBADDR4			0x012
> +#define NPCM_SMBADDR8			0x013
> +#define NPCM_SMBADDR5			0x014
> +#define NPCM_SMBADDR9			0x015
> +#define NPCM_SMBADDR6			0x016
> +#define NPCM_SMBADDR10			0x017
> +
> +// SMBADDR array: because the addr regs are sprinkled all over the address space
> +const int  NPCM_SMBADDR[10] = {NPCM_SMBADDR1, NPCM_SMBADDR2, NPCM_SMBADDR3,

Please only use all caps for macros.

> +			       NPCM_SMBADDR4, NPCM_SMBADDR5, NPCM_SMBADDR6,
> +			       NPCM_SMBADDR7, NPCM_SMBADDR8, NPCM_SMBADDR9,
> +			       NPCM_SMBADDR10};
> +
> +#define NPCM_SMBCTL4			0x01A
> +#define NPCM_SMBCTL5			0x01B
> +#define NPCM_SMBSCLLT			0x01C // SCL Low Time
> +#define NPCM_SMBFIF_CTL			0x01D // FIFO Control
> +#define NPCM_SMBSCLHT			0x01E // SCL High Time
> +
> +// BANK 1 regs
> +#define NPCM_SMBFIF_CTS			0x010 // Both FIFOs Control and status
> +#define NPCM_SMBTXF_CTL			0x012 // Tx-FIFO Control
> +#define NPCM_SMBT_OUT			0x014 // Bus T.O.
> +#define NPCM_SMBPEC			0x016 // PEC Data
> +#define NPCM_SMBTXF_STS			0x01A // Tx-FIFO Status
> +#define NPCM_SMBRXF_STS			0x01C // Rx-FIFO Status
> +#define NPCM_SMBRXF_CTL			0x01E // Rx-FIFO Control
> +
> +// NPCM_SMBST reg fields
> +#define NPCM_SMBST_XMIT			BIT(0)
> +#define NPCM_SMBST_MASTER		BIT(1)
> +#define NPCM_SMBST_NMATCH		BIT(2)
> +#define NPCM_SMBST_STASTR		BIT(3)
> +#define NPCM_SMBST_NEGACK		BIT(4)
> +#define NPCM_SMBST_BER			BIT(5)
> +#define NPCM_SMBST_SDAST		BIT(6)
> +#define NPCM_SMBST_SLVSTP		BIT(7)
> +
> +// NPCM_SMBCST reg fields
> +#define NPCM_SMBCST_BUSY		BIT(0)
> +#define NPCM_SMBCST_BB			BIT(1)
> +#define NPCM_SMBCST_MATCH		BIT(2)
> +#define NPCM_SMBCST_GCMATCH		BIT(3)
> +#define NPCM_SMBCST_TSDA		BIT(4)
> +#define NPCM_SMBCST_TGSCL		BIT(5)
> +#define NPCM_SMBCST_MATCHAF		BIT(6)
> +#define NPCM_SMBCST_ARPMATCH		BIT(7)
> +
> +// NPCM_SMBCTL1 reg fields
> +#define NPCM_SMBCTL1_START		BIT(0)
> +#define NPCM_SMBCTL1_STOP		BIT(1)
> +#define NPCM_SMBCTL1_INTEN		BIT(2)
> +#define NPCM_SMBCTL1_EOBINTE		BIT(3)
> +#define NPCM_SMBCTL1_ACK		BIT(4)
> +#define NPCM_SMBCTL1_GCMEN		BIT(5)
> +#define NPCM_SMBCTL1_NMINTE		BIT(6)
> +#define NPCM_SMBCTL1_STASTRE		BIT(7)
> +
> +// RW1S fields (inside a RW reg):
> +#define NPCM_SMBCTL1_RWS_FIELDS	  (NPCM_SMBCTL1_START | NPCM_SMBCTL1_STOP | \
> +				   NPCM_SMBCTL1_ACK)
> +// NPCM_SMBADDR reg fields
> +#define NPCM_SMBADDR_A			GENMASK(6, 0)
> +#define NPCM_SMBADDR_SAEN		BIT(7)
> +
> +// NPCM_SMBCTL2 reg fields
> +#define SMBCTL2_ENABLE			BIT(0)
> +#define SMBCTL2_SCLFRQ6_0		GENMASK(7, 1)
> +
> +// NPCM_SMBCTL3 reg fields
> +#define SMBCTL3_SCLFRQ8_7		GENMASK(1, 0)
> +#define SMBCTL3_ARPMEN			BIT(2)
> +#define SMBCTL3_IDL_START		BIT(3)
> +#define SMBCTL3_400K_MODE		BIT(4)
> +#define SMBCTL3_BNK_SEL			BIT(5)
> +#define SMBCTL3_SDA_LVL			BIT(6)
> +#define SMBCTL3_SCL_LVL			BIT(7)
> +
> +// NPCM_SMBCST2 reg fields
> +#define NPCM_SMBCST2_MATCHA1F		BIT(0)
> +#define NPCM_SMBCST2_MATCHA2F		BIT(1)
> +#define NPCM_SMBCST2_MATCHA3F		BIT(2)
> +#define NPCM_SMBCST2_MATCHA4F		BIT(3)
> +#define NPCM_SMBCST2_MATCHA5F		BIT(4)
> +#define NPCM_SMBCST2_MATCHA6F		BIT(5)
> +#define NPCM_SMBCST2_MATCHA7F		BIT(5)
> +#define NPCM_SMBCST2_INTSTS		BIT(7)
> +
> +// NPCM_SMBCST3 reg fields
> +#define NPCM_SMBCST3_MATCHA8F		BIT(0)
> +#define NPCM_SMBCST3_MATCHA9F		BIT(1)
> +#define NPCM_SMBCST3_MATCHA10F		BIT(2)
> +#define NPCM_SMBCST3_EO_BUSY		BIT(7)
> +
> +// NPCM_SMBCTL4 reg fields
> +#define SMBCTL4_HLDT			GENMASK(5, 0)
> +#define SMBCTL4_LVL_WE			BIT(7)
> +
> +// NPCM_SMBCTL5 reg fields
> +#define SMBCTL5_DBNCT			GENMASK(3, 0)
> +
> +// NPCM_SMBFIF_CTS reg fields
> +#define NPCM_SMBFIF_CTS_RXF_TXE		BIT(1)
> +#define NPCM_SMBFIF_CTS_RFTE_IE		BIT(3)
> +#define NPCM_SMBFIF_CTS_CLR_FIFO	BIT(6)
> +#define NPCM_SMBFIF_CTS_SLVRSTR		BIT(7)
> +
> +// NPCM_SMBTXF_CTL reg fields
> +#define NPCM_SMBTXF_CTL_TX_THR		GENMASK(4, 0)
> +#define NPCM_SMBTXF_CTL_THR_TXIE	BIT(6)
> +
> +// NPCM_SMBT_OUT reg fields
> +#define NPCM_SMBT_OUT_TO_CKDIV		GENMASK(5, 0)
> +#define NPCM_SMBT_OUT_T_OUTIE		BIT(6)
> +#define NPCM_SMBT_OUT_T_OUTST		BIT(7)
> +
> +// NPCM_SMBTXF_STS reg fields
> +#define NPCM_SMBTXF_STS_TX_BYTES	GENMASK(4, 0)
> +#define NPCM_SMBTXF_STS_TX_THST		BIT(6)
> +
> +// NPCM_SMBRXF_STS reg fields
> +#define NPCM_SMBRXF_STS_RX_BYTES	GENMASK(4, 0)
> +#define NPCM_SMBRXF_STS_RX_THST		BIT(6)
> +
> +// NPCM_SMBFIF_CTL reg fields
> +#define NPCM_SMBFIF_CTL_FIFO_EN		BIT(4)
> +
> +// NPCM_SMBRXF_CTL reg fields
> +#define NPCM_SMBRXF_CTL_RX_THR		GENMASK(4, 0)
> +#define NPCM_SMBRXF_CTL_LAST_PEC	BIT(5)
> +#define NPCM_SMBRXF_CTL_THR_RXIE	BIT(6)
> +
> +#define SMBUS_FIFO_SIZE			16
> +
> +// SMB_VER reg fields
> +#define SMB_VER_VERSION			GENMASK(6, 0)
> +#define SMB_VER_FIFO_EN			BIT(7)
> +
> +// stall/stuck timeout
> +const unsigned int DEFAULT_STALL_COUNT =	25;
> +
> +// retries in a loop for master abort
> +const unsigned int RETRIES_NUM =	10000;
> +
> +// SMBus spec. values in KHZ
> +const unsigned int SMBUS_FREQ_MIN = 10;
> +const unsigned int SMBUS_FREQ_MAX = 1000;
> +const unsigned int SMBUS_FREQ_100KHZ = 100;
> +const unsigned int SMBUS_FREQ_400KHZ = 400;
> +const unsigned int SMBUS_FREQ_1MHZ = 1000;

Does the hardware only support these clock speeds?

> +// SCLFRQ min/max field values
> +const unsigned int SCLFRQ_MIN = 10;
> +const unsigned int SCLFRQ_MAX = 511;
> +
> +// SCLFRQ field position
> +#define SCLFRQ_0_TO_6		GENMASK(6, 0)
> +#define SCLFRQ_7_TO_8		GENMASK(8, 7)
> +
> +const unsigned int SMB_NUM_OF_ADDR = 10;
> +
> +#define NPCM_I2C_EVENT_START	BIT(0)
> +#define NPCM_I2C_EVENT_STOP	BIT(1)
> +#define NPCM_I2C_EVENT_ABORT	BIT(2)
> +#define NPCM_I2C_EVENT_WRITE	BIT(3)
> +
> +#define NPCM_I2C_EVENT_READ	BIT(4)
> +#define NPCM_I2C_EVENT_BER	BIT(5)
> +#define NPCM_I2C_EVENT_NACK	BIT(6)
> +#define NPCM_I2C_EVENT_TO	BIT(7)
> +
> +#define NPCM_I2C_EVENT_EOB	BIT(8)
> +#define NPCM_I2C_EVENT_STALL	BIT(9)
> +#define NPCM_I2C_EVENT_CB	BIT(10)
> +#define NPCM_I2C_EVENT_DONE	BIT(11)
> +
> +#define NPCM_I2C_EVENT_READ1	BIT(12)
> +#define NPCM_I2C_EVENT_READ2	BIT(13)
> +#define NPCM_I2C_EVENT_READ3	BIT(14)
> +#define NPCM_I2C_EVENT_READ4	BIT(15)
> +
> +#define NPCM_I2C_EVENT_NMATCH_SLV	BIT(16)
> +#define NPCM_I2C_EVENT_NMATCH_MSTR	BIT(17)
> +#define NPCM_I2C_EVENT_BER_SLV		BIT(18)
> +
> +#define NPCM_I2C_EVENT_LOG(event)	(bus->event_log |= event)
> +
> +// Status of one SMBus module
> +struct npcm_i2c {
> +	struct i2c_adapter	adap;
> +	struct device		*dev;
> +	unsigned char __iomem	*reg;
> +	spinlock_t		lock;   /* IRQ synchronization */
> +	struct completion	cmd_complete;
> +	int			irq;
> +	int			cmd_err;
> +	struct i2c_msg		*msgs;
> +	int			msgs_num;
> +	int			num;
> +	u32			apb_clk;
> +	struct i2c_bus_recovery_info rinfo;
> +	enum smb_state		state;
> +	enum smb_oper		operation;
> +	enum smb_mode		master_or_slave;
> +	enum smb_state_ind	stop_ind;
> +	u8			dest_addr;
> +	u8			*rd_buf;
> +	u16			rd_size;
> +	u16			rd_ind;
> +	u8			*wr_buf;
> +	u16			wr_size;
> +	u16			wr_ind;
> +	bool			fifo_use;
> +
> +	// PEC bit mask per slave address.
> +	//		1: use PEC for this address,
> +	//		0: do not use PEC for this address
> +	u16			PEC_mask;
> +	bool			PEC_use;
> +	bool			read_block_use;
> +	u8			int_cnt;
> +	u32			event_log;
> +	u32			event_log_prev;
> +	u32			clk_period_us;
> +	unsigned long		int_time_stamp;
> +	unsigned long		bus_freq; // in kHz
> +	u32			xmits;
> +
> +#if IS_ENABLED(CONFIG_I2C_SLAVE)

Aha! It appears that selecting I2C_SLAVE is unnecessary.

Since you already ifdeffed out all the I2C slave code, can you put it in
a separate patch to make this easier to review?

> +	u8			own_slave_addr;
> +	struct i2c_client	*slave;
> +
> +	// currently I2C slave IF only supports single byte operations.
> +	// in order to utilyze the npcm HW FIFO, the driver will ask for 16bytes
> +	// 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 whever the backend requests for it is not supported.
> +
> +	// This module can be master and slave at the same time. separate ptrs
> +	// and counters:
> +	int			slv_rd_size;
> +	int			slv_rd_ind;
> +	int			slv_wr_size;
> +	int			slv_wr_ind;
> +	u8			slv_rd_buf[SMBUS_FIFO_SIZE];
> +	u8			slv_wr_buf[SMBUS_FIFO_SIZE];
> +#endif
> +};

Cheers!

WARNING: multiple messages have this Message-ID (diff)
From: Brendan Higgins <brendanhiggins@google.com>
To: Tali Perry <tali.perry1@gmail.com>
Cc: robh+dt@kernel.org, mark.rutland@arm.com, yuenn@google.com,
	venture@google.com, benjaminfair@google.com,
	avifishman70@gmail.com, joel@jms.id.au, tmaimon77@gmail.com,
	wsa@the-dreams.de, syniurge@gmail.com, linux-i2c@vger.kernel.org,
	openbmc@lists.ozlabs.org, devicetree@vger.kernel.org,
	linux-kernel@vger.kernel.org
Subject: Re: [PATCH v7 2/2] i2c: npcm: Add Nuvoton NPCM I2C controller driver
Date: Tue, 25 Feb 2020 12:01:04 -0800	[thread overview]
Message-ID: <20200225200104.GA105722@google.com> (raw)
In-Reply-To: <20191121095350.158689-3-tali.perry1@gmail.com>

On Thu, Nov 21, 2019 at 11:53:50AM +0200, Tali Perry wrote:
> Add Nuvoton NPCM BMC i2c controller driver.
> 
> Signed-off-by: Tali Perry <tali.perry1@gmail.com>
> ---
>  drivers/i2c/busses/Kconfig       |   11 +
>  drivers/i2c/busses/Makefile      |    1 +
>  drivers/i2c/busses/i2c-npcm7xx.c | 2485 ++++++++++++++++++++++++++++++
>  3 files changed, 2497 insertions(+)
>  create mode 100644 drivers/i2c/busses/i2c-npcm7xx.c
> 
> diff --git a/drivers/i2c/busses/Kconfig b/drivers/i2c/busses/Kconfig
> index 146ce40d8e0a..9091b93aaf90 100644
> --- a/drivers/i2c/busses/Kconfig
> +++ b/drivers/i2c/busses/Kconfig
> @@ -786,6 +786,17 @@ config I2C_NOMADIK
>  	  I2C interface from ST-Ericsson's Nomadik and Ux500 architectures,
>  	  as well as the STA2X11 PCIe I/O HUB.
>  
> +config I2C_NPCM7XX
> +	tristate "Nuvoton I2C Controller"
> +	depends on ARCH_NPCM7XX

This should also depend on "|| COMPILE_TEST"

> +	select I2C_SLAVE

Personally, I would prefer if this was optional, but it's up to you.

> +	help
> +	  If you say yes to this option, support will be included for the
> +	  Nuvoton I2C controller.

Might want to elaborate about the capabilities of the driver/hardware.

> +	  This driver can also be built as a module.  If so, the module
> +	  will be called i2c-npcm7xx.

Probably unnecessary; this follows the pattern that most other I2C
drivers do.

>  config I2C_OCORES
>  	tristate "OpenCores I2C Controller"
>  	help
> diff --git a/drivers/i2c/busses/Makefile b/drivers/i2c/busses/Makefile
> index 3ab8aebc39c9..4af59a806f3c 100644
> --- a/drivers/i2c/busses/Makefile
> +++ b/drivers/i2c/busses/Makefile
> @@ -81,6 +81,7 @@ obj-$(CONFIG_I2C_MT7621)	+= i2c-mt7621.o
>  obj-$(CONFIG_I2C_MV64XXX)	+= i2c-mv64xxx.o
>  obj-$(CONFIG_I2C_MXS)		+= i2c-mxs.o
>  obj-$(CONFIG_I2C_NOMADIK)	+= i2c-nomadik.o
> +obj-$(CONFIG_I2C_NPCM7XX)	+= i2c-npcm7xx.o
>  obj-$(CONFIG_I2C_OCORES)	+= i2c-ocores.o
>  obj-$(CONFIG_I2C_OMAP)		+= i2c-omap.o
>  obj-$(CONFIG_I2C_OWL)		+= i2c-owl.o
> diff --git a/drivers/i2c/busses/i2c-npcm7xx.c b/drivers/i2c/busses/i2c-npcm7xx.c
> new file mode 100644
> index 000000000000..ce9699d56835
> --- /dev/null
> +++ b/drivers/i2c/busses/i2c-npcm7xx.c
> @@ -0,0 +1,2485 @@
> +// SPDX-License-Identifier: GPL-2.0
> +/*
> + * Nuvoton NPCM7xx SMB Controller driver
> + *
> + * Copyright (C) 2018 Nuvoton Technologies tali.perry@nuvoton.com

You should update the date.

> + */
> +#include <linux/bitfield.h>
> +#include <linux/clk.h>
> +#include <linux/errno.h>
> +#include <linux/i2c.h>
> +#include <linux/interrupt.h>
> +#include <linux/irq.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>
> +#include <linux/jiffies.h>
> +
> +#define I2C_VERSION "0.1.0"

nit: You only use this macro in one place. I think it would be clearer
to just use the raw string there.

> +
> +enum smb_mode {
> +	SMB_SLAVE = 1,
> +	SMB_MASTER
> +};

Please use proper namespacing.

> +/*
> + * External SMB Interface driver xfer indication values, which indicate status
> + * of the bus.
> + */
> +enum smb_state_ind {
> +	SMB_NO_STATUS_IND = 0,
> +	SMB_SLAVE_RCV_IND = 1,
> +	SMB_SLAVE_XMIT_IND = 2,
> +	SMB_SLAVE_XMIT_MISSING_DATA_IND = 3,
> +	SMB_SLAVE_RESTART_IND = 4,
> +	SMB_SLAVE_DONE_IND = 5,
> +	SMB_MASTER_DONE_IND = 6,
> +	SMB_NACK_IND = 8,
> +	SMB_BUS_ERR_IND = 9,
> +	SMB_WAKE_UP_IND = 10,
> +	SMB_BLOCK_BYTES_ERR_IND = 12,
> +	SMB_SLAVE_RCV_MISSING_DATA_IND = 14,
> +};
> +
> +// SMBus Operation type values
> +enum smb_oper {
> +	SMB_NO_OPER = 0,
> +	SMB_WRITE_OPER = 1,
> +	SMB_READ_OPER = 2
> +};
> +
> +// SMBus Bank (FIFO mode)
> +enum smb_bank {
> +	SMB_BANK_0 = 0,
> +	SMB_BANK_1 = 1
> +};
> +
> +// Internal SMB states values (for the SMB module state machine).
> +enum smb_state {
> +	SMB_DISABLE = 0,
> +	SMB_IDLE,
> +	SMB_MASTER_START,
> +	SMB_SLAVE_MATCH,
> +	SMB_OPER_STARTED,
> +	SMB_STOP_PENDING
> +};
> +
> +// Module supports setting multiple own slave addresses
> +enum smb_addr {
> +	SMB_SLAVE_ADDR1 = 0,
> +	SMB_SLAVE_ADDR2,
> +	SMB_SLAVE_ADDR3,
> +	SMB_SLAVE_ADDR4,
> +	SMB_SLAVE_ADDR5,
> +	SMB_SLAVE_ADDR6,
> +	SMB_SLAVE_ADDR7,
> +	SMB_SLAVE_ADDR8,
> +	SMB_SLAVE_ADDR9,
> +	SMB_SLAVE_ADDR10,
> +	SMB_GC_ADDR,
> +	SMB_ARP_ADDR
> +};
> +
> +// global regs
> +static struct regmap *gcr_regmap;
> +static struct regmap *clk_regmap;

It's generally best to avoid global variables.

> +#define NPCM_I2CSEGCTL  0xE4
> +#define I2CSEGCTL_VAL	0x0333F000

What is this value? It doesn't look like a register offset.

> +// Common regs
> +#define NPCM_SMBSDA			0x000
> +#define NPCM_SMBST			0x002
> +#define NPCM_SMBCST			0x004
> +#define NPCM_SMBCTL1			0x006
> +#define NPCM_SMBADDR1			0x008
> +#define NPCM_SMBCTL2			0x00A
> +#define NPCM_SMBADDR2			0x00C
> +#define NPCM_SMBCTL3			0x00E
> +#define NPCM_SMBCST2			0x018
> +#define NPCM_SMBCST3			0x019
> +#define SMB_VER				0x01F

nit: I am guessing these are not 12 bit values. Can you use just two digits?

> +// BANK 0 regs
> +#define NPCM_SMBADDR3			0x010
> +#define NPCM_SMBADDR7			0x011
> +#define NPCM_SMBADDR4			0x012
> +#define NPCM_SMBADDR8			0x013
> +#define NPCM_SMBADDR5			0x014
> +#define NPCM_SMBADDR9			0x015
> +#define NPCM_SMBADDR6			0x016
> +#define NPCM_SMBADDR10			0x017
> +
> +// SMBADDR array: because the addr regs are sprinkled all over the address space
> +const int  NPCM_SMBADDR[10] = {NPCM_SMBADDR1, NPCM_SMBADDR2, NPCM_SMBADDR3,

Please only use all caps for macros.

> +			       NPCM_SMBADDR4, NPCM_SMBADDR5, NPCM_SMBADDR6,
> +			       NPCM_SMBADDR7, NPCM_SMBADDR8, NPCM_SMBADDR9,
> +			       NPCM_SMBADDR10};
> +
> +#define NPCM_SMBCTL4			0x01A
> +#define NPCM_SMBCTL5			0x01B
> +#define NPCM_SMBSCLLT			0x01C // SCL Low Time
> +#define NPCM_SMBFIF_CTL			0x01D // FIFO Control
> +#define NPCM_SMBSCLHT			0x01E // SCL High Time
> +
> +// BANK 1 regs
> +#define NPCM_SMBFIF_CTS			0x010 // Both FIFOs Control and status
> +#define NPCM_SMBTXF_CTL			0x012 // Tx-FIFO Control
> +#define NPCM_SMBT_OUT			0x014 // Bus T.O.
> +#define NPCM_SMBPEC			0x016 // PEC Data
> +#define NPCM_SMBTXF_STS			0x01A // Tx-FIFO Status
> +#define NPCM_SMBRXF_STS			0x01C // Rx-FIFO Status
> +#define NPCM_SMBRXF_CTL			0x01E // Rx-FIFO Control
> +
> +// NPCM_SMBST reg fields
> +#define NPCM_SMBST_XMIT			BIT(0)
> +#define NPCM_SMBST_MASTER		BIT(1)
> +#define NPCM_SMBST_NMATCH		BIT(2)
> +#define NPCM_SMBST_STASTR		BIT(3)
> +#define NPCM_SMBST_NEGACK		BIT(4)
> +#define NPCM_SMBST_BER			BIT(5)
> +#define NPCM_SMBST_SDAST		BIT(6)
> +#define NPCM_SMBST_SLVSTP		BIT(7)
> +
> +// NPCM_SMBCST reg fields
> +#define NPCM_SMBCST_BUSY		BIT(0)
> +#define NPCM_SMBCST_BB			BIT(1)
> +#define NPCM_SMBCST_MATCH		BIT(2)
> +#define NPCM_SMBCST_GCMATCH		BIT(3)
> +#define NPCM_SMBCST_TSDA		BIT(4)
> +#define NPCM_SMBCST_TGSCL		BIT(5)
> +#define NPCM_SMBCST_MATCHAF		BIT(6)
> +#define NPCM_SMBCST_ARPMATCH		BIT(7)
> +
> +// NPCM_SMBCTL1 reg fields
> +#define NPCM_SMBCTL1_START		BIT(0)
> +#define NPCM_SMBCTL1_STOP		BIT(1)
> +#define NPCM_SMBCTL1_INTEN		BIT(2)
> +#define NPCM_SMBCTL1_EOBINTE		BIT(3)
> +#define NPCM_SMBCTL1_ACK		BIT(4)
> +#define NPCM_SMBCTL1_GCMEN		BIT(5)
> +#define NPCM_SMBCTL1_NMINTE		BIT(6)
> +#define NPCM_SMBCTL1_STASTRE		BIT(7)
> +
> +// RW1S fields (inside a RW reg):
> +#define NPCM_SMBCTL1_RWS_FIELDS	  (NPCM_SMBCTL1_START | NPCM_SMBCTL1_STOP | \
> +				   NPCM_SMBCTL1_ACK)
> +// NPCM_SMBADDR reg fields
> +#define NPCM_SMBADDR_A			GENMASK(6, 0)
> +#define NPCM_SMBADDR_SAEN		BIT(7)
> +
> +// NPCM_SMBCTL2 reg fields
> +#define SMBCTL2_ENABLE			BIT(0)
> +#define SMBCTL2_SCLFRQ6_0		GENMASK(7, 1)
> +
> +// NPCM_SMBCTL3 reg fields
> +#define SMBCTL3_SCLFRQ8_7		GENMASK(1, 0)
> +#define SMBCTL3_ARPMEN			BIT(2)
> +#define SMBCTL3_IDL_START		BIT(3)
> +#define SMBCTL3_400K_MODE		BIT(4)
> +#define SMBCTL3_BNK_SEL			BIT(5)
> +#define SMBCTL3_SDA_LVL			BIT(6)
> +#define SMBCTL3_SCL_LVL			BIT(7)
> +
> +// NPCM_SMBCST2 reg fields
> +#define NPCM_SMBCST2_MATCHA1F		BIT(0)
> +#define NPCM_SMBCST2_MATCHA2F		BIT(1)
> +#define NPCM_SMBCST2_MATCHA3F		BIT(2)
> +#define NPCM_SMBCST2_MATCHA4F		BIT(3)
> +#define NPCM_SMBCST2_MATCHA5F		BIT(4)
> +#define NPCM_SMBCST2_MATCHA6F		BIT(5)
> +#define NPCM_SMBCST2_MATCHA7F		BIT(5)
> +#define NPCM_SMBCST2_INTSTS		BIT(7)
> +
> +// NPCM_SMBCST3 reg fields
> +#define NPCM_SMBCST3_MATCHA8F		BIT(0)
> +#define NPCM_SMBCST3_MATCHA9F		BIT(1)
> +#define NPCM_SMBCST3_MATCHA10F		BIT(2)
> +#define NPCM_SMBCST3_EO_BUSY		BIT(7)
> +
> +// NPCM_SMBCTL4 reg fields
> +#define SMBCTL4_HLDT			GENMASK(5, 0)
> +#define SMBCTL4_LVL_WE			BIT(7)
> +
> +// NPCM_SMBCTL5 reg fields
> +#define SMBCTL5_DBNCT			GENMASK(3, 0)
> +
> +// NPCM_SMBFIF_CTS reg fields
> +#define NPCM_SMBFIF_CTS_RXF_TXE		BIT(1)
> +#define NPCM_SMBFIF_CTS_RFTE_IE		BIT(3)
> +#define NPCM_SMBFIF_CTS_CLR_FIFO	BIT(6)
> +#define NPCM_SMBFIF_CTS_SLVRSTR		BIT(7)
> +
> +// NPCM_SMBTXF_CTL reg fields
> +#define NPCM_SMBTXF_CTL_TX_THR		GENMASK(4, 0)
> +#define NPCM_SMBTXF_CTL_THR_TXIE	BIT(6)
> +
> +// NPCM_SMBT_OUT reg fields
> +#define NPCM_SMBT_OUT_TO_CKDIV		GENMASK(5, 0)
> +#define NPCM_SMBT_OUT_T_OUTIE		BIT(6)
> +#define NPCM_SMBT_OUT_T_OUTST		BIT(7)
> +
> +// NPCM_SMBTXF_STS reg fields
> +#define NPCM_SMBTXF_STS_TX_BYTES	GENMASK(4, 0)
> +#define NPCM_SMBTXF_STS_TX_THST		BIT(6)
> +
> +// NPCM_SMBRXF_STS reg fields
> +#define NPCM_SMBRXF_STS_RX_BYTES	GENMASK(4, 0)
> +#define NPCM_SMBRXF_STS_RX_THST		BIT(6)
> +
> +// NPCM_SMBFIF_CTL reg fields
> +#define NPCM_SMBFIF_CTL_FIFO_EN		BIT(4)
> +
> +// NPCM_SMBRXF_CTL reg fields
> +#define NPCM_SMBRXF_CTL_RX_THR		GENMASK(4, 0)
> +#define NPCM_SMBRXF_CTL_LAST_PEC	BIT(5)
> +#define NPCM_SMBRXF_CTL_THR_RXIE	BIT(6)
> +
> +#define SMBUS_FIFO_SIZE			16
> +
> +// SMB_VER reg fields
> +#define SMB_VER_VERSION			GENMASK(6, 0)
> +#define SMB_VER_FIFO_EN			BIT(7)
> +
> +// stall/stuck timeout
> +const unsigned int DEFAULT_STALL_COUNT =	25;
> +
> +// retries in a loop for master abort
> +const unsigned int RETRIES_NUM =	10000;
> +
> +// SMBus spec. values in KHZ
> +const unsigned int SMBUS_FREQ_MIN = 10;
> +const unsigned int SMBUS_FREQ_MAX = 1000;
> +const unsigned int SMBUS_FREQ_100KHZ = 100;
> +const unsigned int SMBUS_FREQ_400KHZ = 400;
> +const unsigned int SMBUS_FREQ_1MHZ = 1000;

Does the hardware only support these clock speeds?

> +// SCLFRQ min/max field values
> +const unsigned int SCLFRQ_MIN = 10;
> +const unsigned int SCLFRQ_MAX = 511;
> +
> +// SCLFRQ field position
> +#define SCLFRQ_0_TO_6		GENMASK(6, 0)
> +#define SCLFRQ_7_TO_8		GENMASK(8, 7)
> +
> +const unsigned int SMB_NUM_OF_ADDR = 10;
> +
> +#define NPCM_I2C_EVENT_START	BIT(0)
> +#define NPCM_I2C_EVENT_STOP	BIT(1)
> +#define NPCM_I2C_EVENT_ABORT	BIT(2)
> +#define NPCM_I2C_EVENT_WRITE	BIT(3)
> +
> +#define NPCM_I2C_EVENT_READ	BIT(4)
> +#define NPCM_I2C_EVENT_BER	BIT(5)
> +#define NPCM_I2C_EVENT_NACK	BIT(6)
> +#define NPCM_I2C_EVENT_TO	BIT(7)
> +
> +#define NPCM_I2C_EVENT_EOB	BIT(8)
> +#define NPCM_I2C_EVENT_STALL	BIT(9)
> +#define NPCM_I2C_EVENT_CB	BIT(10)
> +#define NPCM_I2C_EVENT_DONE	BIT(11)
> +
> +#define NPCM_I2C_EVENT_READ1	BIT(12)
> +#define NPCM_I2C_EVENT_READ2	BIT(13)
> +#define NPCM_I2C_EVENT_READ3	BIT(14)
> +#define NPCM_I2C_EVENT_READ4	BIT(15)
> +
> +#define NPCM_I2C_EVENT_NMATCH_SLV	BIT(16)
> +#define NPCM_I2C_EVENT_NMATCH_MSTR	BIT(17)
> +#define NPCM_I2C_EVENT_BER_SLV		BIT(18)
> +
> +#define NPCM_I2C_EVENT_LOG(event)	(bus->event_log |= event)
> +
> +// Status of one SMBus module
> +struct npcm_i2c {
> +	struct i2c_adapter	adap;
> +	struct device		*dev;
> +	unsigned char __iomem	*reg;
> +	spinlock_t		lock;   /* IRQ synchronization */
> +	struct completion	cmd_complete;
> +	int			irq;
> +	int			cmd_err;
> +	struct i2c_msg		*msgs;
> +	int			msgs_num;
> +	int			num;
> +	u32			apb_clk;
> +	struct i2c_bus_recovery_info rinfo;
> +	enum smb_state		state;
> +	enum smb_oper		operation;
> +	enum smb_mode		master_or_slave;
> +	enum smb_state_ind	stop_ind;
> +	u8			dest_addr;
> +	u8			*rd_buf;
> +	u16			rd_size;
> +	u16			rd_ind;
> +	u8			*wr_buf;
> +	u16			wr_size;
> +	u16			wr_ind;
> +	bool			fifo_use;
> +
> +	// PEC bit mask per slave address.
> +	//		1: use PEC for this address,
> +	//		0: do not use PEC for this address
> +	u16			PEC_mask;
> +	bool			PEC_use;
> +	bool			read_block_use;
> +	u8			int_cnt;
> +	u32			event_log;
> +	u32			event_log_prev;
> +	u32			clk_period_us;
> +	unsigned long		int_time_stamp;
> +	unsigned long		bus_freq; // in kHz
> +	u32			xmits;
> +
> +#if IS_ENABLED(CONFIG_I2C_SLAVE)

Aha! It appears that selecting I2C_SLAVE is unnecessary.

Since you already ifdeffed out all the I2C slave code, can you put it in
a separate patch to make this easier to review?

> +	u8			own_slave_addr;
> +	struct i2c_client	*slave;
> +
> +	// currently I2C slave IF only supports single byte operations.
> +	// in order to utilyze the npcm HW FIFO, the driver will ask for 16bytes
> +	// 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 whever the backend requests for it is not supported.
> +
> +	// This module can be master and slave at the same time. separate ptrs
> +	// and counters:
> +	int			slv_rd_size;
> +	int			slv_rd_ind;
> +	int			slv_wr_size;
> +	int			slv_wr_ind;
> +	u8			slv_rd_buf[SMBUS_FIFO_SIZE];
> +	u8			slv_wr_buf[SMBUS_FIFO_SIZE];
> +#endif
> +};

Cheers!

  parent reply	other threads:[~2020-02-25 20:01 UTC|newest]

Thread overview: 10+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2019-11-21  9:53 [PATCH v7 0/2] i2c: npcm: add NPCM i2c controller driver Tali Perry
2019-11-21  9:53 ` [PATCH v7 1/2] dt-bindings: i2c: npcm7xx: add NPCM I2C controller documentation Tali Perry
2019-11-21  9:53 ` [PATCH v7 2/2] i2c: npcm: Add Nuvoton NPCM I2C controller driver Tali Perry
2019-11-25 15:16   ` Wolfram Sang
2019-11-26  6:47     ` Tali Perry
2019-11-26  9:27       ` Tali Perry
     [not found]         ` <CAHb3i=s+u1gHXwi7j7V_N-c8f8n7c1XB3QhkY8EAJuv6PA5GNw-JsoAwUIsXosN+BqQ9rBEUg@public.gmane.org>
2020-02-25 19:30           ` Brendan Higgins
2020-02-25 19:30             ` Brendan Higgins
     [not found]   ` <20191121095350.158689-3-tali.perry1-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org>
2020-02-25 20:01     ` Brendan Higgins [this message]
2020-02-25 20:01       ` Brendan Higgins

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20200225200104.GA105722@google.com \
    --to=brendanhiggins-hpiqsd4aklfqt0dzr+alfa@public.gmane.org \
    --cc=avifishman70-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org \
    --cc=benjaminfair-hpIqsD4AKlfQT0dZR+AlfA@public.gmane.org \
    --cc=devicetree-u79uwXL29TY76Z2rM5mHXA@public.gmane.org \
    --cc=joel-U3u1mxZcP9KHXe+LvDLADg@public.gmane.org \
    --cc=linux-i2c-u79uwXL29TY76Z2rM5mHXA@public.gmane.org \
    --cc=linux-kernel-u79uwXL29TY76Z2rM5mHXA@public.gmane.org \
    --cc=mark.rutland-5wv7dgnIgG8@public.gmane.org \
    --cc=openbmc-uLR06cmDAlY/bJ5BZ2RsiQ@public.gmane.org \
    --cc=robh+dt-DgEjT+Ai2ygdnm+yROfE0A@public.gmane.org \
    --cc=syniurge-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org \
    --cc=tali.perry1-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org \
    --cc=tmaimon77-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org \
    --cc=venture-hpIqsD4AKlfQT0dZR+AlfA@public.gmane.org \
    --cc=wsa-z923LK4zBo2bacvFa/9K2g@public.gmane.org \
    --cc=yuenn-hpIqsD4AKlfQT0dZR+AlfA@public.gmane.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.