1286 lines
34 KiB
Diff
1286 lines
34 KiB
Diff
From f9c3292a2a99acf817f97a2b312a98e42a5eaa2e Mon Sep 17 00:00:00 2001
|
|
From: Sebastian Reichel <sebastian.reichel@collabora.com>
|
|
Date: Thu, 18 Aug 2022 14:21:30 +0200
|
|
Subject: [PATCH 1/2] cpufreq: rockchip: Introduce driver for rk3588
|
|
|
|
This is a heavily modified port from the downstream driver.
|
|
Downstream used it for multiple rockchip generations, while
|
|
upstream just used the generic cpufreq-dt driver so far. For
|
|
rk3588 this is no longer good enough, since two regulators
|
|
need to be controlled.
|
|
|
|
Also during shutdown the correct frequency needs to be configured
|
|
for the big CPU cores to avoid a system hang when firmware tries
|
|
to bring them up at reboot time.
|
|
|
|
Signed-off-by: Sebastian Reichel <sebastian.reichel@collabora.com>
|
|
---
|
|
drivers/cpufreq/Kconfig.arm | 10 +
|
|
drivers/cpufreq/Makefile | 1 +
|
|
drivers/cpufreq/cpufreq-dt-platdev.c | 2 +
|
|
drivers/cpufreq/rockchip-cpufreq.c | 645 +++++++++++++++++++++++++++
|
|
4 files changed, 658 insertions(+)
|
|
create mode 100644 drivers/cpufreq/rockchip-cpufreq.c
|
|
|
|
diff --git a/drivers/cpufreq/Kconfig.arm b/drivers/cpufreq/Kconfig.arm
|
|
index 123b4bbfcfee..6fdc2f0430bb 100644
|
|
--- a/drivers/cpufreq/Kconfig.arm
|
|
+++ b/drivers/cpufreq/Kconfig.arm
|
|
@@ -189,6 +189,16 @@ config ARM_RASPBERRYPI_CPUFREQ
|
|
|
|
If in doubt, say N.
|
|
|
|
+config ARM_ROCKCHIP_CPUFREQ
|
|
+ tristate "Rockchip CPUfreq driver"
|
|
+ depends on ARCH_ROCKCHIP && CPUFREQ_DT
|
|
+ select PM_OPP
|
|
+ help
|
|
+ This adds the CPUFreq driver support for Rockchip SoCs,
|
|
+ based on cpufreq-dt.
|
|
+
|
|
+ If in doubt, say N.
|
|
+
|
|
config ARM_S3C64XX_CPUFREQ
|
|
bool "Samsung S3C64XX"
|
|
depends on CPU_S3C6410
|
|
diff --git a/drivers/cpufreq/Makefile b/drivers/cpufreq/Makefile
|
|
index ef8510774913..c3f8c9cd563f 100644
|
|
--- a/drivers/cpufreq/Makefile
|
|
+++ b/drivers/cpufreq/Makefile
|
|
@@ -71,6 +71,7 @@ obj-$(CONFIG_PXA3xx) += pxa3xx-cpufreq.o
|
|
obj-$(CONFIG_ARM_QCOM_CPUFREQ_HW) += qcom-cpufreq-hw.o
|
|
obj-$(CONFIG_ARM_QCOM_CPUFREQ_NVMEM) += qcom-cpufreq-nvmem.o
|
|
obj-$(CONFIG_ARM_RASPBERRYPI_CPUFREQ) += raspberrypi-cpufreq.o
|
|
+obj-$(CONFIG_ARM_ROCKCHIP_CPUFREQ) += rockchip-cpufreq.o
|
|
obj-$(CONFIG_ARM_S3C64XX_CPUFREQ) += s3c64xx-cpufreq.o
|
|
obj-$(CONFIG_ARM_S5PV210_CPUFREQ) += s5pv210-cpufreq.o
|
|
obj-$(CONFIG_ARM_SA1110_CPUFREQ) += sa1110-cpufreq.o
|
|
diff --git a/drivers/cpufreq/cpufreq-dt-platdev.c b/drivers/cpufreq/cpufreq-dt-platdev.c
|
|
index e2b20080de3a..7bc19a59be26 100644
|
|
--- a/drivers/cpufreq/cpufreq-dt-platdev.c
|
|
+++ b/drivers/cpufreq/cpufreq-dt-platdev.c
|
|
@@ -159,6 +159,8 @@ static const struct of_device_id blocklist[] __initconst = {
|
|
{ .compatible = "qcom,sm8250", },
|
|
{ .compatible = "qcom,sm8350", },
|
|
|
|
+ { .compatible = "rockchip,rk3588", },
|
|
+
|
|
{ .compatible = "st,stih407", },
|
|
{ .compatible = "st,stih410", },
|
|
{ .compatible = "st,stih418", },
|
|
diff --git a/drivers/cpufreq/rockchip-cpufreq.c b/drivers/cpufreq/rockchip-cpufreq.c
|
|
new file mode 100644
|
|
index 000000000000..0bf57ac85e60
|
|
--- /dev/null
|
|
+++ b/drivers/cpufreq/rockchip-cpufreq.c
|
|
@@ -0,0 +1,645 @@
|
|
+// SPDX-License-Identifier: GPL-2.0-only
|
|
+/*
|
|
+ * Rockchip CPUFreq Driver. This is similar to the generic DT
|
|
+ * cpufreq driver, but handles the following platform specific
|
|
+ * quirks:
|
|
+ *
|
|
+ * * support for two regulators - one for the CPU core and one
|
|
+ * for the memory interface
|
|
+ * * reboot handler to setup the reboot frequency
|
|
+ * * handling of read margin registers
|
|
+ *
|
|
+ * Copyright (C) 2017 Fuzhou Rockchip Electronics Co., Ltd
|
|
+ * Copyright (C) 2023 Collabora Ltd.
|
|
+ */
|
|
+
|
|
+#include <linux/cpu.h>
|
|
+#include <linux/cpufreq.h>
|
|
+#include <linux/err.h>
|
|
+#include <linux/init.h>
|
|
+#include <linux/kernel.h>
|
|
+#include <linux/mfd/syscon.h>
|
|
+#include <linux/module.h>
|
|
+#include <linux/of.h>
|
|
+#include <linux/of_address.h>
|
|
+#include <linux/platform_device.h>
|
|
+#include <linux/pm_opp.h>
|
|
+#include <linux/slab.h>
|
|
+#include <linux/reboot.h>
|
|
+#include <linux/regmap.h>
|
|
+#include <linux/regulator/consumer.h>
|
|
+
|
|
+#include "cpufreq-dt.h"
|
|
+
|
|
+#define RK3588_MEMCFG_HSSPRF_LOW 0x20
|
|
+#define RK3588_MEMCFG_HSDPRF_LOW 0x28
|
|
+#define RK3588_MEMCFG_HSDPRF_HIGH 0x2c
|
|
+#define RK3588_CPU_CTRL 0x30
|
|
+
|
|
+#define VOLT_RM_TABLE_END ~1
|
|
+
|
|
+static struct platform_device *cpufreq_pdev;
|
|
+static LIST_HEAD(priv_list);
|
|
+
|
|
+struct volt_rm_table {
|
|
+ uint32_t volt;
|
|
+ uint32_t rm;
|
|
+};
|
|
+
|
|
+struct rockchip_opp_info {
|
|
+ const struct rockchip_opp_data *data;
|
|
+ struct volt_rm_table *volt_rm_tbl;
|
|
+ struct regmap *grf;
|
|
+ u32 current_rm;
|
|
+ u32 reboot_freq;
|
|
+};
|
|
+
|
|
+struct private_data {
|
|
+ struct list_head node;
|
|
+
|
|
+ cpumask_var_t cpus;
|
|
+ struct device *cpu_dev;
|
|
+ struct cpufreq_frequency_table *freq_table;
|
|
+};
|
|
+
|
|
+struct rockchip_opp_data {
|
|
+ int (*set_read_margin)(struct device *dev, struct rockchip_opp_info *opp_info,
|
|
+ unsigned long volt);
|
|
+};
|
|
+
|
|
+struct cluster_info {
|
|
+ struct list_head list_head;
|
|
+ struct rockchip_opp_info opp_info;
|
|
+ cpumask_t cpus;
|
|
+};
|
|
+static LIST_HEAD(cluster_info_list);
|
|
+
|
|
+static int rk3588_cpu_set_read_margin(struct device *dev, struct rockchip_opp_info *opp_info,
|
|
+ unsigned long volt)
|
|
+{
|
|
+ bool is_found = false;
|
|
+ u32 rm;
|
|
+ int i;
|
|
+
|
|
+ if (!opp_info->volt_rm_tbl)
|
|
+ return 0;
|
|
+
|
|
+ for (i = 0; opp_info->volt_rm_tbl[i].rm != VOLT_RM_TABLE_END; i++) {
|
|
+ if (volt >= opp_info->volt_rm_tbl[i].volt) {
|
|
+ rm = opp_info->volt_rm_tbl[i].rm;
|
|
+ is_found = true;
|
|
+ break;
|
|
+ }
|
|
+ }
|
|
+
|
|
+ if (!is_found)
|
|
+ return 0;
|
|
+ if (rm == opp_info->current_rm)
|
|
+ return 0;
|
|
+ if (!opp_info->grf)
|
|
+ return 0;
|
|
+
|
|
+ dev_dbg(dev, "set rm to %d\n", rm);
|
|
+ regmap_write(opp_info->grf, RK3588_MEMCFG_HSSPRF_LOW, 0x001c0000 | (rm << 2));
|
|
+ regmap_write(opp_info->grf, RK3588_MEMCFG_HSDPRF_LOW, 0x003c0000 | (rm << 2));
|
|
+ regmap_write(opp_info->grf, RK3588_MEMCFG_HSDPRF_HIGH, 0x003c0000 | (rm << 2));
|
|
+ regmap_write(opp_info->grf, RK3588_CPU_CTRL, 0x00200020);
|
|
+ udelay(1);
|
|
+ regmap_write(opp_info->grf, RK3588_CPU_CTRL, 0x00200000);
|
|
+
|
|
+ opp_info->current_rm = rm;
|
|
+
|
|
+ return 0;
|
|
+}
|
|
+
|
|
+static const struct rockchip_opp_data rk3588_cpu_opp_data = {
|
|
+ .set_read_margin = rk3588_cpu_set_read_margin,
|
|
+};
|
|
+
|
|
+static const struct of_device_id rockchip_cpufreq_of_match[] = {
|
|
+ {
|
|
+ .compatible = "rockchip,rk3588",
|
|
+ .data = (void *)&rk3588_cpu_opp_data,
|
|
+ },
|
|
+ {},
|
|
+};
|
|
+
|
|
+static struct cluster_info *rockchip_cluster_info_lookup(int cpu)
|
|
+{
|
|
+ struct cluster_info *cluster;
|
|
+
|
|
+ list_for_each_entry(cluster, &cluster_info_list, list_head) {
|
|
+ if (cpumask_test_cpu(cpu, &cluster->cpus))
|
|
+ return cluster;
|
|
+ }
|
|
+
|
|
+ return NULL;
|
|
+}
|
|
+
|
|
+static int rockchip_cpufreq_set_volt(struct device *dev,
|
|
+ struct regulator *reg,
|
|
+ struct dev_pm_opp_supply *supply)
|
|
+{
|
|
+ int ret;
|
|
+
|
|
+ ret = regulator_set_voltage_triplet(reg, supply->u_volt_min,
|
|
+ supply->u_volt, supply->u_volt_max);
|
|
+ if (ret)
|
|
+ dev_err(dev, "%s: failed to set voltage (%lu %lu %lu uV): %d\n",
|
|
+ __func__, supply->u_volt_min, supply->u_volt,
|
|
+ supply->u_volt_max, ret);
|
|
+
|
|
+ return ret;
|
|
+}
|
|
+
|
|
+static int rockchip_cpufreq_set_read_margin(struct device *dev,
|
|
+ struct rockchip_opp_info *opp_info,
|
|
+ unsigned long volt)
|
|
+{
|
|
+ if (opp_info->data && opp_info->data->set_read_margin) {
|
|
+ opp_info->data->set_read_margin(dev, opp_info, volt);
|
|
+ }
|
|
+
|
|
+ return 0;
|
|
+}
|
|
+
|
|
+static int rk_opp_config_regulators(struct device *dev,
|
|
+ struct dev_pm_opp *old_opp, struct dev_pm_opp *new_opp,
|
|
+ struct regulator **regulators, unsigned int count)
|
|
+{
|
|
+ struct dev_pm_opp_supply old_supplies[2];
|
|
+ struct dev_pm_opp_supply new_supplies[2];
|
|
+ struct regulator *vdd_reg = regulators[0];
|
|
+ struct regulator *mem_reg = regulators[1];
|
|
+ struct rockchip_opp_info *opp_info;
|
|
+ struct cluster_info *cluster;
|
|
+ int ret = 0;
|
|
+ unsigned long old_freq = dev_pm_opp_get_freq(old_opp);
|
|
+ unsigned long new_freq = dev_pm_opp_get_freq(new_opp);
|
|
+
|
|
+ /* We must have two regulators here */
|
|
+ WARN_ON(count != 2);
|
|
+
|
|
+ ret = dev_pm_opp_get_supplies(old_opp, old_supplies);
|
|
+ if (ret)
|
|
+ return ret;
|
|
+
|
|
+ ret = dev_pm_opp_get_supplies(new_opp, new_supplies);
|
|
+ if (ret)
|
|
+ return ret;
|
|
+
|
|
+ cluster = rockchip_cluster_info_lookup(dev->id);
|
|
+ if (!cluster)
|
|
+ return -EINVAL;
|
|
+ opp_info = &cluster->opp_info;
|
|
+
|
|
+ if (new_freq >= old_freq) {
|
|
+ ret = rockchip_cpufreq_set_volt(dev, mem_reg, &new_supplies[1]);
|
|
+ if (ret)
|
|
+ goto error;
|
|
+ ret = rockchip_cpufreq_set_volt(dev, vdd_reg, &new_supplies[0]);
|
|
+ if (ret)
|
|
+ goto error;
|
|
+ rockchip_cpufreq_set_read_margin(dev, opp_info, new_supplies[0].u_volt);
|
|
+ } else {
|
|
+ rockchip_cpufreq_set_read_margin(dev, opp_info, new_supplies[0].u_volt);
|
|
+ ret = rockchip_cpufreq_set_volt(dev, vdd_reg, &new_supplies[0]);
|
|
+ if (ret)
|
|
+ goto error;
|
|
+ ret = rockchip_cpufreq_set_volt(dev, mem_reg, &new_supplies[1]);
|
|
+ if (ret)
|
|
+ goto error;
|
|
+ }
|
|
+
|
|
+ return 0;
|
|
+
|
|
+error:
|
|
+ rockchip_cpufreq_set_read_margin(dev, opp_info, old_supplies[0].u_volt);
|
|
+ rockchip_cpufreq_set_volt(dev, mem_reg, &old_supplies[1]);
|
|
+ rockchip_cpufreq_set_volt(dev, vdd_reg, &old_supplies[0]);
|
|
+ return ret;
|
|
+}
|
|
+
|
|
+static void rockchip_get_opp_data(const struct of_device_id *matches,
|
|
+ struct rockchip_opp_info *info)
|
|
+{
|
|
+ const struct of_device_id *match;
|
|
+ struct device_node *node;
|
|
+
|
|
+ node = of_find_node_by_path("/");
|
|
+ match = of_match_node(matches, node);
|
|
+ if (match && match->data)
|
|
+ info->data = match->data;
|
|
+ of_node_put(node);
|
|
+}
|
|
+
|
|
+static int rockchip_get_volt_rm_table(struct device *dev, struct device_node *np,
|
|
+ char *porp_name, struct volt_rm_table **table)
|
|
+{
|
|
+ struct volt_rm_table *rm_table;
|
|
+ const struct property *prop;
|
|
+ int count, i;
|
|
+
|
|
+ prop = of_find_property(np, porp_name, NULL);
|
|
+ if (!prop)
|
|
+ return -EINVAL;
|
|
+
|
|
+ if (!prop->value)
|
|
+ return -ENODATA;
|
|
+
|
|
+ count = of_property_count_u32_elems(np, porp_name);
|
|
+ if (count < 0)
|
|
+ return -EINVAL;
|
|
+
|
|
+ if (count % 2)
|
|
+ return -EINVAL;
|
|
+
|
|
+ rm_table = devm_kzalloc(dev, sizeof(*rm_table) * (count / 2 + 1),
|
|
+ GFP_KERNEL);
|
|
+ if (!rm_table)
|
|
+ return -ENOMEM;
|
|
+
|
|
+ for (i = 0; i < count / 2; i++) {
|
|
+ of_property_read_u32_index(np, porp_name, 2 * i,
|
|
+ &rm_table[i].volt);
|
|
+ of_property_read_u32_index(np, porp_name, 2 * i + 1,
|
|
+ &rm_table[i].rm);
|
|
+ }
|
|
+
|
|
+ rm_table[i].volt = 0;
|
|
+ rm_table[i].rm = VOLT_RM_TABLE_END;
|
|
+
|
|
+ *table = rm_table;
|
|
+
|
|
+ return 0;
|
|
+}
|
|
+
|
|
+static int rockchip_cpufreq_reboot(struct notifier_block *notifier, unsigned long event, void *cmd)
|
|
+{
|
|
+ struct cluster_info *cluster;
|
|
+ struct device *dev;
|
|
+ int freq, ret, cpu;
|
|
+
|
|
+ if (event != SYS_RESTART)
|
|
+ return NOTIFY_DONE;
|
|
+
|
|
+ for_each_possible_cpu(cpu) {
|
|
+ cluster = rockchip_cluster_info_lookup(cpu);
|
|
+ if (!cluster)
|
|
+ continue;
|
|
+
|
|
+ dev = get_cpu_device(cpu);
|
|
+ if (!dev)
|
|
+ continue;
|
|
+
|
|
+ freq = cluster->opp_info.reboot_freq;
|
|
+
|
|
+ if (freq) {
|
|
+ ret = dev_pm_opp_set_rate(dev, freq);
|
|
+ if (ret)
|
|
+ dev_err(dev, "Failed setting reboot freq for cpu %d to %d: %d\n",
|
|
+ cpu, freq, ret);
|
|
+ dev_pm_opp_remove_table(dev);
|
|
+ }
|
|
+ }
|
|
+
|
|
+ return NOTIFY_DONE;
|
|
+}
|
|
+
|
|
+static int rockchip_cpufreq_cluster_init(int cpu, struct cluster_info *cluster)
|
|
+{
|
|
+ struct rockchip_opp_info *opp_info = &cluster->opp_info;
|
|
+ int reg_table_token = -EINVAL;
|
|
+ int opp_table_token = -EINVAL;
|
|
+ struct device_node *np;
|
|
+ struct device *dev;
|
|
+ const char * const reg_names[] = { "cpu", "mem", NULL };
|
|
+ int ret = 0;
|
|
+
|
|
+ dev = get_cpu_device(cpu);
|
|
+ if (!dev)
|
|
+ return -ENODEV;
|
|
+
|
|
+ if (!of_find_property(dev->of_node, "cpu-supply", NULL))
|
|
+ return -ENOENT;
|
|
+
|
|
+ np = of_parse_phandle(dev->of_node, "operating-points-v2", 0);
|
|
+ if (!np) {
|
|
+ dev_warn(dev, "OPP-v2 not supported\n");
|
|
+ return -ENOENT;
|
|
+ }
|
|
+
|
|
+ reg_table_token = dev_pm_opp_set_regulators(dev, reg_names);
|
|
+ if (reg_table_token < 0) {
|
|
+ ret = reg_table_token;
|
|
+ dev_err_probe(dev, ret, "Failed to set opp regulators\n");
|
|
+ goto np_err;
|
|
+ }
|
|
+
|
|
+ ret = dev_pm_opp_of_get_sharing_cpus(dev, &cluster->cpus);
|
|
+ if (ret) {
|
|
+ dev_err_probe(dev, ret, "Failed to get sharing cpus\n");
|
|
+ goto np_err;
|
|
+ }
|
|
+
|
|
+ rockchip_get_opp_data(rockchip_cpufreq_of_match, opp_info);
|
|
+ if (opp_info->data && opp_info->data->set_read_margin) {
|
|
+ opp_info->current_rm = UINT_MAX;
|
|
+ opp_info->grf = syscon_regmap_lookup_by_phandle(np, "rockchip,grf");
|
|
+ if (IS_ERR(opp_info->grf))
|
|
+ opp_info->grf = NULL;
|
|
+ rockchip_get_volt_rm_table(dev, np, "rockchip,volt-mem-read-margin", &opp_info->volt_rm_tbl);
|
|
+
|
|
+ of_property_read_u32(np, "rockchip,reboot-freq", &opp_info->reboot_freq);
|
|
+ }
|
|
+
|
|
+ opp_table_token = dev_pm_opp_set_config_regulators(dev, rk_opp_config_regulators);
|
|
+ if (opp_table_token < 0) {
|
|
+ ret = opp_table_token;
|
|
+ dev_err(dev, "Failed to set opp config regulators\n");
|
|
+ goto reg_opp_table;
|
|
+ }
|
|
+
|
|
+ of_node_put(np);
|
|
+
|
|
+ return 0;
|
|
+
|
|
+reg_opp_table:
|
|
+ if (reg_table_token >= 0)
|
|
+ dev_pm_opp_put_regulators(reg_table_token);
|
|
+np_err:
|
|
+ of_node_put(np);
|
|
+
|
|
+ return ret;
|
|
+}
|
|
+
|
|
+static struct notifier_block rockchip_cpufreq_reboot_notifier = {
|
|
+ .notifier_call = rockchip_cpufreq_reboot,
|
|
+ .priority = 0,
|
|
+};
|
|
+
|
|
+static struct freq_attr *cpufreq_rockchip_attr[] = {
|
|
+ &cpufreq_freq_attr_scaling_available_freqs,
|
|
+ NULL,
|
|
+};
|
|
+
|
|
+static int cpufreq_online(struct cpufreq_policy *policy)
|
|
+{
|
|
+ /* We did light-weight tear down earlier, nothing to do here */
|
|
+ return 0;
|
|
+}
|
|
+
|
|
+static int cpufreq_offline(struct cpufreq_policy *policy)
|
|
+{
|
|
+ /*
|
|
+ * Preserve policy->driver_data and don't free resources on light-weight
|
|
+ * tear down.
|
|
+ */
|
|
+ return 0;
|
|
+}
|
|
+
|
|
+static struct private_data *rockchip_cpufreq_find_data(int cpu)
|
|
+{
|
|
+ struct private_data *priv;
|
|
+
|
|
+ list_for_each_entry(priv, &priv_list, node) {
|
|
+ if (cpumask_test_cpu(cpu, priv->cpus))
|
|
+ return priv;
|
|
+ }
|
|
+
|
|
+ return NULL;
|
|
+}
|
|
+
|
|
+static int cpufreq_init(struct cpufreq_policy *policy)
|
|
+{
|
|
+ struct private_data *priv;
|
|
+ struct device *cpu_dev;
|
|
+ struct clk *cpu_clk;
|
|
+ unsigned int transition_latency;
|
|
+ int ret;
|
|
+
|
|
+ priv = rockchip_cpufreq_find_data(policy->cpu);
|
|
+ if (!priv) {
|
|
+ pr_err("failed to find data for cpu%d\n", policy->cpu);
|
|
+ return -ENODEV;
|
|
+ }
|
|
+ cpu_dev = priv->cpu_dev;
|
|
+
|
|
+ cpu_clk = clk_get(cpu_dev, NULL);
|
|
+ if (IS_ERR(cpu_clk)) {
|
|
+ ret = PTR_ERR(cpu_clk);
|
|
+ dev_err(cpu_dev, "%s: failed to get clk: %d\n", __func__, ret);
|
|
+ return ret;
|
|
+ }
|
|
+
|
|
+ transition_latency = dev_pm_opp_get_max_transition_latency(cpu_dev);
|
|
+ if (!transition_latency)
|
|
+ transition_latency = CPUFREQ_ETERNAL;
|
|
+
|
|
+ cpumask_copy(policy->cpus, priv->cpus);
|
|
+ policy->driver_data = priv;
|
|
+ policy->clk = cpu_clk;
|
|
+ policy->freq_table = priv->freq_table;
|
|
+ policy->suspend_freq = dev_pm_opp_get_suspend_opp_freq(cpu_dev) / 1000;
|
|
+ policy->cpuinfo.transition_latency = transition_latency;
|
|
+ policy->dvfs_possible_from_any_cpu = true;
|
|
+
|
|
+ return 0;
|
|
+}
|
|
+
|
|
+static int cpufreq_exit(struct cpufreq_policy *policy)
|
|
+{
|
|
+ clk_put(policy->clk);
|
|
+ return 0;
|
|
+}
|
|
+
|
|
+static int set_target(struct cpufreq_policy *policy, unsigned int index)
|
|
+{
|
|
+ struct private_data *priv = policy->driver_data;
|
|
+ unsigned long freq = policy->freq_table[index].frequency;
|
|
+
|
|
+ return dev_pm_opp_set_rate(priv->cpu_dev, freq * 1000);
|
|
+}
|
|
+
|
|
+static struct cpufreq_driver rockchip_cpufreq_driver = {
|
|
+ .flags = CPUFREQ_NEED_INITIAL_FREQ_CHECK |
|
|
+ CPUFREQ_IS_COOLING_DEV |
|
|
+ CPUFREQ_HAVE_GOVERNOR_PER_POLICY,
|
|
+ .verify = cpufreq_generic_frequency_table_verify,
|
|
+ .target_index = set_target,
|
|
+ .get = cpufreq_generic_get,
|
|
+ .init = cpufreq_init,
|
|
+ .exit = cpufreq_exit,
|
|
+ .online = cpufreq_online,
|
|
+ .offline = cpufreq_offline,
|
|
+ .register_em = cpufreq_register_em_with_opp,
|
|
+ .name = "rockchip-cpufreq",
|
|
+ .attr = cpufreq_rockchip_attr,
|
|
+ .suspend = cpufreq_generic_suspend,
|
|
+};
|
|
+
|
|
+static int rockchip_cpufreq_init(struct device *dev, int cpu)
|
|
+{
|
|
+ struct private_data *priv;
|
|
+ struct device *cpu_dev;
|
|
+ int ret;
|
|
+
|
|
+ priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL);
|
|
+ if (!priv)
|
|
+ return -ENOMEM;
|
|
+
|
|
+ if (!alloc_cpumask_var(&priv->cpus, GFP_KERNEL))
|
|
+ return -ENOMEM;
|
|
+
|
|
+ cpumask_set_cpu(cpu, priv->cpus);
|
|
+
|
|
+ cpu_dev = get_cpu_device(cpu);
|
|
+ if (!cpu_dev)
|
|
+ return -EPROBE_DEFER;
|
|
+ priv->cpu_dev = cpu_dev;
|
|
+
|
|
+ ret = dev_pm_opp_of_get_sharing_cpus(cpu_dev, priv->cpus);
|
|
+ if (ret)
|
|
+ return ret;
|
|
+
|
|
+ ret = dev_pm_opp_of_cpumask_add_table(priv->cpus);
|
|
+ if (ret)
|
|
+ return ret;
|
|
+
|
|
+ ret = dev_pm_opp_get_opp_count(cpu_dev);
|
|
+ if (ret <= 0)
|
|
+ return dev_err_probe(cpu_dev, -ENODEV, "OPP table can't be empty\n");
|
|
+
|
|
+ ret = dev_pm_opp_init_cpufreq_table(cpu_dev, &priv->freq_table);
|
|
+ if (ret)
|
|
+ return dev_err_probe(cpu_dev, ret, "failed to init cpufreq table\n");
|
|
+
|
|
+ list_add(&priv->node, &priv_list);
|
|
+
|
|
+ return 0;
|
|
+}
|
|
+
|
|
+static void rockchip_cpufreq_free_list(void *data)
|
|
+{
|
|
+ struct cluster_info *cluster, *pos;
|
|
+
|
|
+ list_for_each_entry_safe(cluster, pos, &cluster_info_list, list_head) {
|
|
+ list_del(&cluster->list_head);
|
|
+ }
|
|
+}
|
|
+
|
|
+static int rockchip_cpufreq_init_list(struct device *dev)
|
|
+{
|
|
+ struct cluster_info *cluster;
|
|
+ int cpu, ret;
|
|
+
|
|
+ for_each_possible_cpu(cpu) {
|
|
+ cluster = rockchip_cluster_info_lookup(cpu);
|
|
+ if (cluster)
|
|
+ continue;
|
|
+
|
|
+ cluster = devm_kzalloc(dev, sizeof(*cluster), GFP_KERNEL);
|
|
+ if (!cluster) {
|
|
+ ret = -ENOMEM;
|
|
+ goto release_cluster_info;
|
|
+ }
|
|
+
|
|
+ ret = rockchip_cpufreq_cluster_init(cpu, cluster);
|
|
+ if (ret) {
|
|
+ dev_err_probe(dev, ret, "Failed to initialize dvfs info cpu%d\n", cpu);
|
|
+ goto release_cluster_info;
|
|
+ }
|
|
+ list_add(&cluster->list_head, &cluster_info_list);
|
|
+ }
|
|
+
|
|
+ return 0;
|
|
+
|
|
+release_cluster_info:
|
|
+ rockchip_cpufreq_free_list(NULL);
|
|
+ return ret;
|
|
+}
|
|
+
|
|
+static void rockchip_cpufreq_unregister(void *data)
|
|
+{
|
|
+ cpufreq_unregister_driver(&rockchip_cpufreq_driver);
|
|
+}
|
|
+
|
|
+static int rockchip_cpufreq_probe(struct platform_device *pdev)
|
|
+{
|
|
+ int ret, cpu;
|
|
+
|
|
+ ret = rockchip_cpufreq_init_list(&pdev->dev);
|
|
+ if (ret)
|
|
+ return ret;
|
|
+
|
|
+ ret = devm_add_action_or_reset(&pdev->dev, rockchip_cpufreq_free_list, NULL);
|
|
+ if (ret)
|
|
+ return ret;
|
|
+
|
|
+ ret = devm_register_reboot_notifier(&pdev->dev, &rockchip_cpufreq_reboot_notifier);
|
|
+ if (ret)
|
|
+ return dev_err_probe(&pdev->dev, ret, "Failed to register reboot handler\n");
|
|
+
|
|
+ for_each_possible_cpu(cpu) {
|
|
+ ret = rockchip_cpufreq_init(&pdev->dev, cpu);
|
|
+ if (ret)
|
|
+ return ret;
|
|
+ }
|
|
+
|
|
+ ret = cpufreq_register_driver(&rockchip_cpufreq_driver);
|
|
+ if (ret)
|
|
+ return dev_err_probe(&pdev->dev, ret, "failed register driver\n");
|
|
+
|
|
+ ret = devm_add_action_or_reset(&pdev->dev, rockchip_cpufreq_unregister, NULL);
|
|
+ if (ret)
|
|
+ return ret;
|
|
+
|
|
+ return 0;
|
|
+}
|
|
+
|
|
+static struct platform_driver rockchip_cpufreq_platdrv = {
|
|
+ .driver = {
|
|
+ .name = "rockchip-cpufreq",
|
|
+ },
|
|
+ .probe = rockchip_cpufreq_probe,
|
|
+};
|
|
+
|
|
+static int __init rockchip_cpufreq_driver_init(void)
|
|
+{
|
|
+ int ret;
|
|
+
|
|
+ if (!of_machine_is_compatible("rockchip,rk3588") &&
|
|
+ !of_machine_is_compatible("rockchip,rk3588s")) {
|
|
+ return -ENODEV;
|
|
+ }
|
|
+
|
|
+ ret = platform_driver_register(&rockchip_cpufreq_platdrv);
|
|
+ if (ret)
|
|
+ return ret;
|
|
+
|
|
+ cpufreq_pdev = platform_device_register_data(NULL, "rockchip-cpufreq", -1,
|
|
+ NULL, 0);
|
|
+ if (IS_ERR(cpufreq_pdev)) {
|
|
+ pr_err("failed to register rockchip-cpufreq platform device\n");
|
|
+ ret = PTR_ERR(cpufreq_pdev);
|
|
+ goto unregister_platform_driver;
|
|
+ }
|
|
+
|
|
+ return 0;
|
|
+
|
|
+unregister_platform_driver:
|
|
+ platform_driver_unregister(&rockchip_cpufreq_platdrv);
|
|
+ return ret;
|
|
+}
|
|
+module_init(rockchip_cpufreq_driver_init);
|
|
+
|
|
+static void __exit rockchip_cpufreq_driver_exit(void)
|
|
+{
|
|
+ platform_device_unregister(cpufreq_pdev);
|
|
+ platform_driver_unregister(&rockchip_cpufreq_platdrv);
|
|
+}
|
|
+module_exit(rockchip_cpufreq_driver_exit)
|
|
+
|
|
+MODULE_AUTHOR("Finley Xiao <finley.xiao@rock-chips.com>");
|
|
+MODULE_DESCRIPTION("Rockchip cpufreq driver");
|
|
+MODULE_LICENSE("GPL v2");
|
|
--
|
|
2.41.0
|
|
|
|
|
|
From 1a4f292fcdb4b4a625dda97e8236911b896c8abe Mon Sep 17 00:00:00 2001
|
|
From: Sebastian Reichel <sebastian.reichel@collabora.com>
|
|
Date: Tue, 4 Apr 2023 17:30:46 +0200
|
|
Subject: [PATCH 2/2] arm64: dts: rockchip: rk3588: add cpu frequency scaling
|
|
support
|
|
|
|
Add required bits for CPU frequency scaling to the Rockchip 3588
|
|
devicetree. This is missing the 2.4 GHz operating point for the
|
|
big cpu clusters, since that does not work well on all SoCs.
|
|
Downstream has a driver for PVTM, which reduces the requested
|
|
frequencies based on (among other things) silicon quality.
|
|
|
|
Signed-off-by: Sebastian Reichel <sebastian.reichel@collabora.com>
|
|
---
|
|
arch/arm64/boot/dts/rockchip/rk3588s.dtsi | 452 ++++++++++++++++++++++
|
|
1 file changed, 452 insertions(+)
|
|
|
|
diff --git a/arch/arm64/boot/dts/rockchip/rk3588s.dtsi b/arch/arm64/boot/dts/rockchip/rk3588s.dtsi
|
|
index a90ec13f50b4..aa78f535b27d 100644
|
|
--- a/arch/arm64/boot/dts/rockchip/rk3588s.dtsi
|
|
+++ b/arch/arm64/boot/dts/rockchip/rk3588s.dtsi
|
|
@@ -10,6 +10,7 @@
|
|
#include <dt-bindings/reset/rockchip,rk3588-cru.h>
|
|
#include <dt-bindings/phy/phy.h>
|
|
#include <dt-bindings/ata/ahci.h>
|
|
+#include <dt-bindings/thermal/thermal.h>
|
|
|
|
/ {
|
|
compatible = "rockchip,rk3588";
|
|
@@ -18,6 +19,215 @@ / {
|
|
#address-cells = <2>;
|
|
#size-cells = <2>;
|
|
|
|
+ cluster0_opp_table: opp-table-cluster0 {
|
|
+ compatible = "operating-points-v2";
|
|
+ opp-shared;
|
|
+
|
|
+ opp-408000000 {
|
|
+ opp-hz = /bits/ 64 <408000000>;
|
|
+ opp-microvolt = <750000 750000 950000>,
|
|
+ <750000 750000 950000>;
|
|
+ clock-latency-ns = <40000>;
|
|
+ opp-suspend;
|
|
+ };
|
|
+ opp-600000000 {
|
|
+ opp-hz = /bits/ 64 <600000000>;
|
|
+ opp-microvolt = <750000 750000 950000>,
|
|
+ <750000 750000 950000>;
|
|
+ clock-latency-ns = <40000>;
|
|
+ };
|
|
+ opp-816000000 {
|
|
+ opp-hz = /bits/ 64 <816000000>;
|
|
+ opp-microvolt = <750000 750000 950000>,
|
|
+ <750000 750000 950000>;
|
|
+ clock-latency-ns = <40000>;
|
|
+ };
|
|
+ opp-1008000000 {
|
|
+ opp-hz = /bits/ 64 <1008000000>;
|
|
+ opp-microvolt = <750000 750000 950000>,
|
|
+ <750000 750000 950000>;
|
|
+ clock-latency-ns = <40000>;
|
|
+ };
|
|
+ opp-1200000000 {
|
|
+ opp-hz = /bits/ 64 <1200000000>;
|
|
+ opp-microvolt = <775000 775000 950000>,
|
|
+ <775000 775000 950000>;
|
|
+ clock-latency-ns = <40000>;
|
|
+ };
|
|
+ opp-1416000000 {
|
|
+ opp-hz = /bits/ 64 <1416000000>;
|
|
+ opp-microvolt = <825000 825000 950000>,
|
|
+ <825000 825000 950000>;
|
|
+ clock-latency-ns = <40000>;
|
|
+ };
|
|
+ opp-1608000000 {
|
|
+ opp-hz = /bits/ 64 <1608000000>;
|
|
+ opp-microvolt = <875000 875000 950000>,
|
|
+ <875000 875000 950000>;
|
|
+ clock-latency-ns = <40000>;
|
|
+ };
|
|
+ opp-1800000000 {
|
|
+ opp-hz = /bits/ 64 <1800000000>;
|
|
+ opp-microvolt = <950000 950000 950000>,
|
|
+ <950000 950000 950000>;
|
|
+ clock-latency-ns = <40000>;
|
|
+ };
|
|
+ };
|
|
+
|
|
+ cluster1_opp_table: opp-table-cluster1 {
|
|
+ compatible = "operating-points-v2";
|
|
+ opp-shared;
|
|
+
|
|
+ rockchip,grf = <&bigcore0_grf>;
|
|
+ rockchip,volt-mem-read-margin = <
|
|
+ 855000 1
|
|
+ 765000 2
|
|
+ 675000 3
|
|
+ 495000 4
|
|
+ >;
|
|
+
|
|
+ rockchip,reboot-freq = <1800000000>;
|
|
+
|
|
+ opp-408000000 {
|
|
+ opp-hz = /bits/ 64 <408000000>;
|
|
+ opp-microvolt = <600000 600000 1000000>,
|
|
+ <675000 675000 1000000>;
|
|
+ clock-latency-ns = <40000>;
|
|
+ opp-suspend;
|
|
+ };
|
|
+ opp-600000000 {
|
|
+ opp-hz = /bits/ 64 <600000000>;
|
|
+ opp-microvolt = <600000 600000 1000000>,
|
|
+ <675000 675000 1000000>;
|
|
+ clock-latency-ns = <40000>;
|
|
+ };
|
|
+ opp-816000000 {
|
|
+ opp-hz = /bits/ 64 <816000000>;
|
|
+ opp-microvolt = <600000 600000 1000000>,
|
|
+ <675000 675000 1000000>;
|
|
+ clock-latency-ns = <40000>;
|
|
+ };
|
|
+ opp-1008000000 {
|
|
+ opp-hz = /bits/ 64 <1008000000>;
|
|
+ opp-microvolt = <625000 625000 1000000>,
|
|
+ <675000 675000 1000000>;
|
|
+ clock-latency-ns = <40000>;
|
|
+ };
|
|
+ opp-1200000000 {
|
|
+ opp-hz = /bits/ 64 <1200000000>;
|
|
+ opp-microvolt = <650000 650000 1000000>,
|
|
+ <675000 675000 1000000>;
|
|
+ clock-latency-ns = <40000>;
|
|
+ };
|
|
+ opp-1416000000 {
|
|
+ opp-hz = /bits/ 64 <1416000000>;
|
|
+ opp-microvolt = <675000 675000 1000000>,
|
|
+ <675000 675000 1000000>;
|
|
+ clock-latency-ns = <40000>;
|
|
+ };
|
|
+ opp-1608000000 {
|
|
+ opp-hz = /bits/ 64 <1608000000>;
|
|
+ opp-microvolt = <700000 700000 1000000>,
|
|
+ <700000 700000 1000000>;
|
|
+ clock-latency-ns = <40000>;
|
|
+ };
|
|
+ opp-1800000000 {
|
|
+ opp-hz = /bits/ 64 <1800000000>;
|
|
+ opp-microvolt = <775000 775000 1000000>,
|
|
+ <775000 775000 1000000>;
|
|
+ clock-latency-ns = <40000>;
|
|
+ };
|
|
+ opp-2016000000 {
|
|
+ opp-hz = /bits/ 64 <2016000000>;
|
|
+ opp-microvolt = <850000 850000 1000000>,
|
|
+ <850000 850000 1000000>;
|
|
+ clock-latency-ns = <40000>;
|
|
+ };
|
|
+ opp-2208000000 {
|
|
+ opp-hz = /bits/ 64 <2208000000>;
|
|
+ opp-microvolt = <925000 925000 1000000>,
|
|
+ <925000 925000 1000000>;
|
|
+ clock-latency-ns = <40000>;
|
|
+ };
|
|
+ };
|
|
+
|
|
+ cluster2_opp_table: opp-table-cluster2 {
|
|
+ compatible = "operating-points-v2";
|
|
+ opp-shared;
|
|
+
|
|
+ rockchip,grf = <&bigcore1_grf>;
|
|
+ rockchip,volt-mem-read-margin = <
|
|
+ 855000 1
|
|
+ 765000 2
|
|
+ 675000 3
|
|
+ 495000 4
|
|
+ >;
|
|
+
|
|
+ rockchip,reboot-freq = <1800000000>;
|
|
+
|
|
+ opp-408000000 {
|
|
+ opp-hz = /bits/ 64 <408000000>;
|
|
+ opp-microvolt = <600000 600000 1000000>,
|
|
+ <675000 675000 1000000>;
|
|
+ clock-latency-ns = <40000>;
|
|
+ opp-suspend;
|
|
+ };
|
|
+ opp-600000000 {
|
|
+ opp-hz = /bits/ 64 <600000000>;
|
|
+ opp-microvolt = <600000 600000 1000000>,
|
|
+ <675000 675000 1000000>;
|
|
+ clock-latency-ns = <40000>;
|
|
+ };
|
|
+ opp-816000000 {
|
|
+ opp-hz = /bits/ 64 <816000000>;
|
|
+ opp-microvolt = <600000 600000 1000000>,
|
|
+ <675000 675000 1000000>;
|
|
+ clock-latency-ns = <40000>;
|
|
+ };
|
|
+ opp-1008000000 {
|
|
+ opp-hz = /bits/ 64 <1008000000>;
|
|
+ opp-microvolt = <625000 625000 1000000>,
|
|
+ <675000 675000 1000000>;
|
|
+ clock-latency-ns = <40000>;
|
|
+ };
|
|
+ opp-1200000000 {
|
|
+ opp-hz = /bits/ 64 <1200000000>;
|
|
+ opp-microvolt = <650000 650000 1000000>,
|
|
+ <675000 675000 1000000>;
|
|
+ clock-latency-ns = <40000>;
|
|
+ };
|
|
+ opp-1416000000 {
|
|
+ opp-hz = /bits/ 64 <1416000000>;
|
|
+ opp-microvolt = <675000 675000 1000000>,
|
|
+ <675000 675000 1000000>;
|
|
+ clock-latency-ns = <40000>;
|
|
+ };
|
|
+ opp-1608000000 {
|
|
+ opp-hz = /bits/ 64 <1608000000>;
|
|
+ opp-microvolt = <700000 700000 1000000>,
|
|
+ <700000 700000 1000000>;
|
|
+ clock-latency-ns = <40000>;
|
|
+ };
|
|
+ opp-1800000000 {
|
|
+ opp-hz = /bits/ 64 <1800000000>;
|
|
+ opp-microvolt = <775000 775000 1000000>,
|
|
+ <775000 775000 1000000>;
|
|
+ clock-latency-ns = <40000>;
|
|
+ };
|
|
+ opp-2016000000 {
|
|
+ opp-hz = /bits/ 64 <2016000000>;
|
|
+ opp-microvolt = <850000 850000 1000000>,
|
|
+ <850000 850000 1000000>;
|
|
+ clock-latency-ns = <40000>;
|
|
+ };
|
|
+ opp-2208000000 {
|
|
+ opp-hz = /bits/ 64 <2208000000>;
|
|
+ opp-microvolt = <925000 925000 1000000>,
|
|
+ <925000 925000 1000000>;
|
|
+ clock-latency-ns = <40000>;
|
|
+ };
|
|
+ };
|
|
+
|
|
cpus {
|
|
#address-cells = <1>;
|
|
#size-cells = <0>;
|
|
@@ -64,6 +274,7 @@ cpu_l0: cpu@0 {
|
|
clocks = <&scmi_clk SCMI_CLK_CPUL>;
|
|
assigned-clocks = <&scmi_clk SCMI_CLK_CPUL>;
|
|
assigned-clock-rates = <816000000>;
|
|
+ operating-points-v2 = <&cluster0_opp_table>;
|
|
cpu-idle-states = <&CPU_SLEEP>;
|
|
i-cache-size = <32768>;
|
|
i-cache-line-size = <64>;
|
|
@@ -83,6 +294,7 @@ cpu_l1: cpu@100 {
|
|
enable-method = "psci";
|
|
capacity-dmips-mhz = <530>;
|
|
clocks = <&scmi_clk SCMI_CLK_CPUL>;
|
|
+ operating-points-v2 = <&cluster0_opp_table>;
|
|
cpu-idle-states = <&CPU_SLEEP>;
|
|
i-cache-size = <32768>;
|
|
i-cache-line-size = <64>;
|
|
@@ -102,6 +314,7 @@ cpu_l2: cpu@200 {
|
|
enable-method = "psci";
|
|
capacity-dmips-mhz = <530>;
|
|
clocks = <&scmi_clk SCMI_CLK_CPUL>;
|
|
+ operating-points-v2 = <&cluster0_opp_table>;
|
|
cpu-idle-states = <&CPU_SLEEP>;
|
|
i-cache-size = <32768>;
|
|
i-cache-line-size = <64>;
|
|
@@ -121,6 +334,7 @@ cpu_l3: cpu@300 {
|
|
enable-method = "psci";
|
|
capacity-dmips-mhz = <530>;
|
|
clocks = <&scmi_clk SCMI_CLK_CPUL>;
|
|
+ operating-points-v2 = <&cluster0_opp_table>;
|
|
cpu-idle-states = <&CPU_SLEEP>;
|
|
i-cache-size = <32768>;
|
|
i-cache-line-size = <64>;
|
|
@@ -142,6 +356,7 @@ cpu_b0: cpu@400 {
|
|
clocks = <&scmi_clk SCMI_CLK_CPUB01>;
|
|
assigned-clocks = <&scmi_clk SCMI_CLK_CPUB01>;
|
|
assigned-clock-rates = <816000000>;
|
|
+ operating-points-v2 = <&cluster1_opp_table>;
|
|
cpu-idle-states = <&CPU_SLEEP>;
|
|
i-cache-size = <65536>;
|
|
i-cache-line-size = <64>;
|
|
@@ -161,6 +376,7 @@ cpu_b1: cpu@500 {
|
|
enable-method = "psci";
|
|
capacity-dmips-mhz = <1024>;
|
|
clocks = <&scmi_clk SCMI_CLK_CPUB01>;
|
|
+ operating-points-v2 = <&cluster1_opp_table>;
|
|
cpu-idle-states = <&CPU_SLEEP>;
|
|
i-cache-size = <65536>;
|
|
i-cache-line-size = <64>;
|
|
@@ -182,6 +398,7 @@ cpu_b2: cpu@600 {
|
|
clocks = <&scmi_clk SCMI_CLK_CPUB23>;
|
|
assigned-clocks = <&scmi_clk SCMI_CLK_CPUB23>;
|
|
assigned-clock-rates = <816000000>;
|
|
+ operating-points-v2 = <&cluster2_opp_table>;
|
|
cpu-idle-states = <&CPU_SLEEP>;
|
|
i-cache-size = <65536>;
|
|
i-cache-line-size = <64>;
|
|
@@ -201,6 +418,7 @@ cpu_b3: cpu@700 {
|
|
enable-method = "psci";
|
|
capacity-dmips-mhz = <1024>;
|
|
clocks = <&scmi_clk SCMI_CLK_CPUB23>;
|
|
+ operating-points-v2 = <&cluster2_opp_table>;
|
|
cpu-idle-states = <&CPU_SLEEP>;
|
|
i-cache-size = <65536>;
|
|
i-cache-line-size = <64>;
|
|
@@ -362,6 +580,230 @@ spll: clock-0 {
|
|
#clock-cells = <0>;
|
|
};
|
|
|
|
+ thermal_zones: thermal-zones {
|
|
+ soc_thermal: soc-thermal {
|
|
+ polling-delay-passive = <20>; /* milliseconds */
|
|
+ polling-delay = <1000>; /* milliseconds */
|
|
+ sustainable-power = <2100>; /* milliwatts */
|
|
+
|
|
+ thermal-sensors = <&tsadc 0>;
|
|
+ trips {
|
|
+ trip-point-0 {
|
|
+ temperature = <75000>;
|
|
+ hysteresis = <2000>;
|
|
+ type = "passive";
|
|
+ };
|
|
+ soc_target: trip-point-1 {
|
|
+ temperature = <85000>;
|
|
+ hysteresis = <2000>;
|
|
+ type = "passive";
|
|
+ };
|
|
+ trip-point-2 {
|
|
+ /* millicelsius */
|
|
+ temperature = <115000>;
|
|
+ /* millicelsius */
|
|
+ hysteresis = <2000>;
|
|
+ type = "critical";
|
|
+ };
|
|
+ };
|
|
+
|
|
+ cooling-maps {
|
|
+ map0 {
|
|
+ trip = <&soc_target>;
|
|
+ cooling-device = <&cpu_l0 THERMAL_NO_LIMIT THERMAL_NO_LIMIT>,
|
|
+ <&cpu_l1 THERMAL_NO_LIMIT THERMAL_NO_LIMIT>,
|
|
+ <&cpu_l2 THERMAL_NO_LIMIT THERMAL_NO_LIMIT>,
|
|
+ <&cpu_l3 THERMAL_NO_LIMIT THERMAL_NO_LIMIT>,
|
|
+ <&cpu_b0 THERMAL_NO_LIMIT THERMAL_NO_LIMIT>,
|
|
+ <&cpu_b1 THERMAL_NO_LIMIT THERMAL_NO_LIMIT>,
|
|
+ <&cpu_b2 THERMAL_NO_LIMIT THERMAL_NO_LIMIT>,
|
|
+ <&cpu_b3 THERMAL_NO_LIMIT THERMAL_NO_LIMIT>;
|
|
+ contribution = <1024>;
|
|
+ };
|
|
+ };
|
|
+ };
|
|
+
|
|
+ bigcore0_thermal: bigcore0-thermal {
|
|
+ polling-delay-passive = <20>; /* milliseconds */
|
|
+ polling-delay = <1000>; /* milliseconds */
|
|
+ thermal-sensors = <&tsadc 1>;
|
|
+
|
|
+ trips {
|
|
+ trip-point-0 {
|
|
+ temperature = <75000>;
|
|
+ hysteresis = <2000>;
|
|
+ type = "passive";
|
|
+ };
|
|
+ b0_target: trip-point-1 {
|
|
+ temperature = <85000>;
|
|
+ hysteresis = <2000>;
|
|
+ type = "passive";
|
|
+ };
|
|
+ trip-point-2 {
|
|
+ /* millicelsius */
|
|
+ temperature = <115000>;
|
|
+ /* millicelsius */
|
|
+ hysteresis = <2000>;
|
|
+ type = "critical";
|
|
+ };
|
|
+ };
|
|
+
|
|
+ cooling-maps {
|
|
+ map0 {
|
|
+ trip = <&b0_target>;
|
|
+ cooling-device = <&cpu_b0 THERMAL_NO_LIMIT THERMAL_NO_LIMIT>,
|
|
+ <&cpu_b1 THERMAL_NO_LIMIT THERMAL_NO_LIMIT>;
|
|
+ contribution = <1024>;
|
|
+ };
|
|
+ };
|
|
+ };
|
|
+
|
|
+ bigcore1_thermal: bigcore1-thermal {
|
|
+ polling-delay-passive = <20>; /* milliseconds */
|
|
+ polling-delay = <1000>; /* milliseconds */
|
|
+ thermal-sensors = <&tsadc 2>;
|
|
+ trips {
|
|
+ trip-point-0 {
|
|
+ temperature = <75000>;
|
|
+ hysteresis = <2000>;
|
|
+ type = "passive";
|
|
+ };
|
|
+ b1_target: trip-point-1 {
|
|
+ temperature = <85000>;
|
|
+ hysteresis = <2000>;
|
|
+ type = "passive";
|
|
+ };
|
|
+ trip-point-2 {
|
|
+ /* millicelsius */
|
|
+ temperature = <115000>;
|
|
+ /* millicelsius */
|
|
+ hysteresis = <2000>;
|
|
+ type = "critical";
|
|
+ };
|
|
+ };
|
|
+
|
|
+ cooling-maps {
|
|
+ map0 {
|
|
+ trip = <&b1_target>;
|
|
+ cooling-device = <&cpu_b2 THERMAL_NO_LIMIT THERMAL_NO_LIMIT>,
|
|
+ <&cpu_b3 THERMAL_NO_LIMIT THERMAL_NO_LIMIT>;
|
|
+ contribution = <1024>;
|
|
+ };
|
|
+ };
|
|
+ };
|
|
+
|
|
+ little_core_thermal: littlecore-thermal {
|
|
+ polling-delay-passive = <20>; /* milliseconds */
|
|
+ polling-delay = <1000>; /* milliseconds */
|
|
+ thermal-sensors = <&tsadc 3>;
|
|
+ trips {
|
|
+ trip-point-0 {
|
|
+ temperature = <75000>;
|
|
+ hysteresis = <2000>;
|
|
+ type = "passive";
|
|
+ };
|
|
+ l0_target: trip-point-1 {
|
|
+ temperature = <85000>;
|
|
+ hysteresis = <2000>;
|
|
+ type = "passive";
|
|
+ };
|
|
+ trip-point-2 {
|
|
+ /* millicelsius */
|
|
+ temperature = <115000>;
|
|
+ /* millicelsius */
|
|
+ hysteresis = <2000>;
|
|
+ type = "critical";
|
|
+ };
|
|
+ };
|
|
+
|
|
+ cooling-maps {
|
|
+ map0 {
|
|
+ trip = <&l0_target>;
|
|
+ cooling-device = <&cpu_l0 THERMAL_NO_LIMIT THERMAL_NO_LIMIT>,
|
|
+ <&cpu_l1 THERMAL_NO_LIMIT THERMAL_NO_LIMIT>,
|
|
+ <&cpu_l2 THERMAL_NO_LIMIT THERMAL_NO_LIMIT>,
|
|
+ <&cpu_l3 THERMAL_NO_LIMIT THERMAL_NO_LIMIT>;
|
|
+ contribution = <1024>;
|
|
+ };
|
|
+ };
|
|
+ };
|
|
+
|
|
+ center_thermal: center-thermal {
|
|
+ polling-delay-passive = <20>; /* milliseconds */
|
|
+ polling-delay = <1000>; /* milliseconds */
|
|
+ thermal-sensors = <&tsadc 4>;
|
|
+ trips {
|
|
+ trip-point-0 {
|
|
+ temperature = <75000>;
|
|
+ hysteresis = <2000>;
|
|
+ type = "passive";
|
|
+ };
|
|
+ trip-point-1 {
|
|
+ temperature = <85000>;
|
|
+ hysteresis = <2000>;
|
|
+ type = "passive";
|
|
+ };
|
|
+ trip-point-2 {
|
|
+ /* millicelsius */
|
|
+ temperature = <115000>;
|
|
+ /* millicelsius */
|
|
+ hysteresis = <2000>;
|
|
+ type = "critical";
|
|
+ };
|
|
+ };
|
|
+ };
|
|
+
|
|
+ gpu_thermal: gpu-thermal {
|
|
+ polling-delay-passive = <20>; /* milliseconds */
|
|
+ polling-delay = <1000>; /* milliseconds */
|
|
+ thermal-sensors = <&tsadc 5>;
|
|
+ trips {
|
|
+ trip-point-0 {
|
|
+ temperature = <75000>;
|
|
+ hysteresis = <2000>;
|
|
+ type = "passive";
|
|
+ };
|
|
+ trip-point-1 {
|
|
+ temperature = <85000>;
|
|
+ hysteresis = <2000>;
|
|
+ type = "passive";
|
|
+ };
|
|
+ trip-point-2 {
|
|
+ /* millicelsius */
|
|
+ temperature = <115000>;
|
|
+ /* millicelsius */
|
|
+ hysteresis = <2000>;
|
|
+ type = "critical";
|
|
+ };
|
|
+ };
|
|
+ };
|
|
+
|
|
+ npu_thermal: npu-thermal {
|
|
+ polling-delay-passive = <20>; /* milliseconds */
|
|
+ polling-delay = <1000>; /* milliseconds */
|
|
+ thermal-sensors = <&tsadc 6>;
|
|
+ trips {
|
|
+ trip-point-0 {
|
|
+ temperature = <75000>;
|
|
+ hysteresis = <2000>;
|
|
+ type = "passive";
|
|
+ };
|
|
+ trip-point-1 {
|
|
+ temperature = <85000>;
|
|
+ hysteresis = <2000>;
|
|
+ type = "passive";
|
|
+ };
|
|
+ trip-point-2 {
|
|
+ /* millicelsius */
|
|
+ temperature = <115000>;
|
|
+ /* millicelsius */
|
|
+ hysteresis = <2000>;
|
|
+ type = "critical";
|
|
+ };
|
|
+ };
|
|
+ };
|
|
+ };
|
|
+
|
|
timer {
|
|
compatible = "arm,armv8-timer";
|
|
interrupts = <GIC_PPI 13 IRQ_TYPE_LEVEL_HIGH 0>,
|
|
@@ -491,6 +933,16 @@ sys_grf: syscon@fd58c000 {
|
|
reg = <0x0 0xfd58c000 0x0 0x1000>;
|
|
};
|
|
|
|
+ bigcore0_grf: syscon@fd590000 {
|
|
+ compatible = "rockchip,rk3588-bigcore0-grf", "syscon";
|
|
+ reg = <0x0 0xfd590000 0x0 0x100>;
|
|
+ };
|
|
+
|
|
+ bigcore1_grf: syscon@fd592000 {
|
|
+ compatible = "rockchip,rk3588-bigcore1-grf", "syscon";
|
|
+ reg = <0x0 0xfd592000 0x0 0x100>;
|
|
+ };
|
|
+
|
|
php_grf: syscon@fd5b0000 {
|
|
compatible = "rockchip,rk3588-php-grf", "syscon";
|
|
reg = <0x0 0xfd5b0000 0x0 0x1000>;
|
|
--
|
|
2.41.0
|
|
|