From: Yixun Lan <dlan@kernel.org>
To: Junhui Liu <junhui.liu@pigmoral.tech>
Cc: Guodong Xu <guodong@riscstar.com>,
Heiko Schocher <hs@nabladev.com>,
u-boot-spacemit@groups.io, u-boot@lists.u-boot-project.org,
Huan Zhou <pericycle.cc@gmail.com>,
Guodong Xu <guodong.xu@riscstar.com>,
Tom Rini <trini@konsulko.com>,
Raymond Mao <raymond.mao@riscstar.com>,
Lukasz Majewski <lukma@denx.de>,
Troy Mitchell <troy.mitchell@linux.spacemit.com>
Subject: Re: [PATCH 2/2] i2c: k1: enable all clocks for I2C controllers
Date: Fri, 14 Aug 2026 08:38:00 +0000 [thread overview]
Message-ID: <20260814083800-GKA318749@kernel.org> (raw)
In-Reply-To: <20260814-k1-i2c-fix-v1-2-f2e19cbe0af6@pigmoral.tech>
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 <junhui.liu@pigmoral.tech>
> ---
> 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)
prev parent reply other threads:[~2026-08-14 12:46 UTC|newest]
Thread overview: 5+ messages / expand[flat|nested] mbox.gz Atom feed top
2026-08-14 1:46 [PATCH 0/2] i2c/clk: spacemit: k1: fix bus configuration and clock handling Junhui Liu
2026-08-14 1:46 ` [PATCH 1/2] i2c: k1: fix wrong bus speed setting Junhui Liu
2026-08-14 9:32 ` Heiko Schocher via U-Boot
2026-08-14 1:46 ` [PATCH 2/2] i2c: k1: enable all clocks for I2C controllers Junhui Liu
2026-08-14 8:38 ` Yixun Lan [this message]
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20260814083800-GKA318749@kernel.org \
--to=dlan@kernel.org \
--cc=guodong.xu@riscstar.com \
--cc=guodong@riscstar.com \
--cc=hs@nabladev.com \
--cc=junhui.liu@pigmoral.tech \
--cc=lukma@denx.de \
--cc=pericycle.cc@gmail.com \
--cc=raymond.mao@riscstar.com \
--cc=trini@konsulko.com \
--cc=troy.mitchell@linux.spacemit.com \
--cc=u-boot-spacemit@groups.io \
--cc=u-boot@lists.u-boot-project.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox