mirror of https://lore.kernel.org/lkml/
 help / color / mirror / Atom feed
From: Herman van Hazendonk <github.com@herrie.org>
To: Bjorn Andersson <andersson@kernel.org>,
	Conor Dooley <conor+dt@kernel.org>,
	devicetree@vger.kernel.org,
	Krzysztof Kozlowski <krzk+dt@kernel.org>,
	linux-arm-msm@vger.kernel.org, linux-clk@vger.kernel.org,
	linux-kernel@vger.kernel.org,
	Michael Turquette <mturquette@baylibre.com>,
	Rob Herring <robh@kernel.org>, Stephen Boyd <sboyd@kernel.org>
Subject: [PATCH 2/2] clk: qcom: add MSM8x60 LCC (LPASS) driver
Date: Sat, 30 May 2026 15:59:58 +0200	[thread overview]
Message-ID: <10180e08af4d55e776963932a4c5e60f0f197a96.1780148149.git.github.com@herrie.org> (raw)
In-Reply-To: <cover.1780148149.git.github.com@herrie.org>

Add a clock driver for the LPASS (Low Power Audio SubSystem) Clock
Controller on the MSM8x60 family (MSM8260/MSM8660/APQ8060) - the
Scorpion-class generation that preceded MSM8960's Krait CPUs.

The register layout, parent muxing and divider topology of the LPASS
PLL/clk fabric differ from MSM8960's LCC enough that a clean separate
driver is simpler than parameterising mmcc-msm8960.c. Both drivers
can coexist in tree (different KConfig options, different match
table, different device-tree compatible).

Used on the HP TouchPad (Tenderloin) where the LPASS Q6 audio DSP
needs functional MI2S / SLIMBus / PCM clocks before audio playback
or capture works.

Signed-off-by: Herman van Hazendonk <github.com@herrie.org>
---
 drivers/clk/qcom/Kconfig       |   9 +
 drivers/clk/qcom/Makefile      |   1 +
 drivers/clk/qcom/lcc-msm8660.c | 517 +++++++++++++++++++++++++++++++++
 3 files changed, 527 insertions(+)
 create mode 100644 drivers/clk/qcom/lcc-msm8660.c

diff --git a/drivers/clk/qcom/Kconfig b/drivers/clk/qcom/Kconfig
index d9cff5b0281d..2ea95f69355e 100644
--- a/drivers/clk/qcom/Kconfig
+++ b/drivers/clk/qcom/Kconfig
@@ -547,6 +547,15 @@ config MSM_LCC_8960
 	  Say Y if you want to use audio devices such as i2s, pcm,
 	  SLIMBus, etc.
 
+config MSM_LCC_8660
+	tristate "MSM8x60 LPASS Clock Controller"
+	depends on ARM || COMPILE_TEST
+	help
+	  Support for the LPASS clock controller on the MSM8x60 family
+	  (MSM8260/MSM8660/APQ8060). MSM8960 is the newer
+	  Krait-based generation handled separately by MSM_LCC_8960.
+	  Say Y if you want to use audio devices such as i2s, pcm, SLIMBus.
+
 config MDM_GCC_9607
 	tristate "MDM9607 Global Clock Controller"
 	depends on ARM || COMPILE_TEST
diff --git a/drivers/clk/qcom/Makefile b/drivers/clk/qcom/Makefile
index e100cfd6a52d..41c973d7db59 100644
--- a/drivers/clk/qcom/Makefile
+++ b/drivers/clk/qcom/Makefile
@@ -77,6 +77,7 @@ obj-$(CONFIG_MSM_GCC_8974) += gcc-msm8974.o
 obj-$(CONFIG_MSM_GCC_8976) += gcc-msm8976.o
 obj-$(CONFIG_MSM_GCC_8994) += gcc-msm8994.o
 obj-$(CONFIG_MSM_GCC_8996) += gcc-msm8996.o
+obj-$(CONFIG_MSM_LCC_8660) += lcc-msm8660.o
 obj-$(CONFIG_MSM_LCC_8960) += lcc-msm8960.o
 obj-$(CONFIG_MSM_GCC_8998) += gcc-msm8998.o
 obj-$(CONFIG_MSM_GPUCC_8998) += gpucc-msm8998.o
