[<prev] [next>] [<thread-prev] [thread-next>] [day] [month] [year] [list]
Message-Id: <20231220095141.27883-2-fusibrandon13@gmail.com>
Date: Wed, 20 Dec 2023 10:51:40 +0100
From: Brandon Cheo Fusi <fusibrandon13@...il.com>
To: Rob Herring <robh+dt@...nel.org>,
Krzysztof Kozlowski <krzysztof.kozlowski+dt@...aro.org>,
Conor Dooley <conor+dt@...nel.org>,
Paul Walmsley <paul.walmsley@...ive.com>,
Palmer Dabbelt <palmer@...belt.com>,
Albert Ou <aou@...s.berkeley.edu>,
Chen-Yu Tsai <wens@...e.org>,
Jernej Skrabec <jernej.skrabec@...il.com>,
Samuel Holland <samuel@...lland.org>,
Yangtao Li <tiny.windzz@...il.com>,
"Rafael J . Wysocki" <rafael@...nel.org>,
Viresh Kumar <viresh.kumar@...aro.org>
Cc: devicetree@...r.kernel.org,
linux-arm-kernel@...ts.infradead.org,
linux-sunxi@...ts.linux.dev,
linux-riscv@...ts.infradead.org,
linux-kernel@...r.kernel.org,
linux-pm@...r.kernel.org,
Brandon Cheo Fusi <fusibrandon13@...il.com>
Subject: [RFC PATCH 1/2] cpufreq: sun50i: Add support for D1's speed bin decoding
Adds support for decoding the efuse value read from D1 efuse speed
bins, and factors out equivalent code for sun50i.
The algorithm is gotten from
https://github.com/Tina-Linux/linux-5.4/blob/master/drivers/cpufreq/sun50i-cpufreq-nvmem.c#L293-L338
and maps an efuse value to either 0 or 1, with 1 meaning stable at
a lower supply voltage for the same clock frequency.
Signed-off-by: Brandon Cheo Fusi <fusibrandon13@...il.com>
---
drivers/cpufreq/sun50i-cpufreq-nvmem.c | 85 +++++++++++++++++++++-----
1 file changed, 70 insertions(+), 15 deletions(-)
diff --git a/drivers/cpufreq/sun50i-cpufreq-nvmem.c b/drivers/cpufreq/sun50i-cpufreq-nvmem.c
index ccf83780f..28afbe558 100644
--- a/drivers/cpufreq/sun50i-cpufreq-nvmem.c
+++ b/drivers/cpufreq/sun50i-cpufreq-nvmem.c
@@ -25,6 +25,66 @@
static struct platform_device *cpufreq_dt_pdev, *sun50i_cpufreq_pdev;
+struct sunxi_cpufreq_data {
+ u32 (*efuse_xlate)(u32 efuse_value);
+};
+
+static u32 sun20i_efuse_xlate(u32 efuse_value)
+{
+ u32 ret;
+
+ switch (efuse_value) {
+ case 0x5e00:
+ /* QFN package */
+ ret = 0;
+ break;
+ case 0x5c00:
+ case 0x7400:
+ /* QFN package */
+ ret = 1;
+ break;
+ case 0x5000:
+ default:
+ /* BGA package */
+ ret = 0;
+ }
+
+ return ret;
+}
+
+static u32 sun50i_efuse_xlate(u32 efuse_value)
+{
+ efuse_value = (efuse_value >> NVMEM_SHIFT) & NVMEM_MASK;
+
+ /*
+ * We treat unexpected efuse values as if the SoC was from
+ * the slowest bin. Expected efuse values are 1-3, slowest
+ * to fastest.
+ */
+ if (efuse_value >= 1 && efuse_value <= 3)
+ return efuse_value - 1;
+ else
+ return 0;
+}
+
+struct sunxi_cpufreq_data sun20i_cpufreq_data = {
+ .efuse_xlate = sun20i_efuse_xlate,
+};
+
+struct sunxi_cpufreq_data sun50i_cpufreq_data = {
+ .efuse_xlate = sun50i_efuse_xlate,
+};
+
+static const struct of_device_id cpu_opp_match_list[] = {
+ { .compatible = "allwinner,sun50i-h6-operating-points",
+ .data = &sun50i_cpufreq_data,
+ },
+ { .compatible = "allwinner,sun20i-d1-operating-points",
+ .data = &sun20i_cpufreq_data,
+ },
+ {}
+};
+
/**
* sun50i_cpufreq_get_efuse() - Determine speed grade from efuse value
* @versions: Set to the value parsed from efuse
@@ -36,9 +96,11 @@ static int sun50i_cpufreq_get_efuse(u32 *versions)
struct nvmem_cell *speedbin_nvmem;
struct device_node *np;
struct device *cpu_dev;
- u32 *speedbin, efuse_value;
+ const struct of_device_id *opp_match;
+ const struct sunxi_cpufreq_data *opp_data;
+ u32 *speedbin, efuse_value = 0;
size_t len;
- int ret;
+ int i;
cpu_dev = get_cpu_device(0);
if (!cpu_dev)
@@ -48,9 +110,8 @@ static int sun50i_cpufreq_get_efuse(u32 *versions)
if (!np)
return -ENOENT;
- ret = of_device_is_compatible(np,
- "allwinner,sun50i-h6-operating-points");
- if (!ret) {
+ opp_match = of_match_node(cpu_opp_match_list, np);
+ if (!opp_match) {
of_node_put(np);
return -ENOENT;
}
@@ -66,17 +127,11 @@ static int sun50i_cpufreq_get_efuse(u32 *versions)
if (IS_ERR(speedbin))
return PTR_ERR(speedbin);
- efuse_value = (*speedbin >> NVMEM_SHIFT) & NVMEM_MASK;
+ for (i = 0; i < len; i++)
+ efuse_value |= ((u32)speedbin[i] << (i * 8));
- /*
- * We treat unexpected efuse values as if the SoC was from
- * the slowest bin. Expected efuse values are 1-3, slowest
- * to fastest.
- */
- if (efuse_value >= 1 && efuse_value <= 3)
- *versions = efuse_value - 1;
- else
- *versions = 0;
+ opp_data = opp_match->data;
+ *versions = opp_data->efuse_xlate(efuse_value);
kfree(speedbin);
return 0;
--
2.30.2
Powered by blists - more mailing lists