summaryrefslogtreecommitdiff
path: root/meta-openbmc-mods/meta-common/recipes-kernel/linux/linux-aspeed/0068-i2c-aspeed-add-H-W-timeout-support.patch
diff options
context:
space:
mode:
Diffstat (limited to 'meta-openbmc-mods/meta-common/recipes-kernel/linux/linux-aspeed/0068-i2c-aspeed-add-H-W-timeout-support.patch')
-rw-r--r--meta-openbmc-mods/meta-common/recipes-kernel/linux/linux-aspeed/0068-i2c-aspeed-add-H-W-timeout-support.patch191
1 files changed, 0 insertions, 191 deletions
diff --git a/meta-openbmc-mods/meta-common/recipes-kernel/linux/linux-aspeed/0068-i2c-aspeed-add-H-W-timeout-support.patch b/meta-openbmc-mods/meta-common/recipes-kernel/linux/linux-aspeed/0068-i2c-aspeed-add-H-W-timeout-support.patch
deleted file mode 100644
index 0e8a2b101..000000000
--- a/meta-openbmc-mods/meta-common/recipes-kernel/linux/linux-aspeed/0068-i2c-aspeed-add-H-W-timeout-support.patch
+++ /dev/null
@@ -1,191 +0,0 @@
-From b429cf11ecb2f6009dd9e062ea5e053718802d93 Mon Sep 17 00:00:00 2001
-From: Jae Hyun Yoo <jae.hyun.yoo@intel.com>
-Date: Thu, 11 Jul 2019 13:53:34 -0700
-Subject: [PATCH] i2c: aspeed: add H/W timeout support
-
-This commit adds I2C H/W timeout support.
-
-Signed-off-by: Jae Hyun Yoo <jae.hyun.yoo@intel.com>
----
- drivers/i2c/busses/i2c-aspeed.c | 82 ++++++++++++++++++++++++++++++++++++++---
- 1 file changed, 76 insertions(+), 6 deletions(-)
-
-diff --git a/drivers/i2c/busses/i2c-aspeed.c b/drivers/i2c/busses/i2c-aspeed.c
-index 4420899e2c2d..830b3d2cabad 100644
---- a/drivers/i2c/busses/i2c-aspeed.c
-+++ b/drivers/i2c/busses/i2c-aspeed.c
-@@ -55,6 +55,7 @@
- /* Device Register Definition */
- /* 0x00 : I2CD Function Control Register */
- #define ASPEED_I2CD_BUFFER_PAGE_SEL_MASK GENMASK(22, 20)
-+#define ASPEED_I2CD_BUS_AUTO_RECOVERY_EN BIT(17)
- #define ASPEED_I2CD_MULTI_MASTER_DIS BIT(15)
- #define ASPEED_I2CD_SDA_DRIVE_1T_EN BIT(8)
- #define ASPEED_I2CD_M_SDA_DRIVE_1T_EN BIT(7)
-@@ -71,10 +72,14 @@
- #define ASPEED_I2CD_TIME_SCL_HIGH_MASK GENMASK(19, 16)
- #define ASPEED_I2CD_TIME_SCL_LOW_SHIFT 12
- #define ASPEED_I2CD_TIME_SCL_LOW_MASK GENMASK(15, 12)
-+#define ASPEED_I2CD_TIME_TIMEOUT_BASE_DIVISOR_SHIFT 8
-+#define ASPEED_I2CD_TIME_TIMEOUT_BASE_DIVISOR_MASK GENMASK(9, 8)
- #define ASPEED_I2CD_TIME_BASE_DIVISOR_MASK GENMASK(3, 0)
- #define ASPEED_I2CD_TIME_SCL_REG_MAX GENMASK(3, 0)
-+
- /* 0x08 : I2CD Clock and AC Timing Control Register #2 */
--#define ASPEED_NO_TIMEOUT_CTRL 0
-+#define ASPEED_I2CD_TIMEOUT_CYCLES_SHIFT 0
-+#define ASPEED_I2CD_TIMEOUT_CYCLES_MASK GENMASK(4, 0)
-
- /* 0x0c : I2CD Interrupt Control Register &
- * 0x10 : I2CD Interrupt Status Register
-@@ -82,6 +87,7 @@
- * These share bit definitions, so use the same values for the enable &
- * status bits.
- */
-+#define ASPEED_I2CD_INTR_SLAVE_INACTIVE_TIMEOUT BIT(15)
- #define ASPEED_I2CD_INTR_SDA_DL_TIMEOUT BIT(14)
- #define ASPEED_I2CD_INTR_BUS_RECOVER_DONE BIT(13)
- #define ASPEED_I2CD_INTR_GCALL_ADDR BIT(8)
-@@ -98,8 +104,11 @@
- ASPEED_I2CD_INTR_SCL_TIMEOUT | \
- ASPEED_I2CD_INTR_ABNORMAL | \
- ASPEED_I2CD_INTR_ARBIT_LOSS)
-+#define ASPEED_I2CD_INTR_SLAVE_ERRORS \
-+ ASPEED_I2CD_INTR_SLAVE_INACTIVE_TIMEOUT
- #define ASPEED_I2CD_INTR_ALL \
-- (ASPEED_I2CD_INTR_SDA_DL_TIMEOUT | \
-+ (ASPEED_I2CD_INTR_SLAVE_INACTIVE_TIMEOUT | \
-+ ASPEED_I2CD_INTR_SDA_DL_TIMEOUT | \
- ASPEED_I2CD_INTR_BUS_RECOVER_DONE | \
- ASPEED_I2CD_INTR_SCL_TIMEOUT | \
- ASPEED_I2CD_INTR_ABNORMAL | \
-@@ -186,6 +195,7 @@ struct aspeed_i2c_bus {
- u32 divisor);
- unsigned long parent_clk_frequency;
- u32 bus_frequency;
-+ u32 hw_timeout_ms;
- /* Transaction state. */
- enum aspeed_i2c_master_state master_state;
- struct i2c_msg *msgs;
-@@ -303,6 +313,14 @@ static int aspeed_i2c_recover_bus(struct aspeed_i2c_bus *bus)
- }
-
- #if IS_ENABLED(CONFIG_I2C_SLAVE)
-+static int aspeed_i2c_check_slave_error(u32 irq_status)
-+{
-+ if (irq_status & ASPEED_I2CD_INTR_SLAVE_INACTIVE_TIMEOUT)
-+ return -EIO;
-+
-+ return 0;
-+}
-+
- static inline void
- aspeed_i2c_slave_handle_rx_done(struct aspeed_i2c_bus *bus, u32 irq_status,
- u8 *value)
-@@ -421,6 +439,14 @@ static u32 aspeed_i2c_slave_irq(struct aspeed_i2c_bus *bus, u32 irq_status)
- if (!slave)
- return 0;
-
-+ if (aspeed_i2c_check_slave_error(irq_status)) {
-+ dev_dbg(bus->dev, "received slave error interrupt: 0x%08x\n",
-+ irq_status);
-+ irq_handled |= (irq_status & ASPEED_I2CD_INTR_SLAVE_ERRORS);
-+ bus->slave_state = ASPEED_I2C_SLAVE_INACTIVE;
-+ return irq_handled;
-+ }
-+
- command = readl(bus->base + ASPEED_I2C_CMD_REG);
-
- /* Slave was requested, restart state machine. */
-@@ -681,7 +707,7 @@ static void aspeed_i2c_next_msg_or_stop(struct aspeed_i2c_bus *bus)
- }
- }
-
--static int aspeed_i2c_is_irq_error(u32 irq_status)
-+static int aspeed_i2c_check_master_error(u32 irq_status)
- {
- if (irq_status & ASPEED_I2CD_INTR_ARBIT_LOSS)
- return -EAGAIN;
-@@ -840,9 +866,9 @@ static u32 aspeed_i2c_master_irq(struct aspeed_i2c_bus *bus, u32 irq_status)
- * should clear the command queue effectively taking us back to the
- * INACTIVE state.
- */
-- ret = aspeed_i2c_is_irq_error(irq_status);
-+ ret = aspeed_i2c_check_master_error(irq_status);
- if (ret) {
-- dev_dbg(bus->dev, "received error interrupt: 0x%08x\n",
-+ dev_dbg(bus->dev, "received master error interrupt: 0x%08x\n",
- irq_status);
- irq_handled |= (irq_status & ASPEED_I2CD_INTR_MASTER_ERRORS);
- if (bus->master_state != ASPEED_I2C_MASTER_INACTIVE) {
-@@ -1307,6 +1333,7 @@ static u32 aspeed_i2c_25xx_get_clk_reg_val(struct device *dev, u32 divisor)
- /* precondition: bus.lock has been acquired. */
- static int aspeed_i2c_init_clk(struct aspeed_i2c_bus *bus)
- {
-+ u32 timeout_base_divisor, timeout_tick_us, timeout_cycles;
- u32 divisor, clk_reg_val;
-
- divisor = DIV_ROUND_UP(bus->parent_clk_frequency, bus->bus_frequency);
-@@ -1315,8 +1342,46 @@ static int aspeed_i2c_init_clk(struct aspeed_i2c_bus *bus)
- ASPEED_I2CD_TIME_THDSTA_MASK |
- ASPEED_I2CD_TIME_TACST_MASK);
- clk_reg_val |= bus->get_clk_reg_val(bus->dev, divisor);
-+
-+ if (bus->hw_timeout_ms) {
-+ u8 div_max = ASPEED_I2CD_TIME_TIMEOUT_BASE_DIVISOR_MASK >>
-+ ASPEED_I2CD_TIME_TIMEOUT_BASE_DIVISOR_SHIFT;
-+ u8 cycles_max = ASPEED_I2CD_TIMEOUT_CYCLES_MASK >>
-+ ASPEED_I2CD_TIMEOUT_CYCLES_SHIFT;
-+
-+ timeout_base_divisor = 0;
-+
-+ do {
-+ timeout_tick_us = 1000 * (16384 <<
-+ (timeout_base_divisor << 1)) /
-+ (bus->parent_clk_frequency / 1000);
-+
-+ if (timeout_base_divisor == div_max ||
-+ timeout_tick_us * ASPEED_I2CD_TIMEOUT_CYCLES_MASK >=
-+ bus->hw_timeout_ms * 1000)
-+ break;
-+ } while (timeout_base_divisor++ < div_max);
-+
-+ if (timeout_tick_us) {
-+ timeout_cycles = DIV_ROUND_UP(bus->hw_timeout_ms * 1000,
-+ timeout_tick_us);
-+ if (timeout_cycles == 0)
-+ timeout_cycles = 1;
-+ else if (timeout_cycles > cycles_max)
-+ timeout_cycles = cycles_max;
-+ } else {
-+ timeout_cycles = 0;
-+ }
-+ } else {
-+ timeout_base_divisor = 0;
-+ timeout_cycles = 0;
-+ }
-+
-+ clk_reg_val |= FIELD_PREP(ASPEED_I2CD_TIME_TIMEOUT_BASE_DIVISOR_MASK,
-+ timeout_base_divisor);
-+
- writel(clk_reg_val, bus->base + ASPEED_I2C_AC_TIMING_REG1);
-- writel(ASPEED_NO_TIMEOUT_CTRL, bus->base + ASPEED_I2C_AC_TIMING_REG2);
-+ writel(timeout_cycles, bus->base + ASPEED_I2C_AC_TIMING_REG2);
-
- return 0;
- }
-@@ -1331,6 +1396,11 @@ static int aspeed_i2c_init(struct aspeed_i2c_bus *bus,
- /* Disable everything. */
- writel(0, bus->base + ASPEED_I2C_FUN_CTRL_REG);
-
-+ device_property_read_u32(&pdev->dev, "aspeed,hw-timeout-ms",
-+ &bus->hw_timeout_ms);
-+ if (bus->hw_timeout_ms)
-+ fun_ctrl_reg |= ASPEED_I2CD_BUS_AUTO_RECOVERY_EN;
-+
- ret = aspeed_i2c_init_clk(bus);
- if (ret < 0)
- return ret;
---
-2.7.4
-