mirror of https://lore.kernel.org/linux-amlogic/
 help / color / mirror / Atom feed
* [PATCH 0/4] arm64: amlogic: S4 CPU frequency scaling
@ 2026-10-25 19:22 christian.koever-draxl
  2026-10-25 19:22 ` [PATCH 1/4] dt-bindings: clock: amlogic,s4-pll-clkc: add the CPU clock christian.koever-draxl
                   ` (3 more replies)
  0 siblings, 4 replies; 13+ messages in thread
From: christian.koever-draxl @ 2026-10-25 19:22 UTC (permalink / raw)
  To: neil.armstrong, jbrunet, sboyd, bmasney+clk, khilman,
	martin.blumenstingl, rafael, viresh.kumar, robh, krzk+dt,
	conor+dt
  Cc: linux-kernel, linux-amlogic, linux-clk, linux-arm-kernel,
	linux-pm, devicetree, Christian Stefan Kövér-Draxl

From: Christian Stefan Kövér-Draxl <ckoever@outlook.de>

S4 keeps its CPU clock registers in the secure world and bins its parts
by voltage, so CPU DVFS needs three pieces:

 1-2: the CPU clock in the S4 PLL controller, driven through the two
      BL31 SMC services the firmware exposes (sys_pll and the CPU clock
      tree), modelled as one clock because the firmware calls do not
      map onto separate muxes and dividers;
 3:   the secure monitor call that returns the CPU speed bin;
 4:   a small cpufreq driver that picks the "opp-microvolt-speed<bin>"
      curve and registers cpufreq-dt, like sun50i-cpufreq-nvmem.

This applies on top of "firmware: meson: sm: make power-off work on
S4" (sent separately; the command tables overlap). The patches touch
clk, firmware/meson and cpufreq. Patch 4 depends on patch 3; 1-2 are
independent of 3-4. I am happy to split them if the maintainers prefer
to take them through their trees separately.

Tested on an S905W2 (speed bin 2): 100 MHz to 1.908 GHz with the
vendor voltages, transitions under load for hours, vddcpu follows the
table.

Tool use (Documentation/process/generated-content.rst):
This work was done with the help of an AI coding assistant, Claude
(Anthropic), used through Claude Code over many sessions. It did a large
part of the hands-on work: it read the vendor kernel and the firmware
interfaces, probed registers on the board, drafted the code and the
changelogs, and ran the builds, checkpatch, dt_binding_check and the
tests on the hardware. I directed the work, reviewed every change and
the final patches, and take responsibility for them. There is no single
prompt to quote; the sessions were of the form "find out why X fails on
this board, fix it, test it on the box".

Tested on an Amediatech X98Q TV box (Amlogic S905W2, S4 family, 2 GiB),
vendor U-Boot and BL31/OP-TEE, Linux 7.3 plus this work.

Christian Stefan Kövér-Draxl (4):
  dt-bindings: clock: amlogic,s4-pll-clkc: add the CPU clock
  clk: meson: s4-pll: add the CPU clock
  firmware: meson: sm: add the CPU speed bin call
  cpufreq: add an Amlogic speed-bin driver

 MAINTAINERS                                   |   1 +
 drivers/clk/meson/s4-pll.c                    | 320 ++++++++++++++++++
 drivers/cpufreq/Kconfig.arm                   |  14 +
 drivers/cpufreq/Makefile                      |   1 +
 drivers/cpufreq/amlogic-cpufreq.c             | 184 ++++++++++
 drivers/cpufreq/cpufreq-dt-platdev.c          |   2 +
 drivers/firmware/meson/meson_sm.c             |   1 +
 .../dt-bindings/clock/amlogic,s4-pll-clkc.h   |   1 +
 include/linux/firmware/meson/meson_sm.h       |   1 +
 9 files changed, 525 insertions(+)
 create mode 100644 drivers/cpufreq/amlogic-cpufreq.c


base-commit: 7be4bc52fd9e0e55dc9a2e0232b89427d2c4b614
prerequisite-patch-id: f977117cf7f3a613f667c2106e7f4aafc0ace116
prerequisite-patch-id: 1ec4e1bb456bd13cec4f140219f700f44ea19606
-- 
2.56.0


_______________________________________________
linux-amlogic mailing list
linux-amlogic@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-amlogic

^ permalink raw reply	[flat|nested] 13+ messages in thread

* [PATCH 1/4] dt-bindings: clock: amlogic,s4-pll-clkc: add the CPU clock
  2026-10-25 19:22 [PATCH 0/4] arm64: amlogic: S4 CPU frequency scaling christian.koever-draxl
@ 2026-10-25 19:22 ` christian.koever-draxl
  2026-10-25 19:22 ` [PATCH 2/4] clk: meson: s4-pll: " christian.koever-draxl
                   ` (2 subsequent siblings)
  3 siblings, 0 replies; 13+ messages in thread
From: christian.koever-draxl @ 2026-10-25 19:22 UTC (permalink / raw)
  To: neil.armstrong, jbrunet, sboyd, bmasney+clk, khilman,
	martin.blumenstingl, rafael, viresh.kumar, robh, krzk+dt,
	conor+dt
  Cc: linux-kernel, linux-amlogic, linux-clk, linux-arm-kernel,
	linux-pm, devicetree, Christian Stefan Kövér-Draxl

From: Christian Stefan Kövér-Draxl <ckoever@outlook.de>

Add an identifier for the S4 CPU clock so that the CPU nodes can
reference it for frequency scaling.

Signed-off-by: Christian Stefan Kövér-Draxl <ckoever@outlook.de>
---
 include/dt-bindings/clock/amlogic,s4-pll-clkc.h | 1 +
 1 file changed, 1 insertion(+)

diff --git a/include/dt-bindings/clock/amlogic,s4-pll-clkc.h b/include/dt-bindings/clock/amlogic,s4-pll-clkc.h
index af9f110f8b62..8143c6c1486b 100644
--- a/include/dt-bindings/clock/amlogic,s4-pll-clkc.h
+++ b/include/dt-bindings/clock/amlogic,s4-pll-clkc.h
@@ -39,5 +39,6 @@
 #define CLKID_MPLL2			29
 #define CLKID_MPLL3_DIV			30
 #define CLKID_MPLL3			31
+#define CLKID_CPU_CLK			32
 
 #endif /* _DT_BINDINGS_CLOCK_AMLOGIC_S4_PLL_CLKC_H */
-- 
2.56.0


_______________________________________________
linux-amlogic mailing list
linux-amlogic@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-amlogic

^ permalink raw reply	[flat|nested] 13+ messages in thread

* [PATCH 2/4] clk: meson: s4-pll: add the CPU clock
  2026-10-25 19:22 [PATCH 0/4] arm64: amlogic: S4 CPU frequency scaling christian.koever-draxl
  2026-10-25 19:22 ` [PATCH 1/4] dt-bindings: clock: amlogic,s4-pll-clkc: add the CPU clock christian.koever-draxl
@ 2026-10-25 19:22 ` christian.koever-draxl
  2026-10-25 19:22 ` [PATCH 3/4] firmware: meson: sm: add the CPU speed bin call christian.koever-draxl
  2026-10-25 19:22 ` [PATCH 4/4] cpufreq: add an Amlogic speed-bin driver christian.koever-draxl
  3 siblings, 0 replies; 13+ messages in thread
From: christian.koever-draxl @ 2026-10-25 19:22 UTC (permalink / raw)
  To: neil.armstrong, jbrunet, sboyd, bmasney+clk, khilman,
	martin.blumenstingl, rafael, viresh.kumar, robh, krzk+dt,
	conor+dt
  Cc: linux-kernel, linux-amlogic, linux-clk, linux-arm-kernel,
	linux-pm, devicetree, Christian Stefan Kövér-Draxl

From: Christian Stefan Kövér-Draxl <ckoever@outlook.de>

On S4 the CPU clock control register is not reachable from the normal
world: every access goes through the BL31 firmware, which exposes two
SMC services, one for sys_pll (0x82000098) and one for the CPU clock
tree (0x82000099). They take pre-shifted mask/value pairs and behave
like a secure regmap_update_bits(). The sys_pll status register is
still readable from the ANACTRL block.

The tree behind it is the G12A one: two "dynamic" premux/postmux/divider
chains fed from xtal, fclk_div2 and fclk_div3, and a final mux picking
the dynamic tree or sys_pll. As the firmware calls do not map onto
independent muxes and dividers, and the park/reprogram/restore order is
what keeps the cores alive while sys_pll changes, model the whole tree
as a single clock:

 - rates up to 1 GHz come from the dynamic tree,
 - higher rates come from sys_pll, with the CPU parked on the 1 GHz
   dynamic clock while the PLL is reprogrammed,
 - the switch back to sys_pll waits for the new post divider and lock,
   and stays parked with an error if the PLL does not lock.

The firmware boots the cores from sys_pll at about 1.5 GHz, while a PWM
CPU supply can still be at the bottom of its range until cpufreq takes
over, so the clock parks on 1 GHz at registration.

The settings mirror the tables of the vendor firmware and kernel.

Tested on an S905W2 board with cpufreq cycling through all operating
points from 100 MHz to at least 1.7 GHz.

Signed-off-by: Christian Stefan Kövér-Draxl <ckoever@outlook.de>
---
 drivers/clk/meson/s4-pll.c | 320 +++++++++++++++++++++++++++++++++++++
 1 file changed, 320 insertions(+)

diff --git a/drivers/clk/meson/s4-pll.c b/drivers/clk/meson/s4-pll.c
index 56ce6f566e53..951c7060b544 100644
--- a/drivers/clk/meson/s4-pll.c
+++ b/drivers/clk/meson/s4-pll.c
@@ -6,7 +6,10 @@
  * Author: Yu Tu <yu.tu@amlogic.com>
  */
 
+#include <linux/arm-smccc.h>
+#include <linux/bitfield.h>
 #include <linux/clk-provider.h>
+#include <linux/delay.h>
 #include <linux/of_device.h>
 #include <linux/platform_device.h>
 
@@ -16,6 +19,7 @@
 #include "meson-clkc-utils.h"
 #include <dt-bindings/clock/amlogic,s4-pll-clkc.h>
 
+#define ANACTRL_SYSPLL_CTRL0                       0x000
 #define ANACTRL_FIXPLL_CTRL0                       0x040
 #define ANACTRL_FIXPLL_CTRL1                       0x044
 #define ANACTRL_FIXPLL_CTRL3                       0x04c
@@ -758,6 +762,321 @@ static struct clk_regmap s4_mpll3 = {
 	},
 };
 
+/*
+ * CPU clock.
+ *
+ * On S4 the CPU clock control register is only accessible from the secure
+ * world: it is not mapped in the CLKCTRL block visible to Linux, and every
+ * write has to go through BL31. The firmware exposes two SMC services, one
+ * for sys_pll and one for the CPU clock tree, which take pre-shifted
+ * mask/value pairs and behave like a secure regmap_update_bits().
+ *
+ * The hardware tree itself is the well known G12A one (a "dynamic" mux
+ * chain fed by xtal/fclk_div2/fclk_div3 plus a final mux selecting either
+ * that chain or sys_pll). Because the individual muxes cannot be read or
+ * written independently without firmware help, and because the ordering of
+ * the park/reprogram/restore sequence is what keeps the core alive, the
+ * whole tree is modelled here as a single clock with its own ops instead of
+ * a set of clk_regmap muxes and dividers.
+ */
+#define SECURE_PLL_CLK				0x82000098
+#define SECURE_CPU_CLK				0x82000099
+
+/* SECURE_PLL_CLK sub-commands */
+#define SECURE_PLL_SET_MN			0
+#define SECURE_PLL_PRE_CHANGE			1
+#define SECURE_PLL_SET_OD			2
+
+/* SECURE_CPU_CLK sub-commands */
+#define SECURE_CPU_SET_MUX			6
+#define SECURE_CPU_GET_CTRL			7
+#define SECURE_CPU_SET_DYN			8
+
+#define SYS_PLL_LOCK				BIT(31)
+#define SYS_PLL_M				GENMASK(7, 0)
+#define SYS_PLL_N				GENMASK(14, 10)
+#define SYS_PLL_OD				GENMASK(18, 16)
+
+/* Fields of the secure CPU clock control register */
+#define CPU_CLK_DYN0_PREMUX			GENMASK(1, 0)
+#define CPU_CLK_DYN0_POSTMUX			BIT(2)
+#define CPU_CLK_DYN0_DIV			GENMASK(9, 4)
+#define CPU_CLK_DYN_MUX				BIT(10)
+#define CPU_CLK_FINAL_MUX			BIT(11)
+#define CPU_CLK_DYN1_PREMUX			GENMASK(17, 16)
+#define CPU_CLK_DYN1_POSTMUX			BIT(18)
+#define CPU_CLK_DYN1_DIV			GENMASK(25, 20)
+
+static unsigned long s4_secure_clk_smc(u32 fid, u32 cmd, u32 a2, u32 a3, u32 a4)
+{
+	struct arm_smccc_res res;
+
+	arm_smccc_smc(fid, cmd, a2, a3, a4, 0, 0, 0, &res);
+
+	return res.a0;
+}
+
+/* Settings of the dynamic tree, as used by the vendor firmware */
+struct s4_cpu_dyn_setting {
+	unsigned long	rate;
+	u32		premux;
+	u32		postmux;
+	u32		div;
+};
+
+static const struct s4_cpu_dyn_setting s4_cpu_dyn_table[] = {
+	{   24000000, 0, 0, 0 },
+	{  100000000, 1, 1, 9 },
+	{  250000000, 1, 1, 3 },
+	{  333333333, 2, 1, 1 },
+	{  500000000, 1, 1, 1 },
+	{  666666666, 2, 0, 0 },
+	{ 1000000000, 1, 0, 0 },
+};
+
+/* The clock the CPU is parked on while sys_pll is being reprogrammed */
+#define S4_CPU_PARK_IDX		6
+
+/*
+ * sys_pll settings: rate = xtal * m / 2^od with n = 1. Only multipliers
+ * keeping the DCO between 3 and 6 GHz are usable, which is why the lower
+ * rates use a bigger OD instead of a smaller multiplier.
+ */
+struct s4_sys_pll_setting {
+	unsigned long	rate;
+	u32		m;
+	u32		od;
+};
+
+static const struct s4_sys_pll_setting s4_sys_pll_table[] = {
+	{ 1200000000, 200, 2 },
+	{ 1404000000, 234, 2 },
+	{ 1500000000, 125, 1 },
+	{ 1608000000, 134, 1 },
+	{ 1704000000, 142, 1 },
+	{ 1800000000, 150, 1 },
+};
+
+static unsigned long s4_cpu_clk_dyn_parent_rate(u32 premux)
+{
+	switch (premux) {
+	case 1:
+		return clk_hw_get_rate(&s4_fclk_div2.hw);
+	case 2:
+		return clk_hw_get_rate(&s4_fclk_div3.hw);
+	default:
+		return 0;
+	}
+}
+
+static unsigned long s4_cpu_clk_recalc_rate(struct clk_hw *hw,
+					    unsigned long prate)
+{
+	struct clk_regmap *clk = to_clk_regmap(hw);
+	unsigned long parent;
+	u32 ctrl, val, m, n, od;
+	u32 premux, postmux, div;
+
+	ctrl = s4_secure_clk_smc(SECURE_CPU_CLK, SECURE_CPU_GET_CTRL, 0, 0, 0);
+
+	if (ctrl & CPU_CLK_FINAL_MUX) {
+		regmap_read(clk->map, ANACTRL_SYSPLL_CTRL0, &val);
+
+		m = FIELD_GET(SYS_PLL_M, val);
+		n = FIELD_GET(SYS_PLL_N, val);
+		od = FIELD_GET(SYS_PLL_OD, val);
+		if (!n)
+			return 0;
+
+		return (unsigned long)div_u64((u64)prate * m, n) >> od;
+	}
+
+	if (ctrl & CPU_CLK_DYN_MUX) {
+		premux = FIELD_GET(CPU_CLK_DYN1_PREMUX, ctrl);
+		postmux = FIELD_GET(CPU_CLK_DYN1_POSTMUX, ctrl);
+		div = FIELD_GET(CPU_CLK_DYN1_DIV, ctrl);
+	} else {
+		premux = FIELD_GET(CPU_CLK_DYN0_PREMUX, ctrl);
+		postmux = FIELD_GET(CPU_CLK_DYN0_POSTMUX, ctrl);
+		div = FIELD_GET(CPU_CLK_DYN0_DIV, ctrl);
+	}
+
+	parent = premux ? s4_cpu_clk_dyn_parent_rate(premux) : prate;
+
+	return postmux ? parent / (div + 1) : parent;
+}
+
+/*
+ * Pick the supported setting closest to @rate. Nearest rather than floor
+ * matching is deliberate: cpufreq carries frequencies in kHz, so a rate such
+ * as 666666666 Hz comes back as 666666000 Hz and would otherwise drop
+ * to the next lower operating point.
+ */
+static unsigned long s4_cpu_clk_pick(unsigned long rate,
+				     const struct s4_cpu_dyn_setting **dyn,
+				     const struct s4_sys_pll_setting **pll)
+{
+	unsigned long best = 0, delta = ULONG_MAX;
+	int i;
+
+	*dyn = NULL;
+	*pll = NULL;
+
+	for (i = 0; i < ARRAY_SIZE(s4_cpu_dyn_table); i++) {
+		unsigned long d = abs_diff(s4_cpu_dyn_table[i].rate, rate);
+
+		if (d < delta) {
+			delta = d;
+			best = s4_cpu_dyn_table[i].rate;
+			*dyn = &s4_cpu_dyn_table[i];
+			*pll = NULL;
+		}
+	}
+
+	for (i = 0; i < ARRAY_SIZE(s4_sys_pll_table); i++) {
+		unsigned long d = abs_diff(s4_sys_pll_table[i].rate, rate);
+
+		if (d < delta) {
+			delta = d;
+			best = s4_sys_pll_table[i].rate;
+			*dyn = NULL;
+			*pll = &s4_sys_pll_table[i];
+		}
+	}
+
+	return best;
+}
+
+static int s4_cpu_clk_determine_rate(struct clk_hw *hw,
+				     struct clk_rate_request *req)
+{
+	const struct s4_cpu_dyn_setting *dyn;
+	const struct s4_sys_pll_setting *pll;
+
+	req->rate = s4_cpu_clk_pick(req->rate, &dyn, &pll);
+
+	return 0;
+}
+
+static void s4_cpu_clk_set_dyn(const struct s4_cpu_dyn_setting *dyn)
+{
+	s4_secure_clk_smc(SECURE_CPU_CLK, SECURE_CPU_SET_DYN,
+			  dyn->premux, dyn->postmux, dyn->div);
+	s4_secure_clk_smc(SECURE_CPU_CLK, SECURE_CPU_SET_MUX,
+			  CPU_CLK_FINAL_MUX, 0, 0);
+}
+
+static int s4_cpu_clk_init(struct clk_hw *hw)
+{
+	int ret;
+
+	ret = clk_regmap_init(hw);
+	if (ret)
+		return ret;
+
+	/*
+	 * The firmware hands the cores over running from sys_pll at ~1.5 GHz,
+	 * but the CPU supply only comes under Linux control later and a PWM
+	 * regulator adopts whatever duty cycle the bootloader left behind,
+	 * which can be the minimum of the rail. Running 1.5 GHz at that
+	 * voltage is out of spec and hangs some boards every few boots, so
+	 * park on the 1 GHz dynamic clock until cpufreq starts managing
+	 * frequency and voltage together.
+	 */
+	s4_cpu_clk_set_dyn(&s4_cpu_dyn_table[S4_CPU_PARK_IDX]);
+
+	return 0;
+}
+
+static int s4_cpu_clk_set_rate(struct clk_hw *hw, unsigned long rate,
+			       unsigned long prate)
+{
+	struct clk_regmap *clk = to_clk_regmap(hw);
+	const struct s4_cpu_dyn_setting *dyn;
+	const struct s4_sys_pll_setting *pll;
+	unsigned int val;
+	int ret;
+
+	s4_cpu_clk_pick(rate, &dyn, &pll);
+
+	if (dyn) {
+		s4_cpu_clk_set_dyn(dyn);
+		return 0;
+	}
+
+	if (!pll)
+		return -EINVAL;
+
+	/* Park the CPU on the dynamic tree before touching sys_pll */
+	s4_cpu_clk_set_dyn(&s4_cpu_dyn_table[S4_CPU_PARK_IDX]);
+
+	s4_secure_clk_smc(SECURE_PLL_CLK, SECURE_PLL_PRE_CHANGE, 0, 0, 0);
+	s4_secure_clk_smc(SECURE_PLL_CLK, SECURE_PLL_SET_MN, pll->m, 1, 0);
+	s4_secure_clk_smc(SECURE_PLL_CLK, SECURE_PLL_SET_OD, SYS_PLL_OD,
+			  FIELD_PREP(SYS_PLL_OD, pll->od), 0);
+
+	/*
+	 * Wait for the PLL to relock before running the cores off it again.
+	 * Switching the final mux onto a PLL that has not locked yet kills
+	 * the CPU, so on timeout stay parked on the dynamic tree instead:
+	 * the cores keep running and the caller gets an error.
+	 *
+	 * The lock bit alone is not enough here. SET_MN releases reset and
+	 * BL31 waits for lock internally, so by the time SET_OD runs the bit
+	 * is already set and stays set while the divider changes underneath a
+	 * live PLL - between the two writes the output is the undivided DCO.
+	 * Confirm the divider has actually taken and let the output settle,
+	 * otherwise the mux can land while the cores are still being clocked
+	 * from the DCO.
+	 */
+	ret = regmap_read_poll_timeout(clk->map, ANACTRL_SYSPLL_CTRL0, val,
+				       FIELD_GET(SYS_PLL_OD, val) == pll->od,
+				       10, 10000);
+	if (ret) {
+		pr_err("cpu_clk: sys_pll OD did not take, staying on %lu Hz\n",
+		       s4_cpu_dyn_table[S4_CPU_PARK_IDX].rate);
+		return ret;
+	}
+
+	fsleep(100);
+
+	ret = regmap_read_poll_timeout(clk->map, ANACTRL_SYSPLL_CTRL0, val,
+				       val & SYS_PLL_LOCK, 10, 10000);
+	if (ret) {
+		pr_err("cpu_clk: sys_pll did not lock, staying on %lu Hz\n",
+		       s4_cpu_dyn_table[S4_CPU_PARK_IDX].rate);
+		return ret;
+	}
+
+	s4_secure_clk_smc(SECURE_CPU_CLK, SECURE_CPU_SET_MUX,
+			  CPU_CLK_FINAL_MUX, CPU_CLK_FINAL_MUX, 0);
+
+	return 0;
+}
+
+static const struct clk_ops s4_cpu_clk_ops = {
+	.init		= s4_cpu_clk_init,
+	.recalc_rate	= s4_cpu_clk_recalc_rate,
+	.determine_rate	= s4_cpu_clk_determine_rate,
+	.set_rate	= s4_cpu_clk_set_rate,
+};
+
+static struct clk_regmap s4_cpu_clk = {
+	.hw.init = &(struct clk_init_data){
+		.name = "cpu_clk",
+		.ops = &s4_cpu_clk_ops,
+		.parent_data = (const struct clk_parent_data []) {
+			{ .fw_name = "xtal", }
+		},
+		.num_parents = 1,
+		/*
+		 * The cores run on this clock, it must never be gated and its
+		 * rate is changed behind our back by the firmware on resume.
+		 */
+		.flags = CLK_IS_CRITICAL | CLK_GET_RATE_NOCACHE,
+	},
+};
+
 /* Array of all clocks provided by this provider */
 static struct clk_hw *s4_pll_hw_clks[] = {
 	[CLKID_FIXED_PLL_DCO]		= &s4_fixed_pll_dco.hw,
@@ -792,6 +1111,7 @@ static struct clk_hw *s4_pll_hw_clks[] = {
 	[CLKID_MPLL2]			= &s4_mpll2.hw,
 	[CLKID_MPLL3_DIV]		= &s4_mpll3_div.hw,
 	[CLKID_MPLL3]			= &s4_mpll3.hw,
+	[CLKID_CPU_CLK]			= &s4_cpu_clk.hw,
 };
 
 static const struct reg_sequence s4_pll_init_regs[] = {
-- 
2.56.0


_______________________________________________
linux-amlogic mailing list
linux-amlogic@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-amlogic

^ permalink raw reply	[flat|nested] 13+ messages in thread

* [PATCH 3/4] firmware: meson: sm: add the CPU speed bin call
  2026-10-25 19:22 [PATCH 0/4] arm64: amlogic: S4 CPU frequency scaling christian.koever-draxl
  2026-10-25 19:22 ` [PATCH 1/4] dt-bindings: clock: amlogic,s4-pll-clkc: add the CPU clock christian.koever-draxl
  2026-10-25 19:22 ` [PATCH 2/4] clk: meson: s4-pll: " christian.koever-draxl
@ 2026-10-25 19:22 ` christian.koever-draxl
  2026-10-25 19:22 ` [PATCH 4/4] cpufreq: add an Amlogic speed-bin driver christian.koever-draxl
  3 siblings, 0 replies; 13+ messages in thread
From: christian.koever-draxl @ 2026-10-25 19:22 UTC (permalink / raw)
  To: neil.armstrong, jbrunet, sboyd, bmasney+clk, khilman,
	martin.blumenstingl, rafael, viresh.kumar, robh, krzk+dt,
	conor+dt
  Cc: linux-kernel, linux-amlogic, linux-clk, linux-arm-kernel,
	linux-pm, devicetree, Christian Stefan Kövér-Draxl

From: Christian Stefan Kövér-Draxl <ckoever@outlook.de>

Amlogic SoCs are binned at manufacturing time and the bin selects the
CPU voltage curve. On S4 it can only be read through the secure monitor
(SMC 0x82000088, argument: cluster id), which returns the bin index.

Add the command so that a cpufreq driver can pick the right curve.

Signed-off-by: Christian Stefan Kövér-Draxl <ckoever@outlook.de>
---
 drivers/firmware/meson/meson_sm.c       | 1 +
 include/linux/firmware/meson/meson_sm.h | 1 +
 2 files changed, 2 insertions(+)

diff --git a/drivers/firmware/meson/meson_sm.c b/drivers/firmware/meson/meson_sm.c
index 5410386603c7..540773887fe5 100644
--- a/drivers/firmware/meson/meson_sm.c
+++ b/drivers/firmware/meson/meson_sm.c
@@ -51,6 +51,7 @@ static const struct meson_sm_chip gxbb_chip = {
 		CMD(SM_A1_PWRC_SET,		0x82000093),
 		CMD(SM_A1_PWRC_GET,		0x82000095),
 		CMD(SM_SET_POWEROFF_FLAG,	0x82000042),
+		CMD(SM_GET_CPU_SPEED_BIN,	0x82000088),
 		{ /* sentinel */ },
 	},
 };
diff --git a/include/linux/firmware/meson/meson_sm.h b/include/linux/firmware/meson/meson_sm.h
index 3f2fa160e32f..9d11832bf638 100644
--- a/include/linux/firmware/meson/meson_sm.h
+++ b/include/linux/firmware/meson/meson_sm.h
@@ -16,6 +16,7 @@ enum {
 	SM_A1_PWRC_SET,
 	SM_A1_PWRC_GET,
 	SM_SET_POWEROFF_FLAG,
+	SM_GET_CPU_SPEED_BIN,
 };
 
 struct meson_sm_firmware;
-- 
2.56.0


_______________________________________________
linux-amlogic mailing list
linux-amlogic@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-amlogic

^ permalink raw reply	[flat|nested] 13+ messages in thread

* [PATCH 4/4] cpufreq: add an Amlogic speed-bin driver
  2026-10-25 19:22 [PATCH 0/4] arm64: amlogic: S4 CPU frequency scaling christian.koever-draxl
                   ` (2 preceding siblings ...)
  2026-10-25 19:22 ` [PATCH 3/4] firmware: meson: sm: add the CPU speed bin call christian.koever-draxl
@ 2026-10-25 19:22 ` christian.koever-draxl
  2026-10-26  5:30   ` Viresh Kumar
  3 siblings, 1 reply; 13+ messages in thread
From: christian.koever-draxl @ 2026-10-25 19:22 UTC (permalink / raw)
  To: neil.armstrong, jbrunet, sboyd, bmasney+clk, khilman,
	martin.blumenstingl, rafael, viresh.kumar, robh, krzk+dt,
	conor+dt
  Cc: linux-kernel, linux-amlogic, linux-clk, linux-arm-kernel,
	linux-pm, devicetree, Christian Stefan Kövér-Draxl

From: Christian Stefan Kövér-Draxl <ckoever@outlook.de>

Every S4 speed bin runs the same CPU frequencies but needs its own
voltage curve, and the bin can only be read through the secure monitor.

Read the bin from the firmware, select the matching
"opp-microvolt-speed<bin>" property for all CPUs, then register
cpufreq-dt. Bins outside the known range fall back to bin 0, which
has the highest voltages. Like sun50i-cpufreq-nvmem, the driver binds
on the SoC compatible and needs no node of its own, and S4 is added to
the cpufreq-dt-platdev blocklist so cpufreq-dt is only created after
the bin has been applied.

Signed-off-by: Christian Stefan Kövér-Draxl <ckoever@outlook.de>
---
 MAINTAINERS                          |   1 +
 drivers/cpufreq/Kconfig.arm          |  14 ++
 drivers/cpufreq/Makefile             |   1 +
 drivers/cpufreq/amlogic-cpufreq.c    | 184 +++++++++++++++++++++++++++
 drivers/cpufreq/cpufreq-dt-platdev.c |   2 +
 5 files changed, 202 insertions(+)
 create mode 100644 drivers/cpufreq/amlogic-cpufreq.c

diff --git a/MAINTAINERS b/MAINTAINERS
index 0e9fe9c2a39b..c048aed9f7d9 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -2597,6 +2597,7 @@ F:	Documentation/devicetree/bindings/phy/amlogic*
 F:	arch/arm/boot/dts/amlogic/
 F:	arch/arm/mach-meson/
 F:	arch/arm64/boot/dts/amlogic/
+F:	drivers/cpufreq/amlogic-cpufreq.c
 F:	drivers/pmdomain/amlogic/
 F:	drivers/mmc/host/meson*
 F:	drivers/phy/amlogic/
diff --git a/drivers/cpufreq/Kconfig.arm b/drivers/cpufreq/Kconfig.arm
index a441668f9e0c..c0e60e6801c1 100644
--- a/drivers/cpufreq/Kconfig.arm
+++ b/drivers/cpufreq/Kconfig.arm
@@ -24,6 +24,20 @@ config ARM_AIROHA_SOC_CPUFREQ
 	help
 	  This adds the CPUFreq driver for Airoha EN7581 SoCs.
 
+config ARM_AMLOGIC_CPUFREQ
+	tristate "Amlogic CPUFreq speed-bin support"
+	depends on ARCH_MESON || COMPILE_TEST
+	depends on CPUFREQ_DT
+	depends on MESON_SM
+	help
+	  This adds the CPUFreq driver for Amlogic SoCs whose CPU speed bin
+	  is only readable through the secure monitor, such as the S4 family.
+	  It reads the bin from the firmware, selects the matching voltage
+	  curve from the CPU operating points table and then registers
+	  cpufreq-dt.
+
+	  If unsure, say N.
+
 config ARM_APPLE_SOC_CPUFREQ
 	tristate "Apple Silicon SoC CPUFreq support"
 	depends on ARCH_APPLE || (COMPILE_TEST && 64BIT)
diff --git a/drivers/cpufreq/Makefile b/drivers/cpufreq/Makefile
index 6c7a39b7f8d2..781b92f9d43f 100644
--- a/drivers/cpufreq/Makefile
+++ b/drivers/cpufreq/Makefile
@@ -54,6 +54,7 @@ obj-$(CONFIG_X86_AMD_FREQ_SENSITIVITY)	+= amd_freq_sensitivity.o
 ##################################################################################
 # ARM SoC drivers
 obj-$(CONFIG_ARM_AIROHA_SOC_CPUFREQ)	+= airoha-cpufreq.o
+obj-$(CONFIG_ARM_AMLOGIC_CPUFREQ)	+= amlogic-cpufreq.o
 obj-$(CONFIG_ARM_APPLE_SOC_CPUFREQ)	+= apple-soc-cpufreq.o
 obj-$(CONFIG_ARM_ARMADA_37XX_CPUFREQ)	+= armada-37xx-cpufreq.o
 obj-$(CONFIG_ARM_ARMADA_8K_CPUFREQ)	+= armada-8k-cpufreq.o
diff --git a/drivers/cpufreq/amlogic-cpufreq.c b/drivers/cpufreq/amlogic-cpufreq.c
new file mode 100644
index 000000000000..60f399d14846
--- /dev/null
+++ b/drivers/cpufreq/amlogic-cpufreq.c
@@ -0,0 +1,184 @@
+// SPDX-License-Identifier: GPL-2.0-only
+/*
+ * Amlogic CPUFreq speed-bin driver
+ *
+ * Amlogic SoCs are binned at manufacturing time and every bin has its own
+ * voltage curve for one and the same set of frequencies. The bin is only
+ * readable through the secure monitor. This driver asks the firmware which
+ * bin the chip is, points the OPP core at the matching
+ * "opp-microvolt-speed<bin>" property, and then hands over to cpufreq-dt.
+ *
+ * Copyright (c) 2026 Christian Stefan Kövér-Draxl <ckoever@outlook.de>
+ */
+
+#include <linux/cpu.h>
+#include <linux/firmware/meson/meson_sm.h>
+#include <linux/module.h>
+#include <linux/of.h>
+#include <linux/platform_device.h>
+#include <linux/pm_opp.h>
+#include <linux/slab.h>
+
+/* The firmware reports one of four bins, 0 being the one needing most volts */
+#define AMLOGIC_CPUFREQ_MAX_BIN		3
+
+static struct platform_device *amlogic_cpufreq_pdev;
+
+struct amlogic_cpufreq {
+	struct platform_device *cpufreq_dt;
+	unsigned int nr_configured;
+	int opp_tokens[];
+};
+
+static int amlogic_cpufreq_get_speed_bin(struct device *dev)
+{
+	struct meson_sm_firmware *fw;
+	s32 bin;
+	int ret;
+
+	struct device_node *sm_np __free(device_node) =
+		of_find_compatible_node(NULL, NULL, "amlogic,meson-gxbb-sm");
+	if (!sm_np)
+		return dev_err_probe(dev, -ENODEV, "no secure monitor\n");
+
+	fw = meson_sm_get(sm_np);
+	if (!fw)
+		return -EPROBE_DEFER;
+
+	/* The only argument is the cluster, these SoCs have a single one */
+	ret = meson_sm_call(fw, SM_GET_CPU_SPEED_BIN, &bin, 0, 0, 0, 0, 0);
+	if (ret < 0)
+		return dev_err_probe(dev, ret, "failed to read the speed bin\n");
+
+	/*
+	 * Treat anything outside the known range as bin 0, whose voltages are
+	 * the highest and therefore safe on any chip.
+	 */
+	if (bin < 0 || bin > AMLOGIC_CPUFREQ_MAX_BIN) {
+		dev_warn(dev, "unknown speed bin %d, assuming 0\n", bin);
+		bin = 0;
+	}
+
+	return bin;
+}
+
+static void amlogic_cpufreq_clear_config(struct amlogic_cpufreq *priv)
+{
+	unsigned int cpu;
+
+	for (cpu = 0; cpu < priv->nr_configured; cpu++)
+		dev_pm_opp_clear_config(priv->opp_tokens[cpu]);
+}
+
+static int amlogic_cpufreq_probe(struct platform_device *pdev)
+{
+	struct dev_pm_opp_config config = {};
+	struct device *dev = &pdev->dev;
+	struct amlogic_cpufreq *priv;
+	char name[16];
+	unsigned int cpu;
+	int bin, ret;
+
+	bin = amlogic_cpufreq_get_speed_bin(dev);
+	if (bin < 0)
+		return bin;
+
+	priv = devm_kzalloc(dev, struct_size(priv, opp_tokens, nr_cpu_ids),
+			    GFP_KERNEL);
+	if (!priv)
+		return -ENOMEM;
+
+	snprintf(name, sizeof(name), "speed%d", bin);
+	config.prop_name = name;
+
+	for_each_present_cpu(cpu) {
+		struct device *cpu_dev = get_cpu_device(cpu);
+
+		if (!cpu_dev) {
+			ret = -ENODEV;
+			goto clear_config;
+		}
+
+		ret = dev_pm_opp_set_config(cpu_dev, &config);
+		if (ret < 0)
+			goto clear_config;
+
+		priv->opp_tokens[cpu] = ret;
+		priv->nr_configured = cpu + 1;
+	}
+
+	priv->cpufreq_dt = platform_device_register_simple("cpufreq-dt", -1,
+							   NULL, 0);
+	if (IS_ERR(priv->cpufreq_dt)) {
+		ret = PTR_ERR(priv->cpufreq_dt);
+		goto clear_config;
+	}
+
+	platform_set_drvdata(pdev, priv);
+	dev_info(dev, "using the voltages of speed bin %d\n", bin);
+
+	return 0;
+
+clear_config:
+	amlogic_cpufreq_clear_config(priv);
+
+	return ret;
+}
+
+static void amlogic_cpufreq_remove(struct platform_device *pdev)
+{
+	struct amlogic_cpufreq *priv = platform_get_drvdata(pdev);
+
+	platform_device_unregister(priv->cpufreq_dt);
+	amlogic_cpufreq_clear_config(priv);
+}
+
+static struct platform_driver amlogic_cpufreq_driver = {
+	.probe = amlogic_cpufreq_probe,
+	.remove = amlogic_cpufreq_remove,
+	.driver = {
+		.name = "amlogic-cpufreq",
+	},
+};
+
+static const struct of_device_id amlogic_cpufreq_match_list[] = {
+	{ .compatible = "amlogic,s4" },
+	{}
+};
+MODULE_DEVICE_TABLE(of, amlogic_cpufreq_match_list);
+
+/*
+ * The secure monitor may not have probed yet, so all the real work happens
+ * in probe, which can be deferred. Init only registers the driver and its
+ * device, on the SoCs the driver knows about.
+ */
+static int __init amlogic_cpufreq_init(void)
+{
+	int ret;
+
+	if (!of_machine_device_match(amlogic_cpufreq_match_list))
+		return -ENODEV;
+
+	ret = platform_driver_register(&amlogic_cpufreq_driver);
+	if (ret)
+		return ret;
+
+	amlogic_cpufreq_pdev = platform_device_register_simple("amlogic-cpufreq",
+							       -1, NULL, 0);
+	ret = PTR_ERR_OR_ZERO(amlogic_cpufreq_pdev);
+	if (ret)
+		platform_driver_unregister(&amlogic_cpufreq_driver);
+
+	return ret;
+}
+module_init(amlogic_cpufreq_init);
+
+static void __exit amlogic_cpufreq_exit(void)
+{
+	platform_device_unregister(amlogic_cpufreq_pdev);
+	platform_driver_unregister(&amlogic_cpufreq_driver);
+}
+module_exit(amlogic_cpufreq_exit);
+
+MODULE_DESCRIPTION("Amlogic CPUFreq speed-bin driver");
+MODULE_LICENSE("GPL");
diff --git a/drivers/cpufreq/cpufreq-dt-platdev.c b/drivers/cpufreq/cpufreq-dt-platdev.c
index bce4c87573a1..f452ddc46b2c 100644
--- a/drivers/cpufreq/cpufreq-dt-platdev.c
+++ b/drivers/cpufreq/cpufreq-dt-platdev.c
@@ -115,6 +115,8 @@ static const struct of_device_id blocklist[] __initconst = {
 	{ .compatible = "allwinner,sun50i-h618", },
 	{ .compatible = "allwinner,sun50i-h700", },
 
+	{ .compatible = "amlogic,s4", },
+
 	{ .compatible = "apple,arm-platform", },
 
 	{ .compatible = "arm,vexpress", },
-- 
2.56.0


_______________________________________________
linux-amlogic mailing list
linux-amlogic@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-amlogic

^ permalink raw reply	[flat|nested] 13+ messages in thread

* Re: [PATCH 4/4] cpufreq: add an Amlogic speed-bin driver
  2026-10-25 19:22 ` [PATCH 4/4] cpufreq: add an Amlogic speed-bin driver christian.koever-draxl
@ 2026-10-26  5:30   ` Viresh Kumar
  2026-10-26  8:57     ` Jerome Brunet
  0 siblings, 1 reply; 13+ messages in thread
From: Viresh Kumar @ 2026-10-26  5:30 UTC (permalink / raw)
  To: christian.koever-draxl
  Cc: neil.armstrong, jbrunet, sboyd, bmasney+clk, khilman,
	martin.blumenstingl, rafael, robh, krzk+dt, conor+dt,
	linux-kernel, linux-amlogic, linux-clk, linux-arm-kernel,
	linux-pm, devicetree, Christian Stefan Kövér-Draxl

On 25-10-26, 20:22, christian.koever-draxl@student.uibk.ac.at wrote:
> From: Christian Stefan Kövér-Draxl <ckoever@outlook.de>
> 
> Every S4 speed bin runs the same CPU frequencies but needs its own
> voltage curve, and the bin can only be read through the secure monitor.
> 
> Read the bin from the firmware, select the matching
> "opp-microvolt-speed<bin>" property for all CPUs, then register
> cpufreq-dt. Bins outside the known range fall back to bin 0, which
> has the highest voltages. Like sun50i-cpufreq-nvmem, the driver binds
> on the SoC compatible and needs no node of its own, and S4 is added to
> the cpufreq-dt-platdev blocklist so cpufreq-dt is only created after
> the bin has been applied.
> 
> Signed-off-by: Christian Stefan Kövér-Draxl <ckoever@outlook.de>
> ---
>  MAINTAINERS                          |   1 +
>  drivers/cpufreq/Kconfig.arm          |  14 ++
>  drivers/cpufreq/Makefile             |   1 +
>  drivers/cpufreq/amlogic-cpufreq.c    | 184 +++++++++++++++++++++++++++
>  drivers/cpufreq/cpufreq-dt-platdev.c |   2 +
>  5 files changed, 202 insertions(+)
>  create mode 100644 drivers/cpufreq/amlogic-cpufreq.c

