From nobody Sun Oct 5 07:21:19 2025 Received: from smtpbgsg1.qq.com (smtpbgsg1.qq.com [54.254.200.92]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 333BA17A2EA; Thu, 7 Aug 2025 01:31:08 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=54.254.200.92 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1754530274; cv=none; b=D75g/FhFJUSoFJRzPWUckJppksUOfmEgc4tloe9D884nQL9avyU7tPWrsWHpuEHxEe3AOev0p7sGelM4aJw//eZHoUdd3ZCskSZgh1znT0usr0QhwO0HnnGQW0rpDWNEMkoMhJXr3E/AzaW/cWeVzoJegT/SXY2IlbgxjBk2aVk= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1754530274; c=relaxed/simple; bh=sxGnfSSFz+QDwg50EXWstYMedLLmqKm28v9mT9MsQQQ=; h=From:Date:Subject:MIME-Version:Content-Type:Message-Id:References: In-Reply-To:To:Cc; b=eCuWCFA9C8EAEDlsQd/nGonUrd09/YfQMRfl/zYtaAVew+VHRL9Iw1hew2OeZFmNSU2KPo9xizjPSi9Ed5wOoSyIVsivKd3OW/U0Ka5+Od5swog8WHi21/nZ9MKxSmWbAsbUzpM+S/Ga/d55yiUPg7PfZvoFB6aUZ4CmSQhk1zs= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=none (p=none dis=none) header.from=linux.spacemit.com; spf=none smtp.mailfrom=linux.spacemit.com; dkim=pass (1024-bit key) header.d=linux.spacemit.com header.i=@linux.spacemit.com header.b=ospKx1Jv; arc=none smtp.client-ip=54.254.200.92 Authentication-Results: smtp.subspace.kernel.org; dmarc=none (p=none dis=none) header.from=linux.spacemit.com Authentication-Results: smtp.subspace.kernel.org; spf=none smtp.mailfrom=linux.spacemit.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (1024-bit key) header.d=linux.spacemit.com header.i=@linux.spacemit.com header.b="ospKx1Jv" DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=linux.spacemit.com; s=mxsw2412; t=1754530218; bh=iu88a8ay7VG2RXEtKM0gyJ25kHT+aTDCXwwaMilECgs=; h=From:Date:Subject:MIME-Version:Message-Id:To; b=ospKx1JvFchuu1v0OOBB5cntvdj44pPeeEFayP8p5UNWqe/9f7JiSgBJg4cNYgMam Mo6rntEXtT3tAmLrMNU1xWodHkVvd4sbL+OjYSLxBGa+ht9STACG3SYJKB1Eo+0z+P usMeCPBgDtM5aZYNhK8OB8/zUyDbLYHTPZFLE6jo= X-QQ-mid: esmtpsz19t1754530216t1fe22e97 X-QQ-Originating-IP: XufVyFBFlZPw5gqLYgT9DkQ/sMxsFpvomT926UJMoXo= Received: from = ( [61.145.255.150]) by bizesmtp.qq.com (ESMTP) with id ; Thu, 07 Aug 2025 09:30:13 +0800 (CST) X-QQ-SSF: 0000000000000000000000000000000 X-QQ-GoodBg: 0 X-BIZMAIL-ID: 11800184382334055400 EX-QQ-RecipientCnt: 16 From: Troy Mitchell Date: Thu, 07 Aug 2025 09:30:10 +0800 Subject: [PATCH 1/2] dt-bindings: clock: spacemit: introduce i2s pre-clock Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: quoted-printable Message-Id: <20250807-k1-clk-i2s-generation-v1-1-7dc25eb4e4d3@linux.spacemit.com> References: <20250807-k1-clk-i2s-generation-v1-0-7dc25eb4e4d3@linux.spacemit.com> In-Reply-To: <20250807-k1-clk-i2s-generation-v1-0-7dc25eb4e4d3@linux.spacemit.com> To: Michael Turquette , Stephen Boyd , Rob Herring , Krzysztof Kozlowski , Conor Dooley , Yixun Lan , Alex Elder , Haylen Chu , Inochi Amaoto Cc: linux-clk@vger.kernel.org, devicetree@vger.kernel.org, linux-riscv@lists.infradead.org, spacemit@lists.linux.dev, linux-kernel@vger.kernel.org, Jinmei Wei , Troy Mitchell X-Mailer: b4 0.14.2 X-Developer-Signature: v=1; a=ed25519-sha256; t=1754530210; l=1005; i=troy.mitchell@linux.spacemit.com; s=20250710; h=from:subject:message-id; bh=sxGnfSSFz+QDwg50EXWstYMedLLmqKm28v9mT9MsQQQ=; b=c1WOPEprEFuqX1JuniBPzz1BLPQLK7s+QSaEugX2PSJ5Y4cTmYrzwo7Ci+k3rDHuMf1xlYrpe Jwb3/qeiY+tCfgtzx7K2OAYGp3FBvXZJ4RuOEsXF/dzUQIWTBF3SpqF X-Developer-Key: i=troy.mitchell@linux.spacemit.com; a=ed25519; pk=lQa7BzLrq8DfZnChqmwJ5qQk8fP2USmY/4xZ2/MSsXc= X-QQ-SENDSIZE: 520 Feedback-ID: esmtpsz:linux.spacemit.com:qybglogicsvrsz:qybglogicsvrsz3a-0 X-QQ-XMAILINFO: Mfm8HKGnOlI92RkV1m9AeUnXPV4O3FJ3PiHC0qsdtcuZNsl1anctGK8c 98dj0xNS/Dl6tOtmbTNB6vynzqMJwRLbVXj7DIX4uKErRK0Y/n9GJTYwBJ07BLBh9yaEliy B9AvYLCjd6yU8pEoYF3R19OFXR0LTqdKy5O0P8bso/Z0oScv8rlehqrSqx8EggqIpawwYfL l/n/cMdTDGm045bnTD3kSUzCqukhOEceFUAcr7ci7WZBjP+L8Za29OdrC6jdPUVW9xsZ6hi 9UHRJdLflfl5vo2RhrZ59Ax2GEATw4NoLgBXDsmQIfCtti2t9eYfaIrH8NAe1zrDeA78JnR x37D8dn9N2WvNzX+biS+6J+ClhqqerK22LULm2cvH2Pi9L5M1O0N7Ds2UA/4kcCgUAQSwUO b5DboQ+c/sqgbBGoqkUifcNyybhw8ltP3QfG9MJHf76RCs1NmnWmI6+8pGPUuDcLelH1U+Y CjaASy3vynaicB6n8HNnXgLDWuChyxI6rMer40gcDwZtIqxS2vMOZ4n+QjzkfKDafpbr1nt 2TUXW5inMozAf72iMQWNPosPlyTEcG+yXiSpSYdzPjjG/n3tspyfHhbhTRIC+2M9f6Yp21U xaxMXn7hOmHczCYegEHdHG/B5rpfuqkw7iREEIOaT7lf1VJmHe2hR0DE4XBtRxGyoQvYblL eMAaSfe0w7i45Vla99RlLVEdoCD+YzhUVbMy76q7XlVf6X8PS1PxFLT3ccphqy/YEQa2tww hYmIUfCU8dC3ABr9DCbrzdqjZV3GPZ9Zsp6z1VRdW695J4QzS376lGEn3Hnv57q6Bju43Rw koBUEH3xrGEOCxflaA+x9hP9CX5PkDfY+QqlC2UdPR//moAWQ4WNP3UW0Wt7a3mXpUdUwty V/qN6RsMEPovRTYhIhZNNJw2xJCsa5Io/KdXqB0OpRryAUkeIiyiZSsPgZA9oM3eVKfztPW H3G8fnkKoszmfy4bNgQn2VVrobHHhVDdLo8b2DKoMgNdpJMXDJJ8eQrdGHGhoA2DgImvfNL XkTrNwLQUMk0zlWkbLHpKZ1zWnVNZr/64zXX6oxlyCGk0sbiqRcnJ99dF3UUrk8leVXt7Rn a7ddoS6md2JVnU8XgOUfLFf8zK//aCaCd7+jEkK1NmUmFgvushjgzA= X-QQ-XMRINFO: OD9hHCdaPRBwq3WW+NvGbIU= X-QQ-RECHKSPAM: 0 Previously, the K1 clock driver did not include the parent clocks of the I2S sysclk. This patch adds their definitions to allow proper registration in the driver and usage in the device tree. Fixes: 1b72c59db0add ("clk: spacemit: Add clock support for SpacemiT K1 SoC= ") Signed-off-by: Troy Mitchell --- include/dt-bindings/clock/spacemit,k1-syscon.h | 3 +++ 1 file changed, 3 insertions(+) diff --git a/include/dt-bindings/clock/spacemit,k1-syscon.h b/include/dt-bi= ndings/clock/spacemit,k1-syscon.h index 2714c3fe66cd5b49e12c8b20689f5b01da36b774..524268246fedd3f1238320f3524= 4baf32354fbd2 100644 --- a/include/dt-bindings/clock/spacemit,k1-syscon.h +++ b/include/dt-bindings/clock/spacemit,k1-syscon.h @@ -77,6 +77,9 @@ #define CLK_I2S_BCLK 30 #define CLK_APB 31 #define CLK_WDT_BUS 32 +#define CLK_I2S_153P6 33 +#define CLK_I2S_153P6_BASE 34 +#define CLK_I2S_SYSCLK_SRC 35 =20 /* MPMU resets */ #define RESET_WDT 0 --=20 2.50.1 From nobody Sun Oct 5 07:21:19 2025 Received: from smtpbgjp3.qq.com (smtpbgjp3.qq.com [54.92.39.34]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 718AA1B425C; Thu, 7 Aug 2025 01:31:21 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=54.92.39.34 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1754530287; cv=none; b=gJZnNaxAjNvp4CV/ZJjYyun3zkgnXaplW/UziC6K0fLyjGykxCltXWDIogFoEdR2YEzmJ8o+ipNco+m2XFyhUjfgUMglIQuwmjnz4TbN0h5WHphlJ7KkG6oGdoiQ4+DD4iaqyZN7u2YKZTbvjOXRlHs2zNRtM94fTvFgzhPqxU0= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1754530287; c=relaxed/simple; bh=AbRB8J+EX7w4nB5/nq9KzAMM0hccGR6tSSToSFDQWvI=; h=From:Date:Subject:MIME-Version:Content-Type:Message-Id:References: In-Reply-To:To:Cc; b=mRB3FyvU2/oVoQlOkRPvx/j5v1RgCgwZ1u7HMr1sxzjnVSPsfjEAcnrk3T2J49agE+beYEFB22vmLUCdU5Su4aZ6+DgDFbhRcFD7EB+E2MGXa/1rcDmFE/Z2gUARrgvBsNu4UOztOrlC/Xb26nBtBABPCy5aXQINzRt4pMGKSC0= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=none (p=none dis=none) header.from=linux.spacemit.com; spf=none smtp.mailfrom=linux.spacemit.com; dkim=pass (1024-bit key) header.d=linux.spacemit.com header.i=@linux.spacemit.com header.b=kjGoNI0W; arc=none smtp.client-ip=54.92.39.34 Authentication-Results: smtp.subspace.kernel.org; dmarc=none (p=none dis=none) header.from=linux.spacemit.com Authentication-Results: smtp.subspace.kernel.org; spf=none smtp.mailfrom=linux.spacemit.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (1024-bit key) header.d=linux.spacemit.com header.i=@linux.spacemit.com header.b="kjGoNI0W" DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=linux.spacemit.com; s=mxsw2412; t=1754530221; bh=OU44WJoeZAKubf492SsoWRsfQCJn8pRFYEpU+6pMfV0=; h=From:Date:Subject:MIME-Version:Message-Id:To; b=kjGoNI0WrYAe8XSNYp8kY8BdnpDcFG28vffumiAt+OFKHQ6oeq72baF738lJNEhoi bcui1Lqt24sj0a+1DlULYqFgMos8Km0L14jd6I5IgwlapBBTL97bvoIkauHLuLJFmb nkO8IVz1oilW4E8An3FBOBmmcW/w++5+Ay25QxiA= X-QQ-mid: zesmtpsz2t1754530220t3a52aed6 X-QQ-Originating-IP: WL/WEHYpKq10uOstCy9jPUNzhYSHHI7doG4J4mJvHeg= Received: from = ( [61.145.255.150]) by bizesmtp.qq.com (ESMTP) with id ; Thu, 07 Aug 2025 09:30:17 +0800 (CST) X-QQ-SSF: 0000000000000000000000000000000 X-QQ-GoodBg: 0 X-BIZMAIL-ID: 2328846353165535244 EX-QQ-RecipientCnt: 16 From: Troy Mitchell Date: Thu, 07 Aug 2025 09:30:11 +0800 Subject: [PATCH 2/2] clk: spacemit: introduce i2s pre-clock and fix i2s clock Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: quoted-printable Message-Id: <20250807-k1-clk-i2s-generation-v1-2-7dc25eb4e4d3@linux.spacemit.com> References: <20250807-k1-clk-i2s-generation-v1-0-7dc25eb4e4d3@linux.spacemit.com> In-Reply-To: <20250807-k1-clk-i2s-generation-v1-0-7dc25eb4e4d3@linux.spacemit.com> To: Michael Turquette , Stephen Boyd , Rob Herring , Krzysztof Kozlowski , Conor Dooley , Yixun Lan , Alex Elder , Haylen Chu , Inochi Amaoto Cc: linux-clk@vger.kernel.org, devicetree@vger.kernel.org, linux-riscv@lists.infradead.org, spacemit@lists.linux.dev, linux-kernel@vger.kernel.org, Jinmei Wei , Troy Mitchell X-Mailer: b4 0.14.2 X-Developer-Signature: v=1; a=ed25519-sha256; t=1754530210; l=15324; i=troy.mitchell@linux.spacemit.com; s=20250710; h=from:subject:message-id; bh=AbRB8J+EX7w4nB5/nq9KzAMM0hccGR6tSSToSFDQWvI=; b=bhuT5D5DQiZs2uGLUV+UtbwyM8Z1Pnbdv9yBsc+azvRH1R9FEwbAnbIrSTBhx/mvyRclgWXuJ P6koTDZiiMUCgHmmhW1cSuPq33n4k7qvJInmC4ygmaF+RskyOtnE5ZF X-Developer-Key: i=troy.mitchell@linux.spacemit.com; a=ed25519; pk=lQa7BzLrq8DfZnChqmwJ5qQk8fP2USmY/4xZ2/MSsXc= X-QQ-SENDSIZE: 520 Feedback-ID: zesmtpsz:linux.spacemit.com:qybglogicsvrsz:qybglogicsvrsz3a-0 X-QQ-XMAILINFO: OAf9apBnkUx3nmGJmOzgOJ0+o6d5i/mnT2DXBe+UwC1DeHsT4SRMlmUb CVxUTDXfVH07/CqUYwkqP3SogR+s5y1D+0BB6yPiBjgUUr6RDX08riMWNEdviH8DGL9kzHA LV9TCMVOI/J83/iYWmyFX1CWhIR8Ze2d01jAPOS199bfQ4i5PJiGb5tCe5Tb6qe4jICYK3r PaTFBcZv27LzCr8cEl/cj+EMU0ovhPpajPfPl8zpetCGiwt2a13uxXjLTEo8LMxbA/CbhFH a5i+9vn926rHK12sx0E8W4K4Nquh48opVyk741T/r/kScyBbnDBz9prd75N39wATo0mLXIo 8XRraflZIyZe+lLX4hprB+D0Ada59dqO2t1AgGbs7M3bxbNTCBhtbVrZkqNT70Ie7r7T3Yc Q1Iv4QIK9yt62MrQhHjtefqMVr//WrUvwt/Ctp4Y0TKRXZNmssgCoWuJhmIHKDMmweGP1Yo k9tvkZWl4jhOV17pyYCXHMI1DjNsAFyAL7bmjQvFAG3M5sQJ8OigpwZ2D62/8HDiyISKFWm y92UaYuIPqc0gvIXLCCiKjoS9GVPeuayGFQyHZMWodt9cQUCGLLFbsakWE8X2yRH5usOrxD Qu4fBK8BBEDqwRrYBNaVPEc2i7GFUiwNyjfthuL3rzOoF9N5oH+7lt6ODok8YSG0iUMc4Ns UfP1GB7dXWwF1JhT0R6rFgpO3jp4xocBJgwWDRMIND2RxQIkukKy9RWpPOrbSgwzFWhHLR7 sE6bM+BHajblu7OTm6pwQI0MiDpDQiIAkZnT5L1kD/uXlyxORtRt2nMUzy40Aqc0oSyTmCI YZICV3xnXxoAb16BIO6YEIZfewQVJk2v0rVV2D59E6p1MF5hCv8feDRLfZGq842CFQoo1MX BCcbctqXEmaFWuJwc43NoNPfN3Lj/J6mT0T6n7VJRi68gJeh4o/lCBc3dFNe9155BHOGm71 Xvugb0hVAt6xJnHjd5j35guqCkTi5cnXmyLxxpoSk4YwU+Q82VvkxGTlzvw4d4xpaMWwY1H /cSXA8nlyTy+b63YfwBnCdFutTo7xIKa+m+lqdR8ta2hfjbUnrM22Grn+vVAdu0CE8MYOFD Gl/ziGwYLuTVRAQdpQZHXVgr9ARPR31XwTEXyP5tV6qWT/EwMvrmXQ= X-QQ-XMRINFO: NS+P29fieYNw95Bth2bWPxk= X-QQ-RECHKSPAM: 0 Defining i2s_bclk and i2s_sysclk as fixed-rate clocks is insufficient for real I2S use cases. Moreover, the current I2S clock configuration does not work as expected due to missing parent clocks. This patch adds the missing parent clocks, defines i2s_sysclk as a DDN clock, and i2s_bclk as a DIV clock. The i2s_sysclk behaves as an M/N fractional divider in hardware, with an additional gate control. To properly model this, CCU_DDN_GATE_DEFINE is introduced. The original DDN operations applied an implicit divide-by-2, which should not be a default behavior. This patch removes that assumption, letting each clock define its actual behavior explicitly. The i2s_bclk is a non-linear, discrete divider clock. The previous macro only supported linear dividers, so CCU_DIV_TABLE_GATE_DEFINE is introduced to support the hardware accurately. The I2S-related clock registers can be found here [1]. Link: https://developer.spacemit.com/documentation?token=3DLCrKwWDasiJuROkVNusc2p= WTnEb [1] Fixes: 1b72c59db0add ("clk: spacemit: Add clock support for SpacemiT K1 SoC= ") Co-developer: Jinmei Wei Signed-off-by: Jinmei Wei Signed-off-by: Troy Mitchell --- drivers/clk/spacemit/ccu-k1.c | 34 ++++++++++++++++++++++++---- drivers/clk/spacemit/ccu_common.h | 13 +++++++++++ drivers/clk/spacemit/ccu_ddn.c | 47 ++++++++++++++++++++++++++++++++++-= ---- drivers/clk/spacemit/ccu_ddn.h | 25 +++++++++++++++++++-- drivers/clk/spacemit/ccu_mix.c | 47 +++++++++++++++++++++++++++++------= ---- drivers/clk/spacemit/ccu_mix.h | 26 +++++++++++++--------- include/soc/spacemit/k1-syscon.h | 7 +++--- 7 files changed, 161 insertions(+), 38 deletions(-) diff --git a/drivers/clk/spacemit/ccu-k1.c b/drivers/clk/spacemit/ccu-k1.c index 65e6de030717afa60eefab7bda88f9a13b857650..a6773d4c2ff32d270e1f09b0d93= cfff727ea98fa 100644 --- a/drivers/clk/spacemit/ccu-k1.c +++ b/drivers/clk/spacemit/ccu-k1.c @@ -136,13 +136,36 @@ CCU_GATE_DEFINE(pll1_d3_819p2, CCU_PARENT_HW(pll1_d3)= , MPMU_ACGR, BIT(14), 0); CCU_GATE_DEFINE(pll1_d2_1228p8, CCU_PARENT_HW(pll1_d2), MPMU_ACGR, BIT(16)= , 0); =20 CCU_GATE_DEFINE(slow_uart, CCU_PARENT_NAME(osc), MPMU_ACGR, BIT(1), CLK_IG= NORE_UNUSED); -CCU_DDN_DEFINE(slow_uart1_14p74, pll1_d16_153p6, MPMU_SUCCR, 16, 13, 0, 13= , 0); -CCU_DDN_DEFINE(slow_uart2_48, pll1_d4_614p4, MPMU_SUCCR_1, 16, 13, 0, 13, = 0); +CCU_DDN_DEFINE(slow_uart1_14p74, pll1_d16_153p6, MPMU_SUCCR, 16, 13, 0, 13= , 2, 0); +CCU_DDN_DEFINE(slow_uart2_48, pll1_d4_614p4, MPMU_SUCCR_1, 16, 13, 0, 13, = 2, 0); =20 CCU_GATE_DEFINE(wdt_clk, CCU_PARENT_HW(pll1_d96_25p6), MPMU_WDTPCR, BIT(1)= , 0); =20 -CCU_FACTOR_GATE_DEFINE(i2s_sysclk, CCU_PARENT_HW(pll1_d16_153p6), MPMU_ISC= CR, BIT(31), 50, 1); -CCU_FACTOR_GATE_DEFINE(i2s_bclk, CCU_PARENT_HW(i2s_sysclk), MPMU_ISCCR, BI= T(29), 1, 1); +CCU_FACTOR_DEFINE(i2s_153p6, CCU_PARENT_HW(pll1_d8_307p2), 2, 1); + +static const struct clk_parent_data i2s_153p6_base_parents[] =3D { + CCU_PARENT_HW(i2s_153p6), + CCU_PARENT_HW(pll1_d8_307p2), +}; +CCU_MUX_DEFINE(i2s_153p6_base, i2s_153p6_base_parents, MPMU_FCCR, 29, 1, 0= ); + +static const struct clk_parent_data i2s_sysclk_src_parents[] =3D { + CCU_PARENT_HW(pll1_d96_25p6), + CCU_PARENT_HW(i2s_153p6_base) +}; +CCU_MUX_DEFINE(i2s_sysclk_src, i2s_sysclk_src_parents, MPMU_ISCCR, 30, 1, = 0); + +CCU_DDN_GATE_DEFINE(i2s_sysclk, i2s_sysclk_src, MPMU_ISCCR, 0, 15, 15, 12,= BIT(31), 1, 0); + +static const struct clk_div_table i2s_bclk_div_table[] =3D { + { .val =3D 0, .div =3D 2 }, + { .val =3D 1, .div =3D 4 }, + { .val =3D 2, .div =3D 6 }, + { .val =3D 3, .div =3D 8 }, + { /* sentinel */ }, +}; +CCU_DIV_TABLE_GATE_DEFINE(i2s_bclk, CCU_PARENT_HW(i2s_sysclk), MPMU_ISCCR, + 27, 2, i2s_bclk_div_table, BIT(29), 0); =20 static const struct clk_parent_data apb_parents[] =3D { CCU_PARENT_HW(pll1_d96_25p6), @@ -756,6 +779,9 @@ static struct clk_hw *k1_ccu_mpmu_hws[] =3D { [CLK_I2S_BCLK] =3D &i2s_bclk.common.hw, [CLK_APB] =3D &apb_clk.common.hw, [CLK_WDT_BUS] =3D &wdt_bus_clk.common.hw, + [CLK_I2S_153P6] =3D &i2s_153p6.common.hw, + [CLK_I2S_153P6_BASE] =3D &i2s_153p6_base.common.hw, + [CLK_I2S_SYSCLK_SRC] =3D &i2s_sysclk_src.common.hw, }; =20 static const struct spacemit_ccu_data k1_ccu_mpmu_data =3D { diff --git a/drivers/clk/spacemit/ccu_common.h b/drivers/clk/spacemit/ccu_c= ommon.h index da72f3836e0b5c3482ffbb32d9d0f7f9185bfb54..ebe225dcfaee9ae79915a0d0f6d= cbe8929038b3a 100644 --- a/drivers/clk/spacemit/ccu_common.h +++ b/drivers/clk/spacemit/ccu_common.h @@ -31,11 +31,24 @@ struct ccu_common { struct clk_hw hw; }; =20 + +/** + * struct ccu_gate_config - Gate configuration + * + * @mask: Mask to enable the gate. Some clocks may have more than one bit + * set in this field. + */ +struct ccu_gate_config { + u32 mask; +}; + static inline struct ccu_common *hw_to_ccu_common(struct clk_hw *hw) { return container_of(hw, struct ccu_common, hw); } =20 +#define CCU_GATE_INIT(_mask) { .mask =3D _mask } + #define ccu_read(c, reg) \ ({ \ u32 tmp; \ diff --git a/drivers/clk/spacemit/ccu_ddn.c b/drivers/clk/spacemit/ccu_ddn.c index be311b045698e95a688a35858a8ac1bcfbffd2c7..c2b19dcb1b35c5e2092e5930e53= 236443f1355a9 100644 --- a/drivers/clk/spacemit/ccu_ddn.c +++ b/drivers/clk/spacemit/ccu_ddn.c @@ -22,21 +22,46 @@ =20 #include "ccu_ddn.h" =20 -static unsigned long ccu_ddn_calc_rate(unsigned long prate, - unsigned long num, unsigned long den) +static void ccu_gate_disable(struct clk_hw *hw) { - return prate * den / 2 / num; + struct ccu_ddn *ddn =3D hw_to_ccu_ddn(hw); + + ccu_update(&ddn->common, ctrl, ddn->gate.mask, 0); +} + +static int ccu_gate_enable(struct clk_hw *hw) +{ + struct ccu_ddn *ddn =3D hw_to_ccu_ddn(hw); + struct ccu_gate_config *gate =3D &ddn->gate; + + ccu_update(&ddn->common, ctrl, gate->mask, gate->mask); + + return 0; +} + +static int ccu_gate_is_enabled(struct clk_hw *hw) +{ + struct ccu_ddn *ddn =3D hw_to_ccu_ddn(hw); + struct ccu_gate_config *gate =3D &ddn->gate; + + return (ccu_read(&ddn->common, ctrl) & gate->mask) =3D=3D gate->mask; +} + +static unsigned long ccu_ddn_calc_rate(unsigned long prate, unsigned long = num, + unsigned long den, unsigned int pre_div) +{ + return prate * den / pre_div / num; } =20 static unsigned long ccu_ddn_calc_best_rate(struct ccu_ddn *ddn, unsigned long rate, unsigned long prate, unsigned long *num, unsigned long *den) { - rational_best_approximation(rate, prate / 2, + rational_best_approximation(rate, prate / ddn->pre_div, ddn->den_mask >> ddn->den_shift, ddn->num_mask >> ddn->num_shift, den, num); - return ccu_ddn_calc_rate(prate, *num, *den); + return ccu_ddn_calc_rate(prate, *num, *den, ddn->pre_div); } =20 static long ccu_ddn_round_rate(struct clk_hw *hw, unsigned long rate, @@ -58,7 +83,7 @@ static unsigned long ccu_ddn_recalc_rate(struct clk_hw *h= w, unsigned long prate) num =3D (val & ddn->num_mask) >> ddn->num_shift; den =3D (val & ddn->den_mask) >> ddn->den_shift; =20 - return ccu_ddn_calc_rate(prate, num, den); + return ccu_ddn_calc_rate(prate, num, den, ddn->pre_div); } =20 static int ccu_ddn_set_rate(struct clk_hw *hw, unsigned long rate, @@ -81,3 +106,13 @@ const struct clk_ops spacemit_ccu_ddn_ops =3D { .round_rate =3D ccu_ddn_round_rate, .set_rate =3D ccu_ddn_set_rate, }; + +const struct clk_ops spacemit_ccu_ddn_gate_ops =3D { + .disable =3D ccu_gate_disable, + .enable =3D ccu_gate_enable, + .is_enabled =3D ccu_gate_is_enabled, + + .recalc_rate =3D ccu_ddn_recalc_rate, + .round_rate =3D ccu_ddn_round_rate, + .set_rate =3D ccu_ddn_set_rate, +}; diff --git a/drivers/clk/spacemit/ccu_ddn.h b/drivers/clk/spacemit/ccu_ddn.h index a52fabe77d62eba16426867a9c13481e72f025c0..e44fb93065ed99041003f235a4f= 6f42233020298 100644 --- a/drivers/clk/spacemit/ccu_ddn.h +++ b/drivers/clk/spacemit/ccu_ddn.h @@ -13,18 +13,22 @@ #include "ccu_common.h" =20 struct ccu_ddn { + struct ccu_gate_config gate; struct ccu_common common; unsigned int num_mask; unsigned int num_shift; unsigned int den_mask; unsigned int den_shift; + unsigned int pre_div; }; =20 #define CCU_DDN_INIT(_name, _parent, _flags) \ CLK_HW_INIT_HW(#_name, &_parent.common.hw, &spacemit_ccu_ddn_ops, _flags) +#define CCU_DDN_GATE_INIT(_name, _parent, _flags) \ + CLK_HW_INIT_HW(#_name, &_parent.common.hw, &spacemit_ccu_ddn_gate_ops, _f= lags) =20 #define CCU_DDN_DEFINE(_name, _parent, _reg_ctrl, _num_shift, _num_width, \ - _den_shift, _den_width, _flags) \ + _den_shift, _den_width, _pre_div, _flags) \ static struct ccu_ddn _name =3D { \ .common =3D { \ .reg_ctrl =3D _reg_ctrl, \ @@ -33,7 +37,23 @@ static struct ccu_ddn _name =3D { \ .num_mask =3D GENMASK(_num_shift + _num_width - 1, _num_shift), \ .num_shift =3D _num_shift, \ .den_mask =3D GENMASK(_den_shift + _den_width - 1, _den_shift), \ - .den_shift =3D _den_shift, \ + .den_shift =3D _den_shift, \ + .pre_div =3D _pre_div, \ +} + +#define CCU_DDN_GATE_DEFINE(_name, _parent, _reg_ctrl, _num_shift, _num_wi= dth, \ + _den_shift, _den_width, _mask_gate, _pre_div, _flags) \ +static struct ccu_ddn _name =3D { \ + .gate =3D CCU_GATE_INIT(_mask_gate), \ + .common =3D { \ + .reg_ctrl =3D _reg_ctrl, \ + .hw.init =3D CCU_DDN_GATE_INIT(_name, _parent, _flags), \ + }, \ + .num_mask =3D GENMASK(_num_shift + _num_width - 1, _num_shift), \ + .num_shift =3D _num_shift, \ + .den_mask =3D GENMASK(_den_shift + _den_width - 1, _den_shift), \ + .den_shift =3D _den_shift, \ + .pre_div =3D _pre_div, \ } =20 static inline struct ccu_ddn *hw_to_ccu_ddn(struct clk_hw *hw) @@ -44,5 +64,6 @@ static inline struct ccu_ddn *hw_to_ccu_ddn(struct clk_hw= *hw) } =20 extern const struct clk_ops spacemit_ccu_ddn_ops; +extern const struct clk_ops spacemit_ccu_ddn_gate_ops; =20 #endif diff --git a/drivers/clk/spacemit/ccu_mix.c b/drivers/clk/spacemit/ccu_mix.c index 9b852aa61f78aed5256bfe6fc3b01932d6db6256..183f56ccb92a63ab5f41fe09383= 6bebc73e4162f 100644 --- a/drivers/clk/spacemit/ccu_mix.c +++ b/drivers/clk/spacemit/ccu_mix.c @@ -56,7 +56,7 @@ static unsigned long ccu_div_recalc_rate(struct clk_hw *h= w, val =3D ccu_read(&mix->common, ctrl) >> div->shift; val &=3D (1 << div->width) - 1; =20 - return divider_recalc_rate(hw, parent_rate, val, NULL, 0, div->width); + return divider_recalc_rate(hw, parent_rate, val, div->table, 0, div->widt= h); } =20 /* @@ -92,6 +92,28 @@ static int ccu_factor_set_rate(struct clk_hw *hw, unsign= ed long rate, return 0; } =20 +static void ccu_mix_try_update_best(unsigned long tmp_rate, unsigned long = rate, + unsigned long *best_rate, u32 tmp_val, + u32 *div_val, struct clk_hw *parent, + struct clk_hw **best_parent, + unsigned long *best_parent_rate) +{ + if (abs(tmp_rate - rate) < abs(*best_rate - rate)) { + *best_rate =3D tmp_rate; + + if (div_val) + *div_val =3D tmp_val; + + if (!best_parent) + return; + + *best_parent =3D parent; + if (best_parent_rate) + *best_parent_rate =3D clk_hw_get_rate(parent); + } +} + + static unsigned long ccu_mix_calc_best_rate(struct clk_hw *hw, unsigned long rate, struct clk_hw **best_parent, @@ -113,20 +135,21 @@ ccu_mix_calc_best_rate(struct clk_hw *hw, unsigned lo= ng rate, =20 parent_rate =3D clk_hw_get_rate(parent); =20 - for (int j =3D 1; j <=3D div_max; j++) { - unsigned long tmp =3D DIV_ROUND_CLOSEST_ULL(parent_rate, j); + if (div->table) { + int tmp_val =3D divider_get_val(rate, parent_rate, div->table, div->wid= th, 0); + unsigned long tmp_rate =3D divider_recalc_rate(hw, parent_rate, tmp_val, + div->table, 0, div->width); =20 - if (abs(tmp - rate) < abs(best_rate - rate)) { - best_rate =3D tmp; + ccu_mix_try_update_best(tmp_rate, rate, &best_rate, tmp_val, + div_val, parent, best_parent, best_parent_rate); + continue; + } =20 - if (div_val) - *div_val =3D j - 1; + for (int j =3D 1; j <=3D div_max; j++) { + unsigned long tmp =3D DIV_ROUND_CLOSEST_ULL(parent_rate, j); =20 - if (best_parent) { - *best_parent =3D parent; - *best_parent_rate =3D parent_rate; - } - } + ccu_mix_try_update_best(tmp, rate, &best_rate, j - 1, + div_val, parent, best_parent, best_parent_rate); } } =20 diff --git a/drivers/clk/spacemit/ccu_mix.h b/drivers/clk/spacemit/ccu_mix.h index 54d40cd39b2752260f57d2a96eb8d3eed8116ecd..e93142f74458c0d91394c86d73f= 64e1521a17913 100644 --- a/drivers/clk/spacemit/ccu_mix.h +++ b/drivers/clk/spacemit/ccu_mix.h @@ -11,16 +11,6 @@ =20 #include "ccu_common.h" =20 -/** - * struct ccu_gate_config - Gate configuration - * - * @mask: Mask to enable the gate. Some clocks may have more than one bit - * set in this field. - */ -struct ccu_gate_config { - u32 mask; -}; - struct ccu_factor_config { u32 div; u32 mul; @@ -34,6 +24,7 @@ struct ccu_mux_config { struct ccu_div_config { u8 shift; u8 width; + const struct clk_div_table *table; }; =20 struct ccu_mix { @@ -44,10 +35,11 @@ struct ccu_mix { struct ccu_common common; }; =20 -#define CCU_GATE_INIT(_mask) { .mask =3D _mask } #define CCU_FACTOR_INIT(_div, _mul) { .div =3D _div, .mul =3D _mul } #define CCU_MUX_INIT(_shift, _width) { .shift =3D _shift, .width =3D _widt= h } #define CCU_DIV_INIT(_shift, _width) { .shift =3D _shift, .width =3D _widt= h } +#define CCU_DIV_TABLE_INIT(_shift, _width, _table) \ + { .shift =3D _shift, .width =3D _width, .table =3D _table} =20 #define CCU_PARENT_HW(_parent) { .hw =3D &_parent.common.hw } #define CCU_PARENT_NAME(_name) { .fw_name =3D #_name } @@ -141,6 +133,18 @@ static struct ccu_mix _name =3D { \ } \ } =20 +#define CCU_DIV_TABLE_GATE_DEFINE(_name, _parent, _reg_ctrl, _shift, _widt= h, \ + _table, _mask_gate, _flags) \ +static struct ccu_mix _name =3D { \ + .gate =3D CCU_GATE_INIT(_mask_gate), \ + .div =3D CCU_DIV_TABLE_INIT(_shift, _width, _table), \ + .common =3D { \ + .reg_ctrl =3D _reg_ctrl, \ + CCU_MIX_INITHW(_name, _parent, spacemit_ccu_div_gate_ops, \ + _flags), \ + } \ +} + #define CCU_MUX_DIV_GATE_DEFINE(_name, _parents, _reg_ctrl, _mshift, _mwid= th, \ _muxshift, _muxwidth, _mask_gate, _flags) \ static struct ccu_mix _name =3D { \ diff --git a/include/soc/spacemit/k1-syscon.h b/include/soc/spacemit/k1-sys= con.h index c59bd7a38e5b4219121341b9c0d9ffda13a9c3e2..253db8a602fe43a1109e2ba248a= f11109c7baa22 100644 --- a/include/soc/spacemit/k1-syscon.h +++ b/include/soc/spacemit/k1-syscon.h @@ -29,10 +29,11 @@ to_spacemit_ccu_adev(struct auxiliary_device *adev) #define APBS_PLL3_SWCR3 0x12c =20 /* MPMU register offset */ +#define MPMU_FCCR 0x0008 #define MPMU_POSR 0x0010 -#define POSR_PLL1_LOCK BIT(27) -#define POSR_PLL2_LOCK BIT(28) -#define POSR_PLL3_LOCK BIT(29) +#define POSR_PLL1_LOCK BIT(27) +#define POSR_PLL2_LOCK BIT(28) +#define POSR_PLL3_LOCK BIT(29) #define MPMU_SUCCR 0x0014 #define MPMU_ISCCR 0x0044 #define MPMU_WDTPCR 0x0200 --=20 2.50.1