mirror of https://lore.kernel.org/lkml/
 help / color / mirror / Atom feed
* [PATCH 0/6] sunxi: A133: Add CPU speed grade detection and OPP table
@ 2026-11-05  4:40 Rajan Yadav via B4 Relay
  2026-11-05  4:40 ` [PATCH 1/6] dt-bindings: opp: h6: Add A133 operating points Rajan Yadav via B4 Relay
                   ` (6 more replies)
  0 siblings, 7 replies; 9+ messages in thread
From: Rajan Yadav via B4 Relay @ 2026-11-05  4:40 UTC (permalink / raw)
  To: Yangtao Li, Viresh Kumar, Nishanth Menon, Stephen Boyd,
	Rob Herring, Krzysztof Kozlowski, Conor Dooley, Chen-Yu Tsai,
	Jernej Skrabec, Samuel Holland, Maxime Ripard, Rafael J. Wysocki,
	Viresh Kumar, Andre Przywara
  Cc: linux-pm, devicetree, linux-arm-kernel, linux-sunxi,
	linux-kernel, Cody Eksal, Alexander Sverdlin, Rajan Yadav,
	kernel test robot

Andre asked [1], in his review of my A100 thermal trips patch [2], to
look at the A133 speed bin selection and OPPs. Mainline treats the A133
as an A100: it reads only the CPU bin field and picks one of three A100
voltage tables. The vendor BSP for this family (sun50iw10, KickPi A133
Linux SDK, linux-4.9) picks one of 11 grades from the chip marking ID,
the CPU bin, the ICPU current, a field it calls PCPU, a bin extension
bit and the die revision.

The A100 rule in mainline turns out to be the BSP rule for one group of
parts: revision A-E parts with a normal marking ID get a0-a2 from the
same bin rule and with the same voltages as the A100 table, apart from
a small ICPU/PCPU range that the BSP forces to a0. It is wrong for
revision F and later parts (a3-a6) and for the "high speed" marking IDs
(b0-b3).

My KickPi K5C (A133, PCB V1.3) is such a high speed part of revision F:
the BSP rules select b2, up to 1512 MHz at 1.10 V. Mainline selects
A100 speed1, so the chip runs 40 mV below the vendor voltage at
408-816 MHz and 40 mV above it at 1200 and 1320 MHz, and tops out at
1464 MHz at 1.18 V.

Patch 1 adds the binding, patch 2 prepares the driver without
functional change, patch 3 adds the grade selection, patch 4 adds the
efuse cells (no effect on its own), patch 5 adds the A133 OPP table and
patch 6 switches the three A133 boards in mainline to it.

Dependencies and merge path:
- On the Teclast P80, cpufreq also needs "cpufreq: sun50i: Handle
  boards with the allwinner,sun50i-a133 compatible" [3], which I sent
  separately as a fix for 7.4. The other boards do not need it.
- Patches 1-3 are meant for the cpufreq tree, as the A100 binding and
  driver changes went last time; patches 4-6 are for the sunxi tree.
- The A133 table keeps the A100 compatible as a fallback, with the
  speed bin as its first cell. So patches 5-6 do not break anything if
  they land before patch 3: a kernel without patch 3 gets today's A100
  selection and voltages (with 1008 instead of 1080 MHz).
- The thermal trips patch [2] should land first. All my thermal runs
  had it, and without it patch 6 raises the top OPP of the high speed
  grades with no passive trip.

The die revision comes from SMCCC SOC_ID, as for the H616. On the A133
only TF-A master provides it so far (sun50i_a133 platform, commit
a584e8632a7a, not in a release yet). I did not guess a grade without
it: for the same bin, the revision A-E grades are mostly lower or equal
up to 816 MHz and higher or equal from 1008 MHz. So the driver then
keeps the A100 selection, adds the BSP's a0 rule for normal parts
(which never lowers a voltage) and warns. Revision F parts then still
run 20-40 mV below the vendor voltage at 408 and 600 MHz, some of them
also at 816 MHz, which is why it is a warning; tell me if you prefer a
notice, since owners of some boards may not be able to update their
firmware.

Measurements on the K5C (no heatsink, room temperature not controlled,
4 cores at full load, the 90 C passive trip from [2] in every run):

  OPPs         kernel   top OPP          steady  1 h at full load
  A100 speed1  6.18     1464 MHz 1.18 V  85.6 C  near 90 C from ~20 min,
                                                 throttled at ~33 min
  A133 b2      6.18     1512 MHz 1.10 V  78.2 C  1512 MHz, max 83.7 C
  this series  7.4-rc1  1512 MHz 1.10 V  -       1512 MHz, max 79.4 C

"steady" is the temperature after 10 minutes in a separate run. The b2
row on 6.18 used a test DTB with the b2 voltages. Over the hour, b2 did
3.7% more work (md5 loops) than A100 speed1. At the same 1200 MHz, the
b2 voltage (0.98 V instead of 1.02 V) ran about 2 C cooler. These are
single runs on one board, so take them as indications only.

Questions:

1. 1.6 GHz. Andre mentioned the nominal 1.6 GHz OPP. The SDK's code
   and table select b2 for this chip and stop at 1512 MHz. The factory
   kernel on this board (built January 2026) has a newer table: there
   1608 MHz exists only for b0 and b1, the revision A-E high speed
   grades, at the same voltage as their 1512 MHz OPP (1.18 V and
   1.13 V), and 1416 MHz is added for a0-a2. That kernel selects b0 for
   this revision F chip; its boot log suggests that its cpufreq code
   does not read the revision (the revision is first read about 110 s
   after boot). With the series' rules this board stays b2, so adding
   1608 MHz for b0/b1 would not change it, and I have no revision A-E
   part to test. With the b0 voltages forced by a test DTB (6.18), the
   K5C was stable for an hour but sat at the 90 C trip, cycling between
   1416 and 1608 MHz, with less than 1% more work than b2. The A133
   datasheet says 1.6 GHz in V1.1 and 1.5 GHz in V1.5. Should 1608 MHz
   be added for speed6/7 (b0/b1), as in the factory table?
2. A100. The BSP uses the same rules for the A100, and the mainline A100
   table has the a0-a2 voltages, but at 1080 MHz where the BSP has
   1008 MHz. U-Boot starts the CPU at 1008 MHz, so mainline now logs
   "unlisted initial frequency". Should the A100 table move to
   1008 MHz too, or the A100 board to the new compatible? I can only
   test an A133.
3. SOC_ID. Would you rather have the driver read the revision from
   SYSCON+0x24 itself (the system controller is already in the DT)?
   Then it would not depend on the firmware, and parts would never run
   below the vendor voltage for lack of it. And do the Teclast P80 and
   the Helperboard run a TF-A with SOC_ID?
4. A133P. My SDK has no A133P data, and Andre expects it to go
   higher. An A133P whose marking ID is in the BSP's high speed list
   gets b grades with A133 voltages; otherwise it gets a grades (at
   most 1464 MHz). If someone has a newer BSP (5.4) with A133P tables
   and marking IDs, I can add them.
5. Testing. Patch 6 changes the Helperboard A133, Liontron H-A133L and
   Teclast P80, which I cannot test. A boot log with
   dyndbg="file sun50i-cpufreq-nvmem.c +p" on the kernel command line,
   and the contents of
   /sys/devices/system/cpu/cpu0/cpufreq/scaling_available_frequencies,
   from those boards would be very welcome; no fuse dump is needed. On
   the P80 (secure boot), could someone also check SID bytes 0-1 (the
   marking ID)? If they read as 0 from Linux, a high speed part is
   treated as a normal one: it gets 1464 MHz instead of 1416 and
   1512 MHz and, if its bin extension bit is set, up to 20 mV less than
   its b grade would give.

As agreed with Chen-Yu on the thermal trips thread [2], the
dynamic-power-coefficient for the power allocator will follow as a
separate patch on top of these OPPs.

AI assistance: I used Claude Code (Anthropic, Claude Opus 5.5)
throughout. It read the vendor BSP sources, the datasheets and my board
logs, drafted the code, the DT table and the commit messages, and wrote
the test scripts. I asked it to extract the vendor's selection rules,
to propose a design that fits the existing binding, to review the
series, and to write tests that compare the code with the BSP rules.
No vendor code was copied; only the rules and numbers were taken. I
reviewed every patch, ran all tests myself, and take responsibility
for the series.

Testing:
- host: the grade function, built from the driver source, matches the
  BSP rules for 120,960 combinations of boundary and typical field
  values, reaches all 11 grades and gives the A100 selection with the
  BSP's a0 rule when the revision is unknown; a second harness,
  written separately (also with Claude Code) from the BSP sources,
  checked 161,280,000 combinations with no difference
- host: a script compared every voltage and the frequency set of every
  grade with the BSP table: no difference
- each patch on its own: checkpatch --strict (one expected warning:
  the new OPP dtsi is covered by the existing MAINTAINERS entry), W=1
  build, sparse (patch 2 removes the one existing warning in the
  driver), dt_binding_check, and dtbs_check W=1 on the A100 perf1 and
  the three A133 boards; the binding rejects malformed test tables
- K5C: grade, OPPs and measured regulator voltages, a 1 h soak, the
  revision forced to unknown, the A100 table on the patched kernel, the
  new DTB on a kernel without patch 3 (fallback), the a133-only root
  compatible, and a missing efuse cell

[1] https://lore.kernel.org/all/85dc4135-4684-4e17-95e4-833cf8753b64@arm.com/
[2] https://lore.kernel.org/all/20261103-a100-thermal-trips-v1-1-73bce7ff0767@gmail.com/
[3] https://lore.kernel.org/all/20261104-a133-fix-v1-1-d0b5ad3d4c5d@gmail.com/

---
Rajan Yadav (6):
      dt-bindings: opp: h6: Add A133 operating points
      cpufreq: sun50i: Move nvmem cell reading into a helper
      cpufreq: sun50i: Add A133 speed grade detection
      arm64: dts: allwinner: a100: Add A133 speed grade efuse cells
      arm64: dts: allwinner: a133: Add CPU OPP table
      arm64: dts: allwinner: a133: Use the A133 CPU OPP table

 .../opp/allwinner,sun50i-h6-operating-points.yaml  |  94 ++++++++-
 arch/arm64/boot/dts/allwinner/sun50i-a100.dtsi     |  12 ++
 .../boot/dts/allwinner/sun50i-a133-cpu-opp.dtsi    | 172 +++++++++++++++++
 .../allwinner/sun50i-a133-helperboard-core.dtsi    |   2 +-
 .../dts/allwinner/sun50i-a133-liontron-h-a133l.dts |   2 +-
 .../boot/dts/allwinner/sun50i-a133-teclast-p80.dts |   2 +-
 drivers/cpufreq/sun50i-cpufreq-nvmem.c             | 213 +++++++++++++++++++--
 7 files changed, 465 insertions(+), 32 deletions(-)
---
base-commit: 6628e7d4c6b25c8d18f1345e3a20d21829aae7e4
change-id: 20261104-a133-series-fb6c0de346cc
prerequisite-message-id: <20261104-a133-fix-v1-1-d0b5ad3d4c5d@gmail.com>
prerequisite-patch-id: 24b8eeb24a7f228410c3453027ff79fc785eb38d

Best regards,
--  
Rajan Yadav <rajanyadav0307@gmail.com>



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

* [PATCH 1/6] dt-bindings: opp: h6: Add A133 operating points
  2026-11-05  4:40 [PATCH 0/6] sunxi: A133: Add CPU speed grade detection and OPP table Rajan Yadav via B4 Relay
@ 2026-11-05  4:40 ` Rajan Yadav via B4 Relay
  2026-11-05  4:40 ` [PATCH 2/6] cpufreq: sun50i: Move nvmem cell reading into a helper Rajan Yadav via B4 Relay
                   ` (5 subsequent siblings)
  6 siblings, 0 replies; 9+ messages in thread
From: Rajan Yadav via B4 Relay @ 2026-11-05  4:40 UTC (permalink / raw)
  To: Yangtao Li, Viresh Kumar, Nishanth Menon, Stephen Boyd,
	Rob Herring, Krzysztof Kozlowski, Conor Dooley, Chen-Yu Tsai,
	Jernej Skrabec, Samuel Holland, Maxime Ripard, Rafael J. Wysocki,
	Viresh Kumar, Andre Przywara
  Cc: linux-pm, devicetree, linux-arm-kernel, linux-sunxi,
	linux-kernel, Cody Eksal, Alexander Sverdlin, Rajan Yadav

From: Rajan Yadav <rajanyadav0307@gmail.com>

The vendor BSP for the A100/A133 family (sun50iw10) selects the CPU
speed grade from four efuse fields and the die revision: the speed bin
(SID offset 0x1c, which also holds the ICPU current), the chip marking
ID (0x00), a value programmed at production that the BSP calls PCPU
(0x20) and a bin extension bit (0x28). It knows 11 grades, a0-a6 and
b0-b3. The A100 operating points describe only three speed bins, taken
from 0x1c.

Add allwinner,sun50i-a133-operating-points for this. In its tables the
N of opp-microvolt-speedN is the vendor grade: 0-5 are a0-a5 (a6 has
the same OPPs and voltages as a5) and 6-9 are b0-b3. The four cells are
named, with the speed bin first. The meaning of the PCPU field is not
documented; the name follows the vendor BSP.

Indices 0-2 are the vendor grades a0-a2, which have the voltages of the
three A100 speed bins. So allwinner,sun50i-a100-operating-points is a
valid fallback: software that knows only the A100 compatible reads the
first cell, selects one of speed0-2 with the A100 rule and gets the
OPPs and voltages of the A100 table today, with 1008 instead of
1080 MHz. That is the A100 selection, not the vendor's; the new
compatible adds the vendor's. The binding requires indices 0-2 to stay
usable this way.

The new compatible is SoC specific, like the root compatible
allwinner,sun50i-a133; the A100 compatible stays as it is for existing
DTBs. The schema now also limits the other compatibles to the single
unnamed cell that all in-tree users have.

Claude Code (Anthropic) drafted this change and its message from the
vendor BSP sources (field layout and numbers only, no code copied); I
reviewed it and checked it with dt_binding_check and dtbs_check.

Signed-off-by: Rajan Yadav <rajanyadav0307@gmail.com>
---
 .../opp/allwinner,sun50i-h6-operating-points.yaml  | 94 ++++++++++++++++++++--
 1 file changed, 86 insertions(+), 8 deletions(-)

diff --git a/Documentation/devicetree/bindings/opp/allwinner,sun50i-h6-operating-points.yaml b/Documentation/devicetree/bindings/opp/allwinner,sun50i-h6-operating-points.yaml
index 75ab552f6ec..5fa6a1074da 100644
--- a/Documentation/devicetree/bindings/opp/allwinner,sun50i-h6-operating-points.yaml
+++ b/Documentation/devicetree/bindings/opp/allwinner,sun50i-h6-operating-points.yaml
@@ -16,24 +16,70 @@ description: |
   Voltage Scaling Tables define the voltage and frequency values based
   on the speedbin blown in the efuse combination.
 
+  With allwinner,sun50i-a133-operating-points, the speed bin index N of
+  opp-microvolt-speedN and opp-supported-hw is the speed grade of the
+  Allwinner BSP: 0-5 are a0-a5 (a6 uses the a5 values) and 6-9 are b0-b3.
+  Indices 0-2 must be usable as the A100 speed bins 0-2, because software
+  using the A100 fallback compatible selects only these.
+
 allOf:
   - $ref: opp-v2-base.yaml#
+  - if:
+      properties:
+        compatible:
+          contains:
+            const: allwinner,sun50i-a133-operating-points
+    then:
+      properties:
+        nvmem-cells:
+          minItems: 4
+      required:
+        - nvmem-cell-names
+    else:
+      properties:
+        nvmem-cells:
+          maxItems: 1
+        nvmem-cell-names: false
 
 properties:
   compatible:
-    enum:
-      - allwinner,sun50i-a100-operating-points
-      - allwinner,sun50i-h6-operating-points
-      - allwinner,sun50i-h616-operating-points
+    oneOf:
+      - enum:
+          - allwinner,sun50i-a100-operating-points
+          - allwinner,sun50i-h6-operating-points
+          - allwinner,sun50i-h616-operating-points
+      - items:
+          - const: allwinner,sun50i-a133-operating-points
+          - const: allwinner,sun50i-a100-operating-points
 
   nvmem-cells:
     description: |
-      A phandle pointing to a nvmem-cells node representing the efuse
-      register that has information about the speedbin that is used
-      to select the right frequency/voltage value pair. Please refer
-      to the nvmem-cells bindings in
+      Phandles pointing to nvmem-cells nodes representing the efuse
+      registers that have information about the speedbin that is used
+      to select the right frequency/voltage value pair. Please refer to
+      the nvmem-cells bindings in
       Documentation/devicetree/bindings/nvmem/nvmem.yaml and also the
       examples below.
+    minItems: 1
+    items:
+      - description:
+          Speed bin, or the chip marking ID on the H616. With the A133
+          compatible, bits 15:12 are the CPU bin and bits 11:0 the ICPU
+          current in units of 0.1 mA.
+      - description: Chip marking ID.
+      - description:
+          Value programmed at production, called PCPU by Allwinner. Bits
+          11:0 are used together with the ICPU current to select the speed
+          grade; their unit is not documented.
+      - description:
+          Bin extension. Bit 31 is used to select the speed grade.
+
+  nvmem-cell-names:
+    items:
+      - const: bin
+      - const: marking
+      - const: pcpu
+      - const: bin-ext
 
   opp-shared: true
 
@@ -132,4 +178,36 @@ examples:
         };
     };
 
+  - |
+    opp-table {
+        compatible = "allwinner,sun50i-a133-operating-points",
+                     "allwinner,sun50i-a100-operating-points";
+        nvmem-cells = <&cpu_speed_grade>, <&chip_marking>,
+                      <&cpu_pcpu>, <&cpu_bin_ext>;
+        nvmem-cell-names = "bin", "marking", "pcpu", "bin-ext";
+        opp-shared;
+
+        opp-408000000 {
+            clock-latency-ns = <244144>; /* 8 32k periods */
+            opp-hz = /bits/ 64 <408000000>;
+
+            opp-microvolt-speed0 = <900000>;
+            opp-microvolt-speed1 = <900000>;
+            opp-microvolt-speed2 = <900000>;
+            opp-microvolt-speed8 = <940000>;
+            opp-supported-hw = <0x107>;
+        };
+
+        opp-1512000000 {
+            clock-latency-ns = <244144>; /* 8 32k periods */
+            opp-hz = /bits/ 64 <1512000000>;
+
+            opp-microvolt-speed6 = <1180000>;
+            opp-microvolt-speed7 = <1130000 1130000 1140000>;
+            opp-microvolt-speed8 = <1100000>;
+            opp-microvolt-speed9 = <1080000>;
+            opp-supported-hw = <0x3c0>;
+        };
+    };
+
 ...

-- 
2.34.1



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

* [PATCH 2/6] cpufreq: sun50i: Move nvmem cell reading into a helper
  2026-11-05  4:40 [PATCH 0/6] sunxi: A133: Add CPU speed grade detection and OPP table Rajan Yadav via B4 Relay
  2026-11-05  4:40 ` [PATCH 1/6] dt-bindings: opp: h6: Add A133 operating points Rajan Yadav via B4 Relay
