From: Tyrone Ting <warp5tw@gmail.com>
To: avifishman70@gmail.com, tmaimon77@gmail.com,
tali.perry1@gmail.com, venture@google.com, yuenn@google.com,
benjaminfair@google.com, robh+dt@kernel.org,
krzysztof.kozlowski+dt@linaro.org, wsa@kernel.org,
andriy.shevchenko@linux.intel.com, jarkko.nikula@linux.intel.com,
semen.protsenko@linaro.org, jie.deng@intel.com, jsd@semihalf.com,
sven@svenpeter.dev, lukas.bulwahn@gmail.com, olof@lixom.net,
arnd@arndb.de, warp5tw@gmail.com, tali.perry@nuvoton.com,
Avi.Fishman@nuvoton.com, tomer.maimon@nuvoton.com,
KWLIU@nuvoton.com, JJLIU0@nuvoton.com, kfting@nuvoton.com
Cc: openbmc@lists.ozlabs.org, linux-i2c@vger.kernel.org,
devicetree@vger.kernel.org, linux-kernel@vger.kernel.org
Subject: [PATCH v6 4/5] i2c: npcm: Support NPCM845
Date: Wed, 25 May 2022 11:23:40 +0800 [thread overview]
Message-ID: <20220525032341.3182-5-warp5tw@gmail.com> (raw)
In-Reply-To: <20220525032341.3182-1-warp5tw@gmail.com>
From: Tyrone Ting <kfting@nuvoton.com>
Add NPCM8XX I2C support.
The NPCM8XX uses a similar i2c module as NPCM7XX.
The internal HW FIFO is larger in NPCM8XX.
Signed-off-by: Tyrone Ting <kfting@nuvoton.com>
Acked-by: Tomer Maimon <tmaimon77@gmail.com>
---
drivers/i2c/busses/Kconfig | 8 +--
drivers/i2c/busses/Makefile | 2 +-
drivers/i2c/busses/i2c-npcm7xx.c | 114 +++++++++++++++++++------------
3 files changed, 76 insertions(+), 48 deletions(-)
diff --git a/drivers/i2c/busses/Kconfig b/drivers/i2c/busses/Kconfig
index a1bae59208e3..b1d7069dd377 100644
--- a/drivers/i2c/busses/Kconfig
+++ b/drivers/i2c/busses/Kconfig
@@ -838,13 +838,13 @@ 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
+config I2C_NPCM
tristate "Nuvoton I2C Controller"
- depends on ARCH_NPCM7XX || COMPILE_TEST
+ depends on ARCH_NPCM || COMPILE_TEST
help
If you say yes to this option, support will be included for the
- Nuvoton I2C controller, which is available on the NPCM7xx BMC
- controller.
+ Nuvoton I2C controller, which is available on the NPCM BMC
+ controllers.
Driver can also support slave mode (select I2C_SLAVE).
config I2C_OCORES
diff --git a/drivers/i2c/busses/Makefile b/drivers/i2c/busses/Makefile
index 479f60e4ee3d..b0a10e5d9ee9 100644
--- a/drivers/i2c/busses/Makefile
+++ b/drivers/i2c/busses/Makefile
@@ -84,7 +84,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_NPCM) += 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
index b4d218c6c8fb..86fd942ea648 100644
--- a/drivers/i2c/busses/i2c-npcm7xx.c
+++ b/drivers/i2c/busses/i2c-npcm7xx.c
@@ -17,6 +17,7 @@
#include <linux/mfd/syscon.h>
#include <linux/module.h>
#include <linux/of.h>
+#include <linux/of_device.h>
#include <linux/platform_device.h>
#include <linux/regmap.h>
@@ -91,7 +92,6 @@ enum i2c_addr {
/* init register and default value required to enable module */
#define NPCM_I2CSEGCTL 0xE4
-#define NPCM_I2CSEGCTL_INIT_VAL 0x0333F000
/* Common regs */
#define NPCM_I2CSDA 0x00
@@ -226,8 +226,7 @@ static const int npcm_i2caddr[I2C_NUM_OWN_ADDR] = {
#define NPCM_I2CFIF_CTS_CLR_FIFO BIT(6)
#define NPCM_I2CFIF_CTS_SLVRSTR BIT(7)
-/* NPCM_I2CTXF_CTL reg fields */
-#define NPCM_I2CTXF_CTL_TX_THR GENMASK(4, 0)
+/* NPCM_I2CTXF_CTL reg field */
#define NPCM_I2CTXF_CTL_THR_TXIE BIT(6)
/* NPCM_I2CT_OUT reg fields */
@@ -236,22 +235,18 @@ static const int npcm_i2caddr[I2C_NUM_OWN_ADDR] = {
#define NPCM_I2CT_OUT_T_OUTST BIT(7)
/* NPCM_I2CTXF_STS reg fields */
-#define NPCM_I2CTXF_STS_TX_BYTES GENMASK(4, 0)
#define NPCM_I2CTXF_STS_TX_THST BIT(6)
/* NPCM_I2CRXF_STS reg fields */
-#define NPCM_I2CRXF_STS_RX_BYTES GENMASK(4, 0)
#define NPCM_I2CRXF_STS_RX_THST BIT(6)
/* NPCM_I2CFIF_CTL reg fields */
#define NPCM_I2CFIF_CTL_FIFO_EN BIT(4)
/* NPCM_I2CRXF_CTL reg fields */
-#define NPCM_I2CRXF_CTL_RX_THR GENMASK(4, 0)
-#define NPCM_I2CRXF_CTL_LAST_PEC BIT(5)
#define NPCM_I2CRXF_CTL_THR_RXIE BIT(6)
-#define I2C_HW_FIFO_SIZE 16
+#define MAX_I2C_HW_FIFO_SIZE 32
/* I2C_VER reg fields */
#define I2C_VER_VERSION GENMASK(6, 0)
@@ -268,11 +263,36 @@ static const int npcm_i2caddr[I2C_NUM_OWN_ADDR] = {
#define I2C_FREQ_MIN_HZ 10000
#define I2C_FREQ_MAX_HZ I2C_MAX_FAST_MODE_PLUS_FREQ
+struct npcm_i2c_data {
+ u8 fifo_size;
+ u32 segctl_init_val;
+ u8 txf_sts_tx_bytes;
+ u8 rxf_sts_rx_bytes;
+ u8 rxf_ctl_last_pec;
+};
+
+static const struct npcm_i2c_data npxm7xx_i2c_data = {
+ .fifo_size = 16,
+ .segctl_init_val = 0x0333F000,
+ .txf_sts_tx_bytes = GENMASK(4, 0),
+ .rxf_sts_rx_bytes = GENMASK(4, 0),
+ .rxf_ctl_last_pec = BIT(5),
+};
+
+static const struct npcm_i2c_data npxm8xx_i2c_data = {
+ .fifo_size = 32,
+ .segctl_init_val = 0x9333F000,
+ .txf_sts_tx_bytes = GENMASK(5, 0),
+ .rxf_sts_rx_bytes = GENMASK(5, 0),
+ .rxf_ctl_last_pec = BIT(7),
+};
+
/* Status of one I2C module */
struct npcm_i2c {
struct i2c_adapter adap;
struct device *dev;
unsigned char __iomem *reg;
+ const struct npcm_i2c_data *data;
spinlock_t lock; /* IRQ synchronization */
struct completion cmd_complete;
int cmd_err;
@@ -305,8 +325,8 @@ struct npcm_i2c {
int slv_rd_ind;
int slv_wr_size;
int slv_wr_ind;
- u8 slv_rd_buf[I2C_HW_FIFO_SIZE];
- u8 slv_wr_buf[I2C_HW_FIFO_SIZE];
+ u8 slv_rd_buf[MAX_I2C_HW_FIFO_SIZE];
+ u8 slv_wr_buf[MAX_I2C_HW_FIFO_SIZE];
#endif
struct dentry *debugfs; /* debugfs device directory */
u64 ber_cnt;
@@ -439,7 +459,7 @@ static inline bool npcm_i2c_tx_fifo_empty(struct npcm_i2c *bus)
tx_fifo_sts = ioread8(bus->reg + NPCM_I2CTXF_STS);
/* check if TX FIFO is not empty */
- if ((tx_fifo_sts & NPCM_I2CTXF_STS_TX_BYTES) == 0)
+ if ((tx_fifo_sts & bus->data->txf_sts_tx_bytes) == 0)
return false;
/* check if TX FIFO status bit is set: */
@@ -452,7 +472,7 @@ static inline bool npcm_i2c_rx_fifo_full(struct npcm_i2c *bus)
rx_fifo_sts = ioread8(bus->reg + NPCM_I2CRXF_STS);
/* check if RX FIFO is not empty: */
- if ((rx_fifo_sts & NPCM_I2CRXF_STS_RX_BYTES) == 0)
+ if ((rx_fifo_sts & bus->data->rxf_sts_rx_bytes) == 0)
return false;
/* check if rx fifo full status is set: */
@@ -739,11 +759,11 @@ static void npcm_i2c_callback(struct npcm_i2c *bus,
static u8 npcm_i2c_fifo_usage(struct npcm_i2c *bus)
{
if (bus->operation == I2C_WRITE_OPER)
- return FIELD_GET(NPCM_I2CTXF_STS_TX_BYTES,
- ioread8(bus->reg + NPCM_I2CTXF_STS));
+ return (bus->data->txf_sts_tx_bytes &
+ ioread8(bus->reg + NPCM_I2CTXF_STS));
if (bus->operation == I2C_READ_OPER)
- return FIELD_GET(NPCM_I2CRXF_STS_RX_BYTES,
- ioread8(bus->reg + NPCM_I2CRXF_STS));
+ return (bus->data->rxf_sts_rx_bytes &
+ ioread8(bus->reg + NPCM_I2CRXF_STS));
return 0;
}
@@ -755,13 +775,13 @@ static void npcm_i2c_write_to_fifo_master(struct npcm_i2c *bus, u16 max_bytes)
* Fill the FIFO, while the FIFO is not full and there are more bytes
* to write
*/
- size_free_fifo = I2C_HW_FIFO_SIZE - npcm_i2c_fifo_usage(bus);
+ size_free_fifo = bus->data->fifo_size - npcm_i2c_fifo_usage(bus);
while (max_bytes-- && size_free_fifo) {
if (bus->wr_ind < bus->wr_size)
npcm_i2c_wr_byte(bus, bus->wr_buf[bus->wr_ind++]);
else
npcm_i2c_wr_byte(bus, 0xFF);
- size_free_fifo = I2C_HW_FIFO_SIZE - npcm_i2c_fifo_usage(bus);
+ size_free_fifo = bus->data->fifo_size - npcm_i2c_fifo_usage(bus);
}
}
@@ -782,11 +802,11 @@ static void npcm_i2c_set_fifo(struct npcm_i2c *bus, int nread, int nwrite)
/* configure RX FIFO */
if (nread > 0) {
- rxf_ctl = min_t(int, nread, I2C_HW_FIFO_SIZE);
+ rxf_ctl = min_t(int, nread, bus->data->fifo_size);
/* set LAST bit. if LAST is set next FIFO packet is nacked */
- if (nread <= I2C_HW_FIFO_SIZE)
- rxf_ctl |= NPCM_I2CRXF_CTL_LAST_PEC;
+ if (nread <= bus->data->fifo_size)
+ rxf_ctl |= bus->data->rxf_ctl_last_pec;
/*
* if we are about to read the first byte in blk rd mode,
@@ -804,9 +824,9 @@ static void npcm_i2c_set_fifo(struct npcm_i2c *bus, int nread, int nwrite)
/* configure TX FIFO */
if (nwrite > 0) {
- if (nwrite > I2C_HW_FIFO_SIZE)
+ if (nwrite > bus->data->fifo_size)
/* data to send is more then FIFO size. */
- iowrite8(I2C_HW_FIFO_SIZE, bus->reg + NPCM_I2CTXF_CTL);
+ iowrite8(bus->data->fifo_size, bus->reg + NPCM_I2CTXF_CTL);
else
iowrite8(nwrite, bus->reg + NPCM_I2CTXF_CTL);
@@ -873,13 +893,13 @@ static void npcm_i2c_write_fifo_slave(struct npcm_i2c *bus, u16 max_bytes)
npcm_i2c_clear_fifo_int(bus);
npcm_i2c_clear_tx_fifo(bus);
iowrite8(0, bus->reg + NPCM_I2CTXF_CTL);
- while (max_bytes-- && I2C_HW_FIFO_SIZE != npcm_i2c_fifo_usage(bus)) {
+ while (max_bytes-- && bus->data->fifo_size != npcm_i2c_fifo_usage(bus)) {
if (bus->slv_wr_size <= 0)
break;
- bus->slv_wr_ind = bus->slv_wr_ind % I2C_HW_FIFO_SIZE;
+ bus->slv_wr_ind = bus->slv_wr_ind & (bus->data->fifo_size - 1);
npcm_i2c_wr_byte(bus, bus->slv_wr_buf[bus->slv_wr_ind]);
bus->slv_wr_ind++;
- bus->slv_wr_ind = bus->slv_wr_ind % I2C_HW_FIFO_SIZE;
+ bus->slv_wr_ind = bus->slv_wr_ind & (bus->data->fifo_size - 1);
bus->slv_wr_size--;
}
}
@@ -894,7 +914,7 @@ static void npcm_i2c_read_fifo_slave(struct npcm_i2c *bus, u8 bytes_in_fifo)
while (bytes_in_fifo--) {
data = npcm_i2c_rd_byte(bus);
- bus->slv_rd_ind = bus->slv_rd_ind % I2C_HW_FIFO_SIZE;
+ bus->slv_rd_ind = bus->slv_rd_ind & (bus->data->fifo_size - 1);
bus->slv_rd_buf[bus->slv_rd_ind] = data;
bus->slv_rd_ind++;
@@ -912,8 +932,8 @@ static int npcm_i2c_slave_get_wr_buf(struct npcm_i2c *bus)
int ret = bus->slv_wr_ind;
/* fill a cyclic buffer */
- for (i = 0; i < I2C_HW_FIFO_SIZE; i++) {
- if (bus->slv_wr_size >= I2C_HW_FIFO_SIZE)
+ for (i = 0; i < bus->data->fifo_size; i++) {
+ if (bus->slv_wr_size >= bus->data->fifo_size)
break;
if (bus->state == I2C_SLAVE_MATCH) {
i2c_slave_event(bus->slave, I2C_SLAVE_READ_REQUESTED, &value);
@@ -921,11 +941,11 @@ static int npcm_i2c_slave_get_wr_buf(struct npcm_i2c *bus)
} else {
i2c_slave_event(bus->slave, I2C_SLAVE_READ_PROCESSED, &value);
}
- ind = (bus->slv_wr_ind + bus->slv_wr_size) % I2C_HW_FIFO_SIZE;
+ ind = (bus->slv_wr_ind + bus->slv_wr_size) & (bus->data->fifo_size - 1);
bus->slv_wr_buf[ind] = value;
bus->slv_wr_size++;
}
- return I2C_HW_FIFO_SIZE - ret;
+ return bus->data->fifo_size - ret;
}
static void npcm_i2c_slave_send_rd_buf(struct npcm_i2c *bus)
@@ -960,7 +980,7 @@ static void npcm_i2c_slave_receive(struct npcm_i2c *bus, u16 nread,
bus->slv_rd_ind = 0;
iowrite8(0, bus->reg + NPCM_I2CTXF_CTL);
- iowrite8(I2C_HW_FIFO_SIZE, bus->reg + NPCM_I2CRXF_CTL);
+ iowrite8(bus->data->fifo_size, bus->reg + NPCM_I2CRXF_CTL);
npcm_i2c_clear_tx_fifo(bus);
npcm_i2c_clear_rx_fifo(bus);
}
@@ -993,12 +1013,12 @@ static void npcm_i2c_slave_wr_buf_sync(struct npcm_i2c *bus)
{
int left_in_fifo;
- left_in_fifo = FIELD_GET(NPCM_I2CTXF_STS_TX_BYTES,
- ioread8(bus->reg + NPCM_I2CTXF_STS));
+ left_in_fifo = bus->data->txf_sts_tx_bytes &
+ ioread8(bus->reg + NPCM_I2CTXF_STS);
/* fifo already full: */
- if (left_in_fifo >= I2C_HW_FIFO_SIZE ||
- bus->slv_wr_size >= I2C_HW_FIFO_SIZE)
+ if (left_in_fifo >= bus->data->fifo_size ||
+ bus->slv_wr_size >= bus->data->fifo_size)
return;
/* update the wr fifo index back to the untransmitted bytes: */
@@ -1006,7 +1026,7 @@ static void npcm_i2c_slave_wr_buf_sync(struct npcm_i2c *bus)
bus->slv_wr_size = bus->slv_wr_size + left_in_fifo;
if (bus->slv_wr_ind < 0)
- bus->slv_wr_ind += I2C_HW_FIFO_SIZE;
+ bus->slv_wr_ind += bus->data->fifo_size;
}
static void npcm_i2c_slave_rd_wr(struct npcm_i2c *bus)
@@ -1152,7 +1172,7 @@ static irqreturn_t npcm_i2c_int_slave_handler(struct npcm_i2c *bus)
npcm_i2c_clear_rx_fifo(bus);
npcm_i2c_clear_tx_fifo(bus);
iowrite8(0, bus->reg + NPCM_I2CTXF_CTL);
- iowrite8(I2C_HW_FIFO_SIZE, bus->reg + NPCM_I2CRXF_CTL);
+ iowrite8(bus->data->fifo_size, bus->reg + NPCM_I2CRXF_CTL);
if (NPCM_I2CST_XMIT & i2cst) {
bus->operation = I2C_WRITE_OPER;
} else {
@@ -1313,8 +1333,8 @@ static void npcm_i2c_master_fifo_read(struct npcm_i2c *bus)
* read == FIFO Size + C (where C < FIFO Size)then first read C bytes
* and in the next int we read rest of the data.
*/
- if (rcount < (2 * I2C_HW_FIFO_SIZE) && rcount > I2C_HW_FIFO_SIZE)
- fifo_bytes = rcount - I2C_HW_FIFO_SIZE;
+ if (rcount < (2 * bus->data->fifo_size) && rcount > bus->data->fifo_size)
+ fifo_bytes = rcount - bus->data->fifo_size;
if (rcount <= fifo_bytes) {
/* last bytes are about to be read - end of tx */
@@ -2193,7 +2213,7 @@ static int npcm_i2c_master_xfer(struct i2c_adapter *adap, struct i2c_msg *msgs,
* It cannot be cleared without resetting the module.
*/
else if (bus->cmd_err &&
- (NPCM_I2CRXF_CTL_LAST_PEC & ioread8(bus->reg + NPCM_I2CRXF_CTL)))
+ (bus->data->rxf_ctl_last_pec & ioread8(bus->reg + NPCM_I2CRXF_CTL)))
npcm_i2c_reset(bus);
/* after any xfer, successful or not, stall and EOB must be disabled */
@@ -2262,6 +2282,7 @@ static int npcm_i2c_probe_bus(struct platform_device *pdev)
{
struct device_node *np = pdev->dev.of_node;
static struct regmap *gcr_regmap;
+ struct device *dev = &pdev->dev;
struct i2c_adapter *adap;
struct npcm_i2c *bus;
struct clk *i2c_clk;
@@ -2274,6 +2295,12 @@ static int npcm_i2c_probe_bus(struct platform_device *pdev)
bus->dev = &pdev->dev;
+ bus->data = of_device_get_match_data(dev);
+ if (!bus->data) {
+ dev_err(dev, "OF data missing\n");
+ return -EINVAL;
+ }
+
bus->num = of_alias_get_id(pdev->dev.of_node, "i2c");
/* core clk must be acquired to calculate module timing settings */
i2c_clk = devm_clk_get(&pdev->dev, NULL);
@@ -2287,7 +2314,7 @@ static int npcm_i2c_probe_bus(struct platform_device *pdev)
if (IS_ERR(gcr_regmap))
return PTR_ERR(gcr_regmap);
- regmap_write(gcr_regmap, NPCM_I2CSEGCTL, NPCM_I2CSEGCTL_INIT_VAL);
+ regmap_write(gcr_regmap, NPCM_I2CSEGCTL, bus->data->segctl_init_val);
bus->reg = devm_platform_ioremap_resource(pdev, 0);
if (IS_ERR(bus->reg))
@@ -2349,7 +2376,8 @@ static int npcm_i2c_remove_bus(struct platform_device *pdev)
}
static const struct of_device_id npcm_i2c_bus_of_table[] = {
- { .compatible = "nuvoton,npcm750-i2c", },
+ { .compatible = "nuvoton,npcm750-i2c", .data = &npxm7xx_i2c_data },
+ { .compatible = "nuvoton,npcm845-i2c", .data = &npxm8xx_i2c_data },
{}
};
MODULE_DEVICE_TABLE(of, npcm_i2c_bus_of_table);
--
2.17.1
WARNING: multiple messages have this Message-ID (diff)
From: Tyrone Ting <warp5tw@gmail.com>
To: avifishman70@gmail.com, tmaimon77@gmail.com,
tali.perry1@gmail.com, venture@google.com, yuenn@google.com,
benjaminfair@google.com, robh+dt@kernel.org,
krzysztof.kozlowski+dt@linaro.org, wsa@kernel.org,
andriy.shevchenko@linux.intel.com, jarkko.nikula@linux.intel.com,
semen.protsenko@linaro.org, jie.deng@intel.com, jsd@semihalf.com,
sven@svenpeter.dev, lukas.bulwahn@gmail.com, olof@lixom.net,
arnd@arndb.de, warp5tw@gmail.com, tali.perry@nuvoton.com,
Avi.Fishman@nuvoton.com, tomer.maimon@nuvoton.com,
KWLIU@nuvoton.com, JJLIU0@nuvoton.com, kfting@nuvoton.com
Cc: devicetree@vger.kernel.org, openbmc@lists.ozlabs.org,
linux-i2c@vger.kernel.org, linux-kernel@vger.kernel.org
Subject: [PATCH v6 4/5] i2c: npcm: Support NPCM845
Date: Wed, 25 May 2022 11:23:40 +0800 [thread overview]
Message-ID: <20220525032341.3182-5-warp5tw@gmail.com> (raw)
In-Reply-To: <20220525032341.3182-1-warp5tw@gmail.com>
From: Tyrone Ting <kfting@nuvoton.com>
Add NPCM8XX I2C support.
The NPCM8XX uses a similar i2c module as NPCM7XX.
The internal HW FIFO is larger in NPCM8XX.
Signed-off-by: Tyrone Ting <kfting@nuvoton.com>
Acked-by: Tomer Maimon <tmaimon77@gmail.com>
---
drivers/i2c/busses/Kconfig | 8 +--
drivers/i2c/busses/Makefile | 2 +-
drivers/i2c/busses/i2c-npcm7xx.c | 114 +++++++++++++++++++------------
3 files changed, 76 insertions(+), 48 deletions(-)
diff --git a/drivers/i2c/busses/Kconfig b/drivers/i2c/busses/Kconfig
index a1bae59208e3..b1d7069dd377 100644
--- a/drivers/i2c/busses/Kconfig
+++ b/drivers/i2c/busses/Kconfig
@@ -838,13 +838,13 @@ 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
+config I2C_NPCM
tristate "Nuvoton I2C Controller"
- depends on ARCH_NPCM7XX || COMPILE_TEST
+ depends on ARCH_NPCM || COMPILE_TEST
help
If you say yes to this option, support will be included for the
- Nuvoton I2C controller, which is available on the NPCM7xx BMC
- controller.
+ Nuvoton I2C controller, which is available on the NPCM BMC
+ controllers.
Driver can also support slave mode (select I2C_SLAVE).
config I2C_OCORES
diff --git a/drivers/i2c/busses/Makefile b/drivers/i2c/busses/Makefile
index 479f60e4ee3d..b0a10e5d9ee9 100644
--- a/drivers/i2c/busses/Makefile
+++ b/drivers/i2c/busses/Makefile
@@ -84,7 +84,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_NPCM) += 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
index b4d218c6c8fb..86fd942ea648 100644
--- a/drivers/i2c/busses/i2c-npcm7xx.c
+++ b/drivers/i2c/busses/i2c-npcm7xx.c
@@ -17,6 +17,7 @@
#include <linux/mfd/syscon.h>
#include <linux/module.h>
#include <linux/of.h>
+#include <linux/of_device.h>
#include <linux/platform_device.h>
#include <linux/regmap.h>
@@ -91,7 +92,6 @@ enum i2c_addr {
/* init register and default value required to enable module */
#define NPCM_I2CSEGCTL 0xE4
-#define NPCM_I2CSEGCTL_INIT_VAL 0x0333F000
/* Common regs */
#define NPCM_I2CSDA 0x00
@@ -226,8 +226,7 @@ static const int npcm_i2caddr[I2C_NUM_OWN_ADDR] = {
#define NPCM_I2CFIF_CTS_CLR_FIFO BIT(6)
#define NPCM_I2CFIF_CTS_SLVRSTR BIT(7)
-/* NPCM_I2CTXF_CTL reg fields */
-#define NPCM_I2CTXF_CTL_TX_THR GENMASK(4, 0)
+/* NPCM_I2CTXF_CTL reg field */
#define NPCM_I2CTXF_CTL_THR_TXIE BIT(6)
/* NPCM_I2CT_OUT reg fields */
@@ -236,22 +235,18 @@ static const int npcm_i2caddr[I2C_NUM_OWN_ADDR] = {
#define NPCM_I2CT_OUT_T_OUTST BIT(7)
/* NPCM_I2CTXF_STS reg fields */
-#define NPCM_I2CTXF_STS_TX_BYTES GENMASK(4, 0)
#define NPCM_I2CTXF_STS_TX_THST BIT(6)
/* NPCM_I2CRXF_STS reg fields */
-#define NPCM_I2CRXF_STS_RX_BYTES GENMASK(4, 0)
#define NPCM_I2CRXF_STS_RX_THST BIT(6)
/* NPCM_I2CFIF_CTL reg fields */
#define NPCM_I2CFIF_CTL_FIFO_EN BIT(4)
/* NPCM_I2CRXF_CTL reg fields */
-#define NPCM_I2CRXF_CTL_RX_THR GENMASK(4, 0)
-#define NPCM_I2CRXF_CTL_LAST_PEC BIT(5)
#define NPCM_I2CRXF_CTL_THR_RXIE BIT(6)
-#define I2C_HW_FIFO_SIZE 16
+#define MAX_I2C_HW_FIFO_SIZE 32
/* I2C_VER reg fields */
#define I2C_VER_VERSION GENMASK(6, 0)
@@ -268,11 +263,36 @@ static const int npcm_i2caddr[I2C_NUM_OWN_ADDR] = {
#define I2C_FREQ_MIN_HZ 10000
#define I2C_FREQ_MAX_HZ I2C_MAX_FAST_MODE_PLUS_FREQ
+struct npcm_i2c_data {
+ u8 fifo_size;
+ u32 segctl_init_val;
+ u8 txf_sts_tx_bytes;
+ u8 rxf_sts_rx_bytes;
+ u8 rxf_ctl_last_pec;
+};
+
+static const struct npcm_i2c_data npxm7xx_i2c_data = {
+ .fifo_size = 16,
+ .segctl_init_val = 0x0333F000,
+ .txf_sts_tx_bytes = GENMASK(4, 0),
+ .rxf_sts_rx_bytes = GENMASK(4, 0),
+ .rxf_ctl_last_pec = BIT(5),
+};
+
+static const struct npcm_i2c_data npxm8xx_i2c_data = {
+ .fifo_size = 32,
+ .segctl_init_val = 0x9333F000,
+ .txf_sts_tx_bytes = GENMASK(5, 0),
+ .rxf_sts_rx_bytes = GENMASK(5, 0),
+ .rxf_ctl_last_pec = BIT(7),
+};
+
/* Status of one I2C module */
struct npcm_i2c {
struct i2c_adapter adap;
struct device *dev;
unsigned char __iomem *reg;
+ const struct npcm_i2c_data *data;
spinlock_t lock; /* IRQ synchronization */
struct completion cmd_complete;
int cmd_err;
@@ -305,8 +325,8 @@ struct npcm_i2c {
int slv_rd_ind;
int slv_wr_size;
int slv_wr_ind;
- u8 slv_rd_buf[I2C_HW_FIFO_SIZE];
- u8 slv_wr_buf[I2C_HW_FIFO_SIZE];
+ u8 slv_rd_buf[MAX_I2C_HW_FIFO_SIZE];
+ u8 slv_wr_buf[MAX_I2C_HW_FIFO_SIZE];
#endif
struct dentry *debugfs; /* debugfs device directory */
u64 ber_cnt;
@@ -439,7 +459,7 @@ static inline bool npcm_i2c_tx_fifo_empty(struct npcm_i2c *bus)
tx_fifo_sts = ioread8(bus->reg + NPCM_I2CTXF_STS);
/* check if TX FIFO is not empty */
- if ((tx_fifo_sts & NPCM_I2CTXF_STS_TX_BYTES) == 0)
+ if ((tx_fifo_sts & bus->data->txf_sts_tx_bytes) == 0)
return false;
/* check if TX FIFO status bit is set: */
@@ -452,7 +472,7 @@ static inline bool npcm_i2c_rx_fifo_full(struct npcm_i2c *bus)
rx_fifo_sts = ioread8(bus->reg + NPCM_I2CRXF_STS);
/* check if RX FIFO is not empty: */
- if ((rx_fifo_sts & NPCM_I2CRXF_STS_RX_BYTES) == 0)
+ if ((rx_fifo_sts & bus->data->rxf_sts_rx_bytes) == 0)
return false;
/* check if rx fifo full status is set: */
@@ -739,11 +759,11 @@ static void npcm_i2c_callback(struct npcm_i2c *bus,
static u8 npcm_i2c_fifo_usage(struct npcm_i2c *bus)
{
if (bus->operation == I2C_WRITE_OPER)
- return FIELD_GET(NPCM_I2CTXF_STS_TX_BYTES,
- ioread8(bus->reg + NPCM_I2CTXF_STS));
+ return (bus->data->txf_sts_tx_bytes &
+ ioread8(bus->reg + NPCM_I2CTXF_STS));
if (bus->operation == I2C_READ_OPER)
- return FIELD_GET(NPCM_I2CRXF_STS_RX_BYTES,
- ioread8(bus->reg + NPCM_I2CRXF_STS));
+ return (bus->data->rxf_sts_rx_bytes &
+ ioread8(bus->reg + NPCM_I2CRXF_STS));
return 0;
}
@@ -755,13 +775,13 @@ static void npcm_i2c_write_to_fifo_master(struct npcm_i2c *bus, u16 max_bytes)
* Fill the FIFO, while the FIFO is not full and there are more bytes
* to write
*/
- size_free_fifo = I2C_HW_FIFO_SIZE - npcm_i2c_fifo_usage(bus);
+ size_free_fifo = bus->data->fifo_size - npcm_i2c_fifo_usage(bus);
while (max_bytes-- && size_free_fifo) {
if (bus->wr_ind < bus->wr_size)
npcm_i2c_wr_byte(bus, bus->wr_buf[bus->wr_ind++]);
else
npcm_i2c_wr_byte(bus, 0xFF);
- size_free_fifo = I2C_HW_FIFO_SIZE - npcm_i2c_fifo_usage(bus);
+ size_free_fifo = bus->data->fifo_size - npcm_i2c_fifo_usage(bus);
}
}
@@ -782,11 +802,11 @@ static void npcm_i2c_set_fifo(struct npcm_i2c *bus, int nread, int nwrite)
/* configure RX FIFO */
if (nread > 0) {
- rxf_ctl = min_t(int, nread, I2C_HW_FIFO_SIZE);
+ rxf_ctl = min_t(int, nread, bus->data->fifo_size);
/* set LAST bit. if LAST is set next FIFO packet is nacked */
- if (nread <= I2C_HW_FIFO_SIZE)
- rxf_ctl |= NPCM_I2CRXF_CTL_LAST_PEC;
+ if (nread <= bus->data->fifo_size)
+ rxf_ctl |= bus->data->rxf_ctl_last_pec;
/*
* if we are about to read the first byte in blk rd mode,
@@ -804,9 +824,9 @@ static void npcm_i2c_set_fifo(struct npcm_i2c *bus, int nread, int nwrite)
/* configure TX FIFO */
if (nwrite > 0) {
- if (nwrite > I2C_HW_FIFO_SIZE)
+ if (nwrite > bus->data->fifo_size)
/* data to send is more then FIFO size. */
- iowrite8(I2C_HW_FIFO_SIZE, bus->reg + NPCM_I2CTXF_CTL);
+ iowrite8(bus->data->fifo_size, bus->reg + NPCM_I2CTXF_CTL);
else
iowrite8(nwrite, bus->reg + NPCM_I2CTXF_CTL);
@@ -873,13 +893,13 @@ static void npcm_i2c_write_fifo_slave(struct npcm_i2c *bus, u16 max_bytes)
npcm_i2c_clear_fifo_int(bus);
npcm_i2c_clear_tx_fifo(bus);
iowrite8(0, bus->reg + NPCM_I2CTXF_CTL);
- while (max_bytes-- && I2C_HW_FIFO_SIZE != npcm_i2c_fifo_usage(bus)) {
+ while (max_bytes-- && bus->data->fifo_size != npcm_i2c_fifo_usage(bus)) {
if (bus->slv_wr_size <= 0)
break;
- bus->slv_wr_ind = bus->slv_wr_ind % I2C_HW_FIFO_SIZE;
+ bus->slv_wr_ind = bus->slv_wr_ind & (bus->data->fifo_size - 1);
npcm_i2c_wr_byte(bus, bus->slv_wr_buf[bus->slv_wr_ind]);
bus->slv_wr_ind++;
- bus->slv_wr_ind = bus->slv_wr_ind % I2C_HW_FIFO_SIZE;
+ bus->slv_wr_ind = bus->slv_wr_ind & (bus->data->fifo_size - 1);
bus->slv_wr_size--;
}
}
@@ -894,7 +914,7 @@ static void npcm_i2c_read_fifo_slave(struct npcm_i2c *bus, u8 bytes_in_fifo)
while (bytes_in_fifo--) {
data = npcm_i2c_rd_byte(bus);
- bus->slv_rd_ind = bus->slv_rd_ind % I2C_HW_FIFO_SIZE;
+ bus->slv_rd_ind = bus->slv_rd_ind & (bus->data->fifo_size - 1);
bus->slv_rd_buf[bus->slv_rd_ind] = data;
bus->slv_rd_ind++;
@@ -912,8 +932,8 @@ static int npcm_i2c_slave_get_wr_buf(struct npcm_i2c *bus)
int ret = bus->slv_wr_ind;
/* fill a cyclic buffer */
- for (i = 0; i < I2C_HW_FIFO_SIZE; i++) {
- if (bus->slv_wr_size >= I2C_HW_FIFO_SIZE)
+ for (i = 0; i < bus->data->fifo_size; i++) {
+ if (bus->slv_wr_size >= bus->data->fifo_size)
break;
if (bus->state == I2C_SLAVE_MATCH) {
i2c_slave_event(bus->slave, I2C_SLAVE_READ_REQUESTED, &value);
@@ -921,11 +941,11 @@ static int npcm_i2c_slave_get_wr_buf(struct npcm_i2c *bus)
} else {
i2c_slave_event(bus->slave, I2C_SLAVE_READ_PROCESSED, &value);
}
- ind = (bus->slv_wr_ind + bus->slv_wr_size) % I2C_HW_FIFO_SIZE;
+ ind = (bus->slv_wr_ind + bus->slv_wr_size) & (bus->data->fifo_size - 1);
bus->slv_wr_buf[ind] = value;
bus->slv_wr_size++;
}
- return I2C_HW_FIFO_SIZE - ret;
+ return bus->data->fifo_size - ret;
}
static void npcm_i2c_slave_send_rd_buf(struct npcm_i2c *bus)
@@ -960,7 +980,7 @@ static void npcm_i2c_slave_receive(struct npcm_i2c *bus, u16 nread,
bus->slv_rd_ind = 0;
iowrite8(0, bus->reg + NPCM_I2CTXF_CTL);
- iowrite8(I2C_HW_FIFO_SIZE, bus->reg + NPCM_I2CRXF_CTL);
+ iowrite8(bus->data->fifo_size, bus->reg + NPCM_I2CRXF_CTL);
npcm_i2c_clear_tx_fifo(bus);
npcm_i2c_clear_rx_fifo(bus);
}
@@ -993,12 +1013,12 @@ static void npcm_i2c_slave_wr_buf_sync(struct npcm_i2c *bus)
{
int left_in_fifo;
- left_in_fifo = FIELD_GET(NPCM_I2CTXF_STS_TX_BYTES,
- ioread8(bus->reg + NPCM_I2CTXF_STS));
+ left_in_fifo = bus->data->txf_sts_tx_bytes &
+ ioread8(bus->reg + NPCM_I2CTXF_STS);
/* fifo already full: */
- if (left_in_fifo >= I2C_HW_FIFO_SIZE ||
- bus->slv_wr_size >= I2C_HW_FIFO_SIZE)
+ if (left_in_fifo >= bus->data->fifo_size ||
+ bus->slv_wr_size >= bus->data->fifo_size)
return;
/* update the wr fifo index back to the untransmitted bytes: */
@@ -1006,7 +1026,7 @@ static void npcm_i2c_slave_wr_buf_sync(struct npcm_i2c *bus)
bus->slv_wr_size = bus->slv_wr_size + left_in_fifo;
if (bus->slv_wr_ind < 0)
- bus->slv_wr_ind += I2C_HW_FIFO_SIZE;
+ bus->slv_wr_ind += bus->data->fifo_size;
}
static void npcm_i2c_slave_rd_wr(struct npcm_i2c *bus)
@@ -1152,7 +1172,7 @@ static irqreturn_t npcm_i2c_int_slave_handler(struct npcm_i2c *bus)
npcm_i2c_clear_rx_fifo(bus);
npcm_i2c_clear_tx_fifo(bus);
iowrite8(0, bus->reg + NPCM_I2CTXF_CTL);
- iowrite8(I2C_HW_FIFO_SIZE, bus->reg + NPCM_I2CRXF_CTL);
+ iowrite8(bus->data->fifo_size, bus->reg + NPCM_I2CRXF_CTL);
if (NPCM_I2CST_XMIT & i2cst) {
bus->operation = I2C_WRITE_OPER;
} else {
@@ -1313,8 +1333,8 @@ static void npcm_i2c_master_fifo_read(struct npcm_i2c *bus)
* read == FIFO Size + C (where C < FIFO Size)then first read C bytes
* and in the next int we read rest of the data.
*/
- if (rcount < (2 * I2C_HW_FIFO_SIZE) && rcount > I2C_HW_FIFO_SIZE)
- fifo_bytes = rcount - I2C_HW_FIFO_SIZE;
+ if (rcount < (2 * bus->data->fifo_size) && rcount > bus->data->fifo_size)
+ fifo_bytes = rcount - bus->data->fifo_size;
if (rcount <= fifo_bytes) {
/* last bytes are about to be read - end of tx */
@@ -2193,7 +2213,7 @@ static int npcm_i2c_master_xfer(struct i2c_adapter *adap, struct i2c_msg *msgs,
* It cannot be cleared without resetting the module.
*/
else if (bus->cmd_err &&
- (NPCM_I2CRXF_CTL_LAST_PEC & ioread8(bus->reg + NPCM_I2CRXF_CTL)))
+ (bus->data->rxf_ctl_last_pec & ioread8(bus->reg + NPCM_I2CRXF_CTL)))
npcm_i2c_reset(bus);
/* after any xfer, successful or not, stall and EOB must be disabled */
@@ -2262,6 +2282,7 @@ static int npcm_i2c_probe_bus(struct platform_device *pdev)
{
struct device_node *np = pdev->dev.of_node;
static struct regmap *gcr_regmap;
+ struct device *dev = &pdev->dev;
struct i2c_adapter *adap;
struct npcm_i2c *bus;
struct clk *i2c_clk;
@@ -2274,6 +2295,12 @@ static int npcm_i2c_probe_bus(struct platform_device *pdev)
bus->dev = &pdev->dev;
+ bus->data = of_device_get_match_data(dev);
+ if (!bus->data) {
+ dev_err(dev, "OF data missing\n");
+ return -EINVAL;
+ }
+
bus->num = of_alias_get_id(pdev->dev.of_node, "i2c");
/* core clk must be acquired to calculate module timing settings */
i2c_clk = devm_clk_get(&pdev->dev, NULL);
@@ -2287,7 +2314,7 @@ static int npcm_i2c_probe_bus(struct platform_device *pdev)
if (IS_ERR(gcr_regmap))
return PTR_ERR(gcr_regmap);
- regmap_write(gcr_regmap, NPCM_I2CSEGCTL, NPCM_I2CSEGCTL_INIT_VAL);
+ regmap_write(gcr_regmap, NPCM_I2CSEGCTL, bus->data->segctl_init_val);
bus->reg = devm_platform_ioremap_resource(pdev, 0);
if (IS_ERR(bus->reg))
@@ -2349,7 +2376,8 @@ static int npcm_i2c_remove_bus(struct platform_device *pdev)
}
static const struct of_device_id npcm_i2c_bus_of_table[] = {
- { .compatible = "nuvoton,npcm750-i2c", },
+ { .compatible = "nuvoton,npcm750-i2c", .data = &npxm7xx_i2c_data },
+ { .compatible = "nuvoton,npcm845-i2c", .data = &npxm8xx_i2c_data },
{}
};
MODULE_DEVICE_TABLE(of, npcm_i2c_bus_of_table);
--
2.17.1
next prev parent reply other threads:[~2022-05-25 3:24 UTC|newest]
Thread overview: 31+ messages / expand[flat|nested] mbox.gz Atom feed top
2022-05-25 3:23 [PATCH v6 0/5] i2c: npcm: Bug fixes timeout, spurious interrupts Tyrone Ting
2022-05-25 3:23 ` Tyrone Ting
2022-05-25 3:23 ` [PATCH v6 1/5] dt-bindings: i2c: npcm: support NPCM845 Tyrone Ting
2022-05-25 3:23 ` Tyrone Ting
2022-06-08 20:02 ` Wolfram Sang
2022-06-08 20:02 ` Wolfram Sang
2022-06-09 12:58 ` Tyrone Ting
2022-05-25 3:23 ` [PATCH v6 2/5] i2c: npcm: Remove own slave addresses 2:10 Tyrone Ting
2022-05-25 3:23 ` Tyrone Ting
2022-06-08 20:02 ` Wolfram Sang
2022-06-08 20:02 ` Wolfram Sang
2022-06-09 12:59 ` Tyrone Ting
2022-05-25 3:23 ` [PATCH v6 3/5] i2c: npcm: Correct slave role behavior Tyrone Ting
2022-05-25 3:23 ` Tyrone Ting
2022-06-08 20:03 ` Wolfram Sang
2022-06-08 20:03 ` Wolfram Sang
2022-06-09 13:02 ` Tyrone Ting
2022-05-25 3:23 ` Tyrone Ting [this message]
2022-05-25 3:23 ` [PATCH v6 4/5] i2c: npcm: Support NPCM845 Tyrone Ting
2022-06-08 20:03 ` Wolfram Sang
2022-06-08 20:03 ` Wolfram Sang
2022-06-09 13:06 ` Tyrone Ting
2022-05-25 3:23 ` [PATCH v6 5/5] i2c: npcm: Capitalize the one-line comment Tyrone Ting
2022-05-25 3:23 ` Tyrone Ting
2022-06-08 20:03 ` Wolfram Sang
2022-06-08 20:03 ` Wolfram Sang
2022-06-09 13:07 ` Tyrone Ting
2022-05-25 17:08 ` [PATCH v6 0/5] i2c: npcm: Bug fixes timeout, spurious interrupts Andy Shevchenko
2022-05-25 17:08 ` Andy Shevchenko
2022-05-27 0:31 ` Tyrone Ting
2022-05-27 0:31 ` Tyrone Ting
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=20220525032341.3182-5-warp5tw@gmail.com \
--to=warp5tw@gmail.com \
--cc=Avi.Fishman@nuvoton.com \
--cc=JJLIU0@nuvoton.com \
--cc=KWLIU@nuvoton.com \
--cc=andriy.shevchenko@linux.intel.com \
--cc=arnd@arndb.de \
--cc=avifishman70@gmail.com \
--cc=benjaminfair@google.com \
--cc=devicetree@vger.kernel.org \
--cc=jarkko.nikula@linux.intel.com \
--cc=jie.deng@intel.com \
--cc=jsd@semihalf.com \
--cc=kfting@nuvoton.com \
--cc=krzysztof.kozlowski+dt@linaro.org \
--cc=linux-i2c@vger.kernel.org \
--cc=linux-kernel@vger.kernel.org \
--cc=lukas.bulwahn@gmail.com \
--cc=olof@lixom.net \
--cc=openbmc@lists.ozlabs.org \
--cc=robh+dt@kernel.org \
--cc=semen.protsenko@linaro.org \
--cc=sven@svenpeter.dev \
--cc=tali.perry1@gmail.com \
--cc=tali.perry@nuvoton.com \
--cc=tmaimon77@gmail.com \
--cc=tomer.maimon@nuvoton.com \
--cc=venture@google.com \
--cc=wsa@kernel.org \
--cc=yuenn@google.com \
/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.