summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorAndrew Jeffery <andrew@aj.id.au>2017-08-15 16:51:02 +0930
committerWolfram Sang <wsa@the-dreams.de>2017-08-28 18:05:03 +0200
commit95fd3ad9cd5f8a4bb01215b846a3c8e6adefe21c (patch)
tree6479787ecc386b51750e3b5636b6eb707d758d5b
parent2f13f8c50ae21ce70a437149a0e221755e554912 (diff)
downloadop-kernel-dev-95fd3ad9cd5f8a4bb01215b846a3c8e6adefe21c.zip
op-kernel-dev-95fd3ad9cd5f8a4bb01215b846a3c8e6adefe21c.tar.gz
i2c: aspeed: Retain delay/setup/hold values when configuring bus frequency
In addition to the base, low and high clock configuration, the AC timing register #1 on the AST2400 houses fields controlling: 1. tBUF: Minimum delay between Stop and Start conditions 2. tHDSTA: Hold time for the Start condition 3. tACST: Setup time for Start and Stop conditions, and hold time for the Repeated Start condition These values are defined in hardware on the AST2500 and therefore don't need to be set. aspeed_i2c_init_clk() was performing a direct write of the generated clock values rather than a read/mask/modify/update sequence to retain tBUF, tHDSTA and tACST, and therefore cleared the tBUF, tHDSTA and tACST fields on the AST2400. This resulted in a delay/setup/hold time of 1 base clock, which in some configurations is not enough for some devices (e.g. the MAX31785 fan controller, with an APB of 48MHz and a desired bus speed of 100kHz). Signed-off-by: Andrew Jeffery <andrew@aj.id.au> Reviewed-by: Brendan Higgins <brendanhiggins@google.com> Tested-by: Brendan Higgins <brendanhiggins@google.com> Signed-off-by: Wolfram Sang <wsa@the-dreams.de>
-rw-r--r--drivers/i2c/busses/i2c-aspeed.c9
1 files changed, 8 insertions, 1 deletions
diff --git a/drivers/i2c/busses/i2c-aspeed.c b/drivers/i2c/busses/i2c-aspeed.c
index 60afab8..645e007 100644
--- a/drivers/i2c/busses/i2c-aspeed.c
+++ b/drivers/i2c/busses/i2c-aspeed.c
@@ -53,6 +53,9 @@
#define ASPEED_I2CD_MASTER_EN BIT(0)
/* 0x04 : I2CD Clock and AC Timing Control Register #1 */
+#define ASPEED_I2CD_TIME_TBUF_MASK GENMASK(31, 28)
+#define ASPEED_I2CD_TIME_THDSTA_MASK GENMASK(27, 24)
+#define ASPEED_I2CD_TIME_TACST_MASK GENMASK(23, 20)
#define ASPEED_I2CD_TIME_SCL_HIGH_SHIFT 16
#define ASPEED_I2CD_TIME_SCL_HIGH_MASK GENMASK(19, 16)
#define ASPEED_I2CD_TIME_SCL_LOW_SHIFT 12
@@ -743,7 +746,11 @@ static int aspeed_i2c_init_clk(struct aspeed_i2c_bus *bus)
u32 divisor, clk_reg_val;
divisor = DIV_ROUND_UP(bus->parent_clk_frequency, bus->bus_frequency);
- clk_reg_val = bus->get_clk_reg_val(divisor);
+ clk_reg_val = readl(bus->base + ASPEED_I2C_AC_TIMING_REG1);
+ clk_reg_val &= (ASPEED_I2CD_TIME_TBUF_MASK |
+ ASPEED_I2CD_TIME_THDSTA_MASK |
+ ASPEED_I2CD_TIME_TACST_MASK);
+ clk_reg_val |= bus->get_clk_reg_val(divisor);
writel(clk_reg_val, bus->base + ASPEED_I2C_AC_TIMING_REG1);
writel(ASPEED_NO_TIMEOUT_CTRL, bus->base + ASPEED_I2C_AC_TIMING_REG2);
OpenPOWER on IntegriCloud