@ 2026-11-05  4:40 ` Rajan Yadav via B4 Relay
  2026-11-05  4:40 ` [PATCH 3/6] cpufreq: sun50i: Add A133 speed grade detection Rajan Yadav via B4 Relay
                   ` (4 subsequent siblings)
  6 siblings, 0 replies; 9+ messages in thread
From: Rajan Yadav via B4 Relay @ 2026-11-05  4:40 UTC (permalink / raw)
  To: Yangtao Li, Viresh Kumar, Nishanth Menon, Stephen Boyd,
	Rob Herring, Krzysztof Kozlowski, Conor Dooley, Chen-Yu Tsai,
	Jernej Skrabec, Samuel Holland, Maxime Ripard, Rafael J. Wysocki,
	Viresh Kumar, Andre Przywara
  Cc: linux-pm, devicetree, linux-arm-kernel, linux-sunxi,
	linux-kernel, Cody Eksal, Alexander Sverdlin, kernel test robot,
	Rajan Yadav

From: Rajan Yadav <rajanyadav0307@gmail.com>

The A133 speed grade needs several efuse cells, but the cell reading
is open coded in sun50i_cpufreq_get_efuse() for a single cell. Move it
into sun50i_cpufreq_read_cell(), which takes the cell name, so the next
patch can read the A133 cells by name.

No functional change: the existing users read the first cell, as
before, with the same length check, byte order and error message. The
raw bytes are now held in a __le32, the type le32_to_cpu() expects,
which also removes the sparse warning "cast to restricted __le32" that
the kernel test robot reported.

Claude Code (Anthropic) drafted this refactor and its message; I
reviewed and tested it.

Reported-by: kernel test robot <lkp@intel.com>
Closes: https://lore.kernel.org/oe-kbuild-all/202603021703.aBD0w99y-lkp@intel.com/
Signed-off-by: Rajan Yadav <rajanyadav0307@gmail.com>
---
 drivers/cpufreq/sun50i-cpufreq-nvmem.c | 55 ++++++++++++++++++++--------------
 1 file changed, 33 insertions(+), 22 deletions(-)

diff --git a/drivers/cpufreq/sun50i-cpufreq-nvmem.c b/drivers/cpufreq/sun50i-cpufreq-nvmem.c
index 9261d148a16..34c0897c22c 100644
--- a/drivers/cpufreq/sun50i-cpufreq-nvmem.c
+++ b/drivers/cpufreq/sun50i-cpufreq-nvmem.c
@@ -31,6 +31,34 @@ struct sunxi_cpufreq_data {
 	u32 (*efuse_xlate)(u32 speedbin);
 };
 
+static int sun50i_cpufreq_read_cell(struct device *cpu_dev,
+				    struct device_node *np, const char *id,
+				    u32 *value)
+{
+	struct nvmem_cell *cell;
+	void *buf;
+	size_t len;
+	__le32 tmp = 0;
+
+	cell = of_nvmem_cell_get(np, id);
+	if (IS_ERR(cell))
+		return dev_err_probe(cpu_dev, PTR_ERR(cell),
+				     "Could not get nvmem cell\n");
+
+	buf = nvmem_cell_read(cell, &len);
+	nvmem_cell_put(cell);
+	if (IS_ERR(buf))
+		return PTR_ERR(buf);
+
+	if (len <= 4)
+		memcpy(&tmp, buf, len);
+	*value = le32_to_cpu(tmp);
+
+	kfree(buf);
+
+	return 0;
+}
+
 static u32 sun50i_h6_efuse_xlate(u32 speedbin)
 {
 	u32 efuse_value;
@@ -191,12 +219,9 @@ static bool dt_has_supported_hw(void)
 static int sun50i_cpufreq_get_efuse(void)
 {
 	const struct sunxi_cpufreq_data *opp_data;
-	struct nvmem_cell *speedbin_nvmem;
 	const struct of_device_id *match;
 	struct device *cpu_dev;
-	void *speedbin_ptr;
-	u32 speedbin = 0;
-	size_t len;
+	u32 speedbin;
 	int ret;
 
 	cpu_dev = get_cpu_device(0);
@@ -214,25 +239,11 @@ static int sun50i_cpufreq_get_efuse(void)
 
 	opp_data = match->data;
 
-	speedbin_nvmem = of_nvmem_cell_get(np, NULL);
-	if (IS_ERR(speedbin_nvmem))
-		return dev_err_probe(cpu_dev, PTR_ERR(speedbin_nvmem),
-				     "Could not get nvmem cell\n");
-
-	speedbin_ptr = nvmem_cell_read(speedbin_nvmem, &len);
-	nvmem_cell_put(speedbin_nvmem);
-	if (IS_ERR(speedbin_ptr))
-		return PTR_ERR(speedbin_ptr);
-
-	if (len <= 4)
-		memcpy(&speedbin, speedbin_ptr, len);
-	speedbin = le32_to_cpu(speedbin);
-
-	ret = opp_data->efuse_xlate(speedbin);
-
-	kfree(speedbin_ptr);
+	ret = sun50i_cpufreq_read_cell(cpu_dev, np, NULL, &speedbin);
+	if (ret)
+		return ret;
 
-	return ret;
+	return opp_data->efuse_xlate(speedbin);
 };
 
 static int sun50i_cpufreq_nvmem_probe(struct platform_device *pdev)

-- 
2.34.1



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

* [PATCH 3/6] cpufreq: sun50i: Add A133 speed grade detection
  2026-11-05  4:40 [PATCH 0/6] sunxi: A133: Add CPU speed grade detection and OPP table Rajan Yadav via B4 Relay
  2026-11-05  4:40 ` [PATCH 1/6] dt-bindings: opp: h6: Add A133 operating points Rajan Yadav via B4 Relay
  2026-11-05  4:40 ` [PATCH 2/6] cpufreq: sun50i: Move nvmem cell reading into a helper Rajan Yadav via B4 Relay
@ 2026-11-05  4:40 ` Rajan Yadav via B4 Relay
  2026-11-05  4:40 ` [PATCH 4/6] arm64: dts: allwinner: a100: Add A133 speed grade efuse cells Rajan Yadav via B4 Relay
                   ` (3 subsequent siblings)
  6 siblings, 0 replies; 9+ messages in thread
From: Rajan Yadav via B4 Relay @ 2026-11-05  4:40 UTC (permalink / raw)
  To: Yangtao Li, Viresh Kumar, Nishanth Menon, Stephen Boyd,
	Rob Herring, Krzysztof Kozlowski, Conor Dooley, Chen-Yu Tsai,
	Jernej Skrabec, Samuel Holland, Maxime Ripard, Rafael J. Wysocki,
	Viresh Kumar, Andre Przywara
  Cc: linux-pm, devicetree, linux-arm-kernel, linux-sunxi,
	linux-kernel, Cody Eksal, Alexander Sverdlin, Rajan Yadav

From: Rajan Yadav <rajanyadav0307@gmail.com>

The A133 is handled as an A100 today: only the CPU bin field at SID
offset 0x1c is read, which gives one of three A100 voltage tables.
The vendor BSP for this family (sun50iw10) selects one of 11 grades
from the chip marking ID, the CPU bin, the ICPU current, the PCPU
field, a bin extension bit and the die revision:

- "high speed" marking IDs use the b0-b3 grades, which have 1416 and
  1512 MHz instead of 1464 MHz
- the other parts use a0-a6
- die revisions 0, 3 and 4 ("A-E") use different grades from all other
  revisions ("F and later")
- revision A-E normal parts with ICPU and PCPU within fixed ranges use
  a0

On a KickPi K5C (A133, marking 0x1400, bin 0b010, revision 6), the BSP
selects b2: 408-1512 MHz with 1.10 V at 1512 MHz. Mainline selects the
A100 speed1 table instead. So the chip runs 40 mV below the vendor
voltage at 408-816 MHz and 40 mV above it at 1200 and 1320 MHz, and its
top OPP is 1464 MHz at 1.18 V instead of 1512 MHz at 1.10 V. Grades
with 1416 and 1512 MHz cannot be described at all.

Add the vendor selection for the new A133 OPP compatible. a5 and a6
share their voltages, so the 11 grades map to speed0-9:

  index:  0  1  2  3  4  5      6  7  8  9
  vendor: a0 a1 a2 a3 a4 a5/a6  b0 b1 b2 b3

The die revision comes from SMCCC SOC_ID, as for the H616. On the A133
this needs TF-A with the sun50i_a133 platform, added in commit
a584e8632a7a ("feat(allwinner): add support for allwinner A133 SoC")
and not yet in a release; it reads the same SYSCON register as the
BSP. Neither the A-E nor the F grades always have the lower voltage
(for the same bin, A-E is mostly lower or equal up to 816 MHz and higher
or equal from 1008 MHz). So without SOC_ID the driver keeps the A100
selection, as before, adds the BSP's a0 rule for normal parts, which
never lowers a voltage, and warns. Revision F parts then still run
20-40 mV below the vendor voltage at 408 and 600 MHz, some of them also
at 816 MHz.

The error message for a missing named cell now names the cell.

Testing:
- the function, built on the host from the driver source with stubbed
  cells and revision, matches a transcription of the BSP rules for
  120,960 combinations of boundary and typical field values, and gives
  the A100 selection with the BSP's a0 rule when the revision is
  unknown
- on the K5C it selects b2; the vdd-cpu regulator reads 0.94 V at
  408 MHz, 0.96 V at 1008 MHz, 1.06 V at 1416 MHz and 1.10 V at
  1512 MHz, as in the BSP table
- one hour of full load held 1512 MHz without throttling (max 79 C,
  with the 90 C trip from the A100 thermal trips patch)
- with the revision forced to unknown it warns and selects speed1
- the same kernel with the A100 OPP table gives the same OPPs as
  before
- a missing cell fails the probe with an error naming the cell, and
  the system keeps running without cpufreq

Claude Code (Anthropic) drafted this patch and its message from the
selection rules in the vendor BSP cpufreq driver (no code copied) and
from my test results; I reviewed and tested it.

Suggested-by: Andre Przywara <andre.przywara@arm.com>
Signed-off-by: Rajan Yadav <rajanyadav0307@gmail.com>
---
 drivers/cpufreq/sun50i-cpufreq-nvmem.c | 162 ++++++++++++++++++++++++++++++++-
 1 file changed, 161 insertions(+), 1 deletion(-)

diff --git a/drivers/cpufreq/sun50i-cpufreq-nvmem.c b/drivers/cpufreq/sun50i-cpufreq-nvmem.c
index 34c0897c22c..6bccea2887b 100644
--- a/drivers/cpufreq/sun50i-cpufreq-nvmem.c
+++ b/drivers/cpufreq/sun50i-cpufreq-nvmem.c
@@ -27,8 +27,10 @@
 
 static struct platform_device *cpufreq_dt_pdev, *sun50i_cpufreq_pdev;
 
+/* Exactly one of the two callbacks is set */
 struct sunxi_cpufreq_data {
 	u32 (*efuse_xlate)(u32 speedbin);
+	int (*get_speed)(struct device *cpu_dev, struct device_node *np);
 };
 
 static int sun50i_cpufreq_read_cell(struct device *cpu_dev,
@@ -41,9 +43,14 @@ static int sun50i_cpufreq_read_cell(struct device *cpu_dev,
 	__le32 tmp = 0;
 
 	cell = of_nvmem_cell_get(np, id);
-	if (IS_ERR(cell))
+	if (IS_ERR(cell)) {
+		if (id)
+			return dev_err_probe(cpu_dev, PTR_ERR(cell),
+					     "Could not get nvmem cell %s\n",
+					     id);
 		return dev_err_probe(cpu_dev, PTR_ERR(cell),
 				     "Could not get nvmem cell\n");
+	}
 
 	buf = nvmem_cell_read(cell, &len);
 	nvmem_cell_put(cell);
@@ -152,6 +159,149 @@ static u32 sun50i_h616_efuse_xlate(u32 speedbin)
 	return value;
 }
 
+/*
+ * A133 speed grades, as selected by the vendor BSP (sun50iw10): a0-a6 for
+ * normal parts and b0-b3 for "high speed" parts. a5 and a6 have the same
+ * OPPs and voltages and share an index. The index is the N of
+ * opp-microvolt-speedN and the bit in opp-supported-hw. a0-a2 have the
+ * same voltages as the A100 speed0-speed2.
+ */
+enum sun50i_a133_grade {
+	SUN50I_A133_GRADE_A0,
+	SUN50I_A133_GRADE_A1,
+	SUN50I_A133_GRADE_A2,
+	SUN50I_A133_GRADE_A3,
+	SUN50I_A133_GRADE_A4,
+	SUN50I_A133_GRADE_A5,		/* also a6 */
+	SUN50I_A133_GRADE_B0,
+	SUN50I_A133_GRADE_B1,
+	SUN50I_A133_GRADE_B2,
+	SUN50I_A133_GRADE_B3,
+};
+
+#define SUN50I_A133_MARKING_MASK	0xffff
+#define SUN50I_A133_BIN_SHIFT		12
+#define SUN50I_A133_BIN_MASK		0xf
+#define SUN50I_A133_ICPU_MASK		0xfff
+#define SUN50I_A133_PCPU_MASK		0xfff
+#define SUN50I_A133_BIN_EXT		BIT(31)
+#define SUN50I_A133_REV_MASK		0x7
+
+/*
+ * The BSP runs revision A-E normal parts at a0 when both the ICPU current
+ * (in 0.1 mA) and the PCPU field are in these ranges (upper bounds
+ * exclusive).
+ */
+#define SUN50I_A133_ICPU_A0_MIN		84
+#define SUN50I_A133_ICPU_A0_MAX		160
+#define SUN50I_A133_PCPU_A0_MIN		2900
+#define SUN50I_A133_PCPU_A0_MAX		3100
+
+static bool sun50i_a133_force_a0(u32 icpu, u32 pcpu)
+{
+	return icpu >= SUN50I_A133_ICPU_A0_MIN &&
+	       icpu < SUN50I_A133_ICPU_A0_MAX &&
+	       pcpu >= SUN50I_A133_PCPU_A0_MIN &&
+	       pcpu < SUN50I_A133_PCPU_A0_MAX;
+}
+
+/* Marking IDs that the BSP treats as "high speed" parts */
+static bool sun50i_a133_is_high_speed(u32 marking)
+{
+	switch (marking) {
+	case 0x0200:
+	case 0x0600:
+	case 0x0620:
+	case 0x0640:
+	case 0x0800:
+	case 0x1000:
+	case 0x1400:
+	case 0x2000:
+	case 0x4000:
+		return true;
+	default:
+		return false;
+	}
+}
+
+static int sun50i_a133_get_speed(struct device *cpu_dev,
+				 struct device_node *np)
+{
+	u32 marking, bin_cell, pcpu, bin_ext, bin, icpu;
+	enum sun50i_a133_grade grade;
+	int ver_bits, ver;
+	bool before_f;
+	int ret;
+
+	ret = sun50i_cpufreq_read_cell(cpu_dev, np, "marking", &marking);
+	if (ret)
+		return ret;
+	ret = sun50i_cpufreq_read_cell(cpu_dev, np, "bin", &bin_cell);
+	if (ret)
+		return ret;
+	ret = sun50i_cpufreq_read_cell(cpu_dev, np, "pcpu", &pcpu);
+	if (ret)
+		return ret;
+	ret = sun50i_cpufreq_read_cell(cpu_dev, np, "bin-ext", &bin_ext);
+	if (ret)
+		return ret;
+
+	marking &= SUN50I_A133_MARKING_MASK;
+	bin = (bin_cell >> SUN50I_A133_BIN_SHIFT) & SUN50I_A133_BIN_MASK;
+	icpu = bin_cell & SUN50I_A133_ICPU_MASK;
+	pcpu &= SUN50I_A133_PCPU_MASK;
+
+	/*
+	 * Neither the revision A-E nor the revision F grades always have the
+	 * lower voltage, so there is no safe guess without the revision.
+	 * Keep the A100 selection then (a0-a2), which these SoCs used so far,
+	 * plus the BSP's a0 rule for normal parts, which never lowers a
+	 * voltage. Revision F parts then still run 20-40 mV below the vendor
+	 * voltage at 408 and 600 MHz, some of them also at 816 MHz, and "high
+	 * speed" parts get 1464 MHz instead of 1416 and 1512 MHz.
+	 */
+	ver_bits = get_soc_id_revision();
+	if (ver_bits < 0) {
+		dev_warn(cpu_dev,
+			 "SMCCC SOC_ID not available, using speed grades a0-a2\n");
+		if (!sun50i_a133_is_high_speed(marking) &&
+		    sun50i_a133_force_a0(icpu, pcpu))
+			return SUN50I_A133_GRADE_A0;
+		return sun50i_a100_efuse_xlate(bin_cell);
+	}
+
+	/*
+	 * The BSP treats revisions 0, 3 and 4 as "A-E" and all others as
+	 * "F and later".
+	 */
+	ver = ver_bits & SUN50I_A133_REV_MASK;
+	before_f = ver == 0 || ver == 3 || ver == 4;
+
+	if (sun50i_a133_is_high_speed(marking)) {
+		if (bin == 0b100)
+			grade = before_f ? SUN50I_A133_GRADE_B1 :
+					   SUN50I_A133_GRADE_B3;
+		else
+			grade = before_f ? SUN50I_A133_GRADE_B0 :
+					   SUN50I_A133_GRADE_B2;
+	} else if (!before_f && (bin_ext & SUN50I_A133_BIN_EXT)) {
+		grade = SUN50I_A133_GRADE_A5;		/* a6 */
+	} else if (before_f && sun50i_a133_force_a0(icpu, pcpu)) {
+		grade = SUN50I_A133_GRADE_A0;
+	} else if (bin == 0b100) {
+		grade = before_f ? SUN50I_A133_GRADE_A2 : SUN50I_A133_GRADE_A5;
+	} else if (bin == 0b010) {
+		grade = before_f ? SUN50I_A133_GRADE_A1 : SUN50I_A133_GRADE_A4;
+	} else {
+		grade = before_f ? SUN50I_A133_GRADE_A0 : SUN50I_A133_GRADE_A3;
+	}
+
+	dev_dbg(cpu_dev, "marking 0x%04x, bin %u, revision %d: speed grade %d\n",
+		marking, bin, ver, grade);
+
+	return grade;
+}
+
 static struct sunxi_cpufreq_data sun50i_h6_cpufreq_data = {
 	.efuse_xlate = sun50i_h6_efuse_xlate,
 };
@@ -160,6 +310,10 @@ static struct sunxi_cpufreq_data sun50i_a100_cpufreq_data = {
 	.efuse_xlate = sun50i_a100_efuse_xlate,
 };
 
+static struct sunxi_cpufreq_data sun50i_a133_cpufreq_data = {
+	.get_speed = sun50i_a133_get_speed,
+};
+
 static struct sunxi_cpufreq_data sun50i_h616_cpufreq_data = {
 	.efuse_xlate = sun50i_h616_efuse_xlate,
 };
@@ -171,6 +325,9 @@ static const struct of_device_id cpu_opp_match_list[] = {
 	{ .compatible = "allwinner,sun50i-a100-operating-points",
 	  .data = &sun50i_a100_cpufreq_data,
 	},
+	{ .compatible = "allwinner,sun50i-a133-operating-points",
+	  .data = &sun50i_a133_cpufreq_data,
+	},
 	{ .compatible = "allwinner,sun50i-h616-operating-points",
 	  .data = &sun50i_h616_cpufreq_data,
 	},
@@ -239,6 +396,9 @@ static int sun50i_cpufreq_get_efuse(void)
 
 	opp_data = match->data;
 
+	if (opp_data->get_speed)
+		return opp_data->get_speed(cpu_dev, np);
+
 	ret = sun50i_cpufreq_read_cell(cpu_dev, np, NULL, &speedbin);
 	if (ret)
 		return ret;

-- 
2.34.1



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

* [PATCH 4/6] arm64: dts: allwinner: a100: Add A133 speed grade efuse cells
  2026-11-05  4:40 [PATCH 0/6] sunxi: A133: Add CPU speed grade detection and OPP table Rajan Yadav via B4 Relay
                   ` (2 preceding siblings ...)
  2026-11-05  4:40 ` [PATCH 3/6] cpufreq: sun50i: Add A133 speed grade detection Rajan Yadav via B4 Relay
@ 2026-11-05  4:40 ` Rajan Yadav via B4 Relay
  2026-11-05  4:41 ` [PATCH 5/6] arm64: dts: allwinner: a133: Add CPU OPP table Rajan Yadav via B4 Relay
                   ` (2 subsequent siblings)
  6 siblings, 0 replies; 9+ messages in thread
From: Rajan Yadav via B4 Relay @ 2026-11-05  4:40 UTC (permalink / raw)
  To: Yangtao Li, Viresh Kumar, Nishanth Menon, Stephen Boyd,
	Rob Herring, Krzysztof Kozlowski, Conor Dooley, Chen-Yu Tsai,
	Jernej Skrabec, Samuel Holland, Maxime Ripard, Rafael J. Wysocki,
	Viresh Kumar, Andre Przywara
  Cc: linux-pm, devicetree, linux-arm-kernel, linux-sunxi,
	linux-kernel, Cody Eksal, Alexander Sverdlin, Rajan Yadav

From: Rajan Yadav <rajanyadav0307@gmail.com>

The A133 speed grade selection also needs the chip marking ID (SID
offset 0x00), the word at 0x20, whose low 12 bits the vendor BSP calls
PCPU, and the word at 0x28 with the bin extension bit. Add nvmem cells
for them at the offsets the BSP uses. The H616 reads the same kind of
marking ID at offset 0x00 as its speed grade.

The cells are used by the A133 OPP table added later in this series;
the A100 OPP table keeps using only the existing 0x1c cell.

Claude Code (Anthropic) drafted this change and its message from the
vendor BSP device tree; I reviewed it and checked it with dtbs_check.

Signed-off-by: Rajan Yadav <rajanyadav0307@gmail.com>
---
 arch/arm64/boot/dts/allwinner/sun50i-a100.dtsi | 12 ++++++++++++
 1 file changed, 12 insertions(+)

diff --git a/arch/arm64/boot/dts/allwinner/sun50i-a100.dtsi b/arch/arm64/boot/dts/allwinner/sun50i-a100.dtsi
index ba6020989ce..d1164f3b549 100644
--- a/arch/arm64/boot/dts/allwinner/sun50i-a100.dtsi
+++ b/arch/arm64/boot/dts/allwinner/sun50i-a100.dtsi
@@ -176,6 +176,10 @@ efuse@3006000 {
 			#address-cells = <1>;
 			#size-cells = <1>;
 
+			chip_marking: chip-marking@0 {
+				reg = <0x0 0x2>;
+			};
+
 			ths_calibration: calib@14 {
 				reg = <0x14 8>;
 			};
@@ -183,6 +187,14 @@ ths_calibration: calib@14 {
 			cpu_speed_grade: cpu-speed-grade@1c {
 				reg = <0x1c 0x2>;
 			};
+
+			cpu_pcpu: cpu-pcpu@20 {
+				reg = <0x20 0x2>;
+			};
+
+			cpu_bin_ext: cpu-bin-ext@28 {
+				reg = <0x28 0x4>;
+			};
 		};
 
 		watchdog@30090a0 {

-- 
2.34.1



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

* [PATCH 5/6] arm64: dts: allwinner: a133: Add CPU OPP table
  2026-11-05  4:40 [PATCH 0/6] sunxi: A133: Add CPU speed grade detection and OPP table Rajan Yadav via B4 Relay
                   ` (3 preceding siblings ...)
  2026-11-05  4:40 ` [PATCH 4/6] arm64: dts: allwinner: a100: Add A133 speed grade efuse cells Rajan Yadav via B4 Relay
@ 2026-11-05  4:41 ` Rajan Yadav via B4 Relay
  2026-11-05  4:41 ` [PATCH 6/6] arm64: dts: allwinner: a133: Use the A133 " Rajan Yadav via B4 Relay
  2026-11-05 11:30 ` [PATCH 0/6] sunxi: A133: Add CPU speed grade detection and " Andre Przywara
  6 siblings, 0 replies; 9+ messages in thread
From: Rajan Yadav via B4 Relay @ 2026-11-05  4:41 UTC (permalink / raw)
  To: Yangtao Li, Viresh Kumar, Nishanth Menon, Stephen Boyd,
	Rob Herring, Krzysztof Kozlowski, Conor Dooley, Chen-Yu Tsai,
	Jernej Skrabec, Samuel Holland, Maxime Ripard, Rafael J. Wysocki,
	Viresh Kumar, Andre Przywara
  Cc: linux-pm, devicetree, linux-arm-kernel, linux-sunxi,
	linux-kernel, Cody Eksal, Alexander Sverdlin, Rajan Yadav

From: Rajan Yadav <rajanyadav0307@gmail.com>

Add the A133 CPU OPPs from the vendor BSP (sun50iw10p1.dtsi). There
are ten voltage sets, speed0-5 for the a0-a5/a6 grades and speed6-9
for the "high speed" b0-b3 grades. opp-supported-hw selects the
frequencies of each grade:

- 1464 MHz only for the a grades
- 1416 and 1512 MHz only for the b grades
- 408-1320 MHz for all

The highest voltage is 1.18 V, inside the 0.81-1.2 V recommended
operating range of VDD_CPU in the A133 datasheet (V1.5, table 5-2).

The BSP uses 1008 MHz where the A100 table uses 1080 MHz, at the same
voltages for a0-a2. U-Boot starts the CPU at 1008 MHz, which mainline
now reports as an unlisted initial frequency. This table follows the
BSP. The BSP table stops at 1512 MHz, so there is no 1608 MHz OPP,
although some datasheet versions list 1.6 GHz for the A133. A newer
factory kernel adds 1608 MHz for b0 and b1 only; that is left for a
follow-up.

The table has the A100 compatible as a fallback and the speed bin cell
first, so a kernel without A133 support selects speed0-2 from the speed
bin and gets the voltages of the A100 table, with 1008 instead of
1080 MHz. It needs the efuse cells added to sun50i-a100.dtsi in the
previous patch.

A script compared every voltage and the frequency set of every grade
with the BSP file and found no difference.

Claude Code (Anthropic) drafted this table and its message from the
vendor BSP device tree (numbers only) and wrote the comparison script;
I reviewed it and tested it on a KickPi K5C.

Suggested-by: Andre Przywara <andre.przywara@arm.com>
Signed-off-by: Rajan Yadav <rajanyadav0307@gmail.com>
---
 .../boot/dts/allwinner/sun50i-a133-cpu-opp.dtsi    | 172 +++++++++++++++++++++
 1 file changed, 172 insertions(+)

diff --git a/arch/arm64/boot/dts/allwinner/sun50i-a133-cpu-opp.dtsi b/arch/arm64/boot/dts/allwinner/sun50i-a133-cpu-opp.dtsi
new file mode 100644
index 00000000000..12b6612a920
--- /dev/null
+++ b/arch/arm64/boot/dts/allwinner/sun50i-a133-cpu-opp.dtsi
@@ -0,0 +1,172 @@
+// SPDX-License-Identifier: (GPL-2.0+ OR MIT)
+// Copyright (C) 2026 Rajan Yadav <rajanyadav0307@gmail.com>
+/*
+ * A133 CPU OPPs. The voltages and grade selection follow the Allwinner
+ * vendor BSP (sun50iw10p1.dtsi). Index 0-5 are the vendor's a0-a5 grades
+ * (a6 uses the a5 values), index 6-9 are the "high speed" b0-b3 grades.
+ * This needs the efuse cells from sun50i-a100.dtsi.
+ */
+
+/ {
+	cpu_opp_table: opp-table-cpu {
+		compatible = "allwinner,sun50i-a133-operating-points",
+			     "allwinner,sun50i-a100-operating-points";
+		nvmem-cells = <&cpu_speed_grade>, <&chip_marking>,
+			      <&cpu_pcpu>, <&cpu_bin_ext>;
+		nvmem-cell-names = "bin", "marking", "pcpu", "bin-ext";
+		opp-shared;
+
+		opp-408000000 {
+			clock-latency-ns = <244144>; /* 8 32k periods */
+			opp-hz = /bits/ 64 <408000000>;
+
+			opp-microvolt-speed0 = <900000>;
+			opp-microvolt-speed1 = <900000>;
+			opp-microvolt-speed2 = <900000>;
+			opp-microvolt-speed3 = <940000>;
+			opp-microvolt-speed4 = <940000>;
+			opp-microvolt-speed5 = <920000>;
+			opp-microvolt-speed6 = <900000>;
+			opp-microvolt-speed7 = <900000>;
+			opp-microvolt-speed8 = <940000>;
+			opp-microvolt-speed9 = <920000>;
+			opp-supported-hw = <0x3ff>;
+		};
+
+		opp-600000000 {
+			clock-latency-ns = <244144>; /* 8 32k periods */
+			opp-hz = /bits/ 64 <600000000>;
+
+			opp-microvolt-speed0 = <900000>;
+			opp-microvolt-speed1 = <900000>;
+			opp-microvolt-speed2 = <900000>;
+			opp-microvolt-speed3 = <940000>;
+			opp-microvolt-speed4 = <940000>;
+			opp-microvolt-speed5 = <920000>;
+			opp-microvolt-speed6 = <900000>;
+			opp-microvolt-speed7 = <900000>;
+			opp-microvolt-speed8 = <940000>;
+			opp-microvolt-speed9 = <920000>;
+			opp-supported-hw = <0x3ff>;
+		};
+
+		opp-816000000 {
+			clock-latency-ns = <244144>; /* 8 32k periods */
+			opp-hz = /bits/ 64 <816000000>;
+
+			opp-microvolt-speed0 = <940000>;
+			opp-microvolt-speed1 = <900000>;
+			opp-microvolt-speed2 = <900000>;
+			opp-microvolt-speed3 = <940000>;
+			opp-microvolt-speed4 = <940000>;
+			opp-microvolt-speed5 = <920000>;
+			opp-microvolt-speed6 = <900000>;
+			opp-microvolt-speed7 = <900000>;
+			opp-microvolt-speed8 = <940000>;
+			opp-microvolt-speed9 = <920000>;
+			opp-supported-hw = <0x3ff>;
+		};
+
+		opp-1008000000 {
+			clock-latency-ns = <244144>; /* 8 32k periods */
+			opp-hz = /bits/ 64 <1008000000>;
+
+			opp-microvolt-speed0 = <1020000>;
+			opp-microvolt-speed1 = <980000>;
+			opp-microvolt-speed2 = <950000>;
+			opp-microvolt-speed3 = <1020000>;
+			opp-microvolt-speed4 = <960000>;
+			opp-microvolt-speed5 = <940000>;
+			opp-microvolt-speed6 = <980000>;
+			opp-microvolt-speed7 = <950000>;
+			opp-microvolt-speed8 = <960000>;
+			opp-microvolt-speed9 = <940000>;
+			opp-supported-hw = <0x3ff>;
+		};
+
+		opp-1200000000 {
+			clock-latency-ns = <244144>; /* 8 32k periods */
+			opp-hz = /bits/ 64 <1200000000>;
+
+			opp-microvolt-speed0 = <1100000>;
+			opp-microvolt-speed1 = <1020000>;
+			opp-microvolt-speed2 = <1000000>;
+			opp-microvolt-speed3 = <1100000>;
+			opp-microvolt-speed4 = <980000>;
+			opp-microvolt-speed5 = <960000>;
+			opp-microvolt-speed6 = <1020000>;
+			opp-microvolt-speed7 = <1000000>;
+			opp-microvolt-speed8 = <980000>;
+			opp-microvolt-speed9 = <960000>;
+			opp-supported-hw = <0x3ff>;
+		};
+
+		opp-1320000000 {
+			clock-latency-ns = <244144>; /* 8 32k periods */
+			opp-hz = /bits/ 64 <1320000000>;
+
+			opp-microvolt-speed0 = <1160000>;
+			opp-microvolt-speed1 = <1060000>;
+			opp-microvolt-speed2 = <1030000>;
+			opp-microvolt-speed3 = <1160000>;
+			opp-microvolt-speed4 = <1020000>;
+			opp-microvolt-speed5 = <1000000>;
+			opp-microvolt-speed6 = <1060000>;
+			opp-microvolt-speed7 = <1030000>;
+			opp-microvolt-speed8 = <1020000>;
+			opp-microvolt-speed9 = <1000000>;
+			opp-supported-hw = <0x3ff>;
+		};
+
+		opp-1416000000 {
+			clock-latency-ns = <244144>; /* 8 32k periods */
+			opp-hz = /bits/ 64 <1416000000>;
+
+			opp-microvolt-speed6 = <1100000>;
+			opp-microvolt-speed7 = <1070000>;
+			opp-microvolt-speed8 = <1060000>;
+			opp-microvolt-speed9 = <1040000>;
+			opp-supported-hw = <0x3c0>;
+		};
+
+		opp-1464000000 {
+			clock-latency-ns = <244144>; /* 8 32k periods */
+			opp-hz = /bits/ 64 <1464000000>;
+
+			opp-microvolt-speed0 = <1180000>;
+			opp-microvolt-speed1 = <1180000>;
+			opp-microvolt-speed2 = <1130000>;
+			opp-microvolt-speed3 = <1180000>;
+			opp-microvolt-speed4 = <1100000>;
+			opp-microvolt-speed5 = <1080000>;
+			opp-supported-hw = <0x3f>;
+		};
+
+		opp-1512000000 {
+			clock-latency-ns = <244144>; /* 8 32k periods */
+			opp-hz = /bits/ 64 <1512000000>;
+
+			opp-microvolt-speed6 = <1180000>;
+			opp-microvolt-speed7 = <1130000 1130000 1140000>;
+			opp-microvolt-speed8 = <1100000>;
+			opp-microvolt-speed9 = <1080000>;
+			opp-supported-hw = <0x3c0>;
+		};
+	};
+};
+
+&cpu0 {
+	operating-points-v2 = <&cpu_opp_table>;
+};
+
+&cpu1 {
+	operating-points-v2 = <&cpu_opp_table>;
+};
+
+&cpu2 {
+	operating-points-v2 = <&cpu_opp_table>;
+};
+
+&cpu3 {
+	operating-points-v2 = <&cpu_opp_table>;
+};

-- 
2.34.1



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

* [PATCH 6/6] arm64: dts: allwinner: a133: Use the A133 CPU OPP table
  2026-11-05  4:40 [PATCH 0/6] sunxi: A133: Add CPU speed grade detection and OPP table Rajan Yadav via B4 Relay
                   ` (4 preceding siblings ...)
  2026-11-05  4:41 ` [PATCH 5/6] arm64: dts: allwinner: a133: Add CPU OPP table Rajan Yadav via B4 Relay
@ 2026-11-05  4:41 ` Rajan Yadav via B4 Relay
  2026-11-05 11:30 ` [PATCH 0/6] sunxi: A133: Add CPU speed grade detection and " Andre Przywara
  6 siblings, 0 replies; 9+ messages in thread
From: Rajan Yadav via B4 Relay @ 2026-11-05  4:41 UTC (permalink / raw)
  To: Yangtao Li, Viresh Kumar, Nishanth Menon, Stephen Boyd,
	Rob Herring, Krzysztof Kozlowski, Conor Dooley, Chen-Yu Tsai,
	Jernej Skrabec, Samuel Holland, Maxime Ripard, Rafael J. Wysocki,
	Viresh Kumar, Andre Przywara
  Cc: linux-pm, devicetree, linux-arm-kernel, linux-sunxi,
	linux-kernel, Cody Eksal, Alexander Sverdlin, Rajan Yadav

From: Rajan Yadav <rajanyadav0307@gmail.com>

Switch the three A133 boards in mainline (Baijie Helperboard A133,
Liontron H-A133L and Teclast P80) from the A100 OPP table to the A133
one, so the speed grade is selected as the vendor does it.

What changes depends on the chip:
- revision A-E parts with a normal marking ID get a0-a2 from the bin
  field, as they get speed0-2 today, with the same voltages; only
  1080 MHz becomes 1008 MHz. The exception is a part whose ICPU and
  PCPU values are in the range for which the BSP forces a0.
- revision F and later parts with a normal marking ID get the a3-a6
  voltages: higher at 408 and 600 MHz, equal or lower from 1008 MHz,
  and 1008 instead of 1080 MHz.
- "high speed" parts get the b grades, with 1416 and 1512 MHz instead
  of 1464 MHz.
- if the firmware does not provide SMCCC SOC_ID, the driver keeps the
  A100 selection, adds the BSP's a0 rule for normal parts and warns at
  boot.

All three boards supply the CPUs from AXP803 DCDC2 with a 0.81-1.2 V
range, which covers every new voltage. Without the A133 support in
sun50i-cpufreq-nvmem the A100 fallback applies. The Teclast P80 also
needs "cpufreq: sun50i: Handle boards with the allwinner,sun50i-a133
compatible" to get cpufreq at all.

Claude Code (Anthropic) drafted this change and its message; I
reviewed it. I tested the A133 table on a KickPi K5C; I cannot test
these three boards.

Suggested-by: Andre Przywara <andre.przywara@arm.com>
Signed-off-by: Rajan Yadav <rajanyadav0307@gmail.com>
---
 arch/arm64/boot/dts/allwinner/sun50i-a133-helperboard-core.dtsi | 2 +-
 arch/arm64/boot/dts/allwinner/sun50i-a133-liontron-h-a133l.dts  | 2 +-
 arch/arm64/boot/dts/allwinner/sun50i-a133-teclast-p80.dts       | 2 +-
 3 files changed, 3 insertions(+), 3 deletions(-)

diff --git a/arch/arm64/boot/dts/allwinner/sun50i-a133-helperboard-core.dtsi b/arch/arm64/boot/dts/allwinner/sun50i-a133-helperboard-core.dtsi
index 545972d2324..3a89d3f74b3 100644
--- a/arch/arm64/boot/dts/allwinner/sun50i-a133-helperboard-core.dtsi
+++ b/arch/arm64/boot/dts/allwinner/sun50i-a133-helperboard-core.dtsi
@@ -7,7 +7,7 @@
 /dts-v1/;
 
 #include "sun50i-a100.dtsi"
-#include "sun50i-a100-cpu-opp.dtsi"
+#include "sun50i-a133-cpu-opp.dtsi"
 
 /{
 	model = "Baijie A133 HelperBoard Core";
diff --git a/arch/arm64/boot/dts/allwinner/sun50i-a133-liontron-h-a133l.dts b/arch/arm64/boot/dts/allwinner/sun50i-a133-liontron-h-a133l.dts
index 90a50910f07..1b9cbcbe5f3 100644
--- a/arch/arm64/boot/dts/allwinner/sun50i-a133-liontron-h-a133l.dts
+++ b/arch/arm64/boot/dts/allwinner/sun50i-a133-liontron-h-a133l.dts
@@ -6,7 +6,7 @@
 /dts-v1/;
 
 #include "sun50i-a100.dtsi"
-#include "sun50i-a100-cpu-opp.dtsi"
+#include "sun50i-a133-cpu-opp.dtsi"
 
 #include <dt-bindings/gpio/gpio.h>
 #include <dt-bindings/leds/common.h>
diff --git a/arch/arm64/boot/dts/allwinner/sun50i-a133-teclast-p80.dts b/arch/arm64/boot/dts/allwinner/sun50i-a133-teclast-p80.dts
index 47b5f2ac824..7d4c346276e 100644
--- a/arch/arm64/boot/dts/allwinner/sun50i-a133-teclast-p80.dts
+++ b/arch/arm64/boot/dts/allwinner/sun50i-a133-teclast-p80.dts
@@ -6,7 +6,7 @@
 /dts-v1/;
 
 #include "sun50i-a100.dtsi"
-#include "sun50i-a100-cpu-opp.dtsi"
+#include "sun50i-a133-cpu-opp.dtsi"
 
 #include <dt-bindings/gpio/gpio.h>
 

-- 
2.34.1



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

* Re: [PATCH 0/6] sunxi: A133: Add CPU speed grade detection and OPP table
  2026-11-05  4:40 [PATCH 0/6] sunxi: A133: Add CPU speed grade detection and OPP table Rajan Yadav via B4 Relay
                   ` (5 preceding siblings ...)
  2026-11-05  4:41 ` [PATCH 6/6] arm64: dts: allwinner: a133: Use the A133 " Rajan Yadav via B4 Relay
@ 2026-11-05 11:30 ` Andre Przywara
  2026-11-05 14:49   ` Rajan Yadav
  6 siblings, 1 reply; 9+ messages in thread
From: Andre Przywara @ 2026-11-05 11:30 UTC (permalink / raw)
  To: rajanyadav0307, Yangtao Li, Viresh Kumar, Nishanth Menon,
	Stephen Boyd, Rob Herring, Krzysztof Kozlowski, Conor Dooley,
	Chen-Yu Tsai, Jernej Skrabec, Samuel Holland, Maxime Ripard,
	Rafael J. Wysocki, Viresh Kumar
  Cc: linux-pm, devicetree, linux-arm-kernel, linux-sunxi,
	linux-kernel, Cody Eksal, Alexander Sverdlin, Paul Kocialkowski

Hi Rajan,

many thanks for putting this together, especially for really going deep 
into the problem, and trying to sort out the messy ID scheme that 
Allwinner employs here.

Jumping straight to the questions you asked below:

On 11/5/26 05:40, Rajan Yadav via B4 Relay wrote:
> Andre asked [1], in his review of my A100 thermal trips patch [2], to
> look at the A133 speed bin selection and OPPs. Mainline treats the A133
> as an A100: it reads only the CPU bin field and picks one of three A100
> voltage tables. The vendor BSP for this family (sun50iw10, KickPi A133
> Linux SDK, linux-4.9) picks one of 11 grades from the chip marking ID,

[ ... ]>
> Questions:
> 
> 1. 1.6 GHz. Andre mentioned the nominal 1.6 GHz OPP. The SDK's code
>     and table select b2 for this chip and stop at 1512 MHz. The factory
>     kernel on this board (built January 2026) has a newer table: there
>     1608 MHz exists only for b0 and b1, the revision A-E high speed
>     grades, at the same voltage as their 1512 MHz OPP (1.18 V and
>     1.13 V), and 1416 MHz is added for a0-a2. That kernel selects b0 for
>     this revision F chip; its boot log suggests that its cpufreq code
>     does not read the revision (the revision is first read about 110 s
>     after boot). With the series' rules this board stays b2, so adding
>     1608 MHz for b0/b1 would not change it, and I have no revision A-E
>     part to test. With the b0 voltages forced by a test DTB (6.18), the
>     K5C was stable for an hour but sat at the 90 C trip, cycling between
>     1416 and 1608 MHz, with less than 1% more work than b2. The A133
>     datasheet says 1.6 GHz in V1.1 and 1.5 GHz in V1.5. Should 1608 MHz
>     be added for speed6/7 (b0/b1), as in the factory table?

So I read about the 1.6GHz somewhere, might just be a marketing claim 
about some max frequency. If the common speedbins do not support 1.6GHz, 
that's fine, but apparently some do, so I'd keep them in, for people who 
happen to have those SoC revisions.

> 2. A100. The BSP uses the same rules for the A100, and the mainline A100
>     table has the a0-a2 voltages, but at 1080 MHz where the BSP has
>     1008 MHz. U-Boot starts the CPU at 1008 MHz, so mainline now logs
>     "unlisted initial frequency". Should the A100 table move to
>     1008 MHz too, or the A100 board to the new compatible? I can only
>     test an A133.

I don't think we have ever seen A100s in the wild really, reportedly 
they got phased out very early in favour of the better performing A133. 
A100 is just used as a name because it was the only name back then when 
support was upstreamed, and in the kernel we tend to not care too much 
about vendors' marketing and naming strategies too much ... ;-)
I think if we can be sure that the current mainline OPPs still apply 
with this series, that's good enough.

Regarding 1008 MHz: This was just some frequency close to 1GHz picked by 
U-Boot, that should be low enough to not cause any trouble, even with 
the default voltage. How critical is this "unlisted initial frequency" 
message? If it causes trouble, we can add a made-up 1008MHz OPP with 
some safe voltage, otherwise I'd say we just leave it.

 > 3. SOC_ID. Would you rather have the driver read the revision from> 
   SYSCON+0x24 itself (the system controller is already in the DT)?
>     Then it would not depend on the firmware, and parts would never run
>     below the vendor voltage for lack of it. And do the Teclast P80 and
>     the Helperboard run a TF-A with SOC_ID?

We simply do not support non-mainline firmware, both TF-A and U-Boot, 
with a mainline kernel. For older SoCs they were just not compatible, 
but I don't know about the exact situation with newer parts.
So like for the H616, please just use the SoC ID call, that's a clean 
solution. Maybe just make sure that it can fail somewhat gracefully 
(read: not crash).

> 4. A133P. My SDK has no A133P data, and Andre expects it to go
>     higher. An A133P whose marking ID is in the BSP's high speed list
>     gets b grades with A133 voltages; otherwise it gets a grades (at
>     most 1464 MHz). If someone has a newer BSP (5.4) with A133P tables
>     and marking IDs, I can add them.

I have just read that the "P" allegedly stands for "performance", and 
this it can clock up to 1.8 GHz. So again, just use what the BSP OPP 
table tells us. We are in no position to qualify enough parts to make 
such a decision. And we can always extend the table later should new 
data appear.
I think some of those handheld gaming consoles use the A133P variant? 
Maybe there are some tables in "their" source code?

> 5. Testing. Patch 6 changes the Helperboard A133, Liontron H-A133L and
>     Teclast P80, which I cannot test. A boot log with
>     dyndbg="file sun50i-cpufreq-nvmem.c +p" on the kernel command line,
>     and the contents of
>     /sys/devices/system/cpu/cpu0/cpufreq/scaling_available_frequencies,
>     from those boards would be very welcome; no fuse dump is needed. On
>     the P80 (secure boot), could someone also check SID bytes 0-1 (the
>     marking ID)? If they read as 0 from Linux, a high speed part is
>     treated as a normal one: it gets 1464 MHz instead of 1416 and
>     1512 MHz and, if its bin extension bit is set, up to 20 mV less than
>     its b grade would give.

Thanks, I will try to get those logs, I have the Liontron board and the 
Teclast tablet.

Thanks,
Andre

P.S. Since you mention the KickPi: can you please work with Paul (in 
CC:) to upstream the DT for this board? Seems to be one of the more sane 
and available devices with this SoC. I think Paul has plans to submit 
DTs upstream, but I guess he will be happy to have taken some load off 
his chest on this.

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

* Re: [PATCH 0/6] sunxi: A133: Add CPU speed grade detection and OPP table
  2026-11-05 11:30 ` [PATCH 0/6] sunxi: A133: Add CPU speed grade detection and " Andre Przywara
@ 2026-11-05 14:49   ` Rajan Yadav
  0 siblings, 0 replies; 9+ messages in thread
From: Rajan Yadav @ 2026-11-05 14:49 UTC (permalink / raw)
  To: Andre Przywara
  Cc: Yangtao Li, Viresh Kumar, Nishanth Menon, Stephen Boyd,
	Rob Herring, Krzysztof Kozlowski, Conor Dooley, Chen-Yu Tsai,
	Jernej Skrabec, Samuel Holland, Maxime Ripard, Rafael J. Wysocki,
	Viresh Kumar, linux-pm, devicetree, linux-arm-kernel,
	linux-sunxi, linux-kernel, Cody Eksal, Alexander Sverdlin,
	Paul Kocialkowski

Hi Andre,

Thanks a lot for the quick and detailed answers!

On 11/5/26 12:30, Andre Przywara wrote:
> So I read about the 1.6GHz somewhere, might just be a marketing claim
> about some max frequency. If the common speedbins do not support 1.6GHz,
> that's fine, but apparently some do, so I'd keep them in, for people who
> happen to have those SoC revisions.

OK, v2 will add 1608 MHz for b0 and b1. The SDK table stops at
1512 MHz; 1608 MHz is only in the table of the factory firmware on my
board (its kernel was built in January 2026, the SDK import is from
October 2024). I compared the two tables entry by entry: the factory
table is the SDK table plus five OPPs, all other values are the same:

  1608 MHz: b0 1.18 V, b1 1.13 V (max 1.14 V)
  1416 MHz: a0 1.18 V, a1 1.18 V, a2 1.13 V

Should I add the 1416 MHz OPPs for a0-a2 as well, so that the table
matches the factory one?

> I think if we can be sure that the current mainline OPPs still apply
> with this series, that's good enough.

They do. The series does not change the A100 code path (patch 2 only
moves the cell reading into a helper), and on the K5C the patched
kernel with today's A100 table gives the same OPPs and voltages as
before. A 6.18 kernel without the series and with the new A133 table
falls back to the A100 selection (with 1008 instead of 1080 MHz).

> Regarding 1008 MHz: This was just some frequency close to 1GHz picked by
> U-Boot, that should be low enough to not cause any trouble, even with
> the default voltage. How critical is this "unlisted initial frequency"
> message? If it causes trouble, we can add a made-up 1008MHz OPP with
> some safe voltage, otherwise I'd say we just leave it.

Not critical. It is a pr_info, and cpufreq switches right away to the
next higher OPP (1080 MHz). With the A133 table it does not appear,
since that table has 1008 MHz, as the BSP does. So I would leave the
A100 table as it is.

> So like for the H616, please just use the SoC ID call, that's a clean
> solution. Maybe just make sure that it can fail somewhat gracefully
> (read: not crash).

That is what the series does. Without SOC_ID the driver warns
"SMCCC SOC_ID not available, using speed grades a0-a2", falls back to
the A100 selection (plus the BSP's a0 rule for normal parts) and
continues. I tested this on the K5C with a test build that forces the
revision to unknown.

> I think some of those handheld gaming consoles use the A133P variant?
> Maybe there are some tables in "their" source code?

Good idea, I will look for those.

> Thanks, I will try to get those logs, I have the Liontron board and the
> Teclast tablet.

Thank you! I will wait for your logs and the other reviews before
sending v2.

> P.S. Since you mention the KickPi: can you please work with Paul (in
> CC:) to upstream the DT for this board?

Yes, happy to. Paul, I have a K5C DT that I run on mainline kernels
(6.18 and 7.4-rc1): eMMC, SD card, USB host and the PMIC work.
Ethernet needs a PHY driver (Maxio MAE0621A) that is not in mainline
yet, and the Wi-Fi/BT chip (Seekwave) has no mainline driver. The
"kickpi" vendor prefix is not in mainline either. How would you like to
do this: should I send the DT with you in Cc, or do you already have a
version I should build on?

Thanks,
Rajan

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

end of thread, other threads:[~2026-11-05 14:49 UTC | newest]

Thread overview: 9+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2026-11-05  4:40 [PATCH 0/6] sunxi: A133: Add CPU speed grade detection and OPP table Rajan Yadav via B4 Relay
2026-11-05  4:40 ` [PATCH 1/6] dt-bindings: opp: h6: Add A133 operating points Rajan Yadav via B4 Relay
2026-11-05  4:40 ` [PATCH 2/6] cpufreq: sun50i: Move nvmem cell reading into a helper Rajan Yadav via B4 Relay
2026-11-05  4:40 ` [PATCH 3/6] cpufreq: sun50i: Add A133 speed grade detection Rajan Yadav via B4 Relay
2026-11-05  4:40 ` [PATCH 4/6] arm64: dts: allwinner: a100: Add A133 speed grade efuse cells Rajan Yadav via B4 Relay
2026-11-05  4:41 ` [PATCH 5/6] arm64: dts: allwinner: a133: Add CPU OPP table Rajan Yadav via B4 Relay
2026-11-05  4:41 ` [PATCH 6/6] arm64: dts: allwinner: a133: Use the A133 " Rajan Yadav via B4 Relay
2026-11-05 11:30 ` [PATCH 0/6] sunxi: A133: Add CPU speed grade detection and " Andre Przywara
2026-11-05 14:49   ` Rajan Yadav

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®