Is it safe to apply just this one ? I can take this via the PM tree then.

-- 
viresh

_______________________________________________
linux-amlogic mailing list
linux-amlogic@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-amlogic

^ permalink raw reply	[flat|nested] 13+ messages in thread

* Re: [PATCH 4/4] cpufreq: add an Amlogic speed-bin driver
  2026-10-26  5:30   ` Viresh Kumar
@ 2026-10-26  8:57     ` Jerome Brunet
  2026-10-26  8:59       ` Viresh Kumar
                         ` (2 more replies)
  0 siblings, 3 replies; 13+ messages in thread
From: Jerome Brunet @ 2026-10-26  8:57 UTC (permalink / raw)
  To: Viresh Kumar, christian.koever-draxl
  Cc: neil.armstrong, sboyd, bmasney+clk, khilman, martin.blumenstingl,
	rafael, robh, krzk+dt, conor+dt, linux-kernel, linux-amlogic,
	linux-clk, linux-arm-kernel, linux-pm, devicetree,
	Christian Stefan Kövér-Draxl

On lun. 26 oct. 2026 at 11:00, Viresh Kumar <viresh.kumar@linaro.org> wrote:

> On 25-10-26, 20:22, christian.koever-draxl@student.uibk.ac.at wrote:
>> From: Christian Stefan Kövér-Draxl <ckoever@outlook.de>
>> 
>> Every S4 speed bin runs the same CPU frequencies but needs its own
>> voltage curve, and the bin can only be read through the secure monitor.
>> 
>> Read the bin from the firmware, select the matching
>> "opp-microvolt-speed<bin>" property for all CPUs, then register
>> cpufreq-dt. Bins outside the known range fall back to bin 0, which
>> has the highest voltages. Like sun50i-cpufreq-nvmem, the driver binds
>> on the SoC compatible and needs no node of its own, and S4 is added to
>> the cpufreq-dt-platdev blocklist so cpufreq-dt is only created after
>> the bin has been applied.
>> 
>> Signed-off-by: Christian Stefan Kövér-Draxl <ckoever@outlook.de>
>> ---
>>  MAINTAINERS                          |   1 +
>>  drivers/cpufreq/Kconfig.arm          |  14 ++
>>  drivers/cpufreq/Makefile             |   1 +
>>  drivers/cpufreq/amlogic-cpufreq.c    | 184 +++++++++++++++++++++++++++
>>  drivers/cpufreq/cpufreq-dt-platdev.c |   2 +
>>  5 files changed, 202 insertions(+)
>>  create mode 100644 drivers/cpufreq/amlogic-cpufreq.c
>
> Is it safe to apply just this one ? I can take this via the PM tree then.

I would advise to wait a little for Amlogic to chime in.

Patch 2 is something I already rejected back when S4 support was
initially introduced. I suppose AI just unearthed it and did not bother
to mention it.

Amlogic was supposed to migrate to SCMI at that point, and possibly
handle CPU frequency scaling through the secure fw entirely.

They did on later SoCs, I don't know where their FW stands on the S4.

>
> -- 
> viresh

-- 
Jerome

_______________________________________________
linux-amlogic mailing list
linux-amlogic@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-amlogic

^ permalink raw reply	[flat|nested] 13+ messages in thread

* Re: [PATCH 4/4] cpufreq: add an Amlogic speed-bin driver
  2026-10-26  8:57     ` Jerome Brunet
@ 2026-10-26  8:59       ` Viresh Kumar
  2026-10-26 10:08         ` Christain Stefan Köver-Draxl
  2026-10-27  9:26         ` Chuan Liu
  2026-10-26 10:10       ` Christain Stefan Köver-Draxl
  2026-10-27  9:31       ` Chuan Liu
  2 siblings, 2 replies; 13+ messages in thread
From: Viresh Kumar @ 2026-10-26  8:59 UTC (permalink / raw)
  To: Jerome Brunet
  Cc: christian.koever-draxl, neil.armstrong, sboyd, bmasney+clk,
	khilman, martin.blumenstingl, rafael, robh, krzk+dt, conor+dt,
	linux-kernel, linux-amlogic, linux-clk, linux-arm-kernel,
	linux-pm, devicetree, Christian Stefan Kövér-Draxl

