On 09:46 Fri 14 Aug , Junhui Liu wrote:
> The K1 clock driver modeled the bus clock enable bit as part of the
> functional clock for regular TWSI controllers. The I2C driver then only
> enabled the functional clock, ignoring the separate bus clock described
> by the device tree. Although this happened to work, it did not match the
> hardware clock topology or the device tree binding.
>
> Model the functional and bus clocks separately and make the I2C driver
> acquire and enable all clocks provided by the device tree. Also add the
> TWSI2 and TWSI8 bus clocks, together with their APB clock dependencies,
> to the SPL clock tree.
>
> Keep the combined functional and bus gate for TWSI8, whose clock control
> register is write-only, and retain its bus clock as a fixed-factor
> placeholder.
>
> The clock-provider and I2C-consumer changes should be applied together,
> as either change on its own would leave I2C unusable.
>
> Fixes: 3aa2882a3e1a ("clk: spacemit: Add support for K1 SoC")
> Fixes: 271546fb8e54 ("i2c: k1: add I2C driver support")
> Signed-off-by: Junhui Liu <[email protected]>
> ---
> drivers/clk/spacemit/clk-k1.c | 41 +++++++++++++++++++++++++++++++++--------
> drivers/i2c/k1_i2c.c | 10 ++++------
I'd suggest to have separate patch for clock and i2c changes, as they
belong to different subsystem
> 2 files changed, 37 insertions(+), 14 deletions(-)
>
> diff --git a/drivers/clk/spacemit/clk-k1.c b/drivers/clk/spacemit/clk-k1.c
> index 07adc126ee39..20b8595aa3c4 100644
> --- a/drivers/clk/spacemit/clk-k1.c
> +++ b/drivers/clk/spacemit/clk-k1.c
> @@ -154,11 +154,27 @@ CCU_GATE_DEFINE(CLK_PLL1_409P6, pll1_d6_409p6,
> pll1_d6_409p6, "pll1_d6",
> MPMU_ACGR, BIT(0), 0);
> CCU_GATE_DEFINE(CLK_PLL1_307P2, pll1_d8_307p2, pll1_d8_307p2, "pll1_d8",
> MPMU_ACGR, BIT(13), 0);
> +CCU_FACTOR_GATE_DEFINE(CLK_PLL1_102P4, pll1_d24_102p4, pll1_d24_102p4,
> + "pll1_d8", MPMU_ACGR, BIT(12), 3, 1);
> +CCU_FACTOR_GATE_DEFINE(CLK_PLL1_51P2, pll1_d48_51p2, pll1_d48_51p2,
> + "pll1_d8", MPMU_ACGR, BIT(7), 6, 1);
> +CCU_FACTOR_GATE_DEFINE(CLK_PLL1_25P6, pll1_d96_25p6, pll1_d96_25p6,
> + "pll1_d8", MPMU_ACGR, BIT(4), 12, 1);
> CCU_FACTOR_GATE_DEFINE(CLK_PLL1_31P5, pll1_d78_31p5, pll1_d78_31p5,
> "pll1_d4", MPMU_ACGR, BIT(6), 39, 2);
> CCU_DDN_DEFINE(CLK_SLOW_UART2, slow_uart2_48, slow_uart2_48,
> "pll1_d4_614p4", MPMU_SUCCR_1,
> CCU_DDN_MASK(16, 13), 16, CCU_DDN_MASK(0, 13), 0, 2, 0);
> +
> +static const char * const apb_parents[] = {
> + "pll1_d96_25p6",
> + "pll1_d48_51p2",
> + "pll1_d96_25p6",
> + "pll1_d24_102p4",
> +};
> +
> +CCU_MUX_DEFINE(CLK_APB, apb_clk, apb_clk, apb_parents,
> ARRAY_SIZE(apb_parents),
> + MPMU_APBCSCR, 0, 2, 0);
> #else
> CCU_GATE_DEFINE(CLK_PLL1_307P2, pll1_d8_307p2, pll1_d8_307p2, "pll1_d8",
> MPMU_ACGR, BIT(13), 0);
> @@ -298,7 +314,7 @@ static const char * const twsi_parents[] = {
>
> CCU_MUX_GATE_DEFINE(CLK_TWSI2, twsi2_clk, twsi2_clk, twsi_parents,
> ARRAY_SIZE(twsi_parents), APBC_TWSI2_CLK_RST,
> - 4, 3, BIT(1) | BIT(0), 0);
> + 4, 3, BIT(1), 0);
> /*
> * APBC_TWSI8_CLK_RST has a quirk that reading always results in zero.
> * Combine functional and bus bits together as a gate to avoid sharing the
> @@ -306,6 +322,9 @@ CCU_MUX_GATE_DEFINE(CLK_TWSI2, twsi2_clk, twsi2_clk,
> twsi_parents,
> */
> CCU_GATE_DEFINE(CLK_TWSI8, twsi8_clk, twsi8_clk, "pll1_d78_31p5",
> APBC_TWSI8_CLK_RST, BIT(1) | BIT(0), 0);
> +CCU_GATE_DEFINE(CLK_TWSI2_BUS, twsi2_bus_clk, twsi2_bus_clk, "apb_clk",
> + APBC_TWSI2_CLK_RST, BIT(0), 0);
> +CCU_FACTOR_DEFINE(CLK_TWSI8_BUS, twsi8_bus_clk, twsi8_bus_clk, "apb_clk", 1,
> 1);
>
> #else
> static const char * const uart_clk_parents[] = {
> @@ -326,7 +345,7 @@ static const char * const twsi_parents[] = {
>
> CCU_MUX_GATE_DEFINE(CLK_TWSI2, twsi2_clk, twsi2_clk, twsi_parents,
> ARRAY_SIZE(twsi_parents), APBC_TWSI2_CLK_RST,
> - 4, 3, BIT(1) | BIT(0), 0);
> + 4, 3, BIT(1), 0);
> /*
> * APBC_TWSI8_CLK_RST has a quirk that reading always results in zero.
> * Combine functional and bus bits together as a gate to avoid sharing the
> @@ -448,22 +467,22 @@ CCU_GATE_DEFINE(CLK_RTC, rtc_clk, rtc_clk, "clock-32k",
> APBC_RTC_CLK_RST,
>
> CCU_MUX_GATE_DEFINE(CLK_TWSI0, twsi0_clk, twsi0_clk, twsi_parents,
> ARRAY_SIZE(twsi_parents), APBC_TWSI0_CLK_RST,
> - 4, 3, BIT(1) | BIT(0), 0);
> + 4, 3, BIT(1), 0);
> CCU_MUX_GATE_DEFINE(CLK_TWSI1, twsi1_clk, twsi1_clk, twsi_parents,
> ARRAY_SIZE(twsi_parents), APBC_TWSI1_CLK_RST,
> - 4, 3, BIT(1) | BIT(0), 0);
> + 4, 3, BIT(1), 0);
> CCU_MUX_GATE_DEFINE(CLK_TWSI4, twsi4_clk, twsi4_clk, twsi_parents,
> ARRAY_SIZE(twsi_parents), APBC_TWSI4_CLK_RST,
> - 4, 3, BIT(1) | BIT(0), 0);
> + 4, 3, BIT(1), 0);
> CCU_MUX_GATE_DEFINE(CLK_TWSI5, twsi5_clk, twsi5_clk, twsi_parents,
> ARRAY_SIZE(twsi_parents), APBC_TWSI5_CLK_RST,
> - 4, 3, BIT(1) | BIT(0), 0);
> + 4, 3, BIT(1), 0);
> CCU_MUX_GATE_DEFINE(CLK_TWSI6, twsi6_clk, twsi6_clk, twsi_parents,
> ARRAY_SIZE(twsi_parents), APBC_TWSI6_CLK_RST,
> - 4, 3, BIT(1) | BIT(0), 0);
> + 4, 3, BIT(1), 0);
> CCU_MUX_GATE_DEFINE(CLK_TWSI7, twsi7_clk, twsi7_clk, twsi_parents,
> ARRAY_SIZE(twsi_parents), APBC_TWSI7_CLK_RST,
> - 4, 3, BIT(1) | BIT(0), 0);
> + 4, 3, BIT(1), 0);
>
> static const char * const timer_parents[] = {
> "pll1_d192_12p8",
> @@ -1232,8 +1251,12 @@ static struct clk *k1_ccu_mpmu_clks[] = {
> &pll1_d4_614p4.common.clk,
> &pll1_d6_409p6.common.clk,
> &pll1_d8_307p2.common.clk,
> + &pll1_d24_102p4.common.clk,
> + &pll1_d48_51p2.common.clk,
> + &pll1_d96_25p6.common.clk,
> &pll1_d78_31p5.common.clk,
> &slow_uart2_48.common.clk,
> + &apb_clk.common.clk,
> };
> #else
> static struct clk *k1_ccu_mpmu_clks[] = {
> @@ -1288,6 +1311,8 @@ static struct clk *k1_ccu_apbc_clks[] = {
> &uart0_clk.common.clk,
> &twsi2_clk.common.clk,
> &twsi8_clk.common.clk,
> + &twsi2_bus_clk.common.clk,
> + &twsi8_bus_clk.common.clk,
> };
> #else
> static struct clk *k1_ccu_apbc_clks[] = {
> diff --git a/drivers/i2c/k1_i2c.c b/drivers/i2c/k1_i2c.c
> index 2c7a1e0d3775..b11f73959a08 100644
> --- a/drivers/i2c/k1_i2c.c
> +++ b/drivers/i2c/k1_i2c.c
> @@ -51,7 +51,7 @@ struct k1_i2c {
> struct k1_i2c_priv {
> int id;
> void __iomem *base;
> - struct clk clk;
> + struct clk_bulk clks;
> };
>
> /*
> @@ -487,15 +487,13 @@ static int k1_i2c_probe(struct udevice *bus)
> return ret;
> }
>
> - ret = clk_get_by_index(bus, 0, &priv->clk);
> + ret = clk_get_bulk(bus, &priv->clks);
> if (ret)
> return ret;
>
> - ret = clk_enable(&priv->clk);
> - if (ret && ret != -ENOSYS && ret != -EOPNOTSUPP) {
> - debug("%s: failed to enable clock\n", __func__);
> + ret = clk_enable_bulk(&priv->clks);
I'd suggest to not use bulk api, to align with k1 i2c kernel driver,
also to make it easy to set func frequency if needed (a weak reason)
> + if (ret)
> return ret;
> - }
>
> priv->base = (void *)devfdt_get_addr_ptr(bus);
>
>
> --
> 2.55.0
>
--
Yixun Lan (dlan)