From nobody Tue Dec 2 01:51:39 2025 Received: from layka.disroot.org (layka.disroot.org [178.21.23.139]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id F305934104C; Thu, 20 Nov 2025 13:14:45 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=178.21.23.139 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1763644488; cv=none; b=o6NzmtELPpR6o6CjBy3We9T05miDACV6O3HgrsFYPPUvwRPpNL5h/ca0P7uh7NN7a83IgFakljfXLti0FFEeweMOxUBXLlInV9nIY84nODinJ7blvaNsxHLScS7YFxSrsfiv9bkEp6OpUz/Q3hlnB3JcGV4JNJ3kOqhQC01iIXo= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1763644488; c=relaxed/simple; bh=lPgY6dsHs0ftyRYcHno/kV3MSLoEVVnLwK0wJnu14+I=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=f2km3pQuwjeO7DyRW2HDHdMcdjBX7SJ+WjWZyZVUZq53HguYpyzOxvIpAViCq6XcPvxNPSNJGqDKYASZ06REy4uqqYP70v7ozUcMQlP6tA/qKqwcdtqHoooI6J1SbDeVf8XoMqTyqzJYjRSZoJbcudu8VWqSFpZ2LWH/QDZMlMI= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=reject dis=none) header.from=disroot.org; spf=pass smtp.mailfrom=disroot.org; dkim=pass (2048-bit key) header.d=disroot.org header.i=@disroot.org header.b=Joj8OKyW; arc=none smtp.client-ip=178.21.23.139 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=reject dis=none) header.from=disroot.org Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=disroot.org Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=disroot.org header.i=@disroot.org header.b="Joj8OKyW" Received: from mail01.disroot.lan (localhost [127.0.0.1]) by disroot.org (Postfix) with ESMTP id 92595261B4; Thu, 20 Nov 2025 14:14:44 +0100 (CET) X-Virus-Scanned: SPAM Filter at disroot.org Received: from layka.disroot.org ([127.0.0.1]) by localhost (disroot.org [127.0.0.1]) (amavis, port 10024) with ESMTP id M6_Ke8QVFuIi; Thu, 20 Nov 2025 14:14:44 +0100 (CET) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=disroot.org; s=mail; t=1763644483; bh=lPgY6dsHs0ftyRYcHno/kV3MSLoEVVnLwK0wJnu14+I=; h=From:To:Cc:Subject:Date:In-Reply-To:References; b=Joj8OKyWxN0/1QgaBGPpAu0q2QfuCtgo4VPqdvmTYVffn3wsn6Lk4kMfX3LjSOUkN RxR+WZqZSrA8tYK6qXsVLQSLVY7dy8VYOVIwHsNmo/ES7vv/qi6hXgLl+IBXDz5Lot MGz5qUBHsaDOdILbGd5gmd7cde0xjbJ5CFseSzRxLnwb23iw7T+yrdmK2J0TwWwbU3 HQp5PrM65mKQj2wO5HvGG+mULsDFDbnV0dpy6ViNedywMSjU4IrVWMTt8NHwUrrpRh HfaUChRuhaHQfzePF2QQ7pIDtys0jTZVemjkrs8ezyl3tQB2wiH3XVi2k8908YuzHO 8HbUKJVrBSKdw== From: Yao Zi To: Drew Fustini , Guo Ren , Fu Wei , Rob Herring , Krzysztof Kozlowski , Conor Dooley , Paul Walmsley , Palmer Dabbelt , Albert Ou , Alexandre Ghiti , Michael Turquette , Stephen Boyd , Icenowy Zheng Cc: linux-riscv@lists.infradead.org, devicetree@vger.kernel.org, linux-kernel@vger.kernel.org, linux-clk@vger.kernel.org, Han Gao , Han Gao , Yao Zi Subject: [PATCH 1/7] dt-bindings: clock: thead,th1520-clk-ap: Add ID for C910 bus clock Date: Thu, 20 Nov 2025 13:14:10 +0000 Message-ID: <20251120131416.26236-2-ziyao@disroot.org> In-Reply-To: <20251120131416.26236-1-ziyao@disroot.org> References: <20251120131416.26236-1-ziyao@disroot.org> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset="utf-8" Add binding ID for C910 bus clock, which takes CLK_C910 as parent and is essential for C910 cluster's operation. Signed-off-by: Yao Zi Acked-by: Conor Dooley --- include/dt-bindings/clock/thead,th1520-clk-ap.h | 1 + 1 file changed, 1 insertion(+) diff --git a/include/dt-bindings/clock/thead,th1520-clk-ap.h b/include/dt-b= indings/clock/thead,th1520-clk-ap.h index 09a9aa7b3ab1..68b35cc61204 100644 --- a/include/dt-bindings/clock/thead,th1520-clk-ap.h +++ b/include/dt-bindings/clock/thead,th1520-clk-ap.h @@ -93,6 +93,7 @@ #define CLK_SRAM3 83 #define CLK_PLL_GMAC_100M 84 #define CLK_UART_SCLK 85 +#define CLK_C910_BUS 86 =20 /* VO clocks */ #define CLK_AXI4_VO_ACLK 0 --=20 2.51.2 From nobody Tue Dec 2 01:51:39 2025 Received: from layka.disroot.org (layka.disroot.org [178.21.23.139]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id CC2C5344035; Thu, 20 Nov 2025 13:14:57 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=178.21.23.139 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1763644500; cv=none; b=pqxyYbzNUwlshogBYPN3AG/uYpLiWMcNqi0QYaCOG1SVrozcK4+NDaV40djJIc04xn6kRaRXV7XlW6bY7sIfVpi3t+R/nQIKxEeF0mnLCvoxRJnMdJuYR9IVljbNvs2QE5oH8XIqKVWqJc2izz33t0AnzduylxKzqFs7/mQhHN8= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1763644500; c=relaxed/simple; bh=yRuavE+79rhObkVfJzraR/ld6UeWsLJML/RIv44JkEY=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=psS4pH1AS84bW5xa9ERgpsGmMial/K/w7P/Ni0fYF1mIv36QxK7veCjwJYEEDGCtK5chcAjSdp9YiKLobgXBdReSrQfsxjiB/43n8awYNIfgVN9INf1XFjDCkde+7lSQbVsvCFroVTcm4IJlBhBEqxrOu8p4gXuS1QLzzZIdqsQ= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=reject dis=none) header.from=disroot.org; spf=pass smtp.mailfrom=disroot.org; dkim=pass (2048-bit key) header.d=disroot.org header.i=@disroot.org header.b=IPxJMr3/; arc=none smtp.client-ip=178.21.23.139 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=reject dis=none) header.from=disroot.org Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=disroot.org Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=disroot.org header.i=@disroot.org header.b="IPxJMr3/" Received: from mail01.disroot.lan (localhost [127.0.0.1]) by disroot.org (Postfix) with ESMTP id E67092617B; Thu, 20 Nov 2025 14:14:55 +0100 (CET) X-Virus-Scanned: SPAM Filter at disroot.org Received: from layka.disroot.org ([127.0.0.1]) by localhost (disroot.org [127.0.0.1]) (amavis, port 10024) with ESMTP id lBcYb6eqv8Dq; Thu, 20 Nov 2025 14:14:55 +0100 (CET) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=disroot.org; s=mail; t=1763644495; bh=yRuavE+79rhObkVfJzraR/ld6UeWsLJML/RIv44JkEY=; h=From:To:Cc:Subject:Date:In-Reply-To:References; b=IPxJMr3/Lgn6+XBEK3e05FI6gFR6vMzeCDmz8CVAmZhkaaE7Mn9VYuZ/ZPoTN+dAy tkApJIsC2Vp72FqW7ncA3ZeVUD3PmkkIWnmKyns8Yt7aYSkm5rxiSycU81iiHhPCY8 0RDtGhiau1UM3rxlrulObpjxNvFmXVT8igkh7g2lvUMEYFB7UQWPt17unz7soIDsWF HPueZXnMBRYmkyelBTAkluery1/COhG3+2vk3yDC3Owey1ajHr7wUR4+g6KKRbt5GL XQ5jP+/0vTB4hkCw27ZFj3raViwC7tE4MGZAz2lkigLvu1ONGKXK0/85qIzhZjduBj oQf9k/ZRrXl0w== From: Yao Zi To: Drew Fustini , Guo Ren , Fu Wei , Rob Herring , Krzysztof Kozlowski , Conor Dooley , Paul Walmsley , Palmer Dabbelt , Albert Ou , Alexandre Ghiti , Michael Turquette , Stephen Boyd , Icenowy Zheng Cc: linux-riscv@lists.infradead.org, devicetree@vger.kernel.org, linux-kernel@vger.kernel.org, linux-clk@vger.kernel.org, Han Gao , Han Gao , Yao Zi Subject: [PATCH 2/7] clk: thead: th1520-ap: Poll for PLL lock and wait for stability Date: Thu, 20 Nov 2025 13:14:11 +0000 Message-ID: <20251120131416.26236-3-ziyao@disroot.org> In-Reply-To: <20251120131416.26236-1-ziyao@disroot.org> References: <20251120131416.26236-1-ziyao@disroot.org> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset="utf-8" All PLLs found on TH1520 SoC take 21250ns at maximum to lock, and their lock status is indicated by register PLL_STS (offset 0x80 inside AP clock controller). We should poll the register to ensure the PLL actually locks after enabling it. Furthermore, a 30us delay is added after enabling the PLL, after which the PLL could be considered stable as stated by vendor clock code. Fixes: 56a48c1833aa ("clk: thead: add support for enabling/disabling PLLs") Signed-off-by: Yao Zi Reviewed-by: Drew Fustini --- drivers/clk/thead/clk-th1520-ap.c | 34 +++++++++++++++++++++++++++++-- 1 file changed, 32 insertions(+), 2 deletions(-) diff --git a/drivers/clk/thead/clk-th1520-ap.c b/drivers/clk/thead/clk-th15= 20-ap.c index 71ad03a998e8..d870f0c665f8 100644 --- a/drivers/clk/thead/clk-th1520-ap.c +++ b/drivers/clk/thead/clk-th1520-ap.c @@ -8,11 +8,14 @@ #include #include #include +#include #include #include #include #include =20 +#define TH1520_PLL_STS 0x80 + #define TH1520_PLL_POSTDIV2 GENMASK(26, 24) #define TH1520_PLL_POSTDIV1 GENMASK(22, 20) #define TH1520_PLL_FBDIV GENMASK(19, 8) @@ -23,6 +26,13 @@ #define TH1520_PLL_FRAC GENMASK(23, 0) #define TH1520_PLL_FRAC_BITS 24 =20 +/* + * All PLLs in TH1520 take 21250ns at maximum to lock, let's take its doub= le + * for safety. + */ +#define TH1520_PLL_LOCK_TIMEOUT_US 44 +#define TH1520_PLL_STABLE_DELAY_US 30 + struct ccu_internal { u8 shift; u8 width; @@ -64,6 +74,7 @@ struct ccu_div { =20 struct ccu_pll { struct ccu_common common; + u32 lock_sts_mask; }; =20 #define TH_CCU_ARG(_shift, _width) \ @@ -299,9 +310,21 @@ static void ccu_pll_disable(struct clk_hw *hw) static int ccu_pll_enable(struct clk_hw *hw) { struct ccu_pll *pll =3D hw_to_ccu_pll(hw); + u32 reg; + int ret; =20 - return regmap_clear_bits(pll->common.map, pll->common.cfg1, - TH1520_PLL_VCO_RST); + regmap_clear_bits(pll->common.map, pll->common.cfg1, + TH1520_PLL_VCO_RST); + + ret =3D regmap_read_poll_timeout_atomic(pll->common.map, TH1520_PLL_STS, + reg, reg & pll->lock_sts_mask, + 5, TH1520_PLL_LOCK_TIMEOUT_US); + if (ret) + return ret; + + udelay(TH1520_PLL_STABLE_DELAY_US); + + return 0; } =20 static int ccu_pll_is_enabled(struct clk_hw *hw) @@ -389,6 +412,7 @@ static struct ccu_pll cpu_pll0_clk =3D { &clk_pll_ops, CLK_IS_CRITICAL), }, + .lock_sts_mask =3D BIT(1), }; =20 static struct ccu_pll cpu_pll1_clk =3D { @@ -401,6 +425,7 @@ static struct ccu_pll cpu_pll1_clk =3D { &clk_pll_ops, CLK_IS_CRITICAL), }, + .lock_sts_mask =3D BIT(4), }; =20 static struct ccu_pll gmac_pll_clk =3D { @@ -413,6 +438,7 @@ static struct ccu_pll gmac_pll_clk =3D { &clk_pll_ops, CLK_IS_CRITICAL), }, + .lock_sts_mask =3D BIT(3), }; =20 static const struct clk_hw *gmac_pll_clk_parent[] =3D { @@ -433,6 +459,7 @@ static struct ccu_pll video_pll_clk =3D { &clk_pll_ops, CLK_IS_CRITICAL), }, + .lock_sts_mask =3D BIT(7), }; =20 static const struct clk_hw *video_pll_clk_parent[] =3D { @@ -453,6 +480,7 @@ static struct ccu_pll dpu0_pll_clk =3D { &clk_pll_ops, 0), }, + .lock_sts_mask =3D BIT(8), }; =20 static const struct clk_hw *dpu0_pll_clk_parent[] =3D { @@ -469,6 +497,7 @@ static struct ccu_pll dpu1_pll_clk =3D { &clk_pll_ops, 0), }, + .lock_sts_mask =3D BIT(9), }; =20 static const struct clk_hw *dpu1_pll_clk_parent[] =3D { @@ -485,6 +514,7 @@ static struct ccu_pll tee_pll_clk =3D { &clk_pll_ops, CLK_IS_CRITICAL), }, + .lock_sts_mask =3D BIT(10), }; =20 static const struct clk_parent_data c910_i0_parents[] =3D { --=20 2.51.2 From nobody Tue Dec 2 01:51:39 2025 Received: from layka.disroot.org (layka.disroot.org [178.21.23.139]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 0C95B372AD8; Thu, 20 Nov 2025 13:15:46 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=178.21.23.139 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1763644548; cv=none; b=qtpTMgd/++1rtFFlalDCwvuu+PGxEkNhZ2/EWYbG+lcv5gAyPpwx3J8cdkX8gBpNQLb7srRkU6zofw4j7TuRDeowS4lLyvD0UWGaoeiqyC+aAuDL+87p1rev/PgFe5xaPebE5CaNcwLcm2SO8cWS3FweO5f9MhtPDgv7EZjOh9s= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1763644548; c=relaxed/simple; bh=ryFSKJJYAQEuIhfDnfaPdlN0e3PPj9IXfbwSk6AoBpg=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=WKapchTvZ5wcKkhfkZw8Dcu1kNPI2l46wQhJgg+Gu6FmPnp9uibpy7gbuth+byR3VMNScL9Z33PxE2JKial10IIbPtpQKTevNqagpTE47kb4Q0EXYT2BMa+pWli8HJ65fYXsb7AWvaaN20yLrzpu+JDcoZl+WvUi0fr/XyFoixI= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=reject dis=none) header.from=disroot.org; spf=pass smtp.mailfrom=disroot.org; dkim=pass (2048-bit key) header.d=disroot.org header.i=@disroot.org header.b=TGDzjodr; arc=none smtp.client-ip=178.21.23.139 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=reject dis=none) header.from=disroot.org Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=disroot.org Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=disroot.org header.i=@disroot.org header.b="TGDzjodr" Received: from mail01.disroot.lan (localhost [127.0.0.1]) by disroot.org (Postfix) with ESMTP id AD35722FD2; Thu, 20 Nov 2025 14:15:45 +0100 (CET) X-Virus-Scanned: SPAM Filter at disroot.org Received: from layka.disroot.org ([127.0.0.1]) by localhost (disroot.org [127.0.0.1]) (amavis, port 10024) with ESMTP id cPPvRQRZVFl5; Thu, 20 Nov 2025 14:15:45 +0100 (CET) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=disroot.org; s=mail; t=1763644545; bh=ryFSKJJYAQEuIhfDnfaPdlN0e3PPj9IXfbwSk6AoBpg=; h=From:To:Cc:Subject:Date:In-Reply-To:References; b=TGDzjodrR1emmTiX70eqbr3bcJW1Dwk36Jx9wAgiBJSGlG75bylJyWlsdIHNbtj2z TA/DIhStw85lnIpe/4b1BTjQgOssV9wlI+9des4yRYZmUkOASnHkcNM8BcLOWjrQaY YATCb1NZZXQNm+3ttq2OH/rioX20txzZoJe4kEnO0qRp4AR31Dx8dXv/ZqR+llPGxu 3ksyOsprr39MOGZRbNYR0kz1Pvbei43gEhyEYU/CtvGk3LfHSSr2/qjUpaN5Z1ot2P HCiS4TBtaJiDGbk+r35++gPTSSPyuztCdvE/j/PX+kjgz/rXwHdXN1deu6ujZLeogc UiLSfUGGUvoxw== From: Yao Zi To: Drew Fustini , Guo Ren , Fu Wei , Rob Herring , Krzysztof Kozlowski , Conor Dooley , Paul Walmsley , Palmer Dabbelt , Albert Ou , Alexandre Ghiti , Michael Turquette , Stephen Boyd , Icenowy Zheng Cc: linux-riscv@lists.infradead.org, devicetree@vger.kernel.org, linux-kernel@vger.kernel.org, linux-clk@vger.kernel.org, Han Gao , Han Gao , Yao Zi Subject: [PATCH 3/7] clk: thead: th1520-ap: Add C910 bus clock Date: Thu, 20 Nov 2025 13:14:12 +0000 Message-ID: <20251120131416.26236-4-ziyao@disroot.org> In-Reply-To: <20251120131416.26236-1-ziyao@disroot.org> References: <20251120131416.26236-1-ziyao@disroot.org> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset="utf-8" This divider takes c910_clk as parent and is essential for the C910 cluster to operate, thus is marked as CLK_IS_CRITICAL. Signed-off-by: Yao Zi Reviewed-by: Drew Fustini --- drivers/clk/thead/clk-th1520-ap.c | 17 ++++++++++++++++- 1 file changed, 16 insertions(+), 1 deletion(-) diff --git a/drivers/clk/thead/clk-th1520-ap.c b/drivers/clk/thead/clk-th15= 20-ap.c index d870f0c665f8..b820d47387bb 100644 --- a/drivers/clk/thead/clk-th1520-ap.c +++ b/drivers/clk/thead/clk-th1520-ap.c @@ -539,6 +539,20 @@ static struct ccu_mux c910_clk =3D { .mux =3D TH_CCU_MUX("c910", c910_parents, 0, 1), }; =20 +static struct ccu_div c910_bus_clk =3D { + .enable =3D BIT(7), + .div_en =3D BIT(11), + .div =3D TH_CCU_DIV_FLAGS(8, 3, 0), + .common =3D { + .clkid =3D CLK_C910_BUS, + .cfg0 =3D 0x100, + .hw.init =3D CLK_HW_INIT_HW("c910-bus", + &c910_clk.mux.hw, + &ccu_div_ops, + CLK_IS_CRITICAL), + }, +}; + static const struct clk_parent_data ahb2_cpusys_parents[] =3D { { .hw =3D &gmac_pll_clk.common.hw }, { .index =3D 0 } @@ -1051,6 +1065,7 @@ static struct ccu_common *th1520_pll_clks[] =3D { }; =20 static struct ccu_common *th1520_div_clks[] =3D { + &c910_bus_clk.common, &ahb2_cpusys_hclk.common, &apb3_cpusys_pclk.common, &axi4_cpusys2_aclk.common, @@ -1194,7 +1209,7 @@ static const struct th1520_plat_data th1520_ap_platda= ta =3D { .th1520_mux_clks =3D th1520_mux_clks, .th1520_gate_clks =3D th1520_gate_clks, =20 - .nr_clks =3D CLK_UART_SCLK + 1, + .nr_clks =3D CLK_C910_BUS + 1, =20 .nr_pll_clks =3D ARRAY_SIZE(th1520_pll_clks), .nr_div_clks =3D ARRAY_SIZE(th1520_div_clks), --=20 2.51.2 From nobody Tue Dec 2 01:51:39 2025 Received: from layka.disroot.org (layka.disroot.org [178.21.23.139]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id B88B933CEB0; Thu, 20 Nov 2025 13:15:58 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=178.21.23.139 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1763644560; cv=none; b=D4+jq5Tb8RsSu5kcGhx9sELJqIiUXWniSms8qa4aTtLfRHbDHhQSbhUZzNLOfVhyvsPzyRPmyHDtXwCpRdDImHUxgbp1eKgQwTHiJaG8lF/icHIvWFTHBKK4vYvO+EPr6n/AkVHMeif79wJ3sYCZoK0NTWPM7fcDi/a5U4t48n4= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1763644560; c=relaxed/simple; bh=6xpttd36WKtetXe3TLfe39yIQ65ubw2+nD4vPw42ObU=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=p1OaXKo+ADqrhv0gfWYldHl4w6BRbsfl70uRXVX/KrpsyW5KXF2/4htK8RBjtUvWfOptmIbCUwS0voC+kmddKq39b3IQpyXE9Wj7WmzTg6N0I1obXZ09zuRZNlvfnhU2p2MJrnTxf25akIxTEb0AaTipd4uZiVhDDYZc+k7phFk= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=reject dis=none) header.from=disroot.org; spf=pass smtp.mailfrom=disroot.org; dkim=pass (2048-bit key) header.d=disroot.org header.i=@disroot.org header.b=dauS815v; arc=none smtp.client-ip=178.21.23.139 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=reject dis=none) header.from=disroot.org Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=disroot.org Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=disroot.org header.i=@disroot.org header.b="dauS815v" Received: from mail01.disroot.lan (localhost [127.0.0.1]) by disroot.org (Postfix) with ESMTP id 0713422FD2; Thu, 20 Nov 2025 14:15:55 +0100 (CET) X-Virus-Scanned: SPAM Filter at disroot.org Received: from layka.disroot.org ([127.0.0.1]) by localhost (disroot.org [127.0.0.1]) (amavis, port 10024) with ESMTP id WxLEOPIpJFEM; Thu, 20 Nov 2025 14:15:54 +0100 (CET) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=disroot.org; s=mail; t=1763644554; bh=6xpttd36WKtetXe3TLfe39yIQ65ubw2+nD4vPw42ObU=; h=From:To:Cc:Subject:Date:In-Reply-To:References; b=dauS815vMS2uVrKC/+1pYPMxbH5mEBEWihDJucOXtozNQkP4BM191pFxXMrBAf4wC Bn1NWFEl5dyG7p5wGO79mDFzBbdjbDbm37fUpnXtA0TM1JkJsgHBCo162yBIdiOOW5 6f1GhtpW153JbBviEz/3nMC8+W1DH3qwB4zkrLHC7pu4kNgr8lyUzimoWB2cUwvPd6 dhsX7V31IaUQ/zbjdAHq8CYBkom9fMyv7GqD5FnZjdiHIK9gjG6k8CW3GJhnVtkjHf qCc7Bhju5Q+sNvi0BJyxUgfEW1niaAqiyLICpV7VEoauupfhC+pDvVHxmztydSfGlT 6jYvFd/uUCWIg== From: Yao Zi To: Drew Fustini , Guo Ren , Fu Wei , Rob Herring , Krzysztof Kozlowski , Conor Dooley , Paul Walmsley , Palmer Dabbelt , Albert Ou , Alexandre Ghiti , Michael Turquette , Stephen Boyd , Icenowy Zheng Cc: linux-riscv@lists.infradead.org, devicetree@vger.kernel.org, linux-kernel@vger.kernel.org, linux-clk@vger.kernel.org, Han Gao , Han Gao , Yao Zi Subject: [PATCH 4/7] clk: thead: th1520-ap: Support setting PLL rates Date: Thu, 20 Nov 2025 13:14:13 +0000 Message-ID: <20251120131416.26236-5-ziyao@disroot.org> In-Reply-To: <20251120131416.26236-1-ziyao@disroot.org> References: <20251120131416.26236-1-ziyao@disroot.org> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset="utf-8" TH1520 ships several PLLs that could operate in either integer or fractional mode. However, the TRM only lists a few configuration whose stability is considered guaranteed. Add a table-lookup rate determination logic to support PLL rate setting, and fill up frequency-configuration tables for AP-subsystem PLLs. Signed-off-by: Yao Zi Reviewed-by: Drew Fustini --- drivers/clk/thead/clk-th1520-ap.c | 142 ++++++++++++++++++++++++++++++ 1 file changed, 142 insertions(+) diff --git a/drivers/clk/thead/clk-th1520-ap.c b/drivers/clk/thead/clk-th15= 20-ap.c index b820d47387bb..bf8e80c39a9e 100644 --- a/drivers/clk/thead/clk-th1520-ap.c +++ b/drivers/clk/thead/clk-th1520-ap.c @@ -22,6 +22,7 @@ #define TH1520_PLL_REFDIV GENMASK(5, 0) #define TH1520_PLL_BYPASS BIT(30) #define TH1520_PLL_VCO_RST BIT(29) +#define TH1520_PLL_DACPD BIT(25) #define TH1520_PLL_DSMPD BIT(24) #define TH1520_PLL_FRAC GENMASK(23, 0) #define TH1520_PLL_FRAC_BITS 24 @@ -72,9 +73,19 @@ struct ccu_div { struct ccu_common common; }; =20 +struct ccu_pll_cfg { + unsigned long freq; + u32 fbdiv; + u32 frac; + u32 postdiv1; + u32 postdiv2; +}; + struct ccu_pll { struct ccu_common common; u32 lock_sts_mask; + int cfgnum; + const struct ccu_pll_cfg *cfgs; }; =20 #define TH_CCU_ARG(_shift, _width) \ @@ -391,17 +402,102 @@ static unsigned long ccu_pll_recalc_rate(struct clk_= hw *hw, return rate; } =20 +static const struct ccu_pll_cfg *ccu_pll_lookup_best_cfg(struct ccu_pll *p= ll, + unsigned long rate) +{ + unsigned long best_delta =3D ULONG_MAX; + const struct ccu_pll_cfg *best_cfg; + int i; + + for (i =3D 0; i < pll->cfgnum; i++) { + const struct ccu_pll_cfg *cfg =3D &pll->cfgs[i]; + unsigned long delta; + + delta =3D abs_diff(cfg->freq, rate); + if (delta < best_delta) { + best_delta =3D delta; + best_cfg =3D cfg; + } + } + + return best_cfg; +} + +static int ccu_pll_determine_rate(struct clk_hw *hw, + struct clk_rate_request *req) +{ + struct ccu_pll *pll =3D hw_to_ccu_pll(hw); + + req->rate =3D ccu_pll_lookup_best_cfg(pll, req->rate)->freq; + + return 0; +} + +static int ccu_pll_set_rate(struct clk_hw *hw, unsigned long rate, + unsigned long parent_rate) +{ + struct ccu_pll *pll =3D hw_to_ccu_pll(hw); + const struct ccu_pll_cfg *cfg; + + cfg =3D ccu_pll_lookup_best_cfg(pll, rate); + + ccu_pll_disable(hw); + + regmap_write(pll->common.map, pll->common.cfg0, + FIELD_PREP(TH1520_PLL_REFDIV, 1) | + FIELD_PREP(TH1520_PLL_FBDIV, cfg->fbdiv) | + FIELD_PREP(TH1520_PLL_POSTDIV1, cfg->postdiv1) | + FIELD_PREP(TH1520_PLL_POSTDIV2, cfg->postdiv2)); + + regmap_update_bits(pll->common.map, pll->common.cfg1, + TH1520_PLL_DACPD | TH1520_PLL_DSMPD | + TH1520_PLL_FRAC, + cfg->frac ? cfg->frac : + TH1520_PLL_DACPD | TH1520_PLL_DSMPD); + + return ccu_pll_enable(hw); +} + static const struct clk_ops clk_pll_ops =3D { .disable =3D ccu_pll_disable, .enable =3D ccu_pll_enable, .is_enabled =3D ccu_pll_is_enabled, .recalc_rate =3D ccu_pll_recalc_rate, + .determine_rate =3D ccu_pll_determine_rate, + .set_rate =3D ccu_pll_set_rate, }; =20 static const struct clk_parent_data osc_24m_clk[] =3D { { .index =3D 0 } }; =20 +static const struct ccu_pll_cfg cpu_pll_cfgs[] =3D { + { 125000000, 125, 0, 6, 4 }, + { 200000000, 125, 0, 5, 3 }, + { 300000000, 125, 0, 5, 2 }, + { 400000000, 100, 0, 3, 2 }, + { 500000000, 125, 0, 6, 1 }, + { 600000000, 125, 0, 5, 1 }, + { 702000000, 117, 0, 4, 1 }, + { 800000000, 100, 0, 3, 1 }, + { 900000000, 75, 0, 2, 1 }, + { 1000000000, 125, 0, 3, 1 }, + { 1104000000, 92, 0, 2, 1 }, + { 1200000000, 100, 0, 2, 1 }, + { 1296000000, 108, 0, 2, 1 }, + { 1404000000, 117, 0, 2, 1 }, + { 1500000000, 125, 0, 2, 1 }, + { 1608000000, 67, 0, 1, 1 }, + { 1704000000, 71, 0, 1, 1 }, + { 1800000000, 75, 0, 1, 1 }, + { 1896000000, 79, 0, 1, 1 }, + { 1992000000, 83, 0, 1, 1 }, + { 2112000000, 88, 0, 1, 1 }, + { 2208000000, 92, 0, 1, 1 }, + { 2304000000, 96, 0, 1, 1 }, + { 2400000000, 100, 0, 1, 1 }, +}; + static struct ccu_pll cpu_pll0_clk =3D { .common =3D { .clkid =3D CLK_CPU_PLL0, @@ -413,6 +509,8 @@ static struct ccu_pll cpu_pll0_clk =3D { CLK_IS_CRITICAL), }, .lock_sts_mask =3D BIT(1), + .cfgnum =3D ARRAY_SIZE(cpu_pll_cfgs), + .cfgs =3D cpu_pll_cfgs, }; =20 static struct ccu_pll cpu_pll1_clk =3D { @@ -426,6 +524,16 @@ static struct ccu_pll cpu_pll1_clk =3D { CLK_IS_CRITICAL), }, .lock_sts_mask =3D BIT(4), + .cfgnum =3D ARRAY_SIZE(cpu_pll_cfgs), + .cfgs =3D cpu_pll_cfgs, +}; + +static const struct ccu_pll_cfg gmac_pll_cfg =3D { + .freq =3D 1000000000, + .fbdiv =3D 125, + .frac =3D 0, + .postdiv1 =3D 3, + .postdiv2 =3D 1, }; =20 static struct ccu_pll gmac_pll_clk =3D { @@ -439,6 +547,8 @@ static struct ccu_pll gmac_pll_clk =3D { CLK_IS_CRITICAL), }, .lock_sts_mask =3D BIT(3), + .cfgnum =3D 1, + .cfgs =3D &gmac_pll_cfg, }; =20 static const struct clk_hw *gmac_pll_clk_parent[] =3D { @@ -449,6 +559,14 @@ static const struct clk_parent_data gmac_pll_clk_pd[] = =3D { { .hw =3D &gmac_pll_clk.common.hw } }; =20 +static const struct ccu_pll_cfg video_pll_cfg =3D { + .freq =3D 792000000, + .fbdiv =3D 99, + .frac =3D 0, + .postdiv1 =3D 3, + .postdiv2 =3D 1, +}; + static struct ccu_pll video_pll_clk =3D { .common =3D { .clkid =3D CLK_VIDEO_PLL, @@ -460,6 +578,8 @@ static struct ccu_pll video_pll_clk =3D { CLK_IS_CRITICAL), }, .lock_sts_mask =3D BIT(7), + .cfgnum =3D 1, + .cfgs =3D &video_pll_cfg, }; =20 static const struct clk_hw *video_pll_clk_parent[] =3D { @@ -470,6 +590,14 @@ static const struct clk_parent_data video_pll_clk_pd[]= =3D { { .hw =3D &video_pll_clk.common.hw } }; =20 +static const struct ccu_pll_cfg dpu_pll_cfg =3D { + .freq =3D 1188000000, + .fbdiv =3D 99, + .frac =3D 0, + .postdiv1 =3D 2, + .postdiv2 =3D 1, +}; + static struct ccu_pll dpu0_pll_clk =3D { .common =3D { .clkid =3D CLK_DPU0_PLL, @@ -481,6 +609,8 @@ static struct ccu_pll dpu0_pll_clk =3D { 0), }, .lock_sts_mask =3D BIT(8), + .cfgnum =3D 1, + .cfgs =3D &dpu_pll_cfg, }; =20 static const struct clk_hw *dpu0_pll_clk_parent[] =3D { @@ -498,12 +628,22 @@ static struct ccu_pll dpu1_pll_clk =3D { 0), }, .lock_sts_mask =3D BIT(9), + .cfgnum =3D 1, + .cfgs =3D &dpu_pll_cfg, }; =20 static const struct clk_hw *dpu1_pll_clk_parent[] =3D { &dpu1_pll_clk.common.hw }; =20 +static const struct ccu_pll_cfg tee_pll_cfg =3D { + .freq =3D 792000000, + .fbdiv =3D 99, + .frac =3D 0, + .postdiv1 =3D 3, + .postdiv2 =3D 1, +}; + static struct ccu_pll tee_pll_clk =3D { .common =3D { .clkid =3D CLK_TEE_PLL, @@ -515,6 +655,8 @@ static struct ccu_pll tee_pll_clk =3D { CLK_IS_CRITICAL), }, .lock_sts_mask =3D BIT(10), + .cfgnum =3D 1, + .cfgs =3D &tee_pll_cfg, }; =20 static const struct clk_parent_data c910_i0_parents[] =3D { --=20 2.51.2 From nobody Tue Dec 2 01:51:39 2025 Received: from layka.disroot.org (layka.disroot.org [178.21.23.139]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id F1BC833B6CB; Thu, 20 Nov 2025 13:16:07 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=178.21.23.139 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1763644569; cv=none; b=OBSVMgRvU5XtATcxFIObiCt/1mTv6jhgFCqZtvQ8U1q2By3hLuaEI7bH1rW2hdoZyVShq5BR+KFBYK875TySgbLYhiB+fY7E3NOBP5Evl3PGn4iEKmhTvaO6ndSJo1IDpkSwpOxAVr8XqeWDt0MtU+cbCxYxCD/LTp0MCxDZUp4= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1763644569; c=relaxed/simple; bh=K+u3wqp+9anVmEDTeLD4NstpSo/avmelycIC6VjG2V4=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=VoTaACb9eZC68bCG/25jGtwWeo7NVZ1EHIaR6wSz2R9vHZoXs+nIyREFKRUYH7vYwwWw5Z83H6C2bVg0Va5HE9xtwQPRTZyRouklPkWCDAdzz42G/X2u7DmhJJixpXPuByRQIFhcrJHrC9wavbMj9F3RScz2ODVA6O2r2GOqu40= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=reject dis=none) header.from=disroot.org; spf=pass smtp.mailfrom=disroot.org; dkim=pass (2048-bit key) header.d=disroot.org header.i=@disroot.org header.b=DXCzUbRx; arc=none smtp.client-ip=178.21.23.139 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=reject dis=none) header.from=disroot.org Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=disroot.org Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=disroot.org header.i=@disroot.org header.b="DXCzUbRx" Received: from mail01.disroot.lan (localhost [127.0.0.1]) by disroot.org (Postfix) with ESMTP id 93CFB20B50; Thu, 20 Nov 2025 14:16:06 +0100 (CET) X-Virus-Scanned: SPAM Filter at disroot.org Received: from layka.disroot.org ([127.0.0.1]) by localhost (disroot.org [127.0.0.1]) (amavis, port 10024) with ESMTP id YS_O_oScmD3k; Thu, 20 Nov 2025 14:16:06 +0100 (CET) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=disroot.org; s=mail; t=1763644566; bh=K+u3wqp+9anVmEDTeLD4NstpSo/avmelycIC6VjG2V4=; h=From:To:Cc:Subject:Date:In-Reply-To:References; b=DXCzUbRxsucs7j/08kFZ02NPaYb5vj43V/IJ5XiH/SmhhZFsLSHAR42SBVsOTsU6h BvAOep9lch7VTEiuw9EsB6ceARucg5vSQFzmW3oHNmUC28h7f+1b74VCfOcZIVkH9p JHORoZQgsTp9Pu/9CJACbSUSRLSDpTTXjcorF6j7t8sVVPezZS8EERZ1ECCUSQuJW2 RJi5Z64FlrqTP450pIdOLTKJkxP3UWJ0iCxI7yzm4pGkm3cH5OprBWzATcCoV7Msuc KSOff/Z063NpXIWE6HdRCTqxO+dvtd5EUIULALVeqvWP1EgA01sE9ZfVIjCA+m5IS9 p5+d3fIBq+QRQ== From: Yao Zi To: Drew Fustini , Guo Ren , Fu Wei , Rob Herring , Krzysztof Kozlowski , Conor Dooley , Paul Walmsley , Palmer Dabbelt , Albert Ou , Alexandre Ghiti , Michael Turquette , Stephen Boyd , Icenowy Zheng Cc: linux-riscv@lists.infradead.org, devicetree@vger.kernel.org, linux-kernel@vger.kernel.org, linux-clk@vger.kernel.org, Han Gao , Han Gao , Yao Zi Subject: [PATCH 5/7] clk: thead: th1520-ap: Add macro to define multiplexers with flags Date: Thu, 20 Nov 2025 13:14:14 +0000 Message-ID: <20251120131416.26236-6-ziyao@disroot.org> In-Reply-To: <20251120131416.26236-1-ziyao@disroot.org> References: <20251120131416.26236-1-ziyao@disroot.org> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset="utf-8" The new macro, TH_CCU_MUX_FLAGS, extends TH_CCU_MUX macro by adding two parameters to specify clock flags and multiplexer flags. Signed-off-by: Yao Zi Reviewed-by: Drew Fustini --- drivers/clk/thead/clk-th1520-ap.c | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/drivers/clk/thead/clk-th1520-ap.c b/drivers/clk/thead/clk-th15= 20-ap.c index bf8e80c39a9e..79f001a047b2 100644 --- a/drivers/clk/thead/clk-th1520-ap.c +++ b/drivers/clk/thead/clk-th1520-ap.c @@ -101,17 +101,22 @@ struct ccu_pll { .flags =3D _flags, \ } =20 -#define TH_CCU_MUX(_name, _parents, _shift, _width) \ +#define TH_CCU_MUX_FLAGS(_name, _parents, _shift, _width, _flags, \ + _mux_flags) \ { \ .mask =3D GENMASK(_width - 1, 0), \ .shift =3D _shift, \ + .flags =3D _mux_flags, \ .hw.init =3D CLK_HW_INIT_PARENTS_DATA( \ _name, \ _parents, \ &clk_mux_ops, \ - 0), \ + _flags), \ } =20 +#define TH_CCU_MUX(_name, _parents, _shift, _width) \ + TH_CCU_MUX_FLAGS(_name, _parents, _shift, _width, 0, 0) + #define CCU_GATE(_clkid, _struct, _name, _parent, _reg, _bit, _flags) \ struct ccu_gate _struct =3D { \ .clkid =3D _clkid, \ --=20 2.51.2 From nobody Tue Dec 2 01:51:39 2025 Received: from layka.disroot.org (layka.disroot.org [178.21.23.139]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 6DD0A3112BD; Thu, 20 Nov 2025 13:17:06 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=178.21.23.139 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1763644628; cv=none; b=qzUhhcUakMu4F0VwV4fGy3bmPgWWqR5PyR/GoZZFwCNgASxDFHUSROFDv0jFwaCejTpKTnB8/1nZ9520Dt8LAJKtrsuyMtVa9Ydryybp9CrU0f+WT0Z2gMhiKdzlOf5r7YyjJ57jbsPH6uyr9BIrYUiDmGdbA9EmPfZlgpvD4tQ= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1763644628; c=relaxed/simple; bh=kxSICP8fwMm99AQGf8853Gn6w5FNP1Z6VkgI0xBu+jc=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=NCm6vrl4Ieh/J8qJZVVOWVBk6p/MD9lAkQPZ0TyfvFroMKIA/KiItCk7TbejcmFkDmCru1IAEJ9TE/XVM5xoFbUKUQADH50DDOtqXqey9TBaPquwduYLCJ7XFiC7T9IcdjKgbLg8bc6vNm4pp34Lnx6Hv9HPqdsVxzXgEcxNr1s= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=reject dis=none) header.from=disroot.org; spf=pass smtp.mailfrom=disroot.org; dkim=pass (2048-bit key) header.d=disroot.org header.i=@disroot.org header.b=h/91x6Pd; arc=none smtp.client-ip=178.21.23.139 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=reject dis=none) header.from=disroot.org Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=disroot.org Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=disroot.org header.i=@disroot.org header.b="h/91x6Pd" Received: from mail01.disroot.lan (localhost [127.0.0.1]) by disroot.org (Postfix) with ESMTP id 407732608E; Thu, 20 Nov 2025 14:17:05 +0100 (CET) X-Virus-Scanned: SPAM Filter at disroot.org Received: from layka.disroot.org ([127.0.0.1]) by localhost (disroot.org [127.0.0.1]) (amavis, port 10024) with ESMTP id tAWxe1q3_yOl; Thu, 20 Nov 2025 14:17:04 +0100 (CET) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=disroot.org; s=mail; t=1763644624; bh=kxSICP8fwMm99AQGf8853Gn6w5FNP1Z6VkgI0xBu+jc=; h=From:To:Cc:Subject:Date:In-Reply-To:References; b=h/91x6Pdoy5sdusvGSpzxcKRU7oE9n8KSPTIKw63SMMVE3i3K3mEWVwfezcFdTWf5 rSzum9Hn4jlHWjYiPXA3alvmiZoPX0nMDe9eP/LksmN7r7N2n7L9y41VUwC+60+2wy lVKGH+TBMw5tE26h9tGvplO0jfyIMe0yQ+zLjVzbzAS8PcVT+RtLrm3huZeSK1BZbb B0tF3zpccEWmYwQos0x8m3sVt4qRlguG5z/cKGpLjiRMwB+PUBe+ShGwDfD6IzTyw9 31Av3GooD9gzRqVeoU91goE4bpeEMverL/Xbxq0HI6AhaokkNr3unqMYG26PoXrYlZ TzWipCzM0dy5w== From: Yao Zi To: Drew Fustini , Guo Ren , Fu Wei , Rob Herring , Krzysztof Kozlowski , Conor Dooley , Paul Walmsley , Palmer Dabbelt , Albert Ou , Alexandre Ghiti , Michael Turquette , Stephen Boyd , Icenowy Zheng Cc: linux-riscv@lists.infradead.org, devicetree@vger.kernel.org, linux-kernel@vger.kernel.org, linux-clk@vger.kernel.org, Han Gao , Han Gao , Yao Zi Subject: [PATCH 6/7] clk: thead: th1520-ap: Support CPU frequency scaling Date: Thu, 20 Nov 2025 13:14:15 +0000 Message-ID: <20251120131416.26236-7-ziyao@disroot.org> In-Reply-To: <20251120131416.26236-1-ziyao@disroot.org> References: <20251120131416.26236-1-ziyao@disroot.org> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset="utf-8" On TH1520 SoC, c910_clk feeds the CPU cluster. It could be glitchlessly reparented to one of the two PLLs: either to cpu_pll0 indirectly through c910_i0_clk, or to cpu_pll1 directly. To achieve glitchless rate change, customized clock operations are implemented for c910_clk: on rate change, the PLL not currently in use is configured to the requested rate first, then c910_clk reparents to it. Additionally, c910_bus_clk, which in turn takes c910_clk as parent, has a frequency limit of 750MHz. A clock notifier is registered on c910_clk to adjust c910_bus_clk on c910_clk rate change. Signed-off-by: Yao Zi Reviewed-by: Drew Fustini --- drivers/clk/thead/clk-th1520-ap.c | 148 +++++++++++++++++++++++++++++- 1 file changed, 146 insertions(+), 2 deletions(-) diff --git a/drivers/clk/thead/clk-th1520-ap.c b/drivers/clk/thead/clk-th15= 20-ap.c index 79f001a047b2..cd3b396c9a3d 100644 --- a/drivers/clk/thead/clk-th1520-ap.c +++ b/drivers/clk/thead/clk-th1520-ap.c @@ -7,9 +7,11 @@ =20 #include #include +#include #include #include #include +#include #include #include #include @@ -34,6 +36,9 @@ #define TH1520_PLL_LOCK_TIMEOUT_US 44 #define TH1520_PLL_STABLE_DELAY_US 30 =20 +/* c910_bus_clk must be kept below 750MHz for stability */ +#define TH1520_C910_BUS_MAX_RATE (750 * 1000 * 1000) + struct ccu_internal { u8 shift; u8 width; @@ -472,6 +477,72 @@ static const struct clk_ops clk_pll_ops =3D { .set_rate =3D ccu_pll_set_rate, }; =20 +/* + * c910_clk could be reparented glitchlessly for DVFS. There are two paren= ts, + * - c910_i0_clk, dervided from cpu_pll0_clk or osc_24m. + * - cpu_pll1_clk, which provides the exact same set of rates as cpu_pll0= _clk. + * + * During rate setting, always forward the request to the unused parent, a= nd + * then switch c910_clk to it to avoid glitch. + */ +static u8 c910_clk_get_parent(struct clk_hw *hw) +{ + return clk_mux_ops.get_parent(hw); +} + +static int c910_clk_set_parent(struct clk_hw *hw, u8 index) +{ + return clk_mux_ops.set_parent(hw, index); +} + +static unsigned long c910_clk_recalc_rate(struct clk_hw *hw, + unsigned long parent_rate) +{ + return parent_rate; +} + +static int c910_clk_determine_rate(struct clk_hw *hw, + struct clk_rate_request *req) +{ + u8 alt_parent_index =3D !c910_clk_get_parent(hw); + struct clk_hw *alt_parent; + + alt_parent =3D clk_hw_get_parent_by_index(hw, alt_parent_index); + + req->rate =3D clk_hw_round_rate(alt_parent, req->rate); + req->best_parent_hw =3D alt_parent; + req->best_parent_rate =3D req->rate; + + return 0; +} + +static int c910_clk_set_rate(struct clk_hw *hw, unsigned long rate, + unsigned long parent_rate) +{ + return -EOPNOTSUPP; +} + +static int c910_clk_set_rate_and_parent(struct clk_hw *hw, unsigned long r= ate, + unsigned long parent_rate, u8 index) +{ + struct clk_hw *parent =3D clk_hw_get_parent_by_index(hw, index); + + clk_set_rate(parent->clk, parent_rate); + + c910_clk_set_parent(hw, index); + + return 0; +} + +static const struct clk_ops c910_clk_ops =3D { + .get_parent =3D c910_clk_get_parent, + .set_parent =3D c910_clk_set_parent, + .recalc_rate =3D c910_clk_recalc_rate, + .determine_rate =3D c910_clk_determine_rate, + .set_rate =3D c910_clk_set_rate, + .set_rate_and_parent =3D c910_clk_set_rate_and_parent, +}; + static const struct clk_parent_data osc_24m_clk[] =3D { { .index =3D 0 } }; @@ -672,7 +743,8 @@ static const struct clk_parent_data c910_i0_parents[] = =3D { static struct ccu_mux c910_i0_clk =3D { .clkid =3D CLK_C910_I0, .reg =3D 0x100, - .mux =3D TH_CCU_MUX("c910-i0", c910_i0_parents, 1, 1), + .mux =3D TH_CCU_MUX_FLAGS("c910-i0", c910_i0_parents, 1, 1, + CLK_SET_RATE_PARENT, CLK_MUX_ROUND_CLOSEST), }; =20 static const struct clk_parent_data c910_parents[] =3D { @@ -683,7 +755,14 @@ static const struct clk_parent_data c910_parents[] =3D= { static struct ccu_mux c910_clk =3D { .clkid =3D CLK_C910, .reg =3D 0x100, - .mux =3D TH_CCU_MUX("c910", c910_parents, 0, 1), + .mux =3D { + .mask =3D BIT(0), + .shift =3D 0, + .hw.init =3D CLK_HW_INIT_PARENTS_DATA("c910", + c910_parents, + &c910_clk_ops, + CLK_SET_RATE_PARENT), + }, }; =20 static struct ccu_div c910_bus_clk =3D { @@ -1372,11 +1451,69 @@ static const struct th1520_plat_data th1520_vo_plat= data =3D { .nr_gate_clks =3D ARRAY_SIZE(th1520_vo_gate_clks), }; =20 +/* + * Maintain clock rate of c910_bus_clk below TH1520_C910_BUS_MAX_RATE (750= MHz) + * when its parent, c910_clk, changes the rate. + * + * Additionally, TRM is unclear about c910_bus_clk behavior with divisor s= et to + * 2, thus we should ensure the new divisor stays in (2, MAXDIVISOR). + */ +static unsigned long c910_bus_clk_divisor(struct ccu_div *cd, + unsigned long parent_rate) +{ + return clamp(DIV_ROUND_UP(parent_rate, TH1520_C910_BUS_MAX_RATE), + 2U, 1U << cd->div.width); +} + +static int c910_clk_notifier_cb(struct notifier_block *nb, + unsigned long action, void *data) +{ + struct clk_notifier_data *cnd =3D data; + unsigned long new_divisor, ref_rate; + + if (action !=3D PRE_RATE_CHANGE && action !=3D POST_RATE_CHANGE) + return NOTIFY_DONE; + + new_divisor =3D c910_bus_clk_divisor(&c910_bus_clk, cnd->new_rate); + + if (cnd->new_rate > cnd->old_rate) { + /* + * Scaling up. Adjust c910_bus_clk divisor + * - before c910_clk rate change to ensure the constraints + * aren't broken after scaling to higher rates, + * - after c910_clk rate change to keep c910_bus_clk as high as + * possible + */ + ref_rate =3D action =3D=3D PRE_RATE_CHANGE ? + cnd->old_rate : cnd->new_rate; + clk_set_rate(c910_bus_clk.common.hw.clk, + ref_rate / new_divisor); + } else if (cnd->new_rate < cnd->old_rate && + action =3D=3D POST_RATE_CHANGE) { + /* + * Scaling down. Adjust c910_bus_clk divisor only after + * c910_clk rate change to keep c910_bus_clk as high as + * possible, Scaling down never breaks the constraints. + */ + clk_set_rate(c910_bus_clk.common.hw.clk, + cnd->new_rate / new_divisor); + } else { + return NOTIFY_DONE; + } + + return NOTIFY_OK; +} + +static struct notifier_block c910_clk_notifier =3D { + .notifier_call =3D c910_clk_notifier_cb, +}; + static int th1520_clk_probe(struct platform_device *pdev) { const struct th1520_plat_data *plat_data; struct device *dev =3D &pdev->dev; struct clk_hw_onecell_data *priv; + struct clk *notifier_clk; =20 struct regmap *map; void __iomem *base; @@ -1463,6 +1600,13 @@ static int th1520_clk_probe(struct platform_device *= pdev) ret =3D devm_clk_hw_register(dev, &emmc_sdio_ref_clk.hw); if (ret) return ret; + + notifier_clk =3D devm_clk_hw_get_clk(dev, &c910_clk.mux.hw, + "dvfs"); + ret =3D devm_clk_notifier_register(dev, notifier_clk, + &c910_clk_notifier); + if (ret) + return ret; } =20 ret =3D devm_of_clk_add_hw_provider(dev, of_clk_hw_onecell_get, priv); --=20 2.51.2 From nobody Tue Dec 2 01:51:39 2025 Received: from layka.disroot.org (layka.disroot.org [178.21.23.139]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 7A60533123E; Thu, 20 Nov 2025 13:17:16 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=178.21.23.139 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1763644638; cv=none; b=ldRBqJLXvR3ursyQXqLWohBhxGnlUqZtDb6wy3P/711Ax8mPjeInxChhym0o4Hzoxi6RRX1j4W5s31RC0GkFy/Mt2teEF9f/DNS9KICLMQa/ua27XX+Z6yO+JE3hGBSxa23kBWpb+98TeoEcXX23IeBv03TT5UDLW9JxNJI+AJo= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1763644638; c=relaxed/simple; bh=rzsceNVsLgNTO+X00rj3Tf+eMe4kMyO3UMkIeEbat4c=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=bS59lB9l96gZYdhjD+PkTfMAfadqnrlrpEi94jtnQGbnZ+OO4bknq/tZaoTdw7Vrzt3BzmNPsg1f3X7XkR2Pn9bS4T589zb0xZQAUHnYpGoS6bO7Amq+u8nAmi4T3X1NecR7GPudCtu/scDL5jPZA6f6kpkD+himD7U0W4bEBlk= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=reject dis=none) header.from=disroot.org; spf=pass smtp.mailfrom=disroot.org; dkim=pass (2048-bit key) header.d=disroot.org header.i=@disroot.org header.b=hvu/z7cM; arc=none smtp.client-ip=178.21.23.139 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=reject dis=none) header.from=disroot.org Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=disroot.org Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=disroot.org header.i=@disroot.org header.b="hvu/z7cM" Received: from mail01.disroot.lan (localhost [127.0.0.1]) by disroot.org (Postfix) with ESMTP id 0C6962617B; Thu, 20 Nov 2025 14:17:15 +0100 (CET) X-Virus-Scanned: SPAM Filter at disroot.org Received: from layka.disroot.org ([127.0.0.1]) by localhost (disroot.org [127.0.0.1]) (amavis, port 10024) with ESMTP id fPVi9DDBgPin; Thu, 20 Nov 2025 14:17:14 +0100 (CET) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=disroot.org; s=mail; t=1763644634; bh=rzsceNVsLgNTO+X00rj3Tf+eMe4kMyO3UMkIeEbat4c=; h=From:To:Cc:Subject:Date:In-Reply-To:References; b=hvu/z7cMM9B466fCNUlVTJJ+1uxXSmsnHKCwjPlaWNy3Q67leBSvyfLkAnO46Crrm 4WyXMBl9RniFGROU0WXmQQ0jjpDIoI8BrAr7SKyd5lTZSVY8ACxuo3FXFJ8OK+9elt 75F+5pGPX+Gyj8PAC+Equ6yaGDEJrXRBciCMP6IqGkvcnkXj+HrsXhqNPUn4ohLPpU VhbXeoqQq5qvn/BYvS/ya3foz9SJNa+Ge5bBlmSWmBYUOg63t8MemJBao8NIbdYIl/ +TC1O1C26J79C0OkR+iKa2/y7KKz7/x5pGPgxmDfPkaUqDX31TJZbkZZzhxAVCtWYS 8YHyWOdnZZnHw== From: Yao Zi To: Drew Fustini , Guo Ren , Fu Wei , Rob Herring , Krzysztof Kozlowski , Conor Dooley , Paul Walmsley , Palmer Dabbelt , Albert Ou , Alexandre Ghiti , Michael Turquette , Stephen Boyd , Icenowy Zheng Cc: linux-riscv@lists.infradead.org, devicetree@vger.kernel.org, linux-kernel@vger.kernel.org, linux-clk@vger.kernel.org, Han Gao , Han Gao , Yao Zi Subject: [PATCH 7/7] [Not For Upstream] riscv: dts: thead: Add CPU clock and OPP table for TH1520 Date: Thu, 20 Nov 2025 13:14:16 +0000 Message-ID: <20251120131416.26236-8-ziyao@disroot.org> In-Reply-To: <20251120131416.26236-1-ziyao@disroot.org> References: <20251120131416.26236-1-ziyao@disroot.org> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset="utf-8" Add operating point table for CPU cores, and wire up clocks for CPU nodes. This patch isn't intended for upstreaming but only for testing purpose, since the PMIC driver for scaling CPU voltage isn't ready yet. Only operating points whose voltage is satisified by Lichee Module 4A's PMIC default, i.e. <=3D 1.5GHz, are enabled. Signed-off-by: Yao Zi --- arch/riscv/boot/dts/thead/th1520.dtsi | 35 +++++++++++++++++++++++++++ 1 file changed, 35 insertions(+) diff --git a/arch/riscv/boot/dts/thead/th1520.dtsi b/arch/riscv/boot/dts/th= ead/th1520.dtsi index bd5d33840884..6020d568ad7c 100644 --- a/arch/riscv/boot/dts/thead/th1520.dtsi +++ b/arch/riscv/boot/dts/thead/th1520.dtsi @@ -38,6 +38,8 @@ c910_0: cpu@0 { d-cache-sets =3D <512>; next-level-cache =3D <&l2_cache>; mmu-type =3D "riscv,sv39"; + operating-points-v2 =3D <&cpu_opp>; + clocks =3D <&clk CLK_C910>; =20 cpu0_intc: interrupt-controller { compatible =3D "riscv,cpu-intc"; @@ -65,6 +67,8 @@ c910_1: cpu@1 { d-cache-sets =3D <512>; next-level-cache =3D <&l2_cache>; mmu-type =3D "riscv,sv39"; + operating-points-v2 =3D <&cpu_opp>; + clocks =3D <&clk CLK_C910>; =20 cpu1_intc: interrupt-controller { compatible =3D "riscv,cpu-intc"; @@ -92,6 +96,8 @@ c910_2: cpu@2 { d-cache-sets =3D <512>; next-level-cache =3D <&l2_cache>; mmu-type =3D "riscv,sv39"; + operating-points-v2 =3D <&cpu_opp>; + clocks =3D <&clk CLK_C910>; =20 cpu2_intc: interrupt-controller { compatible =3D "riscv,cpu-intc"; @@ -119,6 +125,8 @@ c910_3: cpu@3 { d-cache-sets =3D <512>; next-level-cache =3D <&l2_cache>; mmu-type =3D "riscv,sv39"; + operating-points-v2 =3D <&cpu_opp>; + clocks =3D <&clk CLK_C910>; =20 cpu3_intc: interrupt-controller { compatible =3D "riscv,cpu-intc"; @@ -137,6 +145,33 @@ l2_cache: l2-cache { }; }; =20 + cpu_opp: opp-table-cpu { + compatible =3D "operating-points-v2"; + opp-shared; + + opp-300000000 { + opp-hz =3D /bits/ 64 <300000000>; + opp-microvolt =3D <600000>; + }; + + opp-800000000 { + opp-hz =3D /bits/ 64 <800000000>; + opp-microvolt =3D <700000>; + }; + + opp-1500000000 { + opp-hz =3D /bits/ 64 <1500000000>; + opp-microvolt =3D <800000>; + }; + +/* + opp-1848000000 { + opp-hz =3D /bits/ 64 <1848000000>; + opp-microvolt =3D <1000000>; + }; + */ + }; + pmu { compatible =3D "riscv,pmu"; riscv,event-to-mhpmcounters =3D --=20 2.51.2