diff --git a/drivers/clk/qcom/lcc-msm8660.c b/drivers/clk/qcom/lcc-msm8660.c
new file mode 100644
index 000000000000..7f13279467f9
--- /dev/null
+++ b/drivers/clk/qcom/lcc-msm8660.c
@@ -0,0 +1,517 @@
+// SPDX-License-Identifier: GPL-2.0-only
+/*
+ * Copyright (c) 2014, The Linux Foundation. All rights reserved.
+ Herman van Hazendonk <github.com@herrie.org>
+ *
+ * Qualcomm MSM8x60 family (MSM8260/MSM8660/APQ8060) LPASS Clock Controller driver.
+ *
+ * Split from lcc-msm8960.c because the MSM8x60 family is a separate
+ * SoC generation (Scorpion) from MSM8960 (Krait). The clock topology is
+ * compatible but PLL4 runs at a different rate (540.672 MHz, L=22) and the
+ * driver has no need for the MDM9615 CXO patch or the 492 MHz frequency plan.
+ */
+
+#include <linux/kernel.h>
+#include <linux/bitops.h>
+#include <linux/err.h>
+#include <linux/platform_device.h>
+#include <linux/module.h>
+#include <linux/of.h>
+#include <linux/clk-provider.h>
+#include <linux/regmap.h>
+
+#include <dt-bindings/clock/qcom,lcc-msm8660.h>
+
+#include "common.h"
+#include "clk-regmap.h"
+#include "clk-pll.h"
+#include "clk-rcg.h"
+#include "clk-branch.h"
+#include "clk-regmap-divider.h"
+#include "clk-regmap-mux.h"
+
+static struct clk_pll pll4 = {
+	.l_reg = 0x4,
+	.m_reg = 0x8,
+	.n_reg = 0xc,
+	.config_reg = 0x14,
+	.mode_reg = 0x0,
+	.status_reg = 0x18,
+	.status_bit = 16,
+	.clkr.hw.init = &(struct clk_init_data){
+		.name = "pll4",
+		.parent_data = &(const struct clk_parent_data){
+			.fw_name = "pxo", .name = "pxo_board",
+		},
+		.num_parents = 1,
+		.ops = &clk_pll_ops,
+	},
+};
+
+enum {
+	P_PXO,
+	P_PLL4,
+};
+
+static const struct parent_map lcc_pxo_pll4_map[] = {
+	{ P_PXO, 0 },
+	{ P_PLL4, 2 }
+};
+
+static const struct clk_parent_data lcc_pxo_pll4[] = {
+	{ .fw_name = "pxo", .name = "pxo_board" },
+	{ .fw_name = "pll4_vote", .name = "pll4_vote" },
+};
+
+/*
+ * MSM8x60 PLL4 runs at 540.672 MHz (24.576 MHz * 22, L=0x16).
+ * Divisors taken from the legacy webOS clock-8x60.c driver.
+ * AIF_OSR has an 8-bit M/N counter, so 512000 Hz is not achievable with
+ * this PLL frequency and is intentionally omitted from the 540 MHz tables.
+ */
+static const struct freq_tbl clk_tbl_aif_osr_540[] = {
+	{   768000, P_PLL4, 4, 1, 176 },
+	{  1024000, P_PLL4, 4, 1, 132 },
+	{  1536000, P_PLL4, 4, 1,  88 },
+	{  2048000, P_PLL4, 4, 1,  66 },
+	{  3072000, P_PLL4, 4, 1,  44 },
+	{  4096000, P_PLL4, 4, 1,  33 },
+	{  6144000, P_PLL4, 4, 1,  22 },
+	{  8192000, P_PLL4, 2, 1,  33 },
+	{ 12288000, P_PLL4, 4, 1,  11 },
+	{ 24576000, P_PLL4, 2, 1,  11 },
+	{ 27000000, P_PXO,  1, 0,   0 },
+	{ }
+};
+
+static const struct freq_tbl clk_tbl_aif_osr_393[] = {
+	{   512000, P_PLL4, 4, 1, 192 },
+	{   768000, P_PLL4, 4, 1, 128 },
+	{  1024000, P_PLL4, 4, 1,  96 },
+	{  1536000, P_PLL4, 4, 1,  64 },
+	{  2048000, P_PLL4, 4, 1,  48 },
+	{  3072000, P_PLL4, 4, 1,  32 },
+	{  4096000, P_PLL4, 4, 1,  24 },
+	{  6144000, P_PLL4, 4, 1,  16 },
+	{  8192000, P_PLL4, 4, 1,  12 },
+	{ 12288000, P_PLL4, 4, 1,   8 },
+	{ 24576000, P_PLL4, 4, 1,   4 },
+	{ 27000000, P_PXO,  1, 0,   0 },
+	{ }
+};
+
+#define CLK_AIF_OSR_SRC(prefix, _ns, _md)			\
+static struct clk_rcg prefix##_osr_src = {			\
+	.ns_reg = _ns,						\
+	.md_reg = _md,						\
+	.mn = {							\
+		.mnctr_en_bit = 8,				\
+		.mnctr_reset_bit = 7,				\
+		.mnctr_mode_shift = 5,				\
+		.n_val_shift = 24,				\
+		.m_val_shift = 8,				\
+		.width = 8,					\
+	},							\
+	.p = {							\
+		.pre_div_shift = 3,				\
+		.pre_div_width = 2,				\
+	},							\
+	.s = {							\
+		.src_sel_shift = 0,				\
+		.parent_map = lcc_pxo_pll4_map,			\
+	},							\
+	.freq_tbl = clk_tbl_aif_osr_393,			\
+	.clkr = {						\
+		.enable_reg = _ns,				\
+		.enable_mask = BIT(9),				\
+		.hw.init = &(struct clk_init_data){		\
+			.name = #prefix "_osr_src",		\
+			.parent_data = lcc_pxo_pll4,		\
+			.num_parents = ARRAY_SIZE(lcc_pxo_pll4), \
+			.ops = &clk_rcg_ops,			\
+			.flags = CLK_SET_RATE_GATE,		\
+		},						\
+	},							\
+};								\
+
+#define CLK_AIF_OSR_CLK(prefix, _ns, hr, en_bit)		\
+static struct clk_branch prefix##_osr_clk = {			\
+	.halt_reg = hr,						\
+	.halt_bit = 1,						\
+	.halt_check = BRANCH_HALT_ENABLE,			\
+	.clkr = {						\
+		.enable_reg = _ns,				\
+		.enable_mask = BIT(en_bit),			\
+		.hw.init = &(struct clk_init_data){		\
+			.name = #prefix "_osr_clk",		\
+			.parent_hws = (const struct clk_hw*[]){	\
+				&prefix##_osr_src.clkr.hw,	\
+			},					\
+			.num_parents = 1,			\
+			.ops = &clk_branch_ops,			\
+			.flags = CLK_SET_RATE_PARENT,		\
+		},						\
+	},							\
+};								\
+
+#define CLK_AIF_OSR_DIV_CLK(prefix, _ns, _width)		\
+static struct clk_regmap_div prefix##_div_clk = {		\
+	.reg = _ns,						\
+	.shift = 10,						\
+	.width = _width,					\
+	.clkr = {						\
+		.hw.init = &(struct clk_init_data){		\
+			.name = #prefix "_div_clk",		\
+			.parent_hws = (const struct clk_hw*[]){	\
+				&prefix##_osr_src.clkr.hw,	\
+			},					\
+			.num_parents = 1,			\
+			.ops = &clk_regmap_div_ops,		\
+		},						\
+	},							\
+};								\
+
+#define CLK_AIF_OSR_BIT_DIV_CLK(prefix, _ns, hr, en_bit)	\
+static struct clk_branch prefix##_bit_div_clk = {		\
+	.halt_reg = hr,						\
+	.halt_bit = 0,						\
+	.halt_check = BRANCH_HALT_ENABLE,			\
+	.clkr = {						\
+		.enable_reg = _ns,				\
+		.enable_mask = BIT(en_bit),			\
+		.hw.init = &(struct clk_init_data){		\
+			.name = #prefix "_bit_div_clk",		\
+			.parent_hws = (const struct clk_hw*[]){	\
+				&prefix##_div_clk.clkr.hw,	\
+			},					\
+			.num_parents = 1,			\
+			.ops = &clk_branch_ops,			\
+			.flags = CLK_SET_RATE_PARENT,		\
+		},						\
+	},							\
+};								\
+
+#define CLK_AIF_OSR_BIT_CLK(prefix, _ns, _shift)		\
+static struct clk_regmap_mux prefix##_bit_clk = {		\
+	.reg = _ns,						\
+	.shift = _shift,					\
+	.width = 1,						\
+	.clkr = {						\
+		.hw.init = &(struct clk_init_data){		\
+			.name = #prefix "_bit_clk",		\
+			.parent_data = (const struct clk_parent_data[]){ \
+				{ .hw = &prefix##_bit_div_clk.clkr.hw, }, \
+				{ .fw_name = #prefix "_codec_clk", \
+				  .name = #prefix "_codec_clk", }, \
+			},					\
+			.num_parents = 2,			\
+			.ops = &clk_regmap_mux_closest_ops,	\
+			.flags = CLK_SET_RATE_PARENT,		\
+		},						\
+	},							\
+};
+
+CLK_AIF_OSR_SRC(mi2s, 0x48, 0x4c)
+CLK_AIF_OSR_CLK(mi2s, 0x48, 0x50, 17)
+CLK_AIF_OSR_DIV_CLK(mi2s, 0x48, 4)
+CLK_AIF_OSR_BIT_DIV_CLK(mi2s, 0x48, 0x50, 15)
+CLK_AIF_OSR_BIT_CLK(mi2s, 0x48, 14)
+
+/*
+ * CLK_AIF_OSR_DIV - Audio Interface with divider clocks.
+ * Enable bits per legacy MSM8660 kernel:
+ *   - OSR branch enable: BIT(17)
+ *   - BIT_DIV branch enable: BIT(15)
+ */
+#define CLK_AIF_OSR_DIV(prefix, _ns, _md, hr)			\
+	CLK_AIF_OSR_SRC(prefix, _ns, _md)			\
+	CLK_AIF_OSR_CLK(prefix, _ns, hr, 17)			\
+	CLK_AIF_OSR_DIV_CLK(prefix, _ns, 8)			\
+	CLK_AIF_OSR_BIT_DIV_CLK(prefix, _ns, hr, 15)		\
+	CLK_AIF_OSR_BIT_CLK(prefix, _ns, 18)
+
+CLK_AIF_OSR_DIV(codec_i2s_mic, 0x60, 0x64, 0x68);
+CLK_AIF_OSR_DIV(spare_i2s_mic, 0x78, 0x7c, 0x80);
+CLK_AIF_OSR_DIV(codec_i2s_spkr, 0x6c, 0x70, 0x74);
+CLK_AIF_OSR_DIV(spare_i2s_spkr, 0x84, 0x88, 0x8c);
+
+/* PCM frequency table for MSM8x60 with PLL4 at 540.672 MHz */
+static const struct freq_tbl clk_tbl_pcm_540[] = {
+	{   256000, P_PLL4, 4, 1, 528 },
+	{   512000, P_PLL4, 4, 1, 264 },
+	{   768000, P_PLL4, 4, 1, 176 },
+	{  1024000, P_PLL4, 4, 1, 132 },
+	{  1536000, P_PLL4, 4, 1,  88 },
+	{  2048000, P_PLL4, 4, 1,  66 },
+	{  3072000, P_PLL4, 4, 1,  44 },
+	{  4096000, P_PLL4, 4, 1,  33 },
+	{  6144000, P_PLL4, 4, 1,  22 },
+	{  8192000, P_PLL4, 2, 1,  33 },
+	{ 12288000, P_PLL4, 4, 1,  11 },
+	{ 24576000, P_PLL4, 2, 1,  11 },
+	{ 27000000, P_PXO,  1, 0,   0 },
+	{ }
+};
+
+static const struct freq_tbl clk_tbl_pcm_393[] = {
+	{   256000, P_PLL4, 4, 1, 384 },
+	{   512000, P_PLL4, 4, 1, 192 },
+	{   768000, P_PLL4, 4, 1, 128 },
+	{  1024000, P_PLL4, 4, 1,  96 },
+	{  1536000, P_PLL4, 4, 1,  64 },
+	{  2048000, P_PLL4, 4, 1,  48 },
+	{  3072000, P_PLL4, 4, 1,  32 },
+	{  4096000, P_PLL4, 4, 1,  24 },
+	{  6144000, P_PLL4, 4, 1,  16 },
+	{  8192000, P_PLL4, 4, 1,  12 },
+	{ 12288000, P_PLL4, 4, 1,   8 },
+	{ 24576000, P_PLL4, 4, 1,   4 },
+	{ }
+};
+
+static struct clk_rcg pcm_src = {
+	.ns_reg = 0x54,
+	.md_reg = 0x58,
+	.mn = {
+		.mnctr_en_bit = 8,
+		.mnctr_reset_bit = 7,
+		.mnctr_mode_shift = 5,
+		.n_val_shift = 16,
+		.m_val_shift = 16,
+		.width = 16,
+	},
+	.p = {
+		.pre_div_shift = 3,
+		.pre_div_width = 2,
+	},
+	.s = {
+		.src_sel_shift = 0,
+		.parent_map = lcc_pxo_pll4_map,
+	},
+	.freq_tbl = clk_tbl_pcm_393,
+	.clkr = {
+		.enable_reg = 0x54,
+		.enable_mask = BIT(9),
+		.hw.init = &(struct clk_init_data){
+			.name = "pcm_src",
+			.parent_data = lcc_pxo_pll4,
+			.num_parents = ARRAY_SIZE(lcc_pxo_pll4),
+			.ops = &clk_rcg_ops,
+			.flags = CLK_SET_RATE_GATE,
+		},
+	},
+};
+
+static struct clk_branch pcm_clk_out = {
+	.halt_reg = 0x5c,
+	.halt_bit = 0,
+	.halt_check = BRANCH_HALT_ENABLE,
+	.clkr = {
+		.enable_reg = 0x54,
+		.enable_mask = BIT(11),
+		.hw.init = &(struct clk_init_data){
+			.name = "pcm_clk_out",
+			.parent_hws = (const struct clk_hw*[]){
+				&pcm_src.clkr.hw
+			},
+			.num_parents = 1,
+			.ops = &clk_branch_ops,
+			.flags = CLK_SET_RATE_PARENT,
+		},
+	},
+};
+
+static struct clk_regmap_mux pcm_clk = {
+	.reg = 0x54,
+	.shift = 10,
+	.width = 1,
+	.clkr = {
+		.hw.init = &(struct clk_init_data){
+			.name = "pcm_clk",
+			.parent_data = (const struct clk_parent_data[]){
+				{ .hw = &pcm_clk_out.clkr.hw },
+				{ .fw_name = "pcm_codec_clk", .name = "pcm_codec_clk" },
+			},
+			.num_parents = 2,
+			.ops = &clk_regmap_mux_closest_ops,
+			.flags = CLK_SET_RATE_PARENT,
+		},
+	},
+};
+
+static struct clk_rcg slimbus_src = {
+	.ns_reg = 0xcc,
+	.md_reg = 0xd0,
+	.mn = {
+		.mnctr_en_bit = 8,
+		.mnctr_reset_bit = 7,
+		.mnctr_mode_shift = 5,
+		.n_val_shift = 24,
+		.m_val_shift = 8,
+		.width = 8,
+	},
+	.p = {
+		.pre_div_shift = 3,
+		.pre_div_width = 2,
+	},
+	.s = {
+		.src_sel_shift = 0,
+		.parent_map = lcc_pxo_pll4_map,
+	},
+	.freq_tbl = clk_tbl_aif_osr_393,
+	.clkr = {
+		.enable_reg = 0xcc,
+		.enable_mask = BIT(9),
+		.hw.init = &(struct clk_init_data){
+			.name = "slimbus_src",
+			.parent_data = lcc_pxo_pll4,
+			.num_parents = ARRAY_SIZE(lcc_pxo_pll4),
+			.ops = &clk_rcg_ops,
+			.flags = CLK_SET_RATE_GATE,
+		},
+	},
+};
+
+static struct clk_branch audio_slimbus_clk = {
+	.halt_reg = 0xd4,
+	.halt_bit = 0,
+	.halt_check = BRANCH_HALT_ENABLE,
+	.clkr = {
+		.enable_reg = 0xcc,
+		.enable_mask = BIT(10),
+		.hw.init = &(struct clk_init_data){
+			.name = "audio_slimbus_clk",
+			.parent_hws = (const struct clk_hw*[]){
+				&slimbus_src.clkr.hw,
+			},
+			.num_parents = 1,
+			.ops = &clk_branch_ops,
+			.flags = CLK_SET_RATE_PARENT,
+		},
+	},
+};
+
+static struct clk_branch sps_slimbus_clk = {
+	.halt_reg = 0xd4,
+	.halt_bit = 1,
+	.halt_check = BRANCH_HALT_ENABLE,
+	.clkr = {
+		.enable_reg = 0xcc,
+		.enable_mask = BIT(12),
+		.hw.init = &(struct clk_init_data){
+			.name = "sps_slimbus_clk",
+			.parent_hws = (const struct clk_hw*[]){
+				&slimbus_src.clkr.hw,
+			},
+			.num_parents = 1,
+			.ops = &clk_branch_ops,
+			.flags = CLK_SET_RATE_PARENT,
+		},
+	},
+};
+
+static struct clk_regmap *lcc_msm8660_clks[] = {
+	[PLL4] = &pll4.clkr,
+	[MI2S_OSR_SRC] = &mi2s_osr_src.clkr,
+	[MI2S_OSR_CLK] = &mi2s_osr_clk.clkr,
+	[MI2S_DIV_CLK] = &mi2s_div_clk.clkr,
+	[MI2S_BIT_DIV_CLK] = &mi2s_bit_div_clk.clkr,
+	[MI2S_BIT_CLK] = &mi2s_bit_clk.clkr,
+	[PCM_SRC] = &pcm_src.clkr,
+	[PCM_CLK_OUT] = &pcm_clk_out.clkr,
+	[PCM_CLK] = &pcm_clk.clkr,
+	[SLIMBUS_SRC] = &slimbus_src.clkr,
+	[AUDIO_SLIMBUS_CLK] = &audio_slimbus_clk.clkr,
+	[SPS_SLIMBUS_CLK] = &sps_slimbus_clk.clkr,
+	[CODEC_I2S_MIC_OSR_SRC] = &codec_i2s_mic_osr_src.clkr,
+	[CODEC_I2S_MIC_OSR_CLK] = &codec_i2s_mic_osr_clk.clkr,
+	[CODEC_I2S_MIC_DIV_CLK] = &codec_i2s_mic_div_clk.clkr,
+	[CODEC_I2S_MIC_BIT_DIV_CLK] = &codec_i2s_mic_bit_div_clk.clkr,
+	[CODEC_I2S_MIC_BIT_CLK] = &codec_i2s_mic_bit_clk.clkr,
+	[SPARE_I2S_MIC_OSR_SRC] = &spare_i2s_mic_osr_src.clkr,
+	[SPARE_I2S_MIC_OSR_CLK] = &spare_i2s_mic_osr_clk.clkr,
+	[SPARE_I2S_MIC_DIV_CLK] = &spare_i2s_mic_div_clk.clkr,
+	[SPARE_I2S_MIC_BIT_DIV_CLK] = &spare_i2s_mic_bit_div_clk.clkr,
+	[SPARE_I2S_MIC_BIT_CLK] = &spare_i2s_mic_bit_clk.clkr,
+	[CODEC_I2S_SPKR_OSR_SRC] = &codec_i2s_spkr_osr_src.clkr,
+	[CODEC_I2S_SPKR_OSR_CLK] = &codec_i2s_spkr_osr_clk.clkr,
+	[CODEC_I2S_SPKR_DIV_CLK] = &codec_i2s_spkr_div_clk.clkr,
+	[CODEC_I2S_SPKR_BIT_DIV_CLK] = &codec_i2s_spkr_bit_div_clk.clkr,
+	[CODEC_I2S_SPKR_BIT_CLK] = &codec_i2s_spkr_bit_clk.clkr,
+	[SPARE_I2S_SPKR_OSR_SRC] = &spare_i2s_spkr_osr_src.clkr,
+	[SPARE_I2S_SPKR_OSR_CLK] = &spare_i2s_spkr_osr_clk.clkr,
+	[SPARE_I2S_SPKR_DIV_CLK] = &spare_i2s_spkr_div_clk.clkr,
+	[SPARE_I2S_SPKR_BIT_DIV_CLK] = &spare_i2s_spkr_bit_div_clk.clkr,
+	[SPARE_I2S_SPKR_BIT_CLK] = &spare_i2s_spkr_bit_clk.clkr,
+};
+
+static const struct regmap_config lcc_msm8660_regmap_config = {
+	.reg_bits	= 32,
+	.reg_stride	= 4,
+	.val_bits	= 32,
+	.max_register	= 0xfc,
+	.fast_io	= true,
+};
+
+static const struct qcom_cc_desc lcc_msm8660_desc = {
+	.config = &lcc_msm8660_regmap_config,
+	.clks = lcc_msm8660_clks,
+	.num_clks = ARRAY_SIZE(lcc_msm8660_clks),
+};
+
+static const struct of_device_id lcc_msm8660_match_table[] = {
+	{ .compatible = "qcom,lcc-msm8660" },
+	{ .compatible = "qcom,lcc-apq8060" },
+	{ }
+};
+MODULE_DEVICE_TABLE(of, lcc_msm8660_match_table);
+
+static int lcc_msm8660_probe(struct platform_device *pdev)
+{
+	struct regmap *regmap;
+	u32 val;
+
+	regmap = qcom_cc_map(pdev, &lcc_msm8660_desc);
+	if (IS_ERR(regmap))
+		return PTR_ERR(regmap);
+
+	/*
+	 * MSM8x60 should always boot with PLL4 L=22 (540.672 MHz).
+	 * Detect anyway so a board with a non-standard L value still gets a
+	 * coherent frequency plan instead of silently producing wrong rates.
+	 */
+	regmap_read(regmap, 0x4, &val);
+	if (val == 0x16) {
+		dev_info(&pdev->dev,
+			 "PLL4 L=0x%x, using 540MHz frequency plan\n", val);
+		slimbus_src.freq_tbl = clk_tbl_aif_osr_540;
+		mi2s_osr_src.freq_tbl = clk_tbl_aif_osr_540;
+		codec_i2s_mic_osr_src.freq_tbl = clk_tbl_aif_osr_540;
+		spare_i2s_mic_osr_src.freq_tbl = clk_tbl_aif_osr_540;
+		codec_i2s_spkr_osr_src.freq_tbl = clk_tbl_aif_osr_540;
+		spare_i2s_spkr_osr_src.freq_tbl = clk_tbl_aif_osr_540;
+		pcm_src.freq_tbl = clk_tbl_pcm_540;
+	} else {
+		dev_info(&pdev->dev,
+			 "PLL4 L=0x%x, using fallback 393MHz frequency plan\n",
+			 val);
+	}
+
+	/* Enable PLL4 source on the LPASS Primary PLL Mux */
+	regmap_write(regmap, 0xc4, 0x1);
+
+	return qcom_cc_really_probe(&pdev->dev, &lcc_msm8660_desc, regmap);
+}
+
+static struct platform_driver lcc_msm8660_driver = {
+	.probe		= lcc_msm8660_probe,
+	.driver		= {
+		.name	= "lcc-msm8660",
+		.of_match_table = lcc_msm8660_match_table,
+	},
+};
+module_platform_driver(lcc_msm8660_driver);
+
+MODULE_DESCRIPTION("Qualcomm MSM8x60 LPASS Clock Controller driver");
+MODULE_LICENSE("GPL");
+MODULE_ALIAS("platform:lcc-msm8660");
-- 
2.43.0


  parent reply	other threads:[~2026-05-30 14:08 UTC|newest]

Thread overview: 51+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2026-05-30 13:59 [PATCH 0/2] clk: qcom: add MSM8x60 LPASS Clock Controller Herman van Hazendonk
2026-05-30 13:58 ` [PATCH 1/3] dt-bindings: clock: qcom: add mmcc-msm8660 clock IDs Herman van Hazendonk
2026-05-31 15:39   ` Dmitry Baryshkov
2026-05-30 13:58 ` [PATCH 2/3] dt-bindings: reset: qcom: add mmcc-msm8660 reset IDs Herman van Hazendonk
2026-05-30 13:58 ` [PATCH 3/3] clk: qcom: add MSM8x60 MMCC driver Herman van Hazendonk
2026-06-08  3:03   ` Dmitry Baryshkov
2026-06-09 13:44   ` Konrad Dybcio
2026-06-09 14:03     ` me
2026-06-10 13:39     ` Dmitry Baryshkov
2026-06-10 20:20       ` Linus Walleij
2026-06-12  7:45         ` Dmitry Baryshkov
2026-06-10 13:32   ` Linus Walleij
2026-05-30 13:59 ` [PATCH 0/3] clk: qcom: add MSM8x60 Multimedia Clock Controller Herman van Hazendonk
2026-05-30 13:59 ` [PATCH 1/2] dt-bindings: clock: qcom: add lcc-msm8660 LPASS clock IDs Herman van Hazendonk
2026-06-08  3:05   ` Dmitry Baryshkov
2026-05-30 13:59 ` Herman van Hazendonk [this message]
2026-05-31 15:46   ` [PATCH 2/2] clk: qcom: add MSM8x60 LCC (LPASS) driver Dmitry Baryshkov
2026-05-30 14:00 ` [PATCH 0/2] interconnect: qcom: add MSM8x60 NoC driver Herman van Hazendonk
2026-05-30 14:00 ` [PATCH 1/2] dt-bindings: interconnect: qcom: add msm8660 fabric IDs Herman van Hazendonk
2026-05-30 14:00 ` [PATCH 2/2] interconnect: qcom: add MSM8x60 NoC driver Herman van Hazendonk
2026-05-30 14:00 ` [PATCH 1/2] dt-bindings: interrupt-controller: qcom: add msm8660-mpm Herman van Hazendonk
2026-06-08  3:11   ` Dmitry Baryshkov
2026-05-30 14:00 ` [PATCH 2/2] irqchip: add MSM8x60 MPM wakeup interrupt controller driver Herman van Hazendonk
2026-05-30 14:00 ` [PATCH 0/2] thermal: qcom: add PM8901 PMIC temperature-alarm driver Herman van Hazendonk
2026-05-30 14:00 ` [PATCH 1/2] dt-bindings: thermal: qcom: add pm8901-temp-alarm Herman van Hazendonk
2026-05-30 20:48   ` Rob Herring (Arm)
2026-06-08  3:14   ` Dmitry Baryshkov
2026-05-30 14:00 ` [PATCH 2/2] thermal: qcom: add PM8901 PMIC temperature-alarm driver Herman van Hazendonk
2026-06-08  3:20   ` Dmitry Baryshkov
2026-05-31  4:08 ` [PATCH v2 0/3] clk: qcom: add MSM8x60 LPASS Clock Controller Herman van Hazendonk
2026-05-31  4:09   ` [PATCH v2 1/3] dt-bindings: clock: qcom,lcc: add MSM8x60 family compatibles Herman van Hazendonk
2026-05-31  7:58     ` Krzysztof Kozlowski
2026-05-31  4:09   ` [PATCH v2 2/3] dt-bindings: clock: qcom: add lcc-msm8660 LPASS clock IDs Herman van Hazendonk
2026-05-31  4:09   ` [PATCH v2 3/3] clk: qcom: add MSM8x60 LCC (LPASS) driver Herman van Hazendonk
2026-06-08  3:22   ` [PATCH v2 0/3] clk: qcom: add MSM8x60 LPASS Clock Controller Dmitry Baryshkov
2026-05-31  4:09 ` [PATCH v2 0/2] irqchip: add MSM8x60 MPM wakeup interrupt controller Herman van Hazendonk
2026-05-31  4:09   ` [PATCH v2 1/2] dt-bindings: interrupt-controller: qcom: add msm8660-mpm Herman van Hazendonk
2026-05-31  8:01     ` Krzysztof Kozlowski
2026-05-31  4:09   ` [PATCH v2 2/2] irqchip: add MSM8x60 MPM wakeup interrupt controller driver Herman van Hazendonk
2026-06-01  7:25     ` Sebastian Andrzej Siewior
2026-06-03 15:12     ` Thomas Gleixner
2026-05-31  4:09 ` [PATCH v2 0/3] thermal: qcom: add PM8901 PMIC temperature-alarm driver Herman van Hazendonk
2026-05-31  4:09   ` [PATCH v2 0/2] interconnect: qcom: add MSM8x60 NoC driver Herman van Hazendonk
2026-05-31  4:09   ` [PATCH v2 1/2] dt-bindings: interconnect: qcom: add msm8660 fabric IDs Herman van Hazendonk
2026-05-31  8:00     ` Krzysztof Kozlowski
2026-05-31  4:09   ` [PATCH v2 2/2] interconnect: qcom: add MSM8x60 NoC driver Herman van Hazendonk
2026-05-31  4:09   ` [PATCH v2 1/3] dt-bindings: mfd: qcom-pm8xxx: allow temp-alarm subnode Herman van Hazendonk
2026-05-31  7:59     ` Krzysztof Kozlowski
2026-05-31  4:09   ` [PATCH v2 2/3] dt-bindings: thermal: qcom: add pm8901-temp-alarm Herman van Hazendonk
2026-05-31  4:09   ` [PATCH v2 3/3] thermal: qcom: add PM8901 PMIC temperature-alarm driver Herman van Hazendonk
2026-05-31 15:36 ` [PATCH 0/2] clk: qcom: add MSM8x60 LPASS Clock Controller Dmitry Baryshkov

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=10180e08af4d55e776963932a4c5e60f0f197a96.1780148149.git.github.com@herrie.org \
    --to=github.com@herrie.org \
    --cc=andersson@kernel.org \
    --cc=conor+dt@kernel.org \
    --cc=devicetree@vger.kernel.org \
    --cc=krzk+dt@kernel.org \
    --cc=linux-arm-msm@vger.kernel.org \
    --cc=linux-clk@vger.kernel.org \
    --cc=linux-kernel@vger.kernel.org \
    --cc=mturquette@baylibre.com \
    --cc=robh@kernel.org \
    --cc=sboyd@kernel.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