From 4ecfb9d3b229fff538c706650a8208fa03660c22 Mon Sep 17 00:00:00 2001 From: Wolfram Sang Date: Mon, 18 Dec 2017 22:58:01 +0100 Subject: [PATCH] i2c: sh_mobile: add new frequency calculation for later SoC The formula to generate the desired bus speeds has changed a little over time. Implement the new formula and allow drivers to opt-in by changing to this new config set. Ensure in probe that we don't divide by zero. The returned values on a R-Car H2 (r8a7790/Lager board) match the suggested values in the datasheet. Signed-off-by: Wolfram Sang Signed-off-by: Wolfram Sang --- drivers/i2c/busses/i2c-sh_mobile.c | 19 ++++++++++++++++++- 1 file changed, 18 insertions(+), 1 deletion(-) diff --git a/drivers/i2c/busses/i2c-sh_mobile.c b/drivers/i2c/busses/i2c-sh_mobile.c index b111191a449a..a0fddfe3c449 100644 --- a/drivers/i2c/busses/i2c-sh_mobile.c +++ b/drivers/i2c/busses/i2c-sh_mobile.c @@ -299,6 +299,18 @@ static int sh_mobile_i2c_init(struct sh_mobile_i2c_data *pd) return sh_mobile_i2c_check_timing(pd); } +static int sh_mobile_i2c_v2_init(struct sh_mobile_i2c_data *pd) +{ + unsigned long clks_per_cycle; + + /* L = 5, H = 4, L + H = 9 */ + clks_per_cycle = clk_get_rate(pd->clk) / pd->bus_speed; + pd->iccl = DIV_ROUND_UP(clks_per_cycle * 5 / 9 - 1, pd->clks_per_count); + pd->icch = DIV_ROUND_UP(clks_per_cycle * 4 / 9 - 5, pd->clks_per_count); + + return sh_mobile_i2c_check_timing(pd); +} + static unsigned char i2c_op(struct sh_mobile_i2c_data *pd, enum sh_mobile_i2c_op op, unsigned char data) { @@ -785,6 +797,11 @@ static const struct sh_mobile_dt_config fast_clock_dt_config = { .setup = sh_mobile_i2c_init, }; +static const struct sh_mobile_dt_config v2_freq_calc_dt_config = { + .clks_per_count = 2, + .setup = sh_mobile_i2c_v2_init, +}; + static const struct sh_mobile_dt_config r8a7740_dt_config = { .clks_per_count = 1, .setup = sh_mobile_i2c_r8a7740_workaround, @@ -875,7 +892,7 @@ static int sh_mobile_i2c_probe(struct platform_device *dev) return PTR_ERR(pd->reg); ret = of_property_read_u32(dev->dev.of_node, "clock-frequency", &bus_speed); - pd->bus_speed = ret ? STANDARD_MODE : bus_speed; + pd->bus_speed = (ret || !bus_speed) ? STANDARD_MODE : bus_speed; pd->clks_per_count = 1; /* Newer variants come with two new bits in ICIC */