[PATCH 2/3] i2c: designware: Introduce per-variant register offset and bit-layout tables

From: Aniket Limaye

Date: Sat Sep 19 2026 - 05:09:38 EST


Every DW_IC_* register offset and CON-register bit position is currently
baked in as a compile-time constant, which only works while there is a
single register layout. Introduce a logical register-ID enum (enum
dw_i2c_reg_idx) plus a per-variant offset table (dev->regs[]) and a
per-variant CON-register bit-layout descriptor (dev->con_bits), selected
at probe time via the new i2c_dw_select_variant().

Replace every direct DW_IC_* offset/bit-position reference with a lookup
through dev->regs[]/dev->con_bits. Also fold the read-to-clear
interrupt-acknowledgment pattern into a new i2c_dw_ack_intr() helper,
driven by a per-variant dev->intr_clr[] table.

Only one variant exists at this point (DW_apb_i2c), so this is a
mechanical, behavior-preserving change: the values in
dw_i2c_reg_offsets[] and dw_i2c_con_bits match the DW_IC_* macros
exactly. It lays the groundwork for adding a second register layout
(DWC_i2c) without duplicating the whole driver.

Signed-off-by: Aniket Limaye <a-limaye@xxxxxx>
---
drivers/i2c/busses/i2c-designware-amdisp.c | 1 +
drivers/i2c/busses/i2c-designware-common.c | 158 ++++++++++++++++++++++------
drivers/i2c/busses/i2c-designware-core.h | 108 ++++++++++++++++++-
drivers/i2c/busses/i2c-designware-master.c | 125 +++++++++++-----------
drivers/i2c/busses/i2c-designware-pcidrv.c | 2 +
drivers/i2c/busses/i2c-designware-platdrv.c | 2 +
drivers/i2c/busses/i2c-designware-slave.c | 42 ++++----
7 files changed, 318 insertions(+), 120 deletions(-)

diff --git a/drivers/i2c/busses/i2c-designware-amdisp.c b/drivers/i2c/busses/i2c-designware-amdisp.c
index 9f0ec0fae6f2..f7aa075c9977 100644
--- a/drivers/i2c/busses/i2c-designware-amdisp.c
+++ b/drivers/i2c/busses/i2c-designware-amdisp.c
@@ -46,6 +46,7 @@ static int amd_isp_dw_i2c_plat_probe(struct platform_device *pdev)
isp_i2c_dev->flags |= ACCESS_POLLING;
platform_set_drvdata(pdev, isp_i2c_dev);