On 26-10-26, 09:57, Jerome Brunet wrote:
> On lun. 26 oct. 2026 at 11:00, Viresh Kumar <viresh.kumar@linaro.org> wrote:
> 
> > On 25-10-26, 20:22, christian.koever-draxl@student.uibk.ac.at wrote:
> >> From: Christian Stefan Kövér-Draxl <ckoever@outlook.de>
> >> 
> >> Every S4 speed bin runs the same CPU frequencies but needs its own
> >> voltage curve, and the bin can only be read through the secure monitor.
> >> 
> >> Read the bin from the firmware, select the matching
> >> "opp-microvolt-speed<bin>" property for all CPUs, then register
> >> cpufreq-dt. Bins outside the known range fall back to bin 0, which
> >> has the highest voltages. Like sun50i-cpufreq-nvmem, the driver binds
> >> on the SoC compatible and needs no node of its own, and S4 is added to
> >> the cpufreq-dt-platdev blocklist so cpufreq-dt is only created after
> >> the bin has been applied.
> >> 
> >> Signed-off-by: Christian Stefan Kövér-Draxl <ckoever@outlook.de>
> >> ---
> >>  MAINTAINERS                          |   1 +
> >>  drivers/cpufreq/Kconfig.arm          |  14 ++
> >>  drivers/cpufreq/Makefile             |   1 +
> >>  drivers/cpufreq/amlogic-cpufreq.c    | 184 +++++++++++++++++++++++++++
> >>  drivers/cpufreq/cpufreq-dt-platdev.c |   2 +
> >>  5 files changed, 202 insertions(+)
> >>  create mode 100644 drivers/cpufreq/amlogic-cpufreq.c
> >
> > Is it safe to apply just this one ? I can take this via the PM tree then.
> 
> I would advise to wait a little for Amlogic to chime in.

Sure, I wasn't going to wait for the maintainers to respond anyway.

-- 
viresh

_______________________________________________
linux-amlogic mailing list
linux-amlogic@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-amlogic

^ permalink raw reply	[flat|nested] 13+ messages in thread

