diff options
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.patch | 191 |
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 - |