[PATCH linux dev-5.1 v1] ARM: ASPEED: I2C: Update I2C driver to use APB_clk
Joel Stanley
joel at jms.id.au
Tue Jun 11 12:36:41 AEST 2019
Hi Hongwei,
On Fri, 7 Jun 2019 at 20:39, Hongwei Zhang <hongweiz at ami.com> wrote:
>
> Update I2C clock driver to calculate the clock frequency based on
> apb_clk, instead of bus's parent clock frequency.
I'm not sure what your patch is trying to do. As I understand it, this
is what the driver already does.
The parent clock frequency should be set in the device tree to be the APB clock:
i2c0: i2c-bus at 40 {
#address-cells = <1>;
#size-cells = <0>;
#interrupt-cells = <1>;
reg = <0x40 0x40>;
compatible = "aspeed,ast2500-i2c-bus";
clocks = <&syscon ASPEED_CLK_APB>;
Cheers,
Joel
>
> Signed-off-by: Hongwei Zhang <hongweiz at ami.com>
> ---
> drivers/i2c/busses/i2c-aspeed.c | 45 ++++++++++++++++++++++++++++++++++++++---
> 1 file changed, 42 insertions(+), 3 deletions(-)
>
> diff --git a/drivers/i2c/busses/i2c-aspeed.c b/drivers/i2c/busses/i2c-aspeed.c
> index 6c8b38f..9cce1fe 100644
> --- a/drivers/i2c/busses/i2c-aspeed.c
> +++ b/drivers/i2c/busses/i2c-aspeed.c
> @@ -167,6 +167,7 @@ struct aspeed_i2c_bus {
> };
>
> static int aspeed_i2c_reset(struct aspeed_i2c_bus *bus);
> +static u32 calculate_APB_clock_freq(struct platform_device *pdev);
>
> static int aspeed_i2c_recover_bus(struct aspeed_i2c_bus *bus)
> {
> @@ -862,11 +863,11 @@ 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)
> +static int aspeed_i2c_init_clk(struct aspeed_i2c_bus *bus, u32 apb_clk)
> {
> u32 divisor, clk_reg_val;
>
> - divisor = DIV_ROUND_UP(bus->parent_clk_frequency, bus->bus_frequency);
> + divisor = DIV_ROUND_UP(apb_clk, bus->bus_frequency);
> clk_reg_val = readl(bus->base + ASPEED_I2C_AC_TIMING_REG1);
> clk_reg_val &= (ASPEED_I2CD_TIME_TBUF_MASK |
> ASPEED_I2CD_TIME_THDSTA_MASK |
> @@ -883,12 +884,16 @@ static int aspeed_i2c_init(struct aspeed_i2c_bus *bus,
> struct platform_device *pdev)
> {
> u32 fun_ctrl_reg = ASPEED_I2CD_MASTER_EN;
> + u32 apb_clk;
> int ret;
>
> /* Disable everything. */
> writel(0, bus->base + ASPEED_I2C_FUN_CTRL_REG);
>
> - ret = aspeed_i2c_init_clk(bus);
> + apb_clk = calculate_APB_clock_freq(pdev);
> +
> + ret = aspeed_i2c_init_clk(bus, apb_clk);
> +
> if (ret < 0)
> return ret;
>
> @@ -945,6 +950,40 @@ static const struct of_device_id aspeed_i2c_bus_of_table[] = {
> };
> MODULE_DEVICE_TABLE(of, aspeed_i2c_bus_of_table);
>
> +static u32 calculate_APB_clock_freq(struct platform_device *pdev)
> +{
> + u8 pclk_div;
> + u32 scu_csr, scu_hpll;
> + u32 apb_clk, output_freq;
> + char *baseptr = ioremap(0x1e6e2000, 0x28);
> + const struct of_device_id *of_id = of_match_device(aspeed_i2c_bus_of_table, &pdev->dev);
> +
> + scu_csr = readl(baseptr + 0x08);
> + scu_hpll = readl(baseptr + 0x24);
> + pclk_div = (scu_csr & 0x03800000) >> 23; /* 23:25 */
> +
> + if (strcmp(of_id->compatible, "aspeed, ast2400-i2c-bus") == 0) {
> + u8 OD, D, N;
> +
> + D = scu_hpll & 0x0000000F; /* 0:3 */
> + OD = (scu_hpll & 0x00000010) >> 4; /* 4 */
> + N = (scu_hpll & 0x000007E0) >> 5; /* 5:10 */
> + output_freq = (24 * (2 - OD) * ((N+2) / (D+1)) * 1000000); /* Output Frequency */
> +
> + apb_clk = (output_freq / ((pclk_div * 2) + 2));
> + } else {
> + u8 M, N, P;
> +
> + N = scu_hpll & 0x0000001F; /* 0:4 */
> + M = (scu_hpll & 0x00001FE0) >> 5; /* 5:12 */
> + P = (scu_hpll & 0x0007E000) >> 13; /* 13:18 */
> + output_freq = ((24 * ((M+1) / (N+1) / (P+1))) * 1000000); /* Output Frequency */
> +
> + apb_clk = (output_freq / ((pclk_div * 4) + 4));
> + }
> + return apb_clk;
> +}
> +
> static int aspeed_i2c_probe_bus(struct platform_device *pdev)
> {
> const struct of_device_id *match;
> --
> 2.7.4
>
More information about the openbmc
mailing list