* Re: [PATCH 4/4] cpufreq: add an Amlogic speed-bin driver
  2026-10-26  8:59       ` Viresh Kumar
@ 2026-10-26 10:08         ` Christain Stefan Köver-Draxl
  2026-10-27  9:26         ` Chuan Liu
  1 sibling, 0 replies; 13+ messages in thread
From: Christain Stefan Köver-Draxl @ 2026-10-26 10:08 UTC (permalink / raw)
  To: Jerome Brunet
  Cc: neil.armstrong, sboyd, bmasney+clk, khilman, martin.blumenstingl,
	rafael, robh, krzk+dt, conor+dt, linux-kernel, linux-amlogic,
	linux-clk, linux-arm-kernel, linux-pm, devicetree,
	Christian Stefan Kövér-Draxl

Hi Viresh,
Hi Jerome,

On 10/26/26 09:59, Viresh Kumar wrote:
> On 26-10-26, 09:57, Jerome Brunet wrote:
>> On lun. 26 oct. 2026 at 11:00, Viresh Kumar <viresh.kumar@linaro.org> wrote:
>>
>>> On 25-10-26, 20:22, christian.koever-draxl@student.uibk.ac.at wrote:
>>>> From: Christian Stefan Kövér-Draxl <ckoever@outlook.de>
>>>>
>>>> Every S4 speed bin runs the same CPU frequencies but needs its own
>>>> voltage curve, and the bin can only be read through the secure monitor.
>>>>
>>>> Read the bin from the firmware, select the matching
>>>> "opp-microvolt-speed<bin>" property for all CPUs, then register
>>>> cpufreq-dt. Bins outside the known range fall back to bin 0, which
>>>> has the highest voltages. Like sun50i-cpufreq-nvmem, the driver binds
>>>> on the SoC compatible and needs no node of its own, and S4 is added to
>>>> the cpufreq-dt-platdev blocklist so cpufreq-dt is only created after
>>>> the bin has been applied.
>>>>
>>>> Signed-off-by: Christian Stefan Kövér-Draxl <ckoever@outlook.de>
>>>> ---
>>>>   MAINTAINERS                          |   1 +
>>>>   drivers/cpufreq/Kconfig.arm          |  14 ++
>>>>   drivers/cpufreq/Makefile             |   1 +
>>>>   drivers/cpufreq/amlogic-cpufreq.c    | 184 +++++++++++++++++++++++++++
>>>>   drivers/cpufreq/cpufreq-dt-platdev.c |   2 +
>>>>   5 files changed, 202 insertions(+)
>>>>   create mode 100644 drivers/cpufreq/amlogic-cpufreq.c
>>> Is it safe to apply just this one ? I can take this via the PM tree then.
>> I would advise to wait a little for Amlogic to chime in.

Viresh, thanks, but please don't apply it alone. It would need the 
speed-bin call from patch 3 (meson_sm), and without the CPU clock from 
patch 2 it has nothing to scale.

Best regards,
Christian

> Sure, I wasn't going to wait for the maintainers to respond anyway.
>

_______________________________________________
linux-amlogic mailing list
linux-amlogic@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-amlogic

^ permalink raw reply	[flat|nested] 13+ messages in thread

* Re: [PATCH 4/4] cpufreq: add an Amlogic speed-bin driver
  2026-10-26  8:57     ` Jerome Brunet
  2026-10-26  8:59       ` Viresh Kumar
@ 2026-10-26 10:10       ` Christain Stefan Köver-Draxl
  2026-10-27  9:31       ` Chuan Liu
  2 siblings, 0 replies; 13+ messages in thread
From: Christain Stefan Köver-Draxl @ 2026-10-26 10:10 UTC (permalink / raw)
  To: Jerome Brunet
  Cc: neil.armstrong, sboyd, bmasney+clk, khilman, martin.blumenstingl,
	rafael, robh, krzk+dt, conor+dt, linux-kernel, linux-amlogic,
	linux-clk, linux-arm-kernel, linux-pm, devicetree,
	Christian Stefan Kövér-Draxl

Hi Viresh,
Hi Jerome,

On 10/26/26 09:57, Jerome Brunet wrote:
> On lun. 26 oct. 2026 at 11:00, Viresh Kumar <viresh.kumar@linaro.org> wrote:
>
>> On 25-10-26, 20:22, christian.koever-draxl@student.uibk.ac.at wrote:
>>> From: Christian Stefan Kövér-Draxl <ckoever@outlook.de>
>>>
>>> Every S4 speed bin runs the same CPU frequencies but needs its own
>>> voltage curve, and the bin can only be read through the secure monitor.
>>>
>>> Read the bin from the firmware, select the matching
>>> "opp-microvolt-speed<bin>" property for all CPUs, then register
>>> cpufreq-dt. Bins outside the known range fall back to bin 0, which
>>> has the highest voltages. Like sun50i-cpufreq-nvmem, the driver binds
>>> on the SoC compatible and needs no node of its own, and S4 is added to
>>> the cpufreq-dt-platdev blocklist so cpufreq-dt is only created after
>>> the bin has been applied.
>>>
>>> Signed-off-by: Christian Stefan Kövér-Draxl <ckoever@outlook.de>
>>> ---
>>>   MAINTAINERS                          |   1 +
>>>   drivers/cpufreq/Kconfig.arm          |  14 ++
>>>   drivers/cpufreq/Makefile             |   1 +
>>>   drivers/cpufreq/amlogic-cpufreq.c    | 184 +++++++++++++++++++++++++++
>>>   drivers/cpufreq/cpufreq-dt-platdev.c |   2 +
>>>   5 files changed, 202 insertions(+)
>>>   create mode 100644 drivers/cpufreq/amlogic-cpufreq.c
>> Is it safe to apply just this one ? I can take this via the PM tree then.
> I would advise to wait a little for Amlogic to chime in.
>
> Patch 2 is something I already rejected back when S4 support was
> initially introduced. I suppose AI just unearthed it and did not bother
> to mention it.
>
> Amlogic was supposed to migrate to SCMI at that point, and possibly
> handle CPU frequency scaling through the secure fw entirely.
>
> They did on later SoCs, I don't know where their FW stands on the S4.

In my board's firmware there is no SCMI. CPU DVFS only works through the 
clock SMCs.

Best regards,
Christian

>
>> -- 
>> viresh

_______________________________________________
linux-amlogic mailing list
linux-amlogic@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-amlogic

^ permalink raw reply	[flat|nested] 13+ messages in thread

* Re: [PATCH 4/4] cpufreq: add an Amlogic speed-bin driver
  2026-10-26  8:59       ` Viresh Kumar
  2026-10-26 10:08         ` Christain Stefan Köver-Draxl
@ 2026-10-27  9:26         ` Chuan Liu
  2026-10-27 10:22           ` Christian Hewitt
  1 sibling, 1 reply; 13+ messages in thread
From: Chuan Liu @ 2026-10-27  9:26 UTC (permalink / raw)
  To: Viresh Kumar, Jerome Brunet
  Cc: christian.koever-draxl, neil.armstrong, sboyd, bmasney+clk,
	khilman, martin.blumenstingl, rafael, robh, krzk+dt, conor+dt,
	linux-kernel, linux-amlogic, linux-clk, linux-arm-kernel,
	linux-pm, devicetree, Christian Stefan Kövér-Draxl

Hi Viresh, Christian,
     Could you please hold off for now on the patches adding cpufreq 
driver support on S4? There are still two issues that need to be 
resolved first:
   - The clock driver currently does not support setting the CPU clock.
   - The CPU regulator needs some time to stabilize after the voltage is 
changed. Without a proper delay, the CPU clock frequency may be raised 
before the regulator voltage has actually reached the target value, 
which can hang the system. The S4 CPU regulator handling currently lacks 
the logic to wait for the regulator voltage to settle, so this part 
needs to be completed first.

We are currently working on submitting our own cpufreq driver. We are 
considering how to address the issues above, taking into account the 
hardware characteristics of previous SoCs and evaluating factors such as 
the transition latency. S4 will be covered by that work (as well as SoCs 
from S4 onward, such as C3, T7, ..., A9). So please give us some time.

On 10/26/2026 4:59 PM, Viresh Kumar wrote:
> On 26-10-26, 09:57, Jerome Brunet wrote:
>> On lun. 26 oct. 2026 at 11:00, Viresh Kumar <viresh.kumar@linaro.org> wrote:
>>
>>> On 25-10-26, 20:22, christian.koever-draxl@student.uibk.ac.at wrote:
>>>> From: Christian Stefan Kövér-Draxl <ckoever@outlook.de>
>>>>
>>>> Every S4 speed bin runs the same CPU frequencies but needs its own
>>>> voltage curve, and the bin can only be read through the secure monitor.
>>>>
>>>> Read the bin from the firmware, select the matching
>>>> "opp-microvolt-speed<bin>" property for all CPUs, then register
>>>> cpufreq-dt. Bins outside the known range fall back to bin 0, which
>>>> has the highest voltages. Like sun50i-cpufreq-nvmem, the driver binds
>>>> on the SoC compatible and needs no node of its own, and S4 is added to
>>>> the cpufreq-dt-platdev blocklist so cpufreq-dt is only created after
>>>> the bin has been applied.
>>>>
>>>> Signed-off-by: Christian Stefan Kövér-Draxl <ckoever@outlook.de>
>>>> ---
>>>>   MAINTAINERS                          |   1 +
>>>>   drivers/cpufreq/Kconfig.arm          |  14 ++
>>>>   drivers/cpufreq/Makefile             |   1 +
>>>>   drivers/cpufreq/amlogic-cpufreq.c    | 184 +++++++++++++++++++++++++++
>>>>   drivers/cpufreq/cpufreq-dt-platdev.c |   2 +
>>>>   5 files changed, 202 insertions(+)
>>>>   create mode 100644 drivers/cpufreq/amlogic-cpufreq.c
>>>
>>> Is it safe to apply just this one ? I can take this via the PM tree then.
>>
>> I would advise to wait a little for Amlogic to chime in.
> 
> Sure, I wasn't going to wait for the maintainers to respond anyway.
> 

-- 
Best regards,
Chuan


_______________________________________________
linux-amlogic mailing list
linux-amlogic@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-amlogic

^ permalink raw reply	[flat|nested] 13+ messages in thread

* Re: [PATCH 4/4] cpufreq: add an Amlogic speed-bin driver
  2026-10-26  8:57     ` Jerome Brunet
  2026-10-26  8:59       ` Viresh Kumar
  2026-10-26 10:10       ` Christain Stefan Köver-Draxl