+ i2c_dw_select_variant(isp_i2c_dev);
isp_i2c_dev->base = devm_platform_ioremap_resource(pdev, 0);
if (IS_ERR(isp_i2c_dev->base))
return dev_err_probe(&pdev->dev, PTR_ERR(isp_i2c_dev->base),
diff --git a/drivers/i2c/busses/i2c-designware-common.c b/drivers/i2c/busses/i2c-designware-common.c
index a1eca6cd4b75..a21aeb7f415a 100644
--- a/drivers/i2c/busses/i2c-designware-common.c
+++ b/drivers/i2c/busses/i2c-designware-common.c
@@ -72,6 +72,95 @@ static const char *const abort_sources[] = {
"incorrect slave-transmitter mode configuration",
};

+/* "snps,designware-i2c" flat register layout */
+static const u32 dw_i2c_reg_offsets[DW_REG_IDX_MAX] = {
+ [DW_REG_IDX_CON] = DW_IC_CON,
+ [DW_REG_IDX_TAR] = DW_IC_TAR,
+ [DW_REG_IDX_SAR] = DW_IC_SAR,
+ [DW_REG_IDX_DATA_CMD] = DW_IC_DATA_CMD,
+ [DW_REG_IDX_SS_SCL_HCNT] = DW_IC_SS_SCL_HCNT,
+ [DW_REG_IDX_SS_SCL_LCNT] = DW_IC_SS_SCL_LCNT,
+ [DW_REG_IDX_FS_SCL_HCNT] = DW_IC_FS_SCL_HCNT,
+ [DW_REG_IDX_FS_SCL_LCNT] = DW_IC_FS_SCL_LCNT,
+ [DW_REG_IDX_HS_SCL_HCNT] = DW_IC_HS_SCL_HCNT,
+ [DW_REG_IDX_HS_SCL_LCNT] = DW_IC_HS_SCL_LCNT,
+ [DW_REG_IDX_INTR_STAT] = DW_IC_INTR_STAT,
+ [DW_REG_IDX_INTR_MASK] = DW_IC_INTR_MASK,
+ [DW_REG_IDX_RAW_INTR_STAT] = DW_IC_RAW_INTR_STAT,
+ [DW_REG_IDX_RX_TL] = DW_IC_RX_TL,
+ [DW_REG_IDX_TX_TL] = DW_IC_TX_TL,
+ [DW_REG_IDX_CLR_INTR] = DW_IC_CLR_INTR,
+ [DW_REG_IDX_CLR_RX_UNDER] = DW_IC_CLR_RX_UNDER,
+ [DW_REG_IDX_CLR_RX_OVER] = DW_IC_CLR_RX_OVER,
+ [DW_REG_IDX_CLR_TX_OVER] = DW_IC_CLR_TX_OVER,
+ [DW_REG_IDX_CLR_RD_REQ] = DW_IC_CLR_RD_REQ,
+ [DW_REG_IDX_CLR_TX_ABRT] = DW_IC_CLR_TX_ABRT,
+ [DW_REG_IDX_CLR_RX_DONE] = DW_IC_CLR_RX_DONE,
+ [DW_REG_IDX_CLR_ACTIVITY] = DW_IC_CLR_ACTIVITY,
+ [DW_REG_IDX_CLR_STOP_DET] = DW_IC_CLR_STOP_DET,
+ [DW_REG_IDX_CLR_START_DET] = DW_IC_CLR_START_DET,
+ [DW_REG_IDX_CLR_GEN_CALL] = DW_IC_CLR_GEN_CALL,
+ [DW_REG_IDX_ENABLE] = DW_IC_ENABLE,
+ [DW_REG_IDX_STATUS] = DW_IC_STATUS,
+ [DW_REG_IDX_TXFLR] = DW_IC_TXFLR,
+ [DW_REG_IDX_RXFLR] = DW_IC_RXFLR,
+ [DW_REG_IDX_SDA_HOLD] = DW_IC_SDA_HOLD,
+ [DW_REG_IDX_TX_ABRT_SOURCE] = DW_IC_TX_ABRT_SOURCE,
+ [DW_REG_IDX_ENABLE_STATUS] = DW_IC_ENABLE_STATUS,
+ [DW_REG_IDX_SMBUS_INTR_MASK] = DW_IC_SMBUS_INTR_MASK,
+ [DW_REG_IDX_COMP_PARAM_1] = DW_IC_COMP_PARAM_1,
+ [DW_REG_IDX_COMP_VERSION] = DW_IC_COMP_VERSION,
+ [DW_REG_IDX_COMP_TYPE] = DW_IC_COMP_TYPE,
+};
+
+static const struct dw_i2c_con_bits dw_i2c_con_bits = {
+ .master = DW_IC_CON_MASTER,
+ .speed_std = DW_IC_CON_SPEED_STD,
+ .speed_fast = DW_IC_CON_SPEED_FAST,
+ .speed_high = DW_IC_CON_SPEED_HIGH,
+ .speed_mask = DW_IC_CON_SPEED_MASK,
+ .bit10_slave = DW_IC_CON_10BITADDR_SLAVE,
+ .bit10_master = DW_IC_CON_10BITADDR_MASTER,
+ .restart_en = DW_IC_CON_RESTART_EN,
+ .slave_disable = DW_IC_CON_SLAVE_DISABLE,
+ .stop_det_ifaddressed = DW_IC_CON_STOP_DET_IFADDRESSED,
+ .tx_empty_ctrl = DW_IC_CON_TX_EMPTY_CTRL,
+ .rx_fifo_full_hld_ctrl = DW_IC_CON_RX_FIFO_FULL_HLD_CTRL,
+ .bus_clear_ctrl = DW_IC_CON_BUS_CLEAR_CTRL,
+};
+
+/* "snps,designware-i2c": dedicated read-to-clear register ID per logical interrupt */
+static const u32 dw_i2c_intr_clr[DW_INTR_IDX_MAX] = {
+ [DW_INTR_IDX_ALL] = DW_REG_IDX_CLR_INTR,
+ [DW_INTR_IDX_RX_UNDER] = DW_REG_IDX_CLR_RX_UNDER,
+ [DW_INTR_IDX_RX_OVER] = DW_REG_IDX_CLR_RX_OVER,
+ [DW_INTR_IDX_TX_OVER] = DW_REG_IDX_CLR_TX_OVER,
+ [DW_INTR_IDX_RD_REQ] = DW_REG_IDX_CLR_RD_REQ,
+ [DW_INTR_IDX_TX_ABRT] = DW_REG_IDX_CLR_TX_ABRT,
+ [DW_INTR_IDX_RX_DONE] = DW_REG_IDX_CLR_RX_DONE,
+ [DW_INTR_IDX_ACTIVITY] = DW_REG_IDX_CLR_ACTIVITY,
+ [DW_INTR_IDX_STOP_DET] = DW_REG_IDX_CLR_STOP_DET,
+ [DW_INTR_IDX_START_DET] = DW_REG_IDX_CLR_START_DET,
+ [DW_INTR_IDX_GEN_CALL] = DW_REG_IDX_CLR_GEN_CALL,
+};
+
+/**
+ * i2c_dw_select_variant() - Pick the register offset table, CON-register bit
+ * layout and interrupt-ack mapping matching this device's IP variant
+ * @dev: device private data
+ *
+ * Must be called after dev->flags has been populated from
+ * device_get_match_data()/ACPI id data, and before any register access
+ * (including i2c_dw_init_regmap()).
+ */
+void i2c_dw_select_variant(struct dw_i2c_dev *dev)
+{
+ dev->regs = dw_i2c_reg_offsets;
+ dev->con_bits = &dw_i2c_con_bits;
+ dev->intr_clr = dw_i2c_intr_clr;
+}
+EXPORT_SYMBOL_GPL(i2c_dw_select_variant);
+
static int dw_reg_read(void *context, unsigned int reg, unsigned int *val)
{
struct dw_i2c_dev *dev = context;
@@ -147,7 +236,7 @@ static int i2c_dw_init_regmap(struct dw_i2c_dev *dev)
.disable_locking = true,
.reg_read = dw_reg_read,
.reg_write = dw_reg_write,
- .max_register = DW_IC_COMP_TYPE,
+ .max_register = dev->regs[DW_REG_IDX_COMP_TYPE],
};
u32 reg;
int ret;
@@ -163,7 +252,7 @@ static int i2c_dw_init_regmap(struct dw_i2c_dev *dev)
if (ret)
return ret;

- reg = readl(dev->base + DW_IC_COMP_TYPE);
+ reg = readl(dev->base + dev->regs[DW_REG_IDX_COMP_TYPE]);
i2c_dw_release_lock(dev);

if ((dev->flags & MODEL_MASK) == MODEL_AMD_NAVI_GPU)
@@ -365,17 +454,17 @@ static void i2c_dw_configure_mode(struct dw_i2c_dev *dev, int mode)
{
switch (mode) {
case DW_IC_MASTER:
- regmap_write(dev->map, DW_IC_TX_TL, dev->tx_fifo_depth / 2);
- regmap_write(dev->map, DW_IC_RX_TL, 0);
- regmap_write(dev->map, DW_IC_CON, dev->master_cfg);
+ regmap_write(dev->map, dev->regs[DW_REG_IDX_TX_TL], dev->tx_fifo_depth / 2);
+ regmap_write(dev->map, dev->regs[DW_REG_IDX_RX_TL], 0);
+ regmap_write(dev->map, dev->regs[DW_REG_IDX_CON], dev->master_cfg);
break;
case DW_IC_SLAVE:
dev->status = 0;
- regmap_write(dev->map, DW_IC_TX_TL, 0);
- regmap_write(dev->map, DW_IC_RX_TL, 0);
- regmap_write(dev->map, DW_IC_CON, dev->slave_cfg);
- regmap_write(dev->map, DW_IC_SAR, dev->slave->addr);
- regmap_write(dev->map, DW_IC_INTR_MASK, DW_IC_INTR_SLAVE_MASK);
+ regmap_write(dev->map, dev->regs[DW_REG_IDX_TX_TL], 0);
+ regmap_write(dev->map, dev->regs[DW_REG_IDX_RX_TL], 0);
+ regmap_write(dev->map, dev->regs[DW_REG_IDX_CON], dev->slave_cfg);
+ regmap_write(dev->map, dev->regs[DW_REG_IDX_SAR], dev->slave->addr);
+ regmap_write(dev->map, dev->regs[DW_REG_IDX_INTR_MASK], DW_IC_INTR_SLAVE_MASK);
__i2c_dw_enable(dev);
break;
default:
@@ -387,16 +476,16 @@ static void i2c_dw_configure_mode(struct dw_i2c_dev *dev, int mode)
static void i2c_dw_write_timings(struct dw_i2c_dev *dev)
{
/* Write standard speed timing parameters */
- regmap_write(dev->map, DW_IC_SS_SCL_HCNT, dev->ss_hcnt);
- regmap_write(dev->map, DW_IC_SS_SCL_LCNT, dev->ss_lcnt);
+ regmap_write(dev->map, dev->regs[DW_REG_IDX_SS_SCL_HCNT], dev->ss_hcnt);
+ regmap_write(dev->map, dev->regs[DW_REG_IDX_SS_SCL_LCNT], dev->ss_lcnt);

/* Write fast mode/fast mode plus timing parameters */
- regmap_write(dev->map, DW_IC_FS_SCL_HCNT, dev->fs_hcnt);
- regmap_write(dev->map, DW_IC_FS_SCL_LCNT, dev->fs_lcnt);
+ regmap_write(dev->map, dev->regs[DW_REG_IDX_FS_SCL_HCNT], dev->fs_hcnt);
+ regmap_write(dev->map, dev->regs[DW_REG_IDX_FS_SCL_LCNT], dev->fs_lcnt);

/* Write high speed timing parameters */
- regmap_write(dev->map, DW_IC_HS_SCL_HCNT, dev->hs_hcnt);
- regmap_write(dev->map, DW_IC_HS_SCL_LCNT, dev->hs_lcnt);
+ regmap_write(dev->map, dev->regs[DW_REG_IDX_HS_SCL_HCNT], dev->hs_hcnt);
+ regmap_write(dev->map, dev->regs[DW_REG_IDX_HS_SCL_LCNT], dev->hs_lcnt);
}

/**
@@ -448,13 +537,13 @@ int i2c_dw_init(struct dw_i2c_dev *dev)
* firmware that leaves IC_SMBUS=1; the handler never
* services them.
*/
- regmap_write(dev->map, DW_IC_SMBUS_INTR_MASK, 0);
+ regmap_write(dev->map, dev->regs[DW_REG_IDX_SMBUS_INTR_MASK], 0);

i2c_dw_write_timings(dev);

/* Write SDA hold time if supported */
if (dev->sda_hold_time)
- regmap_write(dev->map, DW_IC_SDA_HOLD, dev->sda_hold_time);
+ regmap_write(dev->map, dev->regs[DW_REG_IDX_SDA_HOLD], dev->sda_hold_time);

i2c_dw_configure_mode(dev, dev->mode);

@@ -579,14 +668,14 @@ static int i2c_dw_set_sda_hold(struct dw_i2c_dev *dev)
return ret;

/* Configure SDA Hold Time if required */
- ret = regmap_read(dev->map, DW_IC_COMP_VERSION, &reg);
+ ret = regmap_read(dev->map, dev->regs[DW_REG_IDX_COMP_VERSION], &reg);
if (ret)
goto err_release_lock;

if (reg >= DW_IC_SDA_HOLD_MIN_VERS) {
if (!dev->sda_hold_time) {
/* Keep previous hold time setting if no one set it */
- ret = regmap_read(dev->map, DW_IC_SDA_HOLD,
+ ret = regmap_read(dev->map, dev->regs[DW_REG_IDX_SDA_HOLD],
&dev->sda_hold_time);
if (ret)
goto err_release_lock;
@@ -629,9 +718,9 @@ void __i2c_dw_disable(struct dw_i2c_dev *dev)
unsigned int status;
int ret;

- regmap_read(dev->map, DW_IC_RAW_INTR_STAT, &raw_intr_stats);
- regmap_read(dev->map, DW_IC_STATUS, &ic_stats);
- regmap_read(dev->map, DW_IC_ENABLE, &enable);
+ regmap_read(dev->map, dev->regs[DW_REG_IDX_RAW_INTR_STAT], &raw_intr_stats);
+ regmap_read(dev->map, dev->regs[DW_REG_IDX_STATUS], &ic_stats);
+ regmap_read(dev->map, dev->regs[DW_REG_IDX_ENABLE], &enable);

abort_needed = (raw_intr_stats & DW_IC_INTR_MST_ON_HOLD) ||
(ic_stats & DW_IC_STATUS_MASTER_HOLD_TX_FIFO_EMPTY);
@@ -645,7 +734,7 @@ void __i2c_dw_disable(struct dw_i2c_dev *dev)

if (abort_needed) {
if (!(enable & DW_IC_ENABLE_ENABLE)) {
- regmap_write(dev->map, DW_IC_ENABLE, DW_IC_ENABLE_ENABLE);
+ regmap_write(dev->map, dev->regs[DW_REG_IDX_ENABLE], DW_IC_ENABLE_ENABLE);
/*
* Wait 10 times the signaling period of the highest I2C
* transfer supported by the driver (for 400KHz this is
@@ -657,8 +746,8 @@ void __i2c_dw_disable(struct dw_i2c_dev *dev)
enable |= DW_IC_ENABLE_ENABLE;
}

- regmap_write(dev->map, DW_IC_ENABLE, enable | DW_IC_ENABLE_ABORT);
- ret = regmap_read_poll_timeout(dev->map, DW_IC_ENABLE, enable,
+ regmap_write(dev->map, dev->regs[DW_REG_IDX_ENABLE], enable | DW_IC_ENABLE_ABORT);
+ ret = regmap_read_poll_timeout(dev->map, dev->regs[DW_REG_IDX_ENABLE], enable,
!(enable & DW_IC_ENABLE_ABORT),
DW_IC_ABORT_TIMEOUT_US,
10 * DW_IC_ABORT_TIMEOUT_US);
@@ -672,7 +761,7 @@ void __i2c_dw_disable(struct dw_i2c_dev *dev)
* The enable status register may be unimplemented, but
* in that case this test reads zero and exits the loop.
*/
- regmap_read(dev->map, DW_IC_ENABLE_STATUS, &status);
+ regmap_read(dev->map, dev->regs[DW_REG_IDX_ENABLE_STATUS], &status);
if (!(status & 1))
return;

@@ -754,7 +843,7 @@ int i2c_dw_wait_bus_not_busy(struct dw_i2c_dev *dev)
unsigned int status;
int ret;

- ret = regmap_read_poll_timeout(dev->map, DW_IC_STATUS, status,
+ ret = regmap_read_poll_timeout(dev->map, dev->regs[DW_REG_IDX_STATUS], status,
!(status & DW_IC_STATUS_ACTIVITY),
DW_IC_BUSY_POLL_TIMEOUT_US,
20 * DW_IC_BUSY_POLL_TIMEOUT_US);
@@ -763,7 +852,7 @@ int i2c_dw_wait_bus_not_busy(struct dw_i2c_dev *dev)

i2c_recover_bus(&dev->adapter);

- regmap_read(dev->map, DW_IC_STATUS, &status);
+ regmap_read(dev->map, dev->regs[DW_REG_IDX_STATUS], &status);
if (!(status & DW_IC_STATUS_ACTIVITY))
ret = 0;
}
@@ -816,7 +905,7 @@ static int i2c_dw_set_fifo_size(struct dw_i2c_dev *dev)
if (ret)
return ret;

- ret = regmap_read(dev->map, DW_IC_COMP_PARAM_1, &param);
+ ret = regmap_read(dev->map, dev->regs[DW_REG_IDX_COMP_PARAM_1], &param);
i2c_dw_release_lock(dev);
if (ret)
return ret;
@@ -845,7 +934,6 @@ u32 i2c_dw_func(struct i2c_adapter *adap)

void i2c_dw_disable(struct dw_i2c_dev *dev)
{
- unsigned int dummy;
int ret;

ret = i2c_dw_acquire_lock(dev);
@@ -857,7 +945,7 @@ void i2c_dw_disable(struct dw_i2c_dev *dev)

/* Disable all interrupts */
__i2c_dw_write_intr_mask(dev, 0);
- regmap_read(dev->map, DW_IC_CLR_INTR, &dummy);
+ i2c_dw_ack_intr(dev, DW_INTR_IDX_ALL);

i2c_dw_release_lock(dev);
}
@@ -1054,9 +1142,9 @@ void i2c_dw_shutdown(struct dw_i2c_dev *dev)
* To quickly NACK the controller during shutdown, we set the target
* disable bit while the controller is still enabled.
*/
- regmap_read(dev->map, DW_IC_CON, &con);
- con |= DW_IC_CON_SLAVE_DISABLE;
- regmap_write(dev->map, DW_IC_CON, con);
+ regmap_read(dev->map, dev->regs[DW_REG_IDX_CON], &con);
+ con |= dev->con_bits->slave_disable;
+ regmap_write(dev->map, dev->regs[DW_REG_IDX_CON], con);

i2c_dw_disable(dev);
}
diff --git a/drivers/i2c/busses/i2c-designware-core.h b/drivers/i2c/busses/i2c-designware-core.h
index 2c929a6e8da2..2fad18582db7 100644
--- a/drivers/i2c/busses/i2c-designware-core.h
+++ b/drivers/i2c/busses/i2c-designware-core.h
@@ -43,6 +43,91 @@
#define DW_IC_SDA_HOLD_MIN_VERS 0x3131312A /* "111*" == v1.11* */
#define DW_IC_COMP_TYPE_VALUE 0x44570140 /* "DW" + 0x0140 */

+/*
+ * Logical register IDs. The physical offset backing each ID depends on the
+ * variant of the IP (selected via i2c_dw_select_variant() based on the
+ * device's compatible string) and is looked up at runtime through
+ * dev->regs[]. This lets a single set of driver code paths serve IP
+ * variants with different register layouts.
+ */
+enum dw_i2c_reg_idx {
+ DW_REG_IDX_CON,
+ DW_REG_IDX_TAR,
+ DW_REG_IDX_SAR,
+ DW_REG_IDX_DATA_CMD,
+ DW_REG_IDX_SS_SCL_HCNT,
+ DW_REG_IDX_SS_SCL_LCNT,
+ DW_REG_IDX_FS_SCL_HCNT,
+ DW_REG_IDX_FS_SCL_LCNT,
+ DW_REG_IDX_HS_SCL_HCNT,
+ DW_REG_IDX_HS_SCL_LCNT,
+ DW_REG_IDX_INTR_STAT,
+ DW_REG_IDX_INTR_MASK,
+ DW_REG_IDX_RAW_INTR_STAT,
+ DW_REG_IDX_RX_TL,
+ DW_REG_IDX_TX_TL,
+ DW_REG_IDX_CLR_INTR,
+ DW_REG_IDX_CLR_RX_UNDER,
+ DW_REG_IDX_CLR_RX_OVER,
+ DW_REG_IDX_CLR_TX_OVER,
+ DW_REG_IDX_CLR_RD_REQ,
+ DW_REG_IDX_CLR_TX_ABRT,
+ DW_REG_IDX_CLR_RX_DONE,
+ DW_REG_IDX_CLR_ACTIVITY,
+ DW_REG_IDX_CLR_STOP_DET,
+ DW_REG_IDX_CLR_START_DET,
+ DW_REG_IDX_CLR_GEN_CALL,
+ DW_REG_IDX_ENABLE,
+ DW_REG_IDX_STATUS,
+ DW_REG_IDX_TXFLR,
+ DW_REG_IDX_RXFLR,
+ DW_REG_IDX_SDA_HOLD,
+ DW_REG_IDX_TX_ABRT_SOURCE,
+ DW_REG_IDX_ENABLE_STATUS,
+ DW_REG_IDX_SMBUS_INTR_MASK,
+ DW_REG_IDX_COMP_PARAM_1,
+ DW_REG_IDX_COMP_VERSION,
+ DW_REG_IDX_COMP_TYPE,
+ DW_REG_IDX_MAX,
+};
+
+/*
+ * Bit positions within the CON register that could differ between IP
+ * variants. Values here match the DW_IC_CON_* macros in
+ * <linux/designware_i2c.h>.
+ */
+struct dw_i2c_con_bits {
+ u32 master;
+ u32 speed_std;
+ u32 speed_fast;
+ u32 speed_high;
+ u32 speed_mask;
+ u32 bit10_slave;
+ u32 bit10_master;
+ u32 restart_en;
+ u32 slave_disable;
+ u32 stop_det_ifaddressed;
+ u32 tx_empty_ctrl;
+ u32 rx_fifo_full_hld_ctrl;
+ u32 bus_clear_ctrl;
+};
+
+/* Logical interrupt IDs for i2c_dw_ack_intr(); DW_INTR_IDX_ALL = "current pending interrupt" */
+enum dw_i2c_intr_idx {
+ DW_INTR_IDX_ALL,
+ DW_INTR_IDX_RX_UNDER,
+ DW_INTR_IDX_RX_OVER,
+ DW_INTR_IDX_TX_OVER,
+ DW_INTR_IDX_RD_REQ,
+ DW_INTR_IDX_TX_ABRT,
+ DW_INTR_IDX_RX_DONE,
+ DW_INTR_IDX_ACTIVITY,
+ DW_INTR_IDX_STOP_DET,
+ DW_INTR_IDX_START_DET,
+ DW_INTR_IDX_GEN_CALL,
+ DW_INTR_IDX_MAX,
+};
+
#define DW_IC_INTR_DEFAULT_MASK (DW_IC_INTR_RX_FULL | \
DW_IC_INTR_TX_ABRT | \
DW_IC_INTR_STOP_DET)
@@ -126,6 +211,9 @@ struct reset_control;
* struct dw_i2c_dev - private i2c-designware data
* @dev: driver model device node
* @map: IO registers map
+ * @regs: logical-to-physical register offset table for the active IP variant
+ * @con_bits: CON register bit-layout for the active IP variant
+ * @intr_clr: logical intr number to reg table for the active IP variant
* @sysmap: System controller registers map
* @base: IO registers pointer
* @ext: Extended IO registers pointer
@@ -189,6 +277,9 @@ struct reset_control;
struct dw_i2c_dev {
struct device *dev;
struct regmap *map;
+ const u32 *regs;
+ const struct dw_i2c_con_bits *con_bits;
+ const u32 *intr_clr;
struct regmap *sysmap;
void __iomem *base;
void __iomem *ext;
@@ -265,6 +356,7 @@ struct i2c_dw_semaphore_callbacks {
int (*probe)(struct dw_i2c_dev *dev);
};

+void i2c_dw_select_variant(struct dw_i2c_dev *dev);
u32 i2c_dw_scl_hcnt(struct dw_i2c_dev *dev, unsigned int reg, u32 ic_clk,
u32 tSYMBOL, u32 tf, int offset);
u32 i2c_dw_scl_lcnt(struct dw_i2c_dev *dev, unsigned int reg, u32 ic_clk,
@@ -283,12 +375,12 @@ extern const struct dev_pm_ops i2c_dw_dev_pm_ops;
static inline void __i2c_dw_enable(struct dw_i2c_dev *dev)
{
dev->status |= STATUS_ACTIVE;
- regmap_write(dev->map, DW_IC_ENABLE, 1);
+ regmap_write(dev->map, dev->regs[DW_REG_IDX_ENABLE], 1);
}

static inline void __i2c_dw_disable_nowait(struct dw_i2c_dev *dev)
{
- regmap_write(dev->map, DW_IC_ENABLE, 0);
+ regmap_write(dev->map, dev->regs[DW_REG_IDX_ENABLE], 0);
dev->status &= ~STATUS_ACTIVE;
}

@@ -297,7 +389,7 @@ static inline void __i2c_dw_write_intr_mask(struct dw_i2c_dev *dev,
{
unsigned int val = dev->flags & ACCESS_POLLING ? 0 : intr_mask;

- regmap_write(dev->map, DW_IC_INTR_MASK, val);
+ regmap_write(dev->map, dev->regs[DW_REG_IDX_INTR_MASK], val);
dev->sw_mask = intr_mask;
}

@@ -305,11 +397,19 @@ static inline void __i2c_dw_read_intr_mask(struct dw_i2c_dev *dev,
unsigned int *intr_mask)
{
if (!(dev->flags & ACCESS_POLLING))
- regmap_read(dev->map, DW_IC_INTR_MASK, intr_mask);
+ regmap_read(dev->map, dev->regs[DW_REG_IDX_INTR_MASK], intr_mask);
else
*intr_mask = dev->sw_mask;
}

+/* Acknowledge a logical interrupt via dev->intr_clr[]: reg ID */
+static inline void i2c_dw_ack_intr(struct dw_i2c_dev *dev, enum dw_i2c_intr_idx intr)
+{
+ unsigned int dummy;
+
+ regmap_read(dev->map, dev->regs[dev->intr_clr[intr]], &dummy);
+}
+
void __i2c_dw_disable(struct dw_i2c_dev *dev);
void i2c_dw_disable(struct dw_i2c_dev *dev);

diff --git a/drivers/i2c/busses/i2c-designware-master.c b/drivers/i2c/busses/i2c-designware-master.c
index a1bcc3797e4f..f3b952f730bc 100644
--- a/drivers/i2c/busses/i2c-designware-master.c
+++ b/drivers/i2c/busses/i2c-designware-master.c
@@ -46,7 +46,7 @@ static int i2c_dw_set_timings_master(struct dw_i2c_dev *dev)
if (ret)
return ret;

- ret = regmap_read(dev->map, DW_IC_COMP_PARAM_1, &comp_param1);
+ ret = regmap_read(dev->map, dev->regs[DW_REG_IDX_COMP_PARAM_1], &comp_param1);
i2c_dw_release_lock(dev);
if (ret)
return ret;
@@ -60,14 +60,14 @@ static int i2c_dw_set_timings_master(struct dw_i2c_dev *dev)
ic_clk = i2c_dw_clk_rate(dev);
dev->ss_hcnt =
i2c_dw_scl_hcnt(dev,
- DW_IC_SS_SCL_HCNT,
+ dev->regs[DW_REG_IDX_SS_SCL_HCNT],
ic_clk,
4000, /* tHD;STA = tHIGH = 4.0 us */
sda_falling_time,
0); /* No offset */
dev->ss_lcnt =
i2c_dw_scl_lcnt(dev,
- DW_IC_SS_SCL_LCNT,
+ dev->regs[DW_REG_IDX_SS_SCL_LCNT],
ic_clk,
4700, /* tLOW = 4.7 us */
scl_falling_time,
@@ -93,14 +93,14 @@ static int i2c_dw_set_timings_master(struct dw_i2c_dev *dev)
ic_clk = i2c_dw_clk_rate(dev);
dev->fs_hcnt =
i2c_dw_scl_hcnt(dev,
- DW_IC_FS_SCL_HCNT,
+ dev->regs[DW_REG_IDX_FS_SCL_HCNT],
ic_clk,
260, /* tHIGH = 260 ns */
sda_falling_time,
0); /* No offset */
dev->fs_lcnt =
i2c_dw_scl_lcnt(dev,
- DW_IC_FS_SCL_LCNT,
+ dev->regs[DW_REG_IDX_FS_SCL_LCNT],
ic_clk,
500, /* tLOW = 500 ns */
scl_falling_time,
@@ -116,14 +116,14 @@ static int i2c_dw_set_timings_master(struct dw_i2c_dev *dev)
ic_clk = i2c_dw_clk_rate(dev);
dev->fs_hcnt =
i2c_dw_scl_hcnt(dev,
- DW_IC_FS_SCL_HCNT,
+ dev->regs[DW_REG_IDX_FS_SCL_HCNT],
ic_clk,
600, /* tHD;STA = tHIGH = 0.6 us */
sda_falling_time,
0); /* No offset */
dev->fs_lcnt =
i2c_dw_scl_lcnt(dev,
- DW_IC_FS_SCL_LCNT,
+ dev->regs[DW_REG_IDX_FS_SCL_LCNT],
ic_clk,
1300, /* tLOW = 1.3 us */
scl_falling_time,
@@ -133,14 +133,14 @@ static int i2c_dw_set_timings_master(struct dw_i2c_dev *dev)
fp_str, dev->fs_hcnt, dev->fs_lcnt);

/* Check is high speed possible and fall back to fast mode if not */
- if ((dev->master_cfg & DW_IC_CON_SPEED_MASK) ==
- DW_IC_CON_SPEED_HIGH) {
+ if ((dev->master_cfg & dev->con_bits->speed_mask) ==
+ dev->con_bits->speed_high) {
if ((comp_param1 & DW_IC_COMP_PARAM_1_SPEED_MODE_MASK)
!= DW_IC_COMP_PARAM_1_SPEED_MODE_HIGH) {
dev_err(dev->dev, "High Speed not supported!\n");
t->bus_freq_hz = I2C_MAX_FAST_MODE_FREQ;
- dev->master_cfg &= ~DW_IC_CON_SPEED_MASK;
- dev->master_cfg |= DW_IC_CON_SPEED_FAST;
+ dev->master_cfg &= ~dev->con_bits->speed_mask;
+ dev->master_cfg |= dev->con_bits->speed_fast;
dev->hs_hcnt = 0;
dev->hs_lcnt = 0;
} else if (!dev->hs_hcnt || !dev->hs_lcnt) {
@@ -166,14 +166,14 @@ static int i2c_dw_set_timings_master(struct dw_i2c_dev *dev)
ic_clk = i2c_dw_clk_rate(dev);
dev->hs_hcnt =
i2c_dw_scl_hcnt(dev,
- DW_IC_HS_SCL_HCNT,
+ dev->regs[DW_REG_IDX_HS_SCL_HCNT],
ic_clk,
t_high,
sda_falling_time,
0); /* No offset */
dev->hs_lcnt =
i2c_dw_scl_lcnt(dev,
- DW_IC_HS_SCL_LCNT,
+ dev->regs[DW_REG_IDX_HS_SCL_LCNT],
ic_clk,
t_low,
scl_falling_time,
@@ -200,7 +200,7 @@ static void i2c_dw_xfer_init(struct dw_i2c_dev *dev)

/* If the slave address is ten bit address, enable 10BITADDR */
if (msgs[dev->msg_write_idx].flags & I2C_M_TEN) {
- ic_con = DW_IC_CON_10BITADDR_MASTER;
+ ic_con = dev->con_bits->bit10_master;
/*
* If I2C_DYNAMIC_TAR_UPDATE is set, the 10-bit addressing
* mode has to be enabled via bit 12 of IC_TAR register.
@@ -210,14 +210,14 @@ static void i2c_dw_xfer_init(struct dw_i2c_dev *dev)
ic_tar = DW_IC_TAR_10BITADDR_MASTER;
}

- regmap_update_bits(dev->map, DW_IC_CON, DW_IC_CON_10BITADDR_MASTER,
+ regmap_update_bits(dev->map, dev->regs[DW_REG_IDX_CON], dev->con_bits->bit10_master,
ic_con);

/*
* Set the slave (target) address and enable 10-bit addressing mode
* if applicable.
*/
- regmap_write(dev->map, DW_IC_TAR,
+ regmap_write(dev->map, dev->regs[DW_REG_IDX_TAR],
msgs[dev->msg_write_idx].addr | ic_tar);

/* Enforce disabled interrupts (due to HW issues) */
@@ -227,10 +227,10 @@ static void i2c_dw_xfer_init(struct dw_i2c_dev *dev)
__i2c_dw_enable(dev);

/* Dummy read to avoid the register getting stuck on Bay Trail */
- regmap_read(dev->map, DW_IC_ENABLE_STATUS, &dummy);
+ regmap_read(dev->map, dev->regs[DW_REG_IDX_ENABLE_STATUS], &dummy);

/* Clear and enable interrupts */
- regmap_read(dev->map, DW_IC_CLR_INTR, &dummy);
+ i2c_dw_ack_intr(dev, DW_INTR_IDX_ALL);
__i2c_dw_write_intr_mask(dev, DW_IC_INTR_MASTER_MASK);
}

@@ -253,11 +253,11 @@ static bool i2c_dw_is_controller_active(struct dw_i2c_dev *dev)
{
u32 status;

- regmap_read(dev->map, DW_IC_STATUS, &status);
+ regmap_read(dev->map, dev->regs[DW_REG_IDX_STATUS], &status);
if (!(status & DW_IC_STATUS_MASTER_ACTIVITY))
return false;

- return regmap_read_poll_timeout(dev->map, DW_IC_STATUS, status,
+ return regmap_read_poll_timeout(dev->map, dev->regs[DW_REG_IDX_STATUS], status,
!(status & DW_IC_STATUS_MASTER_ACTIVITY),
1100, 20000) != 0;
}
@@ -267,7 +267,7 @@ static int i2c_dw_check_stopbit(struct dw_i2c_dev *dev)
u32 val;
int ret;

- ret = regmap_read_poll_timeout(dev->map, DW_IC_INTR_STAT, val,
+ ret = regmap_read_poll_timeout(dev->map, dev->regs[DW_REG_IDX_INTR_STAT], val,
!(val & DW_IC_INTR_STOP_DET),
1100, 20000);
if (ret)
@@ -320,7 +320,7 @@ static int amd_i2c_dw_xfer_quirk(struct dw_i2c_dev *dev, struct i2c_msg *msgs, i
buf_len = msgs[msg_wrt_idx].len;

if (!(msgs[msg_wrt_idx].flags & I2C_M_RD))
- regmap_write(dev->map, DW_IC_TX_TL, buf_len - 1);
+ regmap_write(dev->map, dev->regs[DW_REG_IDX_TX_TL], buf_len - 1);
/*
* Initiate the i2c read/write transaction of buffer length,
* and poll for bus busy status. For the last message transfer,
@@ -332,11 +332,13 @@ static int amd_i2c_dw_xfer_quirk(struct dw_i2c_dev *dev, struct i2c_msg *msgs, i

if (msgs[msg_wrt_idx].flags & I2C_M_RD) {
/* Due to hardware bug, need to write the same command twice. */
- regmap_write(dev->map, DW_IC_DATA_CMD, 0x100);
- regmap_write(dev->map, DW_IC_DATA_CMD, 0x100 | cmd);
+ regmap_write(dev->map, dev->regs[DW_REG_IDX_DATA_CMD], 0x100);
+ regmap_write(dev->map, dev->regs[DW_REG_IDX_DATA_CMD], 0x100 | cmd);
if (cmd) {
- regmap_write(dev->map, DW_IC_TX_TL, 2 * (buf_len - 1));
- regmap_write(dev->map, DW_IC_RX_TL, 2 * (buf_len - 1));
+ regmap_write(dev->map, dev->regs[DW_REG_IDX_TX_TL],
+ 2 * (buf_len - 1));
+ regmap_write(dev->map, dev->regs[DW_REG_IDX_RX_TL],
+ 2 * (buf_len - 1));
/*
* Need to check the stop bit. However, it cannot be
* detected from the registers so we check it always
@@ -347,7 +349,9 @@ static int amd_i2c_dw_xfer_quirk(struct dw_i2c_dev *dev, struct i2c_msg *msgs, i
return status;

for (data_idx = 0; data_idx < buf_len; data_idx++) {
- regmap_read(dev->map, DW_IC_DATA_CMD, &val);
+ regmap_read(dev->map,
+ dev->regs[DW_REG_IDX_DATA_CMD],
+ &val);
tx_buf[data_idx] = val;
}
status = i2c_dw_check_stopbit(dev);
@@ -355,7 +359,8 @@ static int amd_i2c_dw_xfer_quirk(struct dw_i2c_dev *dev, struct i2c_msg *msgs, i
return status;
}
} else {
- regmap_write(dev->map, DW_IC_DATA_CMD, *tx_buf++ | cmd);
+ regmap_write(dev->map, dev->regs[DW_REG_IDX_DATA_CMD],
+ *tx_buf++ | cmd);
usleep_range(AMD_TIMEOUT_MIN_US, AMD_TIMEOUT_MAX_US);
}
}
@@ -399,15 +404,15 @@ i2c_dw_xfer_msg(struct dw_i2c_dev *dev)
* IC_RESTART_EN are set, we must manually
* set restart bit between messages.
*/
- if ((dev->master_cfg & DW_IC_CON_RESTART_EN) &&
- (dev->msg_write_idx > 0))
+ if (dev->master_cfg & dev->con_bits->restart_en &&
+ dev->msg_write_idx > 0)
need_restart = true;
}

- regmap_read(dev->map, DW_IC_TXFLR, &flr);
+ regmap_read(dev->map, dev->regs[DW_REG_IDX_TXFLR], &flr);
tx_limit = dev->tx_fifo_depth - flr;

- regmap_read(dev->map, DW_IC_RXFLR, &flr);
+ regmap_read(dev->map, dev->regs[DW_REG_IDX_RXFLR], &flr);
rx_limit = dev->rx_fifo_depth - flr;

while (buf_len > 0 && tx_limit > 0 && rx_limit > 0) {
@@ -441,12 +446,12 @@ i2c_dw_xfer_msg(struct dw_i2c_dev *dev)
if (dev->rx_outstanding >= dev->rx_fifo_depth)
break;

- regmap_write(dev->map, DW_IC_DATA_CMD,
+ regmap_write(dev->map, dev->regs[DW_REG_IDX_DATA_CMD],
cmd | 0x100);
rx_limit--;
dev->rx_outstanding++;
} else {
- regmap_write(dev->map, DW_IC_DATA_CMD,
+ regmap_write(dev->map, dev->regs[DW_REG_IDX_DATA_CMD],
cmd | *buf++);
}
tx_limit--; buf_len--;
@@ -537,10 +542,10 @@ i2c_dw_read(struct dw_i2c_dev *dev)
buf = dev->rx_buf;
}

- regmap_read(dev->map, DW_IC_RXFLR, &rx_valid);
+ regmap_read(dev->map, dev->regs[DW_REG_IDX_RXFLR], &rx_valid);

for (; len > 0 && rx_valid > 0; len--, rx_valid--) {
- regmap_read(dev->map, DW_IC_DATA_CMD, &tmp);
+ regmap_read(dev->map, dev->regs[DW_REG_IDX_DATA_CMD], &tmp);
tmp &= DW_IC_DATA_CMD_DAT;
/* Ensure length byte is a valid value */
if (flags & I2C_M_RECV_LEN) {
@@ -574,7 +579,7 @@ i2c_dw_read(struct dw_i2c_dev *dev)

static u32 i2c_dw_read_clear_intrbits(struct dw_i2c_dev *dev)
{
- unsigned int stat, dummy;
+ unsigned int stat;

/*
* The IC_INTR_STAT register just indicates "enabled" interrupts.
@@ -589,9 +594,9 @@ static u32 i2c_dw_read_clear_intrbits(struct dw_i2c_dev *dev)
* The raw version might be useful for debugging purposes.
*/
if (!(dev->flags & ACCESS_POLLING)) {
- regmap_read(dev->map, DW_IC_INTR_STAT, &stat);
+ regmap_read(dev->map, dev->regs[DW_REG_IDX_INTR_STAT], &stat);
} else {
- regmap_read(dev->map, DW_IC_RAW_INTR_STAT, &stat);
+ regmap_read(dev->map, dev->regs[DW_REG_IDX_RAW_INTR_STAT], &stat);
stat &= dev->sw_mask;
}

@@ -603,32 +608,32 @@ static u32 i2c_dw_read_clear_intrbits(struct dw_i2c_dev *dev)
* Instead, use the separately-prepared IC_CLR_* registers.
*/
if (stat & DW_IC_INTR_RX_UNDER)
- regmap_read(dev->map, DW_IC_CLR_RX_UNDER, &dummy);
+ i2c_dw_ack_intr(dev, DW_INTR_IDX_RX_UNDER);
if (stat & DW_IC_INTR_RX_OVER)
- regmap_read(dev->map, DW_IC_CLR_RX_OVER, &dummy);
+ i2c_dw_ack_intr(dev, DW_INTR_IDX_RX_OVER);
if (stat & DW_IC_INTR_TX_OVER)
- regmap_read(dev->map, DW_IC_CLR_TX_OVER, &dummy);
+ i2c_dw_ack_intr(dev, DW_INTR_IDX_TX_OVER);
if (stat & DW_IC_INTR_RD_REQ)
- regmap_read(dev->map, DW_IC_CLR_RD_REQ, &dummy);
+ i2c_dw_ack_intr(dev, DW_INTR_IDX_RD_REQ);
if (stat & DW_IC_INTR_TX_ABRT) {
/*
* The IC_TX_ABRT_SOURCE register is cleared whenever
* the IC_CLR_TX_ABRT is read. Preserve it beforehand.
*/
- regmap_read(dev->map, DW_IC_TX_ABRT_SOURCE, &dev->abort_source);
- regmap_read(dev->map, DW_IC_CLR_TX_ABRT, &dummy);
+ regmap_read(dev->map, dev->regs[DW_REG_IDX_TX_ABRT_SOURCE], &dev->abort_source);
+ i2c_dw_ack_intr(dev, DW_INTR_IDX_TX_ABRT);
}
if (stat & DW_IC_INTR_RX_DONE)
- regmap_read(dev->map, DW_IC_CLR_RX_DONE, &dummy);
+ i2c_dw_ack_intr(dev, DW_INTR_IDX_RX_DONE);
if (stat & DW_IC_INTR_ACTIVITY)
- regmap_read(dev->map, DW_IC_CLR_ACTIVITY, &dummy);
+ i2c_dw_ack_intr(dev, DW_INTR_IDX_ACTIVITY);
if ((stat & DW_IC_INTR_STOP_DET) &&
((dev->rx_outstanding == 0) || (stat & DW_IC_INTR_RX_FULL)))
- regmap_read(dev->map, DW_IC_CLR_STOP_DET, &dummy);
+ i2c_dw_ack_intr(dev, DW_INTR_IDX_STOP_DET);
if (stat & DW_IC_INTR_START_DET)
- regmap_read(dev->map, DW_IC_CLR_START_DET, &dummy);
+ i2c_dw_ack_intr(dev, DW_INTR_IDX_START_DET);
if (stat & DW_IC_INTR_GEN_CALL)
- regmap_read(dev->map, DW_IC_CLR_GEN_CALL, &dummy);
+ i2c_dw_ack_intr(dev, DW_INTR_IDX_GEN_CALL);

return stat;
}
@@ -688,8 +693,8 @@ irqreturn_t i2c_dw_isr_master(struct dw_i2c_dev *dev)
{
unsigned int stat, enabled;

- regmap_read(dev->map, DW_IC_ENABLE, &enabled);
- regmap_read(dev->map, DW_IC_RAW_INTR_STAT, &stat);
+ regmap_read(dev->map, dev->regs[DW_REG_IDX_ENABLE], &enabled);
+ regmap_read(dev->map, dev->regs[DW_REG_IDX_RAW_INTR_STAT], &stat);
if (!enabled || !(stat & ~DW_IC_INTR_ACTIVITY))
return IRQ_NONE;
if (pm_runtime_suspended(dev->dev) || stat == GENMASK(31, 0))
@@ -940,20 +945,20 @@ void i2c_dw_configure_master(struct dw_i2c_dev *dev)
if ((dev->flags & MODEL_MASK) != MODEL_AMD_NAVI_GPU)
dev->functionality |= I2C_FUNC_PROTOCOL_MANGLING;

- dev->master_cfg = DW_IC_CON_MASTER | DW_IC_CON_SLAVE_DISABLE |
- DW_IC_CON_RESTART_EN;
+ dev->master_cfg = dev->con_bits->master | dev->con_bits->slave_disable |
+ dev->con_bits->restart_en;

dev->mode = DW_IC_MASTER;

switch (t->bus_freq_hz) {
case I2C_MAX_STANDARD_MODE_FREQ:
- dev->master_cfg |= DW_IC_CON_SPEED_STD;
+ dev->master_cfg |= dev->con_bits->speed_std;
break;
case I2C_MAX_HIGH_SPEED_MODE_FREQ:
- dev->master_cfg |= DW_IC_CON_SPEED_HIGH;
+ dev->master_cfg |= dev->con_bits->speed_high;
break;
default:
- dev->master_cfg |= DW_IC_CON_SPEED_FAST;
+ dev->master_cfg |= dev->con_bits->speed_fast;
}
}
EXPORT_SYMBOL_GPL(i2c_dw_configure_master);
@@ -1037,13 +1042,13 @@ int i2c_dw_probe_master(struct dw_i2c_dev *dev)
* bus recovery process. Driver should not ignore this BIOS
* advertisement of bus clear feature.
*/
- ret = regmap_read(dev->map, DW_IC_CON, &ic_con);
+ ret = regmap_read(dev->map, dev->regs[DW_REG_IDX_CON], &ic_con);
i2c_dw_release_lock(dev);
if (ret)
return ret;

- if (ic_con & DW_IC_CON_BUS_CLEAR_CTRL)
- dev->master_cfg |= DW_IC_CON_BUS_CLEAR_CTRL;
+ if (ic_con & dev->con_bits->bus_clear_ctrl)
+ dev->master_cfg |= dev->con_bits->bus_clear_ctrl;

return i2c_dw_init_recovery_info(dev);
}
diff --git a/drivers/i2c/busses/i2c-designware-pcidrv.c b/drivers/i2c/busses/i2c-designware-pcidrv.c
index 468287922363..fc73106fb0f9 100644
--- a/drivers/i2c/busses/i2c-designware-pcidrv.c
+++ b/drivers/i2c/busses/i2c-designware-pcidrv.c
@@ -246,6 +246,8 @@ static int i2c_dw_pci_probe(struct pci_dev *pdev,

pci_set_drvdata(pdev, dev);

+ i2c_dw_select_variant(dev);
+
if (controller->setup) {
r = controller->setup(pdev, controller);
if (r)
diff --git a/drivers/i2c/busses/i2c-designware-platdrv.c b/drivers/i2c/busses/i2c-designware-platdrv.c
index 447af5523c2e..42b34c678146 100644
--- a/drivers/i2c/busses/i2c-designware-platdrv.c
+++ b/drivers/i2c/busses/i2c-designware-platdrv.c
@@ -156,6 +156,8 @@ static int dw_i2c_plat_probe(struct platform_device *pdev)
dev->flags = flags;
platform_set_drvdata(pdev, dev);

+ i2c_dw_select_variant(dev);
+
ret = dw_i2c_plat_request_regs(dev);
if (ret)
return ret;
diff --git a/drivers/i2c/busses/i2c-designware-slave.c b/drivers/i2c/busses/i2c-designware-slave.c
index 0abcc7757b23..7f20124d1181 100644
--- a/drivers/i2c/busses/i2c-designware-slave.c
+++ b/drivers/i2c/busses/i2c-designware-slave.c
@@ -53,7 +53,7 @@ int i2c_dw_unreg_slave(struct i2c_client *slave)
{
struct dw_i2c_dev *dev = i2c_get_adapdata(slave->adapter);

- regmap_write(dev->map, DW_IC_INTR_MASK, 0);
+ regmap_write(dev->map, dev->regs[DW_REG_IDX_INTR_MASK], 0);
i2c_dw_disable(dev);
synchronize_irq(dev->irq);
dev->slave = NULL;
@@ -65,7 +65,7 @@ int i2c_dw_unreg_slave(struct i2c_client *slave)

static u32 i2c_dw_read_clear_intrbits_slave(struct dw_i2c_dev *dev)
{
- unsigned int stat, dummy;
+ unsigned int stat;

/*
* The IC_INTR_STAT register just indicates "enabled" interrupts.
@@ -79,7 +79,7 @@ static u32 i2c_dw_read_clear_intrbits_slave(struct dw_i2c_dev *dev)
*
* The raw version might be useful for debugging purposes.
*/
- regmap_read(dev->map, DW_IC_INTR_STAT, &stat);
+ regmap_read(dev->map, dev->regs[DW_REG_IDX_INTR_STAT], &stat);

/*
* Do not use the IC_CLR_INTR register to clear interrupts, or
@@ -89,23 +89,23 @@ static u32 i2c_dw_read_clear_intrbits_slave(struct dw_i2c_dev *dev)
* Instead, use the separately-prepared IC_CLR_* registers.
*/
if (stat & DW_IC_INTR_TX_ABRT)
- regmap_read(dev->map, DW_IC_CLR_TX_ABRT, &dummy);
+ i2c_dw_ack_intr(dev, DW_INTR_IDX_TX_ABRT);
if (stat & DW_IC_INTR_RX_UNDER)
- regmap_read(dev->map, DW_IC_CLR_RX_UNDER, &dummy);
+ i2c_dw_ack_intr(dev, DW_INTR_IDX_RX_UNDER);
if (stat & DW_IC_INTR_RX_OVER)
- regmap_read(dev->map, DW_IC_CLR_RX_OVER, &dummy);
+ i2c_dw_ack_intr(dev, DW_INTR_IDX_RX_OVER);
if (stat & DW_IC_INTR_TX_OVER)
- regmap_read(dev->map, DW_IC_CLR_TX_OVER, &dummy);
+ i2c_dw_ack_intr(dev, DW_INTR_IDX_TX_OVER);
if (stat & DW_IC_INTR_RX_DONE)
- regmap_read(dev->map, DW_IC_CLR_RX_DONE, &dummy);
+ i2c_dw_ack_intr(dev, DW_INTR_IDX_RX_DONE);
if (stat & DW_IC_INTR_ACTIVITY)
- regmap_read(dev->map, DW_IC_CLR_ACTIVITY, &dummy);
+ i2c_dw_ack_intr(dev, DW_INTR_IDX_ACTIVITY);
if (stat & DW_IC_INTR_STOP_DET)
- regmap_read(dev->map, DW_IC_CLR_STOP_DET, &dummy);
+ i2c_dw_ack_intr(dev, DW_INTR_IDX_STOP_DET);
if (stat & DW_IC_INTR_START_DET)
- regmap_read(dev->map, DW_IC_CLR_START_DET, &dummy);
+ i2c_dw_ack_intr(dev, DW_INTR_IDX_START_DET);
if (stat & DW_IC_INTR_GEN_CALL)
- regmap_read(dev->map, DW_IC_CLR_GEN_CALL, &dummy);
+ i2c_dw_ack_intr(dev, DW_INTR_IDX_GEN_CALL);

return stat;
}
@@ -119,9 +119,9 @@ irqreturn_t i2c_dw_isr_slave(struct dw_i2c_dev *dev)
unsigned int raw_stat, stat, enabled, tmp;
u8 val = 0, slave_activity;

- regmap_read(dev->map, DW_IC_ENABLE, &enabled);
- regmap_read(dev->map, DW_IC_RAW_INTR_STAT, &raw_stat);
- regmap_read(dev->map, DW_IC_STATUS, &tmp);
+ regmap_read(dev->map, dev->regs[DW_REG_IDX_ENABLE], &enabled);
+ regmap_read(dev->map, dev->regs[DW_REG_IDX_RAW_INTR_STAT], &raw_stat);
+ regmap_read(dev->map, dev->regs[DW_REG_IDX_STATUS], &tmp);
slave_activity = ((tmp & DW_IC_STATUS_SLAVE_ACTIVITY) >> 6);

if (!enabled || !(raw_stat & ~DW_IC_INTR_ACTIVITY) || !dev->slave)
@@ -141,7 +141,7 @@ irqreturn_t i2c_dw_isr_slave(struct dw_i2c_dev *dev)
}

do {
- regmap_read(dev->map, DW_IC_DATA_CMD, &tmp);
+ regmap_read(dev->map, dev->regs[DW_REG_IDX_DATA_CMD], &tmp);
if (tmp & DW_IC_DATA_CMD_FIRST_DATA_BYTE)
i2c_slave_event(dev->slave,
I2C_SLAVE_WRITE_REQUESTED,
@@ -149,13 +149,13 @@ irqreturn_t i2c_dw_isr_slave(struct dw_i2c_dev *dev)
val = tmp;
i2c_slave_event(dev->slave, I2C_SLAVE_WRITE_RECEIVED,
&val);
- regmap_read(dev->map, DW_IC_STATUS, &tmp);
+ regmap_read(dev->map, dev->regs[DW_REG_IDX_STATUS], &tmp);
} while (tmp & DW_IC_STATUS_RFNE);
}

if (stat & DW_IC_INTR_RD_REQ) {
if (slave_activity) {
- regmap_read(dev->map, DW_IC_CLR_RD_REQ, &tmp);
+ i2c_dw_ack_intr(dev, DW_INTR_IDX_RD_REQ);

if (!(dev->status & STATUS_READ_IN_PROGRESS)) {
i2c_slave_event(dev->slave,
@@ -168,7 +168,7 @@ irqreturn_t i2c_dw_isr_slave(struct dw_i2c_dev *dev)
I2C_SLAVE_READ_PROCESSED,
&val);
}
- regmap_write(dev->map, DW_IC_DATA_CMD, val);
+ regmap_write(dev->map, dev->regs[DW_REG_IDX_DATA_CMD], val);
}
}

@@ -185,8 +185,8 @@ void i2c_dw_configure_slave(struct dw_i2c_dev *dev)

dev->functionality |= I2C_FUNC_SLAVE;

- dev->slave_cfg = DW_IC_CON_RX_FIFO_FULL_HLD_CTRL |
- DW_IC_CON_RESTART_EN | DW_IC_CON_STOP_DET_IFADDRESSED;
+ dev->slave_cfg = dev->con_bits->rx_fifo_full_hld_ctrl |
+ dev->con_bits->restart_en | dev->con_bits->stop_det_ifaddressed;
}
EXPORT_SYMBOL_GPL(i2c_dw_configure_slave);


--
2.53.0