@ 2026-10-27  9:31       ` Chuan Liu
  2 siblings, 0 replies; 13+ messages in thread
From: Chuan Liu @ 2026-10-27  9:31 UTC (permalink / raw)
  To: Jerome Brunet, Viresh Kumar, christian.koever-draxl
  Cc: neil.armstrong, sboyd, bmasney+clk, khilman, martin.blumenstingl,
	rafael, robh, krzk+dt, conor+dt, linux-kernel, linux-amlogic,
	linux-clk, linux-arm-kernel, linux-pm, devicetree,
	Christian Stefan Kövér-Draxl

Hi Jerome,

On 10/26/2026 4:57 PM, Jerome Brunet wrote:
> On lun. 26 oct. 2026 at 11:00, Viresh Kumar <viresh.kumar@linaro.org> wrote:
> 
>> On 25-10-26, 20:22, christian.koever-draxl@student.uibk.ac.at wrote:
>>> From: Christian Stefan Kövér-Draxl <ckoever@outlook.de>
>>>
>>> Every S4 speed bin runs the same CPU frequencies but needs its own
>>> voltage curve, and the bin can only be read through the secure monitor.
>>>
>>> Read the bin from the firmware, select the matching
>>> "opp-microvolt-speed<bin>" property for all CPUs, then register
>>> cpufreq-dt. Bins outside the known range fall back to bin 0, which
>>> has the highest voltages. Like sun50i-cpufreq-nvmem, the driver binds
>>> on the SoC compatible and needs no node of its own, and S4 is added to
>>> the cpufreq-dt-platdev blocklist so cpufreq-dt is only created after
>>> the bin has been applied.
>>>
>>> Signed-off-by: Christian Stefan Kövér-Draxl <ckoever@outlook.de>
>>> ---
>>>   MAINTAINERS                          |   1 +
>>>   drivers/cpufreq/Kconfig.arm          |  14 ++
>>>   drivers/cpufreq/Makefile             |   1 +
>>>   drivers/cpufreq/amlogic-cpufreq.c    | 184 +++++++++++++++++++++++++++
>>>   drivers/cpufreq/cpufreq-dt-platdev.c |   2 +
>>>   5 files changed, 202 insertions(+)
>>>   create mode 100644 drivers/cpufreq/amlogic-cpufreq.c
>>
>> Is it safe to apply just this one ? I can take this via the PM tree then.
> 
> I would advise to wait a little for Amlogic to chime in.>
> Patch 2 is something I already rejected back when S4 support was
> initially introduced. I suppose AI just unearthed it and did not bother
> to mention it.
> 
> Amlogic was supposed to migrate to SCMI at that point, and possibly
> handle CPU frequency scaling through the secure fw entirely.

Yes, starting from the C3 clock upstream submission, we replaced the 
SMCs implementation of the secure-clock with SCMI. For the latest 
released Amlogic SoCs (S7 and later), secure-clock is implemented 
uniformly through SCMI.

> 
> They did on later SoCs, I don't know where their FW stands on the S4.

Most S4 customers receive a secure firmware (bl31.bin) that sets 
secure-clock via SMCs (because the S4 SDK had already been released by 
the time we added SCMI support). We have also provided an SCMI-capable 
bl31.bin to some customers.

> 
>>
>> -- 
>> viresh
> 

-- 
Best regards,
Chuan


_______________________________________________
linux-amlogic mailing list
linux-amlogic@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-amlogic

^ permalink raw reply	[flat|nested] 13+ messages in thread

* Re: [PATCH 4/4] cpufreq: add an Amlogic speed-bin driver
  2026-10-27  9:26         ` Chuan Liu
@ 2026-10-27 10:22           ` Christian Hewitt
  0 siblings, 0 replies; 13+ messages in thread
From: Christian Hewitt @ 2026-10-27 10:22 UTC (permalink / raw)
  To: Chuan Liu
  Cc: Viresh Kumar, Jerome Brunet, christian.koever-draxl,
	neil.armstrong, sboyd, bmasney+clk, khilman, martin.blumenstingl,
	rafael, robh, krzk+dt, conor+dt, linux-kernel, linux-amlogic,
	linux-clk, linux-arm-kernel, linux-pm, devicetree,
	Christian Stefan Kövér-Draxl

> On 27 Oct 2026, at 1:26 pm, Chuan Liu <chuan.liu686@gmail.com> wrote:
> 
> Hi Viresh, Christian,
>    Could you please hold off for now on the patches adding cpufreq driver support on S4? There are still two issues that need to be resolved first:
>  - The clock driver currently does not support setting the CPU clock.
>  - The CPU regulator needs some time to stabilize after the voltage is changed. Without a proper delay, the CPU clock frequency may be raised before the regulator voltage has actually reached the target value, which can hang the system. The S4 CPU regulator handling currently lacks the logic to wait for the regulator voltage to settle, so this part needs to be completed first.
> 
> We are currently working on submitting our own cpufreq driver. We are considering how to address the issues above, taking into account the hardware characteristics of previous SoCs and evaluating factors such as the transition latency. S4 will be covered by that work (as well as SoCs from S4 onward, such as C3, T7, ..., A9). So please give us some time.

Please don’t top-post, keep inline threading!

FWIW, the recent bindings/clock/driver work I’ve done for S4 is here:

https://github.com/chewitt/linux/commits/amlogic-7.3.y

My speed-bin driver is based on earlier work from Martin Blumenstingl:

https://github.com/chewitt/linux/commit/77e12d4d584d6a8bbd93304bbd4e9bbbb6ee159a

Setting a ramp-delay was the key to opp transition stability:

https://github.com/chewitt/linux/commit/ca7a99e86e23677c7b5af887e6f3b3c8ce3470d2

CH.
also a Christian, to confuse people :)

> On 10/26/2026 4:59 PM, Viresh Kumar wrote:
>> On 26-10-26, 09:57, Jerome Brunet wrote:
>>> On lun. 26 oct. 2026 at 11:00, Viresh Kumar <viresh.kumar@linaro.org> wrote:
>>> 
>>>> On 25-10-26, 20:22, christian.koever-draxl@student.uibk.ac.at wrote:
>>>>> From: Christian Stefan Kövér-Draxl <ckoever@outlook.de>
>>>>> 
>>>>> Every S4 speed bin runs the same CPU frequencies but needs its own
>>>>> voltage curve, and the bin can only be read through the secure monitor.
>>>>> 
>>>>> Read the bin from the firmware, select the matching
>>>>> "opp-microvolt-speed<bin>" property for all CPUs, then register
>>>>> cpufreq-dt. Bins outside the known range fall back to bin 0, which
>>>>> has the highest voltages. Like sun50i-cpufreq-nvmem, the driver binds
>>>>> on the SoC compatible and needs no node of its own, and S4 is added to
>>>>> the cpufreq-dt-platdev blocklist so cpufreq-dt is only created after
>>>>> the bin has been applied.
>>>>> 
>>>>> Signed-off-by: Christian Stefan Kövér-Draxl <ckoever@outlook.de>
>>>>> ---
>>>>>  MAINTAINERS                          |   1 +
>>>>>  drivers/cpufreq/Kconfig.arm          |  14 ++
>>>>>  drivers/cpufreq/Makefile             |   1 +
>>>>>  drivers/cpufreq/amlogic-cpufreq.c    | 184 +++++++++++++++++++++++++++
>>>>>  drivers/cpufreq/cpufreq-dt-platdev.c |   2 +
>>>>>  5 files changed, 202 insertions(+)
>>>>>  create mode 100644 drivers/cpufreq/amlogic-cpufreq.c
>>>> 
>>>> Is it safe to apply just this one ? I can take this via the PM tree then.
>>> 
>>> I would advise to wait a little for Amlogic to chime in.
>> Sure, I wasn't going to wait for the maintainers to respond anyway.
> 
> -- 
> Best regards,
> Chuan
> 
> 
> _______________________________________________
> linux-amlogic mailing list
> linux-amlogic@lists.infradead.org
> http://lists.infradead.org/mailman/listinfo/linux-amlogic



_______________________________________________
linux-amlogic mailing list
linux-amlogic@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-amlogic

^ permalink raw reply	[flat|nested] 13+ messages in thread

end of thread, other threads:[~2026-10-27 10:22 UTC | newest]

Thread overview: 13+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2026-10-25 19:22 [PATCH 0/4] arm64: amlogic: S4 CPU frequency scaling christian.koever-draxl
2026-10-25 19:22 ` [PATCH 1/4] dt-bindings: clock: amlogic,s4-pll-clkc: add the CPU clock christian.koever-draxl
2026-10-25 19:22 ` [PATCH 2/4] clk: meson: s4-pll: " christian.koever-draxl
2026-10-25 19:22 ` [PATCH 3/4] firmware: meson: sm: add the CPU speed bin call christian.koever-draxl
2026-10-25 19:22 ` [PATCH 4/4] cpufreq: add an Amlogic speed-bin driver christian.koever-draxl
2026-10-26  5:30   ` Viresh Kumar
2026-10-26  8:57     ` Jerome Brunet
2026-10-26  8:59       ` Viresh Kumar
2026-10-26 10:08         ` Christain Stefan Köver-Draxl
2026-10-27  9:26         ` Chuan Liu
2026-10-27 10:22           ` Christian Hewitt
2026-10-26 10:10       ` Christain Stefan Köver-Draxl
2026-10-27  9:31       ` Chuan Liu

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox

all inboxes | Powered by JetHome®