diff --git a/target/linux/rockchip/armv8/config-6.1 b/target/linux/rockchip/armv8/config-6.1 index 8e7e27d022..5b125e6008 100644 --- a/target/linux/rockchip/armv8/config-6.1 +++ b/target/linux/rockchip/armv8/config-6.1 @@ -68,6 +68,7 @@ CONFIG_ARM_PSCI_CPUIDLE_DOMAIN=y CONFIG_ARM_PSCI_FW=y CONFIG_ARM_RK3328_DMC_DEVFREQ=y # CONFIG_ARM_RK3399_DMC_DEVFREQ is not set +CONFIG_ARM_ROCKCHIP_CPUFREQ=y CONFIG_ARM_SCMI_CPUFREQ=y CONFIG_ARM_SCMI_HAVE_SHMEM=y CONFIG_ARM_SCMI_HAVE_TRANSPORT=y @@ -493,6 +494,7 @@ CONFIG_PHY_ROCKCHIP_PCIE=y CONFIG_PHY_ROCKCHIP_SNPS_PCIE3=y CONFIG_PHY_ROCKCHIP_TYPEC=y CONFIG_PHY_ROCKCHIP_USB=y +CONFIG_PHY_ROCKCHIP_USBDP=y CONFIG_PINCTRL=y CONFIG_PINCTRL_RK805=y CONFIG_PINCTRL_ROCKCHIP=y diff --git a/target/linux/rockchip/patches-6.1/110-01-cpufreq-rockchip-Introduce-driver-for-rk3588.patch b/target/linux/rockchip/patches-6.1/110-01-cpufreq-rockchip-Introduce-driver-for-rk3588.patch new file mode 100644 index 0000000000..5a6e1cc049 --- /dev/null +++ b/target/linux/rockchip/patches-6.1/110-01-cpufreq-rockchip-Introduce-driver-for-rk3588.patch @@ -0,0 +1,707 @@ +From 8da601637e2ed438b83fe56e49dacea84fd3b056 Mon Sep 17 00:00:00 2001 +From: Sebastian Reichel +Date: Thu, 18 Aug 2022 14:21:30 +0200 +Subject: [PATCH] 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 +--- + drivers/cpufreq/Kconfig.arm | 10 + + drivers/cpufreq/Makefile | 1 + + drivers/cpufreq/cpufreq-dt-platdev.c | 2 + + drivers/cpufreq/rockchip-cpufreq.c | 640 +++++++++++++++++++++++++++ + 4 files changed, 653 insertions(+) + create mode 100644 drivers/cpufreq/rockchip-cpufreq.c + +--- a/drivers/cpufreq/Kconfig.arm ++++ b/drivers/cpufreq/Kconfig.arm +@@ -180,6 +180,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_S3C_CPUFREQ + bool + help +--- a/drivers/cpufreq/Makefile ++++ b/drivers/cpufreq/Makefile +@@ -70,6 +70,7 @@ obj-$(CONFIG_PXA3xx) += pxa3xx-cpufreq + 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_S3C2410_CPUFREQ) += s3c2410-cpufreq.o + obj-$(CONFIG_ARM_S3C2412_CPUFREQ) += s3c2412-cpufreq.o + obj-$(CONFIG_ARM_S3C2416_CPUFREQ) += s3c2416-cpufreq.o +--- a/drivers/cpufreq/cpufreq-dt-platdev.c ++++ b/drivers/cpufreq/cpufreq-dt-platdev.c +@@ -154,6 +154,8 @@ static const struct of_device_id blockli + { .compatible = "qcom,sm8250", }, + { .compatible = "qcom,sm8350", }, + ++ { .compatible = "rockchip,rk3588", }, ++ + { .compatible = "st,stih407", }, + { .compatible = "st,stih410", }, + { .compatible = "st,stih418", }, +--- /dev/null ++++ b/drivers/cpufreq/rockchip-cpufreq.c +@@ -0,0 +1,640 @@ ++// 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 ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++#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; ++ ++ 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 "); ++MODULE_DESCRIPTION("Rockchip cpufreq driver"); ++MODULE_LICENSE("GPL v2"); diff --git a/target/linux/rockchip/patches-6.1/110-02-arm64-dts-rockchip-rk3588-add-cpu-frequency-scaling.patch b/target/linux/rockchip/patches-6.1/110-02-arm64-dts-rockchip-rk3588-add-cpu-frequency-scaling.patch new file mode 100644 index 0000000000..e49013da98 --- /dev/null +++ b/target/linux/rockchip/patches-6.1/110-02-arm64-dts-rockchip-rk3588-add-cpu-frequency-scaling.patch @@ -0,0 +1,555 @@ +From 28ce8a074fe8944a0614dcde539456312f915113 Mon Sep 17 00:00:00 2001 +From: Sebastian Reichel +Date: Tue, 4 Apr 2023 17:30:46 +0200 +Subject: [PATCH] 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 +--- + arch/arm64/boot/dts/rockchip/rk3588s.dtsi | 452 ++++++++++++++++++++++ + 1 file changed, 452 insertions(+) + +--- a/arch/arm64/boot/dts/rockchip/rk3588s.dtsi ++++ b/arch/arm64/boot/dts/rockchip/rk3588s.dtsi +@@ -8,6 +8,7 @@ + #include + #include + #include ++#include + + / { + compatible = "rockchip,rk3588"; +@@ -16,6 +17,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>; +@@ -62,6 +272,7 @@ + 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>; +@@ -81,6 +292,7 @@ + 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>; +@@ -100,6 +312,7 @@ + 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>; +@@ -119,6 +332,7 @@ + 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>; +@@ -140,6 +354,7 @@ + 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>; +@@ -159,6 +374,7 @@ + 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>; +@@ -180,6 +396,7 @@ + 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>; +@@ -199,6 +416,7 @@ + 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>; +@@ -351,6 +569,230 @@ + #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 = , +@@ -393,6 +835,16 @@ + 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>; diff --git a/target/linux/rockchip/patches-6.1/110-03-soc-rockchip-power-domain-add-rk3588-mem-module-support.patch b/target/linux/rockchip/patches-6.1/110-03-soc-rockchip-power-domain-add-rk3588-mem-module-support.patch new file mode 100644 index 0000000000..be4ef6a4c7 --- /dev/null +++ b/target/linux/rockchip/patches-6.1/110-03-soc-rockchip-power-domain-add-rk3588-mem-module-support.patch @@ -0,0 +1,260 @@ +From 80299d07e63d41bffcf6bb38b0339e22e3ad87da Mon Sep 17 00:00:00 2001 +From: Boris Brezillon +Date: Tue, 12 Jul 2022 09:20:43 +0200 +Subject: [PATCH] soc: rockchip: power-domain: add rk3588 mem module support + +On RK3588 it's also possible to power down the memory used by the +particular power domains via PMU_MEM_PWR_GATE_SFTCON. This adds +support for this feature. + +Tested-by: Vincent Legoll +Co-Developed-by: Finley Xiao +Signed-off-by: Finley Xiao +Signed-off-by: Boris Brezillon +Signed-off-by: Sebastian Reichel +--- + drivers/soc/rockchip/pm_domains.c | 160 +++++++++++++++++++++++------- + 1 file changed, 125 insertions(+), 35 deletions(-) + +--- a/drivers/soc/rockchip/pm_domains.c ++++ b/drivers/soc/rockchip/pm_domains.c +@@ -43,8 +43,10 @@ struct rockchip_domain_info { + bool active_wakeup; + int pwr_w_mask; + int req_w_mask; ++ int mem_status_mask; + int repair_status_mask; + u32 pwr_offset; ++ u32 mem_offset; + u32 req_offset; + }; + +@@ -54,6 +56,9 @@ struct rockchip_pmu_info { + u32 req_offset; + u32 idle_offset; + u32 ack_offset; ++ u32 mem_pwr_offset; ++ u32 chain_status_offset; ++ u32 mem_status_offset; + u32 repair_status_offset; + + u32 core_pwrcnt_offset; +@@ -119,13 +124,15 @@ struct rockchip_pmu { + .active_wakeup = wakeup, \ + } + +-#define DOMAIN_M_O_R(_name, p_offset, pwr, status, r_status, r_offset, req, idle, ack, wakeup) \ ++#define DOMAIN_M_O_R(_name, p_offset, pwr, status, m_offset, m_status, r_status, r_offset, req, idle, ack, wakeup) \ + { \ + .name = _name, \ + .pwr_offset = p_offset, \ + .pwr_w_mask = (pwr) << 16, \ + .pwr_mask = (pwr), \ + .status_mask = (status), \ ++ .mem_offset = m_offset, \ ++ .mem_status_mask = (m_status), \ + .repair_status_mask = (r_status), \ + .req_offset = r_offset, \ + .req_w_mask = (req) << 16, \ +@@ -269,8 +276,8 @@ void rockchip_pmu_unblock(void) + } + EXPORT_SYMBOL_GPL(rockchip_pmu_unblock); + +-#define DOMAIN_RK3588(name, p_offset, pwr, status, r_status, r_offset, req, idle, wakeup) \ +- DOMAIN_M_O_R(name, p_offset, pwr, status, r_status, r_offset, req, idle, idle, wakeup) ++#define DOMAIN_RK3588(name, p_offset, pwr, status, m_offset, m_status, r_status, r_offset, req, idle, wakeup) \ ++ DOMAIN_M_O_R(name, p_offset, pwr, status, m_offset, m_status, r_status, r_offset, req, idle, idle, wakeup) + + static bool rockchip_pmu_domain_is_idle(struct rockchip_pm_domain *pd) + { +@@ -408,17 +415,92 @@ static bool rockchip_pmu_domain_is_on(st + return !(val & pd->info->status_mask); + } + ++static bool rockchip_pmu_domain_is_mem_on(struct rockchip_pm_domain *pd) ++{ ++ struct rockchip_pmu *pmu = pd->pmu; ++ unsigned int val; ++ ++ regmap_read(pmu->regmap, ++ pmu->info->mem_status_offset + pd->info->mem_offset, &val); ++ ++ /* 1'b0: power on, 1'b1: power off */ ++ return !(val & pd->info->mem_status_mask); ++} ++ ++static bool rockchip_pmu_domain_is_chain_on(struct rockchip_pm_domain *pd) ++{ ++ struct rockchip_pmu *pmu = pd->pmu; ++ unsigned int val; ++ ++ regmap_read(pmu->regmap, ++ pmu->info->chain_status_offset + pd->info->mem_offset, &val); ++ ++ /* 1'b1: power on, 1'b0: power off */ ++ return val & pd->info->mem_status_mask; ++} ++ ++static int rockchip_pmu_domain_mem_reset(struct rockchip_pm_domain *pd) ++{ ++ struct rockchip_pmu *pmu = pd->pmu; ++ struct generic_pm_domain *genpd = &pd->genpd; ++ bool is_on; ++ int ret = 0; ++ ++ ret = readx_poll_timeout_atomic(rockchip_pmu_domain_is_chain_on, pd, is_on, ++ is_on == true, 0, 10000); ++ if (ret) { ++ dev_err(pmu->dev, ++ "failed to get chain status '%s', target_on=1, val=%d\n", ++ genpd->name, is_on); ++ goto error; ++ } ++ ++ udelay(20); ++ ++ regmap_write(pmu->regmap, pmu->info->mem_pwr_offset + pd->info->pwr_offset, ++ (pd->info->pwr_mask | pd->info->pwr_w_mask)); ++ wmb(); ++ ++ ret = readx_poll_timeout_atomic(rockchip_pmu_domain_is_mem_on, pd, is_on, ++ is_on == false, 0, 10000); ++ if (ret) { ++ dev_err(pmu->dev, ++ "failed to get mem status '%s', target_on=0, val=%d\n", ++ genpd->name, is_on); ++ goto error; ++ } ++ ++ regmap_write(pmu->regmap, pmu->info->mem_pwr_offset + pd->info->pwr_offset, ++ pd->info->pwr_w_mask); ++ wmb(); ++ ++ ret = readx_poll_timeout_atomic(rockchip_pmu_domain_is_mem_on, pd, is_on, ++ is_on == true, 0, 10000); ++ if (ret) { ++ dev_err(pmu->dev, ++ "failed to get mem status '%s', target_on=1, val=%d\n", ++ genpd->name, is_on); ++ } ++ ++error: ++ return ret; ++} ++ + static void rockchip_do_pmu_set_power_domain(struct rockchip_pm_domain *pd, + bool on) + { + struct rockchip_pmu *pmu = pd->pmu; + struct generic_pm_domain *genpd = &pd->genpd; + u32 pd_pwr_offset = pd->info->pwr_offset; +- bool is_on; ++ bool is_on, is_mem_on = false; + + if (pd->info->pwr_mask == 0) + return; +- else if (pd->info->pwr_w_mask) ++ ++ if (on && pd->info->mem_status_mask) ++ is_mem_on = rockchip_pmu_domain_is_mem_on(pd); ++ ++ if (pd->info->pwr_w_mask) + regmap_write(pmu->regmap, pmu->info->pwr_offset + pd_pwr_offset, + on ? pd->info->pwr_w_mask : + (pd->info->pwr_mask | pd->info->pwr_w_mask)); +@@ -428,6 +510,9 @@ static void rockchip_do_pmu_set_power_do + + wmb(); + ++ if (is_mem_on && rockchip_pmu_domain_mem_reset(pd)) ++ return; ++ + if (readx_poll_timeout_atomic(rockchip_pmu_domain_is_on, pd, is_on, + is_on == on, 0, 10000)) { + dev_err(pmu->dev, +@@ -645,7 +730,9 @@ static int rockchip_pm_add_one_domain(st + pd->genpd.flags = GENPD_FLAG_PM_CLK; + if (pd_info->active_wakeup) + pd->genpd.flags |= GENPD_FLAG_ACTIVE_WAKEUP; +- pm_genpd_init(&pd->genpd, NULL, !rockchip_pmu_domain_is_on(pd)); ++ pm_genpd_init(&pd->genpd, NULL, ++ !rockchip_pmu_domain_is_on(pd) || ++ (pd->info->mem_status_mask && !rockchip_pmu_domain_is_mem_on(pd))); + + pmu->genpd_data.domains[id] = &pd->genpd; + return 0; +@@ -1024,35 +1111,35 @@ static const struct rockchip_domain_info + }; + + static const struct rockchip_domain_info rk3588_pm_domains[] = { +- [RK3588_PD_GPU] = DOMAIN_RK3588("gpu", 0x0, BIT(0), 0, BIT(1), 0x0, BIT(0), BIT(0), false), +- [RK3588_PD_NPU] = DOMAIN_RK3588("npu", 0x0, BIT(1), BIT(1), 0, 0x0, 0, 0, false), +- [RK3588_PD_VCODEC] = DOMAIN_RK3588("vcodec", 0x0, BIT(2), BIT(2), 0, 0x0, 0, 0, false), +- [RK3588_PD_NPUTOP] = DOMAIN_RK3588("nputop", 0x0, BIT(3), 0, BIT(2), 0x0, BIT(1), BIT(1), false), +- [RK3588_PD_NPU1] = DOMAIN_RK3588("npu1", 0x0, BIT(4), 0, BIT(3), 0x0, BIT(2), BIT(2), false), +- [RK3588_PD_NPU2] = DOMAIN_RK3588("npu2", 0x0, BIT(5), 0, BIT(4), 0x0, BIT(3), BIT(3), false), +- [RK3588_PD_VENC0] = DOMAIN_RK3588("venc0", 0x0, BIT(6), 0, BIT(5), 0x0, BIT(4), BIT(4), false), +- [RK3588_PD_VENC1] = DOMAIN_RK3588("venc1", 0x0, BIT(7), 0, BIT(6), 0x0, BIT(5), BIT(5), false), +- [RK3588_PD_RKVDEC0] = DOMAIN_RK3588("rkvdec0", 0x0, BIT(8), 0, BIT(7), 0x0, BIT(6), BIT(6), false), +- [RK3588_PD_RKVDEC1] = DOMAIN_RK3588("rkvdec1", 0x0, BIT(9), 0, BIT(8), 0x0, BIT(7), BIT(7), false), +- [RK3588_PD_VDPU] = DOMAIN_RK3588("vdpu", 0x0, BIT(10), 0, BIT(9), 0x0, BIT(8), BIT(8), false), +- [RK3588_PD_RGA30] = DOMAIN_RK3588("rga30", 0x0, BIT(11), 0, BIT(10), 0x0, 0, 0, false), +- [RK3588_PD_AV1] = DOMAIN_RK3588("av1", 0x0, BIT(12), 0, BIT(11), 0x0, BIT(9), BIT(9), false), +- [RK3588_PD_VI] = DOMAIN_RK3588("vi", 0x0, BIT(13), 0, BIT(12), 0x0, BIT(10), BIT(10), false), +- [RK3588_PD_FEC] = DOMAIN_RK3588("fec", 0x0, BIT(14), 0, BIT(13), 0x0, 0, 0, false), +- [RK3588_PD_ISP1] = DOMAIN_RK3588("isp1", 0x0, BIT(15), 0, BIT(14), 0x0, BIT(11), BIT(11), false), +- [RK3588_PD_RGA31] = DOMAIN_RK3588("rga31", 0x4, BIT(0), 0, BIT(15), 0x0, BIT(12), BIT(12), false), +- [RK3588_PD_VOP] = DOMAIN_RK3588("vop", 0x4, BIT(1), 0, BIT(16), 0x0, BIT(13) | BIT(14), BIT(13) | BIT(14), false), +- [RK3588_PD_VO0] = DOMAIN_RK3588("vo0", 0x4, BIT(2), 0, BIT(17), 0x0, BIT(15), BIT(15), false), +- [RK3588_PD_VO1] = DOMAIN_RK3588("vo1", 0x4, BIT(3), 0, BIT(18), 0x4, BIT(0), BIT(16), false), +- [RK3588_PD_AUDIO] = DOMAIN_RK3588("audio", 0x4, BIT(4), 0, BIT(19), 0x4, BIT(1), BIT(17), false), +- [RK3588_PD_PHP] = DOMAIN_RK3588("php", 0x4, BIT(5), 0, BIT(20), 0x4, BIT(5), BIT(21), false), +- [RK3588_PD_GMAC] = DOMAIN_RK3588("gmac", 0x4, BIT(6), 0, BIT(21), 0x0, 0, 0, false), +- [RK3588_PD_PCIE] = DOMAIN_RK3588("pcie", 0x4, BIT(7), 0, BIT(22), 0x0, 0, 0, true), +- [RK3588_PD_NVM] = DOMAIN_RK3588("nvm", 0x4, BIT(8), BIT(24), 0, 0x4, BIT(2), BIT(18), false), +- [RK3588_PD_NVM0] = DOMAIN_RK3588("nvm0", 0x4, BIT(9), 0, BIT(23), 0x0, 0, 0, false), +- [RK3588_PD_SDIO] = DOMAIN_RK3588("sdio", 0x4, BIT(10), 0, BIT(24), 0x4, BIT(3), BIT(19), false), +- [RK3588_PD_USB] = DOMAIN_RK3588("usb", 0x4, BIT(11), 0, BIT(25), 0x4, BIT(4), BIT(20), true), +- [RK3588_PD_SDMMC] = DOMAIN_RK3588("sdmmc", 0x4, BIT(13), 0, BIT(26), 0x0, 0, 0, false), ++ [RK3588_PD_GPU] = DOMAIN_RK3588("gpu", 0x0, BIT(0), 0, 0x0, 0, BIT(1), 0x0, BIT(0), BIT(0), false), ++ [RK3588_PD_NPU] = DOMAIN_RK3588("npu", 0x0, BIT(1), BIT(1), 0x0, 0, 0, 0x0, 0, 0, false), ++ [RK3588_PD_VCODEC] = DOMAIN_RK3588("vcodec", 0x0, BIT(2), BIT(2), 0x0, 0, 0, 0x0, 0, 0, false), ++ [RK3588_PD_NPUTOP] = DOMAIN_RK3588("nputop", 0x0, BIT(3), 0, 0x0, BIT(11), BIT(2), 0x0, BIT(1), BIT(1), false), ++ [RK3588_PD_NPU1] = DOMAIN_RK3588("npu1", 0x0, BIT(4), 0, 0x0, BIT(12), BIT(3), 0x0, BIT(2), BIT(2), false), ++ [RK3588_PD_NPU2] = DOMAIN_RK3588("npu2", 0x0, BIT(5), 0, 0x0, BIT(13), BIT(4), 0x0, BIT(3), BIT(3), false), ++ [RK3588_PD_VENC0] = DOMAIN_RK3588("venc0", 0x0, BIT(6), 0, 0x0, BIT(14), BIT(5), 0x0, BIT(4), BIT(4), false), ++ [RK3588_PD_VENC1] = DOMAIN_RK3588("venc1", 0x0, BIT(7), 0, 0x0, BIT(15), BIT(6), 0x0, BIT(5), BIT(5), false), ++ [RK3588_PD_RKVDEC0] = DOMAIN_RK3588("rkvdec0", 0x0, BIT(8), 0, 0x0, BIT(16), BIT(7), 0x0, BIT(6), BIT(6), false), ++ [RK3588_PD_RKVDEC1] = DOMAIN_RK3588("rkvdec1", 0x0, BIT(9), 0, 0x0, BIT(17), BIT(8), 0x0, BIT(7), BIT(7), false), ++ [RK3588_PD_VDPU] = DOMAIN_RK3588("vdpu", 0x0, BIT(10), 0, 0x0, BIT(18), BIT(9), 0x0, BIT(8), BIT(8), false), ++ [RK3588_PD_RGA30] = DOMAIN_RK3588("rga30", 0x0, BIT(11), 0, 0x0, BIT(19), BIT(10), 0x0, 0, 0, false), ++ [RK3588_PD_AV1] = DOMAIN_RK3588("av1", 0x0, BIT(12), 0, 0x0, BIT(20), BIT(11), 0x0, BIT(9), BIT(9), false), ++ [RK3588_PD_VI] = DOMAIN_RK3588("vi", 0x0, BIT(13), 0, 0x0, BIT(21), BIT(12), 0x0, BIT(10), BIT(10), false), ++ [RK3588_PD_FEC] = DOMAIN_RK3588("fec", 0x0, BIT(14), 0, 0x0, BIT(22), BIT(13), 0x0, 0, 0, false), ++ [RK3588_PD_ISP1] = DOMAIN_RK3588("isp1", 0x0, BIT(15), 0, 0x0, BIT(23), BIT(14), 0x0, BIT(11), BIT(11), false), ++ [RK3588_PD_RGA31] = DOMAIN_RK3588("rga31", 0x4, BIT(0), 0, 0x0, BIT(24), BIT(15), 0x0, BIT(12), BIT(12), false), ++ [RK3588_PD_VOP] = DOMAIN_RK3588("vop", 0x4, BIT(1), 0, 0x0, BIT(25), BIT(16), 0x0, BIT(13) | BIT(14), BIT(13) | BIT(14), false), ++ [RK3588_PD_VO0] = DOMAIN_RK3588("vo0", 0x4, BIT(2), 0, 0x0, BIT(26), BIT(17), 0x0, BIT(15), BIT(15), false), ++ [RK3588_PD_VO1] = DOMAIN_RK3588("vo1", 0x4, BIT(3), 0, 0x0, BIT(27), BIT(18), 0x4, BIT(0), BIT(16), false), ++ [RK3588_PD_AUDIO] = DOMAIN_RK3588("audio", 0x4, BIT(4), 0, 0x0, BIT(28), BIT(19), 0x4, BIT(1), BIT(17), false), ++ [RK3588_PD_PHP] = DOMAIN_RK3588("php", 0x4, BIT(5), 0, 0x0, BIT(29), BIT(20), 0x4, BIT(5), BIT(21), false), ++ [RK3588_PD_GMAC] = DOMAIN_RK3588("gmac", 0x4, BIT(6), 0, 0x0, BIT(30), BIT(21), 0x0, 0, 0, false), ++ [RK3588_PD_PCIE] = DOMAIN_RK3588("pcie", 0x4, BIT(7), 0, 0x0, BIT(31), BIT(22), 0x0, 0, 0, true), ++ [RK3588_PD_NVM] = DOMAIN_RK3588("nvm", 0x4, BIT(8), BIT(24), 0x4, 0, 0, 0x4, BIT(2), BIT(18), false), ++ [RK3588_PD_NVM0] = DOMAIN_RK3588("nvm0", 0x4, BIT(9), 0, 0x4, BIT(1), BIT(23), 0x0, 0, 0, false), ++ [RK3588_PD_SDIO] = DOMAIN_RK3588("sdio", 0x4, BIT(10), 0, 0x4, BIT(2), BIT(24), 0x4, BIT(3), BIT(19), false), ++ [RK3588_PD_USB] = DOMAIN_RK3588("usb", 0x4, BIT(11), 0, 0x4, BIT(3), BIT(25), 0x4, BIT(4), BIT(20), true), ++ [RK3588_PD_SDMMC] = DOMAIN_RK3588("sdmmc", 0x4, BIT(13), 0, 0x4, BIT(5), BIT(26), 0x0, 0, 0, false), + }; + + static const struct rockchip_pmu_info px30_pmu = { +@@ -1207,6 +1294,9 @@ static const struct rockchip_pmu_info rk + .req_offset = 0x10c, + .idle_offset = 0x120, + .ack_offset = 0x118, ++ .mem_pwr_offset = 0x1a0, ++ .chain_status_offset = 0x1f0, ++ .mem_status_offset = 0x1f8, + .repair_status_offset = 0x290, + + .num_domains = ARRAY_SIZE(rk3588_pm_domains), diff --git a/target/linux/rockchip/patches-6.1/110-04-arm64-dts-rockchip-rk3588-evb1-add-pmic.patch b/target/linux/rockchip/patches-6.1/110-04-arm64-dts-rockchip-rk3588-evb1-add-pmic.patch new file mode 100644 index 0000000000..afbf6e2339 --- /dev/null +++ b/target/linux/rockchip/patches-6.1/110-04-arm64-dts-rockchip-rk3588-evb1-add-pmic.patch @@ -0,0 +1,763 @@ +From e7b9bfa6608f131c2575094b3e9c65394227b115 Mon Sep 17 00:00:00 2001 +From: Sebastian Reichel +Date: Tue, 12 Jul 2022 15:17:33 +0200 +Subject: [PATCH] arm64: dts: rockchip: rk3588-evb1: add pmic + +This adds PMIC support for the RK3588 EVB. + +Signed-off-by: shengfei Xu +Co-developed-by: shengfei Xu +Signed-off-by: Sebastian Reichel +--- + .../boot/dts/rockchip/rk3588-evb1-v10.dts | 740 ++++++++++++++++++ + 1 file changed, 740 insertions(+) + +--- a/arch/arm64/boot/dts/rockchip/rk3588-evb1-v10.dts ++++ b/arch/arm64/boot/dts/rockchip/rk3588-evb1-v10.dts +@@ -123,6 +123,746 @@ + status = "okay"; + }; + ++&spi2 { ++ status = "okay"; ++ assigned-clocks = <&cru CLK_SPI2>; ++ assigned-clock-rates = <200000000>; ++ num-cs = <2>; ++ ++ pmic@0 { ++ compatible = "rockchip,rk806"; ++ spi-max-frequency = <1000000>; ++ reg = <0x0>; ++ ++ interrupt-parent = <&gpio0>; ++ interrupts = <7 IRQ_TYPE_LEVEL_LOW>; ++ ++ pinctrl-names = "default", "pmic-power-off"; ++ pinctrl-0 = <&pmic_pins>, <&rk806_dvs1_null>, <&rk806_dvs2_null>, <&rk806_dvs3_null>; ++ pinctrl-1 = <&rk806_dvs1_pwrdn>; ++ ++ vcc1-supply = <&vcc5v0_sys>; ++ vcc2-supply = <&vcc5v0_sys>; ++ vcc3-supply = <&vcc5v0_sys>; ++ vcc4-supply = <&vcc5v0_sys>; ++ vcc5-supply = <&vcc5v0_sys>; ++ vcc6-supply = <&vcc5v0_sys>; ++ vcc7-supply = <&vcc5v0_sys>; ++ vcc8-supply = <&vcc5v0_sys>; ++ vcc9-supply = <&vcc5v0_sys>; ++ vcc10-supply = <&vcc5v0_sys>; ++ vcc11-supply = <&vcc_2v0_pldo_s3>; ++ vcc12-supply = <&vcc5v0_sys>; ++ vcc13-supply = <&vcc5v0_sys>; ++ vcc14-supply = <&vcc_1v1_nldo_s3>; ++ vcca-supply = <&vcc5v0_sys>; ++ ++ gpio-controller; ++ #gpio-cells = <2>; ++ ++ rk806_dvs1_null: dvs1-null-pins { ++ pins = "gpio_pwrctrl1"; ++ function = "pin_fun0"; ++ }; ++ ++ rk806_dvs1_slp: dvs1-slp-pins { ++ pins = "gpio_pwrctrl1"; ++ function = "pin_fun1"; ++ }; ++ ++ rk806_dvs1_pwrdn: dvs1-pwrdn-pins { ++ pins = "gpio_pwrctrl1"; ++ function = "pin_fun2"; ++ }; ++ ++ rk806_dvs1_rst: dvs1-rst-pins { ++ pins = "gpio_pwrctrl1"; ++ function = "pin_fun3"; ++ }; ++ ++ rk806_dvs2_null: dvs2-null-pins { ++ pins = "gpio_pwrctrl2"; ++ function = "pin_fun0"; ++ }; ++ ++ rk806_dvs2_slp: dvs2-slp-pins { ++ pins = "gpio_pwrctrl2"; ++ function = "pin_fun1"; ++ }; ++ ++ rk806_dvs2_pwrdn: dvs2-pwrdn-pins { ++ pins = "gpio_pwrctrl2"; ++ function = "pin_fun2"; ++ }; ++ ++ rk806_dvs2_rst: dvs2-rst-pins { ++ pins = "gpio_pwrctrl2"; ++ function = "pin_fun3"; ++ }; ++ ++ rk806_dvs2_dvs: dvs2-dvs-pins { ++ pins = "gpio_pwrctrl2"; ++ function = "pin_fun4"; ++ }; ++ ++ rk806_dvs2_gpio: dvs2-gpio-pins { ++ pins = "gpio_pwrctrl2"; ++ function = "pin_fun5"; ++ }; ++ ++ rk806_dvs3_null: dvs3-null-pins { ++ pins = "gpio_pwrctrl3"; ++ function = "pin_fun0"; ++ }; ++ ++ rk806_dvs3_slp: dvs3-slp-pins { ++ pins = "gpio_pwrctrl3"; ++ function = "pin_fun1"; ++ }; ++ ++ rk806_dvs3_pwrdn: dvs3-pwrdn-pins { ++ pins = "gpio_pwrctrl3"; ++ function = "pin_fun2"; ++ }; ++ ++ rk806_dvs3_rst: dvs3-rst-pins { ++ pins = "gpio_pwrctrl3"; ++ function = "pin_fun3"; ++ }; ++ ++ rk806_dvs3_dvs: dvs3-dvs-pins { ++ pins = "gpio_pwrctrl3"; ++ function = "pin_fun4"; ++ }; ++ ++ rk806_dvs3_gpio: dvs3-gpio-pins { ++ pins = "gpio_pwrctrl3"; ++ function = "pin_fun5"; ++ }; ++ ++ regulators { ++ vdd_gpu_s0: dcdc-reg1 { ++ regulator-boot-on; ++ regulator-min-microvolt = <550000>; ++ regulator-max-microvolt = <950000>; ++ regulator-ramp-delay = <12500>; ++ regulator-name = "vdd_gpu_s0"; ++ regulator-enable-ramp-delay = <400>; ++ regulator-state-mem { ++ regulator-off-in-suspend; ++ }; ++ }; ++ ++ vdd_npu_s0: dcdc-reg2 { ++ regulator-always-on; ++ regulator-boot-on; ++ regulator-min-microvolt = <550000>; ++ regulator-max-microvolt = <950000>; ++ regulator-ramp-delay = <12500>; ++ regulator-name = "vdd_npu_s0"; ++ regulator-state-mem { ++ regulator-off-in-suspend; ++ }; ++ }; ++ ++ vdd_log_s0: dcdc-reg3 { ++ regulator-always-on; ++ regulator-boot-on; ++ regulator-min-microvolt = <675000>; ++ regulator-max-microvolt = <750000>; ++ regulator-ramp-delay = <12500>; ++ regulator-name = "vdd_log_s0"; ++ regulator-state-mem { ++ regulator-off-in-suspend; ++ regulator-suspend-microvolt = <750000>; ++ }; ++ }; ++ ++ vdd_vdenc_s0: dcdc-reg4 { ++ regulator-always-on; ++ regulator-boot-on; ++ regulator-min-microvolt = <550000>; ++ regulator-max-microvolt = <950000>; ++ regulator-ramp-delay = <12500>; ++ regulator-name = "vdd_vdenc_s0"; ++ regulator-state-mem { ++ regulator-off-in-suspend; ++ }; ++ ++ }; ++ ++ vdd_gpu_mem_s0: dcdc-reg5 { ++ regulator-boot-on; ++ regulator-min-microvolt = <675000>; ++ regulator-max-microvolt = <950000>; ++ regulator-ramp-delay = <12500>; ++ regulator-enable-ramp-delay = <400>; ++ regulator-name = "vdd_gpu_mem_s0"; ++ regulator-state-mem { ++ regulator-off-in-suspend; ++ }; ++ ++ }; ++ ++ vdd_npu_mem_s0: dcdc-reg6 { ++ regulator-always-on; ++ regulator-boot-on; ++ regulator-min-microvolt = <675000>; ++ regulator-max-microvolt = <950000>; ++ regulator-ramp-delay = <12500>; ++ regulator-name = "vdd_npu_mem_s0"; ++ regulator-state-mem { ++ regulator-off-in-suspend; ++ }; ++ ++ }; ++ ++ vcc_2v0_pldo_s3: dcdc-reg7 { ++ regulator-always-on; ++ regulator-boot-on; ++ regulator-min-microvolt = <2000000>; ++ regulator-max-microvolt = <2000000>; ++ regulator-ramp-delay = <12500>; ++ regulator-name = "vdd_2v0_pldo_s3"; ++ regulator-state-mem { ++ regulator-on-in-suspend; ++ regulator-suspend-microvolt = <2000000>; ++ }; ++ }; ++ ++ vdd_vdenc_mem_s0: dcdc-reg8 { ++ regulator-always-on; ++ regulator-boot-on; ++ regulator-min-microvolt = <675000>; ++ regulator-max-microvolt = <950000>; ++ regulator-ramp-delay = <12500>; ++ regulator-name = "vdd_vdenc_mem_s0"; ++ regulator-state-mem { ++ regulator-off-in-suspend; ++ }; ++ }; ++ ++ vdd2_ddr_s3: dcdc-reg9 { ++ regulator-always-on; ++ regulator-boot-on; ++ regulator-name = "vdd2_ddr_s3"; ++ regulator-state-mem { ++ regulator-on-in-suspend; ++ }; ++ }; ++ ++ vcc_1v1_nldo_s3: dcdc-reg10 { ++ regulator-always-on; ++ regulator-boot-on; ++ regulator-min-microvolt = <1100000>; ++ regulator-max-microvolt = <1100000>; ++ regulator-ramp-delay = <12500>; ++ regulator-name = "vcc_1v1_nldo_s3"; ++ regulator-state-mem { ++ regulator-on-in-suspend; ++ regulator-suspend-microvolt = <1100000>; ++ }; ++ }; ++ ++ avcc_1v8_s0: pldo-reg1 { ++ regulator-always-on; ++ regulator-boot-on; ++ regulator-min-microvolt = <1800000>; ++ regulator-max-microvolt = <1800000>; ++ regulator-ramp-delay = <12500>; ++ regulator-name = "avcc_1v8_s0"; ++ regulator-state-mem { ++ regulator-off-in-suspend; ++ }; ++ }; ++ ++ vdd1_1v8_ddr_s3: pldo-reg2 { ++ regulator-always-on; ++ regulator-boot-on; ++ regulator-min-microvolt = <1800000>; ++ regulator-max-microvolt = <1800000>; ++ regulator-ramp-delay = <12500>; ++ regulator-name = "vdd1_1v8_ddr_s3"; ++ regulator-state-mem { ++ regulator-on-in-suspend; ++ regulator-suspend-microvolt = <1800000>; ++ }; ++ }; ++ ++ avcc_1v8_codec_s0: pldo-reg3 { ++ regulator-always-on; ++ regulator-boot-on; ++ regulator-min-microvolt = <1800000>; ++ regulator-max-microvolt = <1800000>; ++ regulator-ramp-delay = <12500>; ++ regulator-name = "avcc_1v8_codec_s0"; ++ regulator-state-mem { ++ regulator-off-in-suspend; ++ }; ++ }; ++ ++ vcc_3v3_s3: pldo-reg4 { ++ regulator-always-on; ++ regulator-boot-on; ++ regulator-min-microvolt = <3300000>; ++ regulator-max-microvolt = <3300000>; ++ regulator-ramp-delay = <12500>; ++ regulator-name = "vcc_3v3_s3"; ++ regulator-state-mem { ++ regulator-on-in-suspend; ++ regulator-suspend-microvolt = <3300000>; ++ }; ++ }; ++ ++ vccio_sd_s0: pldo-reg5 { ++ regulator-always-on; ++ regulator-boot-on; ++ regulator-min-microvolt = <1800000>; ++ regulator-max-microvolt = <3300000>; ++ regulator-ramp-delay = <12500>; ++ regulator-name = "vccio_sd_s0"; ++ regulator-state-mem { ++ regulator-off-in-suspend; ++ }; ++ }; ++ ++ vccio_1v8_s3: pldo-reg6 { ++ regulator-always-on; ++ regulator-boot-on; ++ regulator-min-microvolt = <1800000>; ++ regulator-max-microvolt = <1800000>; ++ regulator-ramp-delay = <12500>; ++ regulator-name = "vccio_1v8_s3"; ++ regulator-state-mem { ++ regulator-on-in-suspend; ++ regulator-suspend-microvolt = <1800000>; ++ }; ++ }; ++ ++ vdd_0v75_s3: nldo-reg1 { ++ regulator-always-on; ++ regulator-boot-on; ++ regulator-min-microvolt = <750000>; ++ regulator-max-microvolt = <750000>; ++ regulator-ramp-delay = <12500>; ++ regulator-name = "vdd_0v75_s3"; ++ regulator-state-mem { ++ regulator-on-in-suspend; ++ regulator-suspend-microvolt = <750000>; ++ }; ++ }; ++ ++ vdd2l_0v9_ddr_s3: nldo-reg2 { ++ regulator-always-on; ++ regulator-boot-on; ++ regulator-min-microvolt = <900000>; ++ regulator-max-microvolt = <900000>; ++ regulator-name = "vdd2l_0v9_ddr_s3"; ++ regulator-state-mem { ++ regulator-on-in-suspend; ++ regulator-suspend-microvolt = <900000>; ++ }; ++ }; ++ ++ vdd_0v75_hdmi_edp_s0: nldo-reg3 { ++ regulator-always-on; ++ regulator-boot-on; ++ regulator-min-microvolt = <750000>; ++ regulator-max-microvolt = <750000>; ++ regulator-name = "vdd_0v75_hdmi_edp_s0"; ++ regulator-state-mem { ++ regulator-off-in-suspend; ++ }; ++ }; ++ ++ avdd_0v75_s0: nldo-reg4 { ++ regulator-always-on; ++ regulator-boot-on; ++ regulator-min-microvolt = <750000>; ++ regulator-max-microvolt = <750000>; ++ regulator-name = "avdd_0v75_s0"; ++ regulator-state-mem { ++ regulator-off-in-suspend; ++ }; ++ }; ++ ++ vdd_0v85_s0: nldo-reg5 { ++ regulator-always-on; ++ regulator-boot-on; ++ regulator-min-microvolt = <850000>; ++ regulator-max-microvolt = <850000>; ++ regulator-name = "vdd_0v85_s0"; ++ regulator-state-mem { ++ regulator-off-in-suspend; ++ }; ++ }; ++ }; ++ }; ++ ++ pmic@1 { ++ compatible = "rockchip,rk806"; ++ spi-max-frequency = <1000000>; ++ reg = <0x01>; ++ ++ interrupt-parent = <&gpio0>; ++ interrupts = <7 IRQ_TYPE_LEVEL_LOW>; ++ ++ pinctrl-names = "default", "pmic-sleep"; ++ pinctrl-0 = <&rk806_slave_dvs1_null>, <&rk806_slave_dvs2_null>, <&rk806_slave_dvs3_null>; ++ pinctrl-1 = <&rk806_slave_dvs1_slp>, <&rk806_slave_dvs2_null>, <&rk806_slave_dvs3_null>; ++ ++ vcc1-supply = <&vcc5v0_sys>; ++ vcc2-supply = <&vcc5v0_sys>; ++ vcc3-supply = <&vcc5v0_sys>; ++ vcc4-supply = <&vcc5v0_sys>; ++ vcc5-supply = <&vcc5v0_sys>; ++ vcc6-supply = <&vcc5v0_sys>; ++ vcc7-supply = <&vcc5v0_sys>; ++ vcc8-supply = <&vcc5v0_sys>; ++ vcc9-supply = <&vcc5v0_sys>; ++ vcc10-supply = <&vcc5v0_sys>; ++ vcc11-supply = <&vcc_2v0_pldo_s3>; ++ vcc12-supply = <&vcc5v0_sys>; ++ vcc13-supply = <&vcc_1v1_nldo_s3>; ++ vcc14-supply = <&vcc_2v0_pldo_s3>; ++ vcca-supply = <&vcc5v0_sys>; ++ ++ gpio-controller; ++ #gpio-cells = <2>; ++ ++ rk806_slave_dvs1_null: dvs1-null-pins { ++ pins = "gpio_pwrctrl1"; ++ function = "pin_fun0"; ++ }; ++ ++ rk806_slave_dvs1_slp: dvs1-slp-pins { ++ pins = "gpio_pwrctrl1"; ++ function = "pin_fun1"; ++ }; ++ ++ rk806_slave_dvs1_pwrdn: dvs1-pwrdn-pins { ++ pins = "gpio_pwrctrl1"; ++ function = "pin_fun2"; ++ }; ++ ++ rk806_slave_dvs1_rst: dvs1-rst-pins { ++ pins = "gpio_pwrctrl1"; ++ function = "pin_fun3"; ++ }; ++ ++ rk806_slave_dvs2_null: dvs2-null-pins { ++ pins = "gpio_pwrctrl2"; ++ function = "pin_fun0"; ++ }; ++ ++ rk806_slave_dvs2_slp: dvs2-slp-pins { ++ pins = "gpio_pwrctrl2"; ++ function = "pin_fun1"; ++ }; ++ ++ rk806_slave_dvs2_pwrdn: dvs2-pwrdn-pins { ++ pins = "gpio_pwrctrl2"; ++ function = "pin_fun2"; ++ }; ++ ++ rk806_slave_dvs2_rst: dvs2-rst-pins { ++ pins = "gpio_pwrctrl2"; ++ function = "pin_fun3"; ++ }; ++ ++ rk806_slave_dvs2_dvs: dvs2-dvs-pins { ++ pins = "gpio_pwrctrl2"; ++ function = "pin_fun4"; ++ }; ++ ++ rk806_slave_dvs2_gpio: dvs2-gpio-pins { ++ pins = "gpio_pwrctrl2"; ++ function = "pin_fun5"; ++ }; ++ ++ rk806_slave_dvs3_null: dvs3-null-pins { ++ pins = "gpio_pwrctrl3"; ++ function = "pin_fun0"; ++ }; ++ ++ rk806_slave_dvs3_slp: dvs3-slp-pins { ++ pins = "gpio_pwrctrl3"; ++ function = "pin_fun1"; ++ }; ++ ++ rk806_slave_dvs3_pwrdn: dvs3-pwrdn-pins { ++ pins = "gpio_pwrctrl3"; ++ function = "pin_fun2"; ++ }; ++ ++ rk806_slave_dvs3_rst: dvs3-rst-pins { ++ pins = "gpio_pwrctrl3"; ++ function = "pin_fun3"; ++ }; ++ ++ rk806_slave_dvs3_dvs: dvs3-dvs-pins { ++ pins = "gpio_pwrctrl3"; ++ function = "pin_fun4"; ++ }; ++ ++ rk806_slave_dvs3_gpio: dvs3-gpio-pins { ++ pins = "gpio_pwrctrl3"; ++ function = "pin_fun5"; ++ }; ++ ++ regulators { ++ vdd_cpu_big1_s0: dcdc-reg1 { ++ regulator-always-on; ++ regulator-boot-on; ++ regulator-min-microvolt = <550000>; ++ regulator-max-microvolt = <1050000>; ++ regulator-ramp-delay = <12500>; ++ regulator-name = "vdd_cpu_big1_s0"; ++ regulator-state-mem { ++ regulator-off-in-suspend; ++ }; ++ }; ++ ++ vdd_cpu_big0_s0: dcdc-reg2 { ++ regulator-always-on; ++ regulator-boot-on; ++ regulator-min-microvolt = <550000>; ++ regulator-max-microvolt = <1050000>; ++ regulator-ramp-delay = <12500>; ++ regulator-name = "vdd_cpu_big0_s0"; ++ regulator-state-mem { ++ regulator-off-in-suspend; ++ }; ++ }; ++ ++ vdd_cpu_lit_s0: dcdc-reg3 { ++ regulator-always-on; ++ regulator-boot-on; ++ regulator-min-microvolt = <550000>; ++ regulator-max-microvolt = <950000>; ++ regulator-ramp-delay = <12500>; ++ regulator-name = "vdd_cpu_lit_s0"; ++ regulator-state-mem { ++ regulator-off-in-suspend; ++ }; ++ }; ++ ++ vcc_3v3_s0: dcdc-reg4 { ++ regulator-always-on; ++ regulator-boot-on; ++ regulator-min-microvolt = <3300000>; ++ regulator-max-microvolt = <3300000>; ++ regulator-ramp-delay = <12500>; ++ regulator-name = "vcc_3v3_s0"; ++ regulator-state-mem { ++ regulator-off-in-suspend; ++ }; ++ }; ++ ++ vdd_cpu_big1_mem_s0: dcdc-reg5 { ++ regulator-always-on; ++ regulator-boot-on; ++ regulator-min-microvolt = <675000>; ++ regulator-max-microvolt = <1050000>; ++ regulator-ramp-delay = <12500>; ++ regulator-name = "vdd_cpu_big1_mem_s0"; ++ regulator-state-mem { ++ regulator-off-in-suspend; ++ }; ++ }; ++ ++ ++ vdd_cpu_big0_mem_s0: dcdc-reg6 { ++ regulator-always-on; ++ regulator-boot-on; ++ regulator-min-microvolt = <675000>; ++ regulator-max-microvolt = <1050000>; ++ regulator-ramp-delay = <12500>; ++ regulator-name = "vdd_cpu_big0_mem_s0"; ++ regulator-state-mem { ++ regulator-off-in-suspend; ++ }; ++ }; ++ ++ vcc_1v8_s0: dcdc-reg7 { ++ regulator-always-on; ++ regulator-boot-on; ++ regulator-min-microvolt = <1800000>; ++ regulator-max-microvolt = <1800000>; ++ regulator-ramp-delay = <12500>; ++ regulator-name = "vcc_1v8_s0"; ++ regulator-state-mem { ++ regulator-off-in-suspend; ++ }; ++ }; ++ ++ vdd_cpu_lit_mem_s0: dcdc-reg8 { ++ regulator-always-on; ++ regulator-boot-on; ++ regulator-min-microvolt = <675000>; ++ regulator-max-microvolt = <950000>; ++ regulator-ramp-delay = <12500>; ++ regulator-name = "vdd_cpu_lit_mem_s0"; ++ regulator-state-mem { ++ regulator-off-in-suspend; ++ }; ++ }; ++ ++ vddq_ddr_s0: dcdc-reg9 { ++ regulator-always-on; ++ regulator-boot-on; ++ regulator-name = "vddq_ddr_s0"; ++ regulator-state-mem { ++ regulator-off-in-suspend; ++ }; ++ }; ++ ++ vdd_ddr_s0: dcdc-reg10 { ++ regulator-always-on; ++ regulator-boot-on; ++ regulator-min-microvolt = <675000>; ++ regulator-max-microvolt = <900000>; ++ regulator-ramp-delay = <12500>; ++ regulator-name = "vdd_ddr_s0"; ++ regulator-state-mem { ++ regulator-off-in-suspend; ++ }; ++ }; ++ ++ vcc_1v8_cam_s0: pldo-reg1 { ++ regulator-always-on; ++ regulator-boot-on; ++ regulator-min-microvolt = <1800000>; ++ regulator-max-microvolt = <1800000>; ++ regulator-ramp-delay = <12500>; ++ regulator-name = "vcc_1v8_cam_s0"; ++ regulator-state-mem { ++ regulator-off-in-suspend; ++ }; ++ }; ++ ++ avdd1v8_ddr_pll_s0: pldo-reg2 { ++ regulator-always-on; ++ regulator-boot-on; ++ regulator-min-microvolt = <1800000>; ++ regulator-max-microvolt = <1800000>; ++ regulator-ramp-delay = <12500>; ++ regulator-name = "avdd1v8_ddr_pll_s0"; ++ regulator-state-mem { ++ regulator-off-in-suspend; ++ }; ++ }; ++ ++ vdd_1v8_pll_s0: pldo-reg3 { ++ regulator-always-on; ++ regulator-boot-on; ++ regulator-min-microvolt = <1800000>; ++ regulator-max-microvolt = <1800000>; ++ regulator-ramp-delay = <12500>; ++ regulator-name = "vdd_1v8_pll_s0"; ++ regulator-state-mem { ++ regulator-off-in-suspend; ++ }; ++ }; ++ ++ vcc_3v3_sd_s0: pldo-reg4 { ++ regulator-always-on; ++ regulator-boot-on; ++ regulator-min-microvolt = <3300000>; ++ regulator-max-microvolt = <3300000>; ++ regulator-ramp-delay = <12500>; ++ regulator-name = "vcc_3v3_sd_s0"; ++ regulator-state-mem { ++ regulator-off-in-suspend; ++ }; ++ }; ++ ++ vcc_2v8_cam_s0: pldo-reg5 { ++ regulator-always-on; ++ regulator-boot-on; ++ regulator-min-microvolt = <2800000>; ++ regulator-max-microvolt = <2800000>; ++ regulator-ramp-delay = <12500>; ++ regulator-name = "vcc_2v8_cam_s0"; ++ regulator-state-mem { ++ regulator-off-in-suspend; ++ }; ++ }; ++ ++ pldo6_s3: pldo-reg6 { ++ regulator-always-on; ++ regulator-boot-on; ++ regulator-min-microvolt = <1800000>; ++ regulator-max-microvolt = <1800000>; ++ regulator-name = "pldo6_s3"; ++ regulator-state-mem { ++ regulator-on-in-suspend; ++ regulator-suspend-microvolt = <1800000>; ++ }; ++ }; ++ ++ vdd_0v75_pll_s0: nldo-reg1 { ++ regulator-always-on; ++ regulator-boot-on; ++ regulator-min-microvolt = <750000>; ++ regulator-max-microvolt = <750000>; ++ regulator-ramp-delay = <12500>; ++ regulator-name = "vdd_0v75_pll_s0"; ++ regulator-state-mem { ++ regulator-off-in-suspend; ++ }; ++ }; ++ ++ vdd_ddr_pll_s0: nldo-reg2 { ++ regulator-always-on; ++ regulator-boot-on; ++ regulator-min-microvolt = <850000>; ++ regulator-max-microvolt = <850000>; ++ regulator-name = "vdd_ddr_pll_s0"; ++ regulator-state-mem { ++ regulator-off-in-suspend; ++ }; ++ }; ++ ++ avdd_0v85_s0: nldo-reg3 { ++ regulator-always-on; ++ regulator-boot-on; ++ regulator-min-microvolt = <850000>; ++ regulator-max-microvolt = <850000>; ++ regulator-ramp-delay = <12500>; ++ regulator-name = "avdd_0v85_s0"; ++ regulator-state-mem { ++ regulator-off-in-suspend; ++ }; ++ }; ++ ++ avdd_1v2_cam_s0: nldo-reg4 { ++ regulator-always-on; ++ regulator-boot-on; ++ regulator-min-microvolt = <1200000>; ++ regulator-max-microvolt = <1200000>; ++ regulator-ramp-delay = <12500>; ++ regulator-name = "avdd_1v2_cam_s0"; ++ regulator-state-mem { ++ regulator-off-in-suspend; ++ }; ++ }; ++ ++ avdd_1v2_s0: nldo-reg5 { ++ regulator-always-on; ++ regulator-boot-on; ++ regulator-min-microvolt = <1200000>; ++ regulator-max-microvolt = <1200000>; ++ regulator-ramp-delay = <12500>; ++ regulator-name = "avdd_1v2_s0"; ++ regulator-state-mem { ++ regulator-off-in-suspend; ++ }; ++ }; ++ }; ++ }; ++}; ++ + &uart2 { + pinctrl-0 = <&uart2m0_xfer>; + status = "okay"; diff --git a/target/linux/rockchip/patches-6.1/110-05-arm64-dts-rockchip-rk3588-evb1-add-cpu-regulator-info.patch b/target/linux/rockchip/patches-6.1/110-05-arm64-dts-rockchip-rk3588-evb1-add-cpu-regulator-info.patch new file mode 100644 index 0000000000..2691b4a353 --- /dev/null +++ b/target/linux/rockchip/patches-6.1/110-05-arm64-dts-rockchip-rk3588-evb1-add-cpu-regulator-info.patch @@ -0,0 +1,48 @@ +From 44ab35d703a396c625ae90fcaa2777e4dcfd6c73 Mon Sep 17 00:00:00 2001 +From: Sebastian Reichel +Date: Thu, 18 Aug 2022 14:35:46 +0200 +Subject: [PATCH] arm64: dts: rockchip: rk3588-evb1: add cpu regulator info + +Add regulator information for the CPU and enable the thermal sensor +to have working cpu frequency scaling. + +Signed-off-by: Sebastian Reichel +--- + .../boot/dts/rockchip/rk3588-evb1-v10.dts | 19 +++++++++++++++++++ + 1 file changed, 19 insertions(+) + +--- a/arch/arm64/boot/dts/rockchip/rk3588-evb1-v10.dts ++++ b/arch/arm64/boot/dts/rockchip/rk3588-evb1-v10.dts +@@ -49,6 +49,21 @@ + }; + }; + ++&cpu_l0 { ++ cpu-supply = <&vdd_cpu_lit_s0>; ++ mem-supply = <&vdd_cpu_lit_mem_s0>; ++}; ++ ++&cpu_b0 { ++ cpu-supply = <&vdd_cpu_big0_s0>; ++ mem-supply = <&vdd_cpu_big0_mem_s0>; ++}; ++ ++&cpu_b2 { ++ cpu-supply = <&vdd_cpu_big1_s0>; ++ mem-supply = <&vdd_cpu_big1_mem_s0>; ++}; ++ + &gmac0 { + clock_in_out = "output"; + phy-handle = <&rgmii_phy>; +@@ -863,6 +878,10 @@ + }; + }; + ++&tsadc { ++ status = "okay"; ++}; ++ + &uart2 { + pinctrl-0 = <&uart2m0_xfer>; + status = "okay"; diff --git a/target/linux/rockchip/patches-6.1/111-usb-host-ohci-platform-increase-max-clock-number-to-4.patch b/target/linux/rockchip/patches-6.1/111-usb-host-ohci-platform-increase-max-clock-number-to-4.patch new file mode 100644 index 0000000000..2f54b9dc32 --- /dev/null +++ b/target/linux/rockchip/patches-6.1/111-usb-host-ohci-platform-increase-max-clock-number-to-4.patch @@ -0,0 +1,24 @@ +From eb587e7611e9c61f5a8af5d9bfc4f994e9e1fda2 Mon Sep 17 00:00:00 2001 +From: Sebastian Reichel +Date: Wed, 29 Mar 2023 18:54:49 +0200 +Subject: [PATCH] usb: host: ohci-platform: increase max clock number to 4 + +Rockchip RK3588 OHCI requires 4 clocks to be enabled. + +Acked-by: Alan Stern +Signed-off-by: Sebastian Reichel +--- + drivers/usb/host/ohci-platform.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +--- a/drivers/usb/host/ohci-platform.c ++++ b/drivers/usb/host/ohci-platform.c +@@ -33,7 +33,7 @@ + #include "ohci.h" + + #define DRIVER_DESC "OHCI generic platform driver" +-#define OHCI_MAX_CLKS 3 ++#define OHCI_MAX_CLKS 4 + #define hcd_to_ohci_priv(h) ((struct ohci_platform_priv *)hcd_to_ohci(h)->priv) + + struct ohci_platform_priv { diff --git a/target/linux/rockchip/patches-6.1/112-01-phy-phy-rockchip-inno-usb2-add-rk3588-support.patch b/target/linux/rockchip/patches-6.1/112-01-phy-phy-rockchip-inno-usb2-add-rk3588-support.patch new file mode 100644 index 0000000000..37f901c445 --- /dev/null +++ b/target/linux/rockchip/patches-6.1/112-01-phy-phy-rockchip-inno-usb2-add-rk3588-support.patch @@ -0,0 +1,361 @@ +From: Sebastian Reichel +To: Vinod Koul , + Kishon Vijay Abraham I , + Rob Herring , + Krzysztof Kozlowski +Cc: Heiko Stuebner , + linux-phy@lists.infradead.org, + linux-arm-kernel@lists.infradead.org, + linux-rockchip@lists.infradead.org, linux-kernel@vger.kernel.org, + devicetree@vger.kernel.org, + Sebastian Reichel , + kernel@collabora.com, William Wu +Subject: [PATCH v3 2/7] phy: phy-rockchip-inno-usb2: add rk3588 support +Date: Mon, 22 May 2023 19:03:19 +0200 [thread overview] +Message-ID: <20230522170324.61349-3-sebastian.reichel@collabora.com> (raw) +In-Reply-To: <20230522170324.61349-1-sebastian.reichel@collabora.com> + +Add basic support for the USB2 PHY found in the Rockchip RK3588. + +Co-developed-by: William Wu +Signed-off-by: William Wu +Signed-off-by: Sebastian Reichel +--- + drivers/phy/rockchip/phy-rockchip-inno-usb2.c | 226 ++++++++++++++++-- + 1 file changed, 211 insertions(+), 15 deletions(-) + +--- a/drivers/phy/rockchip/phy-rockchip-inno-usb2.c ++++ b/drivers/phy/rockchip/phy-rockchip-inno-usb2.c +@@ -116,6 +116,12 @@ struct rockchip_chg_det_reg { + * @bvalid_det_en: vbus valid rise detection enable register. + * @bvalid_det_st: vbus valid rise detection status register. + * @bvalid_det_clr: vbus valid rise detection clear register. ++ * @disfall_en: host disconnect fall edge detection enable. ++ * @disfall_st: host disconnect fall edge detection state. ++ * @disfall_clr: host disconnect fall edge detection clear. ++ * @disrise_en: host disconnect rise edge detection enable. ++ * @disrise_st: host disconnect rise edge detection state. ++ * @disrise_clr: host disconnect rise edge detection clear. + * @id_det_en: id detection enable register. + * @id_det_st: id detection state register. + * @id_det_clr: id detection clear register. +@@ -133,6 +139,12 @@ struct rockchip_usb2phy_port_cfg { + struct usb2phy_reg bvalid_det_en; + struct usb2phy_reg bvalid_det_st; + struct usb2phy_reg bvalid_det_clr; ++ struct usb2phy_reg disfall_en; ++ struct usb2phy_reg disfall_st; ++ struct usb2phy_reg disfall_clr; ++ struct usb2phy_reg disrise_en; ++ struct usb2phy_reg disrise_st; ++ struct usb2phy_reg disrise_clr; + struct usb2phy_reg id_det_en; + struct usb2phy_reg id_det_st; + struct usb2phy_reg id_det_clr; +@@ -168,6 +180,7 @@ struct rockchip_usb2phy_cfg { + * @port_id: flag for otg port or host port. + * @suspended: phy suspended flag. + * @vbus_attached: otg device vbus status. ++ * @host_disconnect: usb host disconnect status. + * @bvalid_irq: IRQ number assigned for vbus valid rise detection. + * @id_irq: IRQ number assigned for ID pin detection. + * @ls_irq: IRQ number assigned for linestate detection. +@@ -187,6 +200,7 @@ struct rockchip_usb2phy_port { + unsigned int port_id; + bool suspended; + bool vbus_attached; ++ bool host_disconnect; + int bvalid_irq; + int id_irq; + int ls_irq; +@@ -405,6 +419,27 @@ static int rockchip_usb2phy_extcon_regis + return 0; + } + ++static int rockchip_usb2phy_enable_host_disc_irq(struct rockchip_usb2phy *rphy, ++ struct rockchip_usb2phy_port *rport, ++ bool en) ++{ ++ int ret; ++ ++ ret = property_enable(rphy->grf, &rport->port_cfg->disfall_clr, true); ++ if (ret) ++ return ret; ++ ++ ret = property_enable(rphy->grf, &rport->port_cfg->disfall_en, en); ++ if (ret) ++ return ret; ++ ++ ret = property_enable(rphy->grf, &rport->port_cfg->disrise_clr, true); ++ if (ret) ++ return ret; ++ ++ return property_enable(rphy->grf, &rport->port_cfg->disrise_en, en); ++} ++ + static int rockchip_usb2phy_init(struct phy *phy) + { + struct rockchip_usb2phy_port *rport = phy_get_drvdata(phy); +@@ -449,6 +484,15 @@ static int rockchip_usb2phy_init(struct + dev_dbg(&rport->phy->dev, "mode %d\n", rport->mode); + } + } else if (rport->port_id == USB2PHY_PORT_HOST) { ++ if (rport->port_cfg->disfall_en.offset) { ++ rport->host_disconnect = true; ++ ret = rockchip_usb2phy_enable_host_disc_irq(rphy, rport, true); ++ if (ret) { ++ dev_err(rphy->dev, "failed to enable disconnect irq\n"); ++ goto out; ++ } ++ } ++ + /* clear linestate and enable linestate detect irq */ + ret = property_enable(rphy->grf, + &rport->port_cfg->ls_det_clr, true); +@@ -810,9 +854,7 @@ static void rockchip_usb2phy_sm_work(str + struct rockchip_usb2phy_port *rport = + container_of(work, struct rockchip_usb2phy_port, sm_work.work); + struct rockchip_usb2phy *rphy = dev_get_drvdata(rport->phy->dev.parent); +- unsigned int sh = rport->port_cfg->utmi_hstdet.bitend - +- rport->port_cfg->utmi_hstdet.bitstart + 1; +- unsigned int ul, uhd, state; ++ unsigned int sh, ul, uhd, state; + unsigned int ul_mask, uhd_mask; + int ret; + +@@ -822,18 +864,26 @@ static void rockchip_usb2phy_sm_work(str + if (ret < 0) + goto next_schedule; + +- ret = regmap_read(rphy->grf, rport->port_cfg->utmi_hstdet.offset, &uhd); +- if (ret < 0) +- goto next_schedule; +- +- uhd_mask = GENMASK(rport->port_cfg->utmi_hstdet.bitend, +- rport->port_cfg->utmi_hstdet.bitstart); + ul_mask = GENMASK(rport->port_cfg->utmi_ls.bitend, + rport->port_cfg->utmi_ls.bitstart); + +- /* stitch on utmi_ls and utmi_hstdet as phy state */ +- state = ((uhd & uhd_mask) >> rport->port_cfg->utmi_hstdet.bitstart) | +- (((ul & ul_mask) >> rport->port_cfg->utmi_ls.bitstart) << sh); ++ if (rport->port_cfg->utmi_hstdet.offset) { ++ ret = regmap_read(rphy->grf, rport->port_cfg->utmi_hstdet.offset, &uhd); ++ if (ret < 0) ++ goto next_schedule; ++ ++ uhd_mask = GENMASK(rport->port_cfg->utmi_hstdet.bitend, ++ rport->port_cfg->utmi_hstdet.bitstart); ++ ++ sh = rport->port_cfg->utmi_hstdet.bitend - ++ rport->port_cfg->utmi_hstdet.bitstart + 1; ++ /* stitch on utmi_ls and utmi_hstdet as phy state */ ++ state = ((uhd & uhd_mask) >> rport->port_cfg->utmi_hstdet.bitstart) | ++ (((ul & ul_mask) >> rport->port_cfg->utmi_ls.bitstart) << sh); ++ } else { ++ state = ((ul & ul_mask) >> rport->port_cfg->utmi_ls.bitstart) << 1 | ++ rport->host_disconnect; ++ } + + switch (state) { + case PHY_STATE_HS_ONLINE: +@@ -966,6 +1016,31 @@ static irqreturn_t rockchip_usb2phy_otg_ + return ret; + } + ++static irqreturn_t rockchip_usb2phy_host_disc_irq(int irq, void *data) ++{ ++ struct rockchip_usb2phy_port *rport = data; ++ struct rockchip_usb2phy *rphy = dev_get_drvdata(rport->phy->dev.parent); ++ ++ if (!property_enabled(rphy->grf, &rport->port_cfg->disfall_st) && ++ !property_enabled(rphy->grf, &rport->port_cfg->disrise_st)) ++ return IRQ_NONE; ++ ++ mutex_lock(&rport->mutex); ++ ++ /* clear disconnect fall or rise detect irq pending status */ ++ if (property_enabled(rphy->grf, &rport->port_cfg->disfall_st)) { ++ property_enable(rphy->grf, &rport->port_cfg->disfall_clr, true); ++ rport->host_disconnect = false; ++ } else if (property_enabled(rphy->grf, &rport->port_cfg->disrise_st)) { ++ property_enable(rphy->grf, &rport->port_cfg->disrise_clr, true); ++ rport->host_disconnect = true; ++ } ++ ++ mutex_unlock(&rport->mutex); ++ ++ return IRQ_HANDLED; ++} ++ + static irqreturn_t rockchip_usb2phy_irq(int irq, void *data) + { + struct rockchip_usb2phy *rphy = data; +@@ -978,6 +1053,10 @@ static irqreturn_t rockchip_usb2phy_irq( + if (!rport->phy) + continue; + ++ if (rport->port_id == USB2PHY_PORT_HOST && ++ rport->port_cfg->disfall_en.offset) ++ ret |= rockchip_usb2phy_host_disc_irq(irq, rport); ++ + switch (rport->port_id) { + case USB2PHY_PORT_OTG: + if (rport->mode != USB_DR_MODE_HOST && +@@ -1233,7 +1312,7 @@ static int rockchip_usb2phy_probe(struct + } + + /* support address_cells=2 */ +- if (reg == 0) { ++ if (of_property_count_u32_elems(np, "reg") > 2 && reg == 0) { + if (of_property_read_u32_index(np, "reg", 1, ®)) { + dev_err(dev, "the reg property is not assigned in %pOFn node\n", + np); +@@ -1254,14 +1333,14 @@ static int rockchip_usb2phy_probe(struct + + /* find out a proper config which can be matched with dt. */ + index = 0; +- while (phy_cfgs[index].reg) { ++ do { + if (phy_cfgs[index].reg == reg) { + rphy->phy_cfg = &phy_cfgs[index]; + break; + } + + ++index; +- } ++ } while (phy_cfgs[index].reg); + + if (!rphy->phy_cfg) { + dev_err(dev, "no phy-config can be matched with %pOFn node\n", +@@ -1664,6 +1743,122 @@ static const struct rockchip_usb2phy_cfg + { /* sentinel */ } + }; + ++static const struct rockchip_usb2phy_cfg rk3588_phy_cfgs[] = { ++ { ++ .reg = 0x0000, ++ .num_ports = 1, ++ .clkout_ctl = { 0x0000, 0, 0, 1, 0 }, ++ .port_cfgs = { ++ [USB2PHY_PORT_OTG] = { ++ .phy_sus = { 0x000c, 11, 11, 0, 1 }, ++ .bvalid_det_en = { 0x0080, 1, 1, 0, 1 }, ++ .bvalid_det_st = { 0x0084, 1, 1, 0, 1 }, ++ .bvalid_det_clr = { 0x0088, 1, 1, 0, 1 }, ++ .ls_det_en = { 0x0080, 0, 0, 0, 1 }, ++ .ls_det_st = { 0x0084, 0, 0, 0, 1 }, ++ .ls_det_clr = { 0x0088, 0, 0, 0, 1 }, ++ .disfall_en = { 0x0080, 6, 6, 0, 1 }, ++ .disfall_st = { 0x0084, 6, 6, 0, 1 }, ++ .disfall_clr = { 0x0088, 6, 6, 0, 1 }, ++ .disrise_en = { 0x0080, 5, 5, 0, 1 }, ++ .disrise_st = { 0x0084, 5, 5, 0, 1 }, ++ .disrise_clr = { 0x0088, 5, 5, 0, 1 }, ++ .utmi_avalid = { 0x00c0, 7, 7, 0, 1 }, ++ .utmi_bvalid = { 0x00c0, 6, 6, 0, 1 }, ++ .utmi_ls = { 0x00c0, 10, 9, 0, 1 }, ++ } ++ }, ++ .chg_det = { ++ .cp_det = { 0x00c0, 0, 0, 0, 1 }, ++ .dcp_det = { 0x00c0, 0, 0, 0, 1 }, ++ .dp_det = { 0x00c0, 1, 1, 1, 0 }, ++ .idm_sink_en = { 0x0008, 5, 5, 1, 0 }, ++ .idp_sink_en = { 0x0008, 5, 5, 0, 1 }, ++ .idp_src_en = { 0x0008, 14, 14, 0, 1 }, ++ .rdm_pdwn_en = { 0x0008, 14, 14, 0, 1 }, ++ .vdm_src_en = { 0x0008, 7, 6, 0, 3 }, ++ .vdp_src_en = { 0x0008, 7, 6, 0, 3 }, ++ }, ++ }, ++ { ++ .reg = 0x4000, ++ .num_ports = 1, ++ .clkout_ctl = { 0x0000, 0, 0, 1, 0 }, ++ .port_cfgs = { ++ [USB2PHY_PORT_OTG] = { ++ .phy_sus = { 0x000c, 11, 11, 0, 1 }, ++ .bvalid_det_en = { 0x0080, 1, 1, 0, 1 }, ++ .bvalid_det_st = { 0x0084, 1, 1, 0, 1 }, ++ .bvalid_det_clr = { 0x0088, 1, 1, 0, 1 }, ++ .ls_det_en = { 0x0080, 0, 0, 0, 1 }, ++ .ls_det_st = { 0x0084, 0, 0, 0, 1 }, ++ .ls_det_clr = { 0x0088, 0, 0, 0, 1 }, ++ .disfall_en = { 0x0080, 6, 6, 0, 1 }, ++ .disfall_st = { 0x0084, 6, 6, 0, 1 }, ++ .disfall_clr = { 0x0088, 6, 6, 0, 1 }, ++ .disrise_en = { 0x0080, 5, 5, 0, 1 }, ++ .disrise_st = { 0x0084, 5, 5, 0, 1 }, ++ .disrise_clr = { 0x0088, 5, 5, 0, 1 }, ++ .utmi_avalid = { 0x00c0, 7, 7, 0, 1 }, ++ .utmi_bvalid = { 0x00c0, 6, 6, 0, 1 }, ++ .utmi_ls = { 0x00c0, 10, 9, 0, 1 }, ++ } ++ }, ++ .chg_det = { ++ .cp_det = { 0x00c0, 0, 0, 0, 1 }, ++ .dcp_det = { 0x00c0, 0, 0, 0, 1 }, ++ .dp_det = { 0x00c0, 1, 1, 1, 0 }, ++ .idm_sink_en = { 0x0008, 5, 5, 1, 0 }, ++ .idp_sink_en = { 0x0008, 5, 5, 0, 1 }, ++ .idp_src_en = { 0x0008, 14, 14, 0, 1 }, ++ .rdm_pdwn_en = { 0x0008, 14, 14, 0, 1 }, ++ .vdm_src_en = { 0x0008, 7, 6, 0, 3 }, ++ .vdp_src_en = { 0x0008, 7, 6, 0, 3 }, ++ }, ++ }, ++ { ++ .reg = 0x8000, ++ .num_ports = 1, ++ .clkout_ctl = { 0x0000, 0, 0, 1, 0 }, ++ .port_cfgs = { ++ [USB2PHY_PORT_HOST] = { ++ .phy_sus = { 0x0008, 2, 2, 0, 1 }, ++ .ls_det_en = { 0x0080, 0, 0, 0, 1 }, ++ .ls_det_st = { 0x0084, 0, 0, 0, 1 }, ++ .ls_det_clr = { 0x0088, 0, 0, 0, 1 }, ++ .disfall_en = { 0x0080, 6, 6, 0, 1 }, ++ .disfall_st = { 0x0084, 6, 6, 0, 1 }, ++ .disfall_clr = { 0x0088, 6, 6, 0, 1 }, ++ .disrise_en = { 0x0080, 5, 5, 0, 1 }, ++ .disrise_st = { 0x0084, 5, 5, 0, 1 }, ++ .disrise_clr = { 0x0088, 5, 5, 0, 1 }, ++ .utmi_ls = { 0x00c0, 10, 9, 0, 1 }, ++ } ++ }, ++ }, ++ { ++ .reg = 0xc000, ++ .num_ports = 1, ++ .clkout_ctl = { 0x0000, 0, 0, 1, 0 }, ++ .port_cfgs = { ++ [USB2PHY_PORT_HOST] = { ++ .phy_sus = { 0x0008, 2, 2, 0, 1 }, ++ .ls_det_en = { 0x0080, 0, 0, 0, 1 }, ++ .ls_det_st = { 0x0084, 0, 0, 0, 1 }, ++ .ls_det_clr = { 0x0088, 0, 0, 0, 1 }, ++ .disfall_en = { 0x0080, 6, 6, 0, 1 }, ++ .disfall_st = { 0x0084, 6, 6, 0, 1 }, ++ .disfall_clr = { 0x0088, 6, 6, 0, 1 }, ++ .disrise_en = { 0x0080, 5, 5, 0, 1 }, ++ .disrise_st = { 0x0084, 5, 5, 0, 1 }, ++ .disrise_clr = { 0x0088, 5, 5, 0, 1 }, ++ .utmi_ls = { 0x00c0, 10, 9, 0, 1 }, ++ } ++ }, ++ }, ++ { /* sentinel */ } ++}; ++ + static const struct rockchip_usb2phy_cfg rv1108_phy_cfgs[] = { + { + .reg = 0x100, +@@ -1714,6 +1909,7 @@ static const struct of_device_id rockchi + { .compatible = "rockchip,rk3366-usb2phy", .data = &rk3366_phy_cfgs }, + { .compatible = "rockchip,rk3399-usb2phy", .data = &rk3399_phy_cfgs }, + { .compatible = "rockchip,rk3568-usb2phy", .data = &rk3568_phy_cfgs }, ++ { .compatible = "rockchip,rk3588-usb2phy", .data = &rk3588_phy_cfgs }, + { .compatible = "rockchip,rv1108-usb2phy", .data = &rv1108_phy_cfgs }, + {} + }; diff --git a/target/linux/rockchip/patches-6.1/112-02-phy-phy-rockchip-inno-usb2-add-reset-support.patch b/target/linux/rockchip/patches-6.1/112-02-phy-phy-rockchip-inno-usb2-add-reset-support.patch new file mode 100644 index 0000000000..53846dc4e1 --- /dev/null +++ b/target/linux/rockchip/patches-6.1/112-02-phy-phy-rockchip-inno-usb2-add-reset-support.patch @@ -0,0 +1,107 @@ +From: Sebastian Reichel +To: Vinod Koul , + Kishon Vijay Abraham I , + Rob Herring , + Krzysztof Kozlowski +Cc: Heiko Stuebner , + linux-phy@lists.infradead.org, + linux-arm-kernel@lists.infradead.org, + linux-rockchip@lists.infradead.org, linux-kernel@vger.kernel.org, + devicetree@vger.kernel.org, + Sebastian Reichel , + kernel@collabora.com +Subject: [PATCH v3 3/7] phy: phy-rockchip-inno-usb2: add reset support +Date: Mon, 22 May 2023 19:03:20 +0200 [thread overview] +Message-ID: <20230522170324.61349-4-sebastian.reichel@collabora.com> (raw) +In-Reply-To: <20230522170324.61349-1-sebastian.reichel@collabora.com> + +Add reset handling support, which is needed for proper +operation with RK3588. + +Signed-off-by: Sebastian Reichel +--- + drivers/phy/rockchip/phy-rockchip-inno-usb2.c | 38 +++++++++++++++++++ + 1 file changed, 38 insertions(+) + +--- a/drivers/phy/rockchip/phy-rockchip-inno-usb2.c ++++ b/drivers/phy/rockchip/phy-rockchip-inno-usb2.c +@@ -24,6 +24,7 @@ + #include + #include + #include ++#include + #include + #include + #include +@@ -223,6 +224,7 @@ struct rockchip_usb2phy_port { + * @clk: clock struct of phy input clk. + * @clk480m: clock struct of phy output clk. + * @clk480m_hw: clock struct of phy output clk management. ++ * @phy_reset: phy reset control. + * @chg_state: states involved in USB charger detection. + * @chg_type: USB charger types. + * @dcd_retries: The retry count used to track Data contact +@@ -239,6 +241,7 @@ struct rockchip_usb2phy { + struct clk *clk; + struct clk *clk480m; + struct clk_hw clk480m_hw; ++ struct reset_control *phy_reset; + enum usb_chg_state chg_state; + enum power_supply_type chg_type; + u8 dcd_retries; +@@ -280,6 +283,25 @@ static inline bool property_enabled(stru + return tmp != reg->disable; + } + ++static int rockchip_usb2phy_reset(struct rockchip_usb2phy *rphy) ++{ ++ int ret; ++ ++ ret = reset_control_assert(rphy->phy_reset); ++ if (ret) ++ return ret; ++ ++ udelay(10); ++ ++ ret = reset_control_deassert(rphy->phy_reset); ++ if (ret) ++ return ret; ++ ++ usleep_range(100, 200); ++ ++ return 0; ++} ++ + static int rockchip_usb2phy_clk480m_prepare(struct clk_hw *hw) + { + struct rockchip_usb2phy *rphy = +@@ -534,6 +556,18 @@ static int rockchip_usb2phy_power_on(str + return ret; + } + ++ /* ++ * For rk3588, it needs to reset phy when exit from ++ * suspend mode with common_on_n 1'b1(aka REFCLK_LOGIC, ++ * Bias, and PLL blocks are powered down) for lower ++ * power consumption. If you don't want to reset phy, ++ * please keep the common_on_n 1'b0 to set these blocks ++ * remain powered. ++ */ ++ ret = rockchip_usb2phy_reset(rphy); ++ if (ret) ++ return ret; ++ + /* waiting for the utmi_clk to become stable */ + usleep_range(1500, 2000); + +@@ -1348,6 +1382,10 @@ static int rockchip_usb2phy_probe(struct + return -EINVAL; + } + ++ rphy->phy_reset = devm_reset_control_get_optional(dev, "phy"); ++ if (IS_ERR(rphy->phy_reset)) ++ return PTR_ERR(rphy->phy_reset); ++ + rphy->clk = of_clk_get_by_name(np, "phyclk"); + if (!IS_ERR(rphy->clk)) { + clk_prepare_enable(rphy->clk); diff --git a/target/linux/rockchip/patches-6.1/112-03-phy-phy-rockchip-inno-usb2-add-rk3588-phy-tuning-support.patch b/target/linux/rockchip/patches-6.1/112-03-phy-phy-rockchip-inno-usb2-add-rk3588-phy-tuning-support.patch new file mode 100644 index 0000000000..ffb13e2e77 --- /dev/null +++ b/target/linux/rockchip/patches-6.1/112-03-phy-phy-rockchip-inno-usb2-add-rk3588-phy-tuning-support.patch @@ -0,0 +1,158 @@ +From: Sebastian Reichel +To: Vinod Koul , + Kishon Vijay Abraham I , + Rob Herring , + Krzysztof Kozlowski +Cc: Heiko Stuebner , + linux-phy@lists.infradead.org, + linux-arm-kernel@lists.infradead.org, + linux-rockchip@lists.infradead.org, linux-kernel@vger.kernel.org, + devicetree@vger.kernel.org, + Sebastian Reichel , + kernel@collabora.com +Subject: [PATCH v3 4/7] phy: phy-rockchip-inno-usb2: add rk3588 phy tuning support +Date: Mon, 22 May 2023 19:03:21 +0200 [thread overview] +Message-ID: <20230522170324.61349-5-sebastian.reichel@collabora.com> (raw) +In-Reply-To: <20230522170324.61349-1-sebastian.reichel@collabora.com> + +On RK3588 some registers need to be tweaked to support waking up from +suspend when a USB device is plugged into a port from a suspended PHY. +Without this change USB devices only work when they are plugged at +boot time. + +Apart from that it optimizes settings to avoid devices toggling +between fullspeed and highspeed mode. + +Signed-off-by: Sebastian Reichel +--- + drivers/phy/rockchip/phy-rockchip-inno-usb2.c | 63 +++++++++++++++++++ + 1 file changed, 63 insertions(+) + +--- a/drivers/phy/rockchip/phy-rockchip-inno-usb2.c ++++ b/drivers/phy/rockchip/phy-rockchip-inno-usb2.c +@@ -33,6 +33,8 @@ + #define SCHEDULE_DELAY (60 * HZ) + #define OTG_SCHEDULE_DELAY (2 * HZ) + ++struct rockchip_usb2phy; ++ + enum rockchip_usb2phy_port_id { + USB2PHY_PORT_OTG, + USB2PHY_PORT_HOST, +@@ -163,6 +165,7 @@ struct rockchip_usb2phy_port_cfg { + * struct rockchip_usb2phy_cfg - usb-phy configuration. + * @reg: the address offset of grf for usb-phy config. + * @num_ports: specify how many ports that the phy has. ++ * @phy_tuning: phy default parameters tuning. + * @clkout_ctl: keep on/turn off output clk of phy. + * @port_cfgs: usb-phy port configurations. + * @chg_det: charger detection registers. +@@ -170,6 +173,7 @@ struct rockchip_usb2phy_port_cfg { + struct rockchip_usb2phy_cfg { + unsigned int reg; + unsigned int num_ports; ++ int (*phy_tuning)(struct rockchip_usb2phy *rphy); + struct usb2phy_reg clkout_ctl; + const struct rockchip_usb2phy_port_cfg port_cfgs[USB2PHY_NUM_PORTS]; + const struct rockchip_chg_det_reg chg_det; +@@ -1400,6 +1404,12 @@ static int rockchip_usb2phy_probe(struct + goto disable_clks; + } + ++ if (rphy->phy_cfg->phy_tuning) { ++ ret = rphy->phy_cfg->phy_tuning(rphy); ++ if (ret) ++ goto disable_clks; ++ } ++ + index = 0; + for_each_available_child_of_node(np, child_np) { + struct rockchip_usb2phy_port *rport = &rphy->ports[index]; +@@ -1468,6 +1478,55 @@ disable_clks: + return ret; + } + ++static int rk3588_usb2phy_tuning(struct rockchip_usb2phy *rphy) ++{ ++ int ret; ++ bool usb3otg = false; ++ /* ++ * utmi_termselect = 1'b1 (en FS terminations) ++ * utmi_xcvrselect = 2'b01 (FS transceiver) ++ */ ++ int suspend_cfg = 0x14; ++ ++ if (rphy->phy_cfg->reg == 0x0000 || rphy->phy_cfg->reg == 0x4000) { ++ /* USB2 config for USB3_0 and USB3_1 */ ++ suspend_cfg |= 0x01; /* utmi_opmode = 2'b01 (no-driving) */ ++ usb3otg = true; ++ } else if (rphy->phy_cfg->reg == 0x8000 || rphy->phy_cfg->reg == 0xc000) { ++ /* USB2 config for USB2_0 and USB2_1 */ ++ suspend_cfg |= 0x00; /* utmi_opmode = 2'b00 (normal) */ ++ } else { ++ return -EINVAL; ++ } ++ ++ /* Deassert SIDDQ to power on analog block */ ++ ret = regmap_write(rphy->grf, 0x0008, GENMASK(29, 29) | 0x0000); ++ if (ret) ++ return ret; ++ ++ /* Do reset after exit IDDQ mode */ ++ ret = rockchip_usb2phy_reset(rphy); ++ if (ret) ++ return ret; ++ ++ /* suspend configuration */ ++ ret |= regmap_write(rphy->grf, 0x000c, GENMASK(20, 16) | suspend_cfg); ++ ++ /* HS DC Voltage Level Adjustment 4'b1001 : +5.89% */ ++ ret |= regmap_write(rphy->grf, 0x0004, GENMASK(27, 24) | 0x0900); ++ ++ /* HS Transmitter Pre-Emphasis Current Control 2'b10 : 2x */ ++ ret |= regmap_write(rphy->grf, 0x0008, GENMASK(20, 19) | 0x0010); ++ ++ if (!usb3otg) ++ return ret; ++ ++ /* Pullup iddig pin for USB3_0 OTG mode */ ++ ret |= regmap_write(rphy->grf, 0x0010, GENMASK(17, 16) | 0x0003); ++ ++ return ret; ++} ++ + static const struct rockchip_usb2phy_cfg rk3228_phy_cfgs[] = { + { + .reg = 0x760, +@@ -1785,6 +1844,7 @@ static const struct rockchip_usb2phy_cfg + { + .reg = 0x0000, + .num_ports = 1, ++ .phy_tuning = rk3588_usb2phy_tuning, + .clkout_ctl = { 0x0000, 0, 0, 1, 0 }, + .port_cfgs = { + [USB2PHY_PORT_OTG] = { +@@ -1821,6 +1881,7 @@ static const struct rockchip_usb2phy_cfg + { + .reg = 0x4000, + .num_ports = 1, ++ .phy_tuning = rk3588_usb2phy_tuning, + .clkout_ctl = { 0x0000, 0, 0, 1, 0 }, + .port_cfgs = { + [USB2PHY_PORT_OTG] = { +@@ -1857,6 +1918,7 @@ static const struct rockchip_usb2phy_cfg + { + .reg = 0x8000, + .num_ports = 1, ++ .phy_tuning = rk3588_usb2phy_tuning, + .clkout_ctl = { 0x0000, 0, 0, 1, 0 }, + .port_cfgs = { + [USB2PHY_PORT_HOST] = { +@@ -1877,6 +1939,7 @@ static const struct rockchip_usb2phy_cfg + { + .reg = 0xc000, + .num_ports = 1, ++ .phy_tuning = rk3588_usb2phy_tuning, + .clkout_ctl = { 0x0000, 0, 0, 1, 0 }, + .port_cfgs = { + [USB2PHY_PORT_HOST] = { diff --git a/target/linux/rockchip/patches-6.1/112-04-phy-phy-rockchip-inno-usb2-simplify-phy-clock-handling.patch b/target/linux/rockchip/patches-6.1/112-04-phy-phy-rockchip-inno-usb2-simplify-phy-clock-handling.patch new file mode 100644 index 0000000000..375d48e3d7 --- /dev/null +++ b/target/linux/rockchip/patches-6.1/112-04-phy-phy-rockchip-inno-usb2-simplify-phy-clock-handling.patch @@ -0,0 +1,71 @@ +From: Sebastian Reichel +To: Vinod Koul , + Kishon Vijay Abraham I , + Rob Herring , + Krzysztof Kozlowski +Cc: Heiko Stuebner , + linux-phy@lists.infradead.org, + linux-arm-kernel@lists.infradead.org, + linux-rockchip@lists.infradead.org, linux-kernel@vger.kernel.org, + devicetree@vger.kernel.org, + Sebastian Reichel , + kernel@collabora.com +Subject: [PATCH v3 5/7] phy: phy-rockchip-inno-usb2: simplify phy clock handling +Date: Mon, 22 May 2023 19:03:22 +0200 [thread overview] +Message-ID: <20230522170324.61349-6-sebastian.reichel@collabora.com> (raw) +In-Reply-To: <20230522170324.61349-1-sebastian.reichel@collabora.com> + +Simplify phyclk handling by using devm_clk_get_optional_enabled to +acquire and enable the optional clock. This also fixes a resource +leak in driver remove path and adds proper error handling. + +Signed-off-by: Sebastian Reichel +--- + drivers/phy/rockchip/phy-rockchip-inno-usb2.c | 19 ++++++------------- + 1 file changed, 6 insertions(+), 13 deletions(-) + +--- a/drivers/phy/rockchip/phy-rockchip-inno-usb2.c ++++ b/drivers/phy/rockchip/phy-rockchip-inno-usb2.c +@@ -1390,24 +1390,22 @@ static int rockchip_usb2phy_probe(struct + if (IS_ERR(rphy->phy_reset)) + return PTR_ERR(rphy->phy_reset); + +- rphy->clk = of_clk_get_by_name(np, "phyclk"); +- if (!IS_ERR(rphy->clk)) { +- clk_prepare_enable(rphy->clk); +- } else { +- dev_info(&pdev->dev, "no phyclk specified\n"); +- rphy->clk = NULL; ++ rphy->clk = devm_clk_get_optional_enabled(dev, "phyclk"); ++ if (IS_ERR(rphy->clk)) { ++ return dev_err_probe(&pdev->dev, PTR_ERR(rphy->clk), ++ "failed to get phyclk\n"); + } + + ret = rockchip_usb2phy_clk480m_register(rphy); + if (ret) { + dev_err(dev, "failed to register 480m output clock\n"); +- goto disable_clks; ++ return ret; + } + + if (rphy->phy_cfg->phy_tuning) { + ret = rphy->phy_cfg->phy_tuning(rphy); + if (ret) +- goto disable_clks; ++ return ret; + } + + index = 0; +@@ -1470,11 +1468,6 @@ next_child: + + put_child: + of_node_put(child_np); +-disable_clks: +- if (rphy->clk) { +- clk_disable_unprepare(rphy->clk); +- clk_put(rphy->clk); +- } + return ret; + } + diff --git a/target/linux/rockchip/patches-6.1/112-05-phy-phy-rockchip-inno-usb2-simplify-getting-match-data.patch b/target/linux/rockchip/patches-6.1/112-05-phy-phy-rockchip-inno-usb2-simplify-getting-match-data.patch new file mode 100644 index 0000000000..8306903f1b --- /dev/null +++ b/target/linux/rockchip/patches-6.1/112-05-phy-phy-rockchip-inno-usb2-simplify-getting-match-data.patch @@ -0,0 +1,65 @@ +From: Sebastian Reichel +To: Vinod Koul , + Kishon Vijay Abraham I , + Rob Herring , + Krzysztof Kozlowski +Cc: Heiko Stuebner , + linux-phy@lists.infradead.org, + linux-arm-kernel@lists.infradead.org, + linux-rockchip@lists.infradead.org, linux-kernel@vger.kernel.org, + devicetree@vger.kernel.org, + Sebastian Reichel , + kernel@collabora.com +Subject: [PATCH v3 6/7] phy: phy-rockchip-inno-usb2: simplify getting match data +Date: Mon, 22 May 2023 19:03:23 +0200 [thread overview] +Message-ID: <20230522170324.61349-7-sebastian.reichel@collabora.com> (raw) +In-Reply-To: <20230522170324.61349-1-sebastian.reichel@collabora.com> + +Simplify the code by directly getting the match data via +device_get_match_data() instead of open coding its functionality. + +Signed-off-by: Sebastian Reichel +--- + drivers/phy/rockchip/phy-rockchip-inno-usb2.c | 12 ++++-------- + 1 file changed, 4 insertions(+), 8 deletions(-) + +--- a/drivers/phy/rockchip/phy-rockchip-inno-usb2.c ++++ b/drivers/phy/rockchip/phy-rockchip-inno-usb2.c +@@ -1305,7 +1305,6 @@ static int rockchip_usb2phy_probe(struct + struct phy_provider *provider; + struct rockchip_usb2phy *rphy; + const struct rockchip_usb2phy_cfg *phy_cfgs; +- const struct of_device_id *match; + unsigned int reg; + int index, ret; + +@@ -1313,12 +1312,6 @@ static int rockchip_usb2phy_probe(struct + if (!rphy) + return -ENOMEM; + +- match = of_match_device(dev->driver->of_match_table, dev); +- if (!match || !match->data) { +- dev_err(dev, "phy configs are not assigned!\n"); +- return -EINVAL; +- } +- + if (!dev->parent || !dev->parent->of_node) { + rphy->grf = syscon_regmap_lookup_by_phandle(np, "rockchip,usbgrf"); + if (IS_ERR(rphy->grf)) { +@@ -1359,12 +1352,15 @@ static int rockchip_usb2phy_probe(struct + } + + rphy->dev = dev; +- phy_cfgs = match->data; ++ phy_cfgs = device_get_match_data(dev); + rphy->chg_state = USB_CHG_STATE_UNDEFINED; + rphy->chg_type = POWER_SUPPLY_TYPE_UNKNOWN; + rphy->irq = platform_get_irq_optional(pdev, 0); + platform_set_drvdata(pdev, rphy); + ++ if (!phy_cfgs) ++ return dev_err_probe(dev, -EINVAL, "phy configs are not assigned!\n"); ++ + ret = rockchip_usb2phy_extcon_register(rphy); + if (ret) + return ret; diff --git a/target/linux/rockchip/patches-6.1/112-06-phy-phy-rockchip-inno-usb2-improve-error-message.patch b/target/linux/rockchip/patches-6.1/112-06-phy-phy-rockchip-inno-usb2-improve-error-message.patch new file mode 100644 index 0000000000..f7a3595ff0 --- /dev/null +++ b/target/linux/rockchip/patches-6.1/112-06-phy-phy-rockchip-inno-usb2-improve-error-message.patch @@ -0,0 +1,38 @@ +From: Sebastian Reichel +To: Vinod Koul , + Kishon Vijay Abraham I , + Rob Herring , + Krzysztof Kozlowski +Cc: Heiko Stuebner , + linux-phy@lists.infradead.org, + linux-arm-kernel@lists.infradead.org, + linux-rockchip@lists.infradead.org, linux-kernel@vger.kernel.org, + devicetree@vger.kernel.org, + Sebastian Reichel , + kernel@collabora.com +Subject: [PATCH v3 7/7] phy: phy-rockchip-inno-usb2: improve error message +Date: Mon, 22 May 2023 19:03:24 +0200 [thread overview] +Message-ID: <20230522170324.61349-8-sebastian.reichel@collabora.com> (raw) +In-Reply-To: <20230522170324.61349-1-sebastian.reichel@collabora.com> + +Printing the OF node is not useful, since we get the same information +from the device context. Instead print the reg address, that could +not be found. + +Signed-off-by: Sebastian Reichel +--- + drivers/phy/rockchip/phy-rockchip-inno-usb2.c | 3 +-- + 1 file changed, 1 insertion(+), 2 deletions(-) + +--- a/drivers/phy/rockchip/phy-rockchip-inno-usb2.c ++++ b/drivers/phy/rockchip/phy-rockchip-inno-usb2.c +@@ -1377,8 +1377,7 @@ static int rockchip_usb2phy_probe(struct + } while (phy_cfgs[index].reg); + + if (!rphy->phy_cfg) { +- dev_err(dev, "no phy-config can be matched with %pOFn node\n", +- np); ++ dev_err(dev, "could not find phy config for reg=0x%08x\n", reg); + return -EINVAL; + } + diff --git a/target/linux/rockchip/patches-6.1/112-07-arm64-dts-rockchip-rk3588-add-USB2-support.patch b/target/linux/rockchip/patches-6.1/112-07-arm64-dts-rockchip-rk3588-add-USB2-support.patch new file mode 100644 index 0000000000..4eca9a690c --- /dev/null +++ b/target/linux/rockchip/patches-6.1/112-07-arm64-dts-rockchip-rk3588-add-USB2-support.patch @@ -0,0 +1,121 @@ +From 734459837fe67a306f7fe63ab03c0c2c0042bf7c Mon Sep 17 00:00:00 2001 +From: Sebastian Reichel +Date: Thu, 12 Jan 2023 19:20:37 +0100 +Subject: [PATCH] arm64: dts: rockchip: rk3588: add USB2 support + +This adds USB2 (EHCI & OHCI) ports including the related PHYs +and GRF modules to the rk3588(s) device tree. + +Signed-off-by: Sebastian Reichel +--- + arch/arm64/boot/dts/rockchip/rk3588s.dtsi | 94 +++++++++++++++++++++++ + 1 file changed, 94 insertions(+) + +--- a/arch/arm64/boot/dts/rockchip/rk3588s.dtsi ++++ b/arch/arm64/boot/dts/rockchip/rk3588s.dtsi +@@ -830,11 +830,105 @@ + }; + }; + ++ usb_host0_ehci: usb@fc800000 { ++ compatible = "rockchip,rk3588-ehci", "generic-ehci"; ++ reg = <0x0 0xfc800000 0x0 0x40000>; ++ interrupts = ; ++ clocks = <&cru HCLK_HOST0>, <&cru HCLK_HOST_ARB0>, <&cru ACLK_USB>, <&u2phy2>; ++ phys = <&u2phy2_host>; ++ phy-names = "usb"; ++ power-domains = <&power RK3588_PD_USB>; ++ status = "disabled"; ++ }; ++ ++ usb_host0_ohci: usb@fc840000 { ++ compatible = "rockchip,rk3588-ohci", "generic-ohci"; ++ reg = <0x0 0xfc840000 0x0 0x40000>; ++ interrupts = ; ++ clocks = <&cru HCLK_HOST0>, <&cru HCLK_HOST_ARB0>, <&cru ACLK_USB>, <&u2phy2>; ++ phys = <&u2phy2_host>; ++ phy-names = "usb"; ++ power-domains = <&power RK3588_PD_USB>; ++ status = "disabled"; ++ }; ++ ++ usb_host1_ehci: usb@fc880000 { ++ compatible = "rockchip,rk3588-ehci", "generic-ehci"; ++ reg = <0x0 0xfc880000 0x0 0x40000>; ++ interrupts = ; ++ clocks = <&cru HCLK_HOST1>, <&cru HCLK_HOST_ARB1>, <&cru ACLK_USB>, <&u2phy3>; ++ phys = <&u2phy3_host>; ++ phy-names = "usb"; ++ power-domains = <&power RK3588_PD_USB>; ++ status = "disabled"; ++ }; ++ ++ usb_host1_ohci: usb@fc8c0000 { ++ compatible = "rockchip,rk3588-ohci", "generic-ohci"; ++ reg = <0x0 0xfc8c0000 0x0 0x40000>; ++ interrupts = ; ++ clocks = <&cru HCLK_HOST1>, <&cru HCLK_HOST_ARB1>, <&cru ACLK_USB>, <&u2phy3>; ++ phys = <&u2phy3_host>; ++ phy-names = "usb"; ++ power-domains = <&power RK3588_PD_USB>; ++ status = "disabled"; ++ }; ++ + sys_grf: syscon@fd58c000 { + compatible = "rockchip,rk3588-sys-grf", "syscon"; + reg = <0x0 0xfd58c000 0x0 0x1000>; + }; + ++ usb2phy2_grf: syscon@fd5d8000 { ++ compatible = "rockchip,rk3588-usb2phy-grf", "syscon", "simple-mfd"; ++ reg = <0x0 0xfd5d8000 0x0 0x4000>; ++ #address-cells = <1>; ++ #size-cells = <1>; ++ ++ u2phy2: usb2-phy@8000 { ++ compatible = "rockchip,rk3588-usb2phy"; ++ reg = <0x8000 0x10>; ++ interrupts = ; ++ resets = <&cru SRST_OTGPHY_U2_0>, <&cru SRST_P_USB2PHY_U2_0_GRF0>; ++ reset-names = "phy", "apb"; ++ clocks = <&cru CLK_USB2PHY_HDPTXRXPHY_REF>; ++ clock-names = "phyclk"; ++ clock-output-names = "usb480m_phy2"; ++ #clock-cells = <0>; ++ status = "disabled"; ++ ++ u2phy2_host: host-port { ++ #phy-cells = <0>; ++ status = "disabled"; ++ }; ++ }; ++ }; ++ ++ usb2phy3_grf: syscon@fd5dc000 { ++ compatible = "rockchip,rk3588-usb2phy-grf", "syscon", "simple-mfd"; ++ reg = <0x0 0xfd5dc000 0x0 0x4000>; ++ #address-cells = <1>; ++ #size-cells = <1>; ++ ++ u2phy3: usb2-phy@c000 { ++ compatible = "rockchip,rk3588-usb2phy"; ++ reg = <0xc000 0x10>; ++ interrupts = ; ++ resets = <&cru SRST_OTGPHY_U2_1>, <&cru SRST_P_USB2PHY_U2_1_GRF0>; ++ reset-names = "phy", "apb"; ++ clocks = <&cru CLK_USB2PHY_HDPTXRXPHY_REF>; ++ clock-names = "phyclk"; ++ clock-output-names = "usb480m_phy3"; ++ #clock-cells = <0>; ++ status = "disabled"; ++ ++ u2phy3_host: host-port { ++ #phy-cells = <0>; ++ status = "disabled"; ++ }; ++ }; ++ }; ++ + bigcore0_grf: syscon@fd590000 { + compatible = "rockchip,rk3588-bigcore0-grf", "syscon"; + reg = <0x0 0xfd590000 0x0 0x100>; diff --git a/target/linux/rockchip/patches-6.1/112-08-arm64-dts-rockchip-rk3588-evb1-add-USB2.patch b/target/linux/rockchip/patches-6.1/112-08-arm64-dts-rockchip-rk3588-evb1-add-USB2.patch new file mode 100644 index 0000000000..e9caf56c6f --- /dev/null +++ b/target/linux/rockchip/patches-6.1/112-08-arm64-dts-rockchip-rk3588-evb1-add-USB2.patch @@ -0,0 +1,108 @@ +From dc6a92371915067b5f8880bacae21498eaab69dd Mon Sep 17 00:00:00 2001 +From: Sebastian Reichel +Date: Thu, 12 Jan 2023 19:23:27 +0100 +Subject: [PATCH] arm64: dts: rockchip: rk3588-evb1: add USB2 + +Enable USB2 (EHCI and OCHI mode) support for the Rockchip RK3588 EVB1. + +Signed-off-by: Sebastian Reichel +--- + .../boot/dts/rockchip/rk3588-evb1-v10.dts | 76 +++++++++++++++++++ + 1 file changed, 76 insertions(+) + +--- a/arch/arm64/boot/dts/rockchip/rk3588-evb1-v10.dts ++++ b/arch/arm64/boot/dts/rockchip/rk3588-evb1-v10.dts +@@ -47,6 +47,40 @@ + regulator-max-microvolt = <5000000>; + vin-supply = <&vcc12v_dcin>; + }; ++ ++ vcc5v0_usbdcin: vcc5v0-usbdcin { ++ compatible = "regulator-fixed"; ++ regulator-name = "vcc5v0_usbdcin"; ++ regulator-always-on; ++ regulator-boot-on; ++ regulator-min-microvolt = <5000000>; ++ regulator-max-microvolt = <5000000>; ++ vin-supply = <&vcc12v_dcin>; ++ }; ++ ++ vcc5v0_usb: vcc5v0-usb { ++ compatible = "regulator-fixed"; ++ regulator-name = "vcc5v0_usb"; ++ regulator-always-on; ++ regulator-boot-on; ++ regulator-min-microvolt = <5000000>; ++ regulator-max-microvolt = <5000000>; ++ vin-supply = <&vcc5v0_usbdcin>; ++ }; ++ ++ vcc5v0_host: vcc5v0-host { ++ compatible = "regulator-fixed"; ++ regulator-name = "vcc5v0_host"; ++ regulator-boot-on; ++ regulator-always-on; ++ regulator-min-microvolt = <5000000>; ++ regulator-max-microvolt = <5000000>; ++ enable-active-high; ++ gpio = <&gpio4 RK_PB0 GPIO_ACTIVE_HIGH>; ++ vin-supply = <&vcc5v0_usb>; ++ pinctrl-names = "default"; ++ pinctrl-0 = <&vcc5v0_host_en>; ++ }; + }; + + &cpu_l0 { +@@ -64,6 +98,40 @@ + mem-supply = <&vdd_cpu_big1_mem_s0>; + }; + ++&u2phy2 { ++ status = "okay"; ++}; ++ ++&u2phy3 { ++ status = "okay"; ++}; ++ ++&u2phy2_host { ++ phy-supply = <&vcc5v0_host>; ++ status = "okay"; ++}; ++ ++&u2phy3_host { ++ phy-supply = <&vcc5v0_host>; ++ status = "okay"; ++}; ++ ++&usb_host0_ehci { ++ status = "okay"; ++}; ++ ++&usb_host0_ohci { ++ status = "okay"; ++}; ++ ++&usb_host1_ehci { ++ status = "okay"; ++}; ++ ++&usb_host1_ohci { ++ status = "okay"; ++}; ++ + &gmac0 { + clock_in_out = "output"; + phy-handle = <&rgmii_phy>; +@@ -886,3 +954,11 @@ + pinctrl-0 = <&uart2m0_xfer>; + status = "okay"; + }; ++ ++&pinctrl { ++ usb { ++ vcc5v0_host_en: vcc5v0-host-en { ++ rockchip,pins = <4 RK_PB0 RK_FUNC_GPIO &pcfg_pull_none>; ++ }; ++ }; ++}; diff --git a/target/linux/rockchip/patches-6.1/112-09-arm64-dts-rockchip-rk3588-rock5b-add-USB2.patch b/target/linux/rockchip/patches-6.1/112-09-arm64-dts-rockchip-rk3588-rock5b-add-USB2.patch new file mode 100644 index 0000000000..12885d5d42 --- /dev/null +++ b/target/linux/rockchip/patches-6.1/112-09-arm64-dts-rockchip-rk3588-rock5b-add-USB2.patch @@ -0,0 +1,95 @@ +From ec584a8d73148b9c936edbea13b4badc1de41069 Mon Sep 17 00:00:00 2001 +From: Sebastian Reichel +Date: Thu, 30 Mar 2023 15:44:36 +0200 +Subject: [PATCH] arm64: dts: rockchip: rk3588-rock5b: add USB2 + +Enable USB2 (EHCI and OCHI mode) support for the Radxa ROCK 5 Model B. +This adds USB support on the M.2 Key E, both USB2 ports and USB2 mode +for the upper USB3 port (the one further away from the PCB). + +The lower USB3 (closer to the PCB) and the USB-C ports use the RK3588 +USB TypeC host controller, which is not yet supported upstream. + +Signed-off-by: Sebastian Reichel +--- + .../boot/dts/rockchip/rk3588-rock-5b.dts | 58 +++++++++++++++++++ + 1 file changed, 58 insertions(+) + +--- a/arch/arm64/boot/dts/rockchip/rk3588-rock-5b.dts ++++ b/arch/arm64/boot/dts/rockchip/rk3588-rock-5b.dts +@@ -3,6 +3,7 @@ + /dts-v1/; + + #include ++#include + #include "rk3588.dtsi" + + / { +@@ -51,6 +52,20 @@ + regulator-min-microvolt = <5000000>; + regulator-max-microvolt = <5000000>; + }; ++ ++ vcc5v0_host: vcc5v0-host-regulator { ++ compatible = "regulator-fixed"; ++ regulator-name = "vcc5v0_host"; ++ regulator-boot-on; ++ regulator-always-on; ++ regulator-min-microvolt = <5000000>; ++ regulator-max-microvolt = <5000000>; ++ enable-active-high; ++ gpio = <&gpio4 RK_PB0 GPIO_ACTIVE_HIGH>; ++ pinctrl-names = "default"; ++ pinctrl-0 = <&vcc5v0_host_en>; ++ vin-supply = <&vcc5v0_sys>; ++ }; + }; + + &cpu_b0 { +@@ -194,3 +209,46 @@ + pinctrl-0 = <&uart2m0_xfer>; + status = "okay"; + }; ++ ++&u2phy2_host { ++ /* connected to USB hub, which is powered by vcc5v0_sys */ ++ phy-supply = <&vcc5v0_sys>; ++ status = "okay"; ++}; ++ ++&u2phy3_host { ++ phy-supply = <&vcc5v0_host>; ++ status = "okay"; ++}; ++ ++&u2phy2 { ++ status = "okay"; ++}; ++ ++&u2phy3 { ++ status = "okay"; ++}; ++ ++&usb_host0_ehci { ++ status = "okay"; ++}; ++ ++&usb_host0_ohci { ++ status = "okay"; ++}; ++ ++&usb_host1_ehci { ++ status = "okay"; ++}; ++ ++&usb_host1_ohci { ++ status = "okay"; ++}; ++ ++&pinctrl { ++ usb { ++ vcc5v0_host_en: vcc5v0-host-en { ++ rockchip,pins = <4 RK_PB0 RK_FUNC_GPIO &pcfg_pull_none>; ++ }; ++ }; ++}; diff --git a/target/linux/rockchip/patches-6.1/113-01-arm64-dts-rockchip-rk3588-add-combo-PHYs.patch b/target/linux/rockchip/patches-6.1/113-01-arm64-dts-rockchip-rk3588-add-combo-PHYs.patch new file mode 100644 index 0000000000..20d2dee18f --- /dev/null +++ b/target/linux/rockchip/patches-6.1/113-01-arm64-dts-rockchip-rk3588-add-combo-PHYs.patch @@ -0,0 +1,120 @@ +From: Sebastian Reichel +To: Heiko Stuebner +Cc: Rob Herring , + Krzysztof Kozlowski , + Damien Le Moal , + Serge Semin , + Vinod Koul , + Kishon Vijay Abraham I , + linux-ide@vger.kernel.org, linux-phy@lists.infradead.org, + linux-rockchip@lists.infradead.org, devicetree@vger.kernel.org, + linux-kernel@vger.kernel.org, + Sebastian Reichel , + kernel@collabora.com +Subject: [PATCH v2 5/6] arm64: dts: rockchip: rk3588: add combo PHYs +Date: Mon, 22 May 2023 19:34:22 +0200 [thread overview] +Message-ID: <20230522173423.64691-6-sebastian.reichel@collabora.com> (raw) +In-Reply-To: <20230522173423.64691-1-sebastian.reichel@collabora.com> + +Add all 3 combo PHYs that can be found in RK3588. +They are used for SATA, PCIe or USB3. + +Signed-off-by: Sebastian Reichel +--- + arch/arm64/boot/dts/rockchip/rk3588.dtsi | 21 ++++++++++++ + arch/arm64/boot/dts/rockchip/rk3588s.dtsi | 42 +++++++++++++++++++++++ + 2 files changed, 63 insertions(+) + +--- a/arch/arm64/boot/dts/rockchip/rk3588.dtsi ++++ b/arch/arm64/boot/dts/rockchip/rk3588.dtsi +@@ -7,6 +7,11 @@ + #include "rk3588-pinctrl.dtsi" + + / { ++ pipe_phy1_grf: syscon@fd5c0000 { ++ compatible = "rockchip,rk3588-pipe-phy-grf", "syscon"; ++ reg = <0x0 0xfd5c0000 0x0 0x100>; ++ }; ++ + i2s8_8ch: i2s@fddc8000 { + compatible = "rockchip,rk3588-i2s-tdm"; + reg = <0x0 0xfddc8000 0x0 0x1000>; +@@ -123,4 +128,20 @@ + queue1 {}; + }; + }; ++ ++ combphy1_ps: phy@fee10000 { ++ compatible = "rockchip,rk3588-naneng-combphy"; ++ reg = <0x0 0xfee10000 0x0 0x100>; ++ #phy-cells = <1>; ++ clocks = <&cru CLK_REF_PIPE_PHY1>, <&cru PCLK_PCIE_COMBO_PIPE_PHY1>, ++ <&cru PCLK_PHP_ROOT>; ++ clock-names = "ref", "apb", "pipe"; ++ assigned-clocks = <&cru CLK_REF_PIPE_PHY1>; ++ assigned-clock-rates = <100000000>; ++ resets = <&cru SRST_REF_PIPE_PHY1>, <&cru SRST_P_PCIE2_PHY1>; ++ reset-names = "phy", "apb"; ++ rockchip,pipe-grf = <&php_grf>; ++ rockchip,pipe-phy-grf = <&pipe_phy1_grf>; ++ status = "disabled"; ++ }; + }; +--- a/arch/arm64/boot/dts/rockchip/rk3588s.dtsi ++++ b/arch/arm64/boot/dts/rockchip/rk3588s.dtsi +@@ -944,6 +944,16 @@ + reg = <0x0 0xfd5b0000 0x0 0x1000>; + }; + ++ pipe_phy0_grf: syscon@fd5bc000 { ++ compatible = "rockchip,rk3588-pipe-phy-grf", "syscon"; ++ reg = <0x0 0xfd5bc000 0x0 0x100>; ++ }; ++ ++ pipe_phy2_grf: syscon@fd5c4000 { ++ compatible = "rockchip,rk3588-pipe-phy-grf", "syscon"; ++ reg = <0x0 0xfd5c4000 0x0 0x100>; ++ }; ++ + ioc: syscon@fd5f0000 { + compatible = "rockchip,rk3588-ioc", "syscon"; + reg = <0x0 0xfd5f0000 0x0 0x10000>; +@@ -2450,6 +2460,38 @@ + #dma-cells = <1>; + }; + ++ combphy0_ps: phy@fee00000 { ++ compatible = "rockchip,rk3588-naneng-combphy"; ++ reg = <0x0 0xfee00000 0x0 0x100>; ++ #phy-cells = <1>; ++ clocks = <&cru CLK_REF_PIPE_PHY0>, <&cru PCLK_PCIE_COMBO_PIPE_PHY0>, ++ <&cru PCLK_PHP_ROOT>; ++ clock-names = "ref", "apb", "pipe"; ++ assigned-clocks = <&cru CLK_REF_PIPE_PHY0>; ++ assigned-clock-rates = <100000000>; ++ resets = <&cru SRST_REF_PIPE_PHY0>, <&cru SRST_P_PCIE2_PHY0>; ++ reset-names = "phy", "apb"; ++ rockchip,pipe-grf = <&php_grf>; ++ rockchip,pipe-phy-grf = <&pipe_phy0_grf>; ++ status = "disabled"; ++ }; ++ ++ combphy2_psu: phy@fee20000 { ++ compatible = "rockchip,rk3588-naneng-combphy"; ++ reg = <0x0 0xfee20000 0x0 0x100>; ++ #phy-cells = <1>; ++ clocks = <&cru CLK_REF_PIPE_PHY2>, <&cru PCLK_PCIE_COMBO_PIPE_PHY2>, ++ <&cru PCLK_PHP_ROOT>; ++ clock-names = "ref", "apb", "pipe"; ++ assigned-clocks = <&cru CLK_REF_PIPE_PHY2>; ++ assigned-clock-rates = <100000000>; ++ resets = <&cru SRST_REF_PIPE_PHY2>, <&cru SRST_P_PCIE2_PHY2>; ++ reset-names = "phy", "apb"; ++ rockchip,pipe-grf = <&php_grf>; ++ rockchip,pipe-phy-grf = <&pipe_phy2_grf>; ++ status = "disabled"; ++ }; ++ + system_sram2: sram@ff001000 { + compatible = "mmio-sram"; + reg = <0x0 0xff001000 0x0 0xef000>; diff --git a/target/linux/rockchip/patches-6.1/114-02-arm64-dts-rockchip-rk3588-add-SATA-support.patch b/target/linux/rockchip/patches-6.1/114-02-arm64-dts-rockchip-rk3588-add-SATA-support.patch new file mode 100644 index 0000000000..e69ca3f89c --- /dev/null +++ b/target/linux/rockchip/patches-6.1/114-02-arm64-dts-rockchip-rk3588-add-SATA-support.patch @@ -0,0 +1,122 @@ +From: Sebastian Reichel +To: Heiko Stuebner +Cc: Rob Herring , + Krzysztof Kozlowski , + Damien Le Moal , + Serge Semin , + Vinod Koul , + Kishon Vijay Abraham I , + linux-ide@vger.kernel.org, linux-phy@lists.infradead.org, + linux-rockchip@lists.infradead.org, devicetree@vger.kernel.org, + linux-kernel@vger.kernel.org, + Sebastian Reichel , + kernel@collabora.com +Subject: [PATCH v2 6/6] arm64: dts: rockchip: rk3588: add SATA support +Date: Mon, 22 May 2023 19:34:23 +0200 [thread overview] +Message-ID: <20230522173423.64691-7-sebastian.reichel@collabora.com> (raw) +In-Reply-To: <20230522173423.64691-1-sebastian.reichel@collabora.com> + +Add all three SATA IP blocks to the RK3588 DT. + +Signed-off-by: Sebastian Reichel +--- + arch/arm64/boot/dts/rockchip/rk3588.dtsi | 23 +++++++++++ + arch/arm64/boot/dts/rockchip/rk3588s.dtsi | 48 +++++++++++++++++++++++ + 2 files changed, 71 insertions(+) + +--- a/arch/arm64/boot/dts/rockchip/rk3588.dtsi ++++ b/arch/arm64/boot/dts/rockchip/rk3588.dtsi +@@ -129,6 +129,29 @@ + }; + }; + ++ sata1: sata@fe220000 { ++ compatible = "rockchip,rk3588-dwc-ahci", "snps,dwc-ahci"; ++ reg = <0 0xfe220000 0 0x1000>; ++ clocks = <&cru ACLK_SATA1>, <&cru CLK_PMALIVE1>, ++ <&cru CLK_RXOOB1>, <&cru CLK_PIPEPHY1_REF>, ++ <&cru CLK_PIPEPHY1_PIPE_ASIC_G>; ++ clock-names = "sata", "pmalive", "rxoob", "ref", "asic"; ++ interrupts = ; ++ ports-implemented = <0x1>; ++ #address-cells = <1>; ++ #size-cells = <0>; ++ status = "disabled"; ++ ++ sata-port@0 { ++ reg = <0>; ++ hba-port-cap = ; ++ phys = <&combphy1_ps PHY_TYPE_SATA>; ++ phy-names = "sata-phy"; ++ snps,rx-ts-max = <32>; ++ snps,tx-ts-max = <32>; ++ }; ++ }; ++ + combphy1_ps: phy@fee10000 { + compatible = "rockchip,rk3588-naneng-combphy"; + reg = <0x0 0xfee10000 0x0 0x100>; +--- a/arch/arm64/boot/dts/rockchip/rk3588s.dtsi ++++ b/arch/arm64/boot/dts/rockchip/rk3588s.dtsi +@@ -9,6 +9,8 @@ + #include + #include + #include ++#include ++#include + + / { + compatible = "rockchip,rk3588"; +@@ -1717,6 +1719,52 @@ + }; + }; + ++ sata0: sata@fe210000 { ++ compatible = "rockchip,rk3588-dwc-ahci", "snps,dwc-ahci"; ++ reg = <0 0xfe210000 0 0x1000>; ++ clocks = <&cru ACLK_SATA0>, <&cru CLK_PMALIVE0>, ++ <&cru CLK_RXOOB0>, <&cru CLK_PIPEPHY0_REF>, ++ <&cru CLK_PIPEPHY0_PIPE_ASIC_G>; ++ clock-names = "sata", "pmalive", "rxoob", "ref", "asic"; ++ interrupts = ; ++ ports-implemented = <0x1>; ++ #address-cells = <1>; ++ #size-cells = <0>; ++ status = "disabled"; ++ ++ sata-port@0 { ++ reg = <0>; ++ hba-port-cap = ; ++ phys = <&combphy0_ps PHY_TYPE_SATA>; ++ phy-names = "sata-phy"; ++ snps,rx-ts-max = <32>; ++ snps,tx-ts-max = <32>; ++ }; ++ }; ++ ++ sata2: sata@fe230000 { ++ compatible = "rockchip,rk3588-dwc-ahci", "snps,dwc-ahci"; ++ reg = <0 0xfe230000 0 0x1000>; ++ clocks = <&cru ACLK_SATA2>, <&cru CLK_PMALIVE2>, ++ <&cru CLK_RXOOB2>, <&cru CLK_PIPEPHY2_REF>, ++ <&cru CLK_PIPEPHY2_PIPE_ASIC_G>; ++ clock-names = "sata", "pmalive", "rxoob", "ref", "asic"; ++ interrupts = ; ++ ports-implemented = <0x1>; ++ #address-cells = <1>; ++ #size-cells = <0>; ++ status = "disabled"; ++ ++ sata-port@0 { ++ reg = <0>; ++ hba-port-cap = ; ++ phys = <&combphy2_psu PHY_TYPE_SATA>; ++ phy-names = "sata-phy"; ++ snps,rx-ts-max = <32>; ++ snps,tx-ts-max = <32>; ++ }; ++ }; ++ + sdmmc: mmc@fe2c0000 { + compatible = "rockchip,rk3588-dw-mshc", "rockchip,rk3288-dw-mshc"; + reg = <0x0 0xfe2c0000 0x0 0x4000>; diff --git a/target/linux/rockchip/patches-6.1/114-03-arm64-dts-rockchip-rk3588-evb1-add-SATA.patch b/target/linux/rockchip/patches-6.1/114-03-arm64-dts-rockchip-rk3588-evb1-add-SATA.patch new file mode 100644 index 0000000000..8f90d500b7 --- /dev/null +++ b/target/linux/rockchip/patches-6.1/114-03-arm64-dts-rockchip-rk3588-evb1-add-SATA.patch @@ -0,0 +1,31 @@ +From 0af5c1ec425427c0c49b8185e2ca301262062ce2 Mon Sep 17 00:00:00 2001 +From: Sebastian Reichel +Date: Thu, 6 Apr 2023 17:32:02 +0200 +Subject: [PATCH] arm64: dts: rockchip: rk3588-evb1: add SATA + +Add support for the SATA0_0 port found on the RK3588 EVB1. The +second port (SATA0_1) does not work, which matches the downstream +behaviour. + +Signed-off-by: Sebastian Reichel +--- + arch/arm64/boot/dts/rockchip/rk3588-evb1-v10.dts | 8 ++++++++ + 1 file changed, 8 insertions(+) + +--- a/arch/arm64/boot/dts/rockchip/rk3588-evb1-v10.dts ++++ b/arch/arm64/boot/dts/rockchip/rk3588-evb1-v10.dts +@@ -946,6 +946,14 @@ + }; + }; + ++&combphy0_ps { ++ status = "okay"; ++}; ++ ++&sata0 { ++ status = "okay"; ++}; ++ + &tsadc { + status = "okay"; + }; diff --git a/target/linux/rockchip/patches-6.1/115-01-arm64-dts-rockchip-rk3588-add-PCIe2-support.patch b/target/linux/rockchip/patches-6.1/115-01-arm64-dts-rockchip-rk3588-add-PCIe2-support.patch new file mode 100644 index 0000000000..12834f1053 --- /dev/null +++ b/target/linux/rockchip/patches-6.1/115-01-arm64-dts-rockchip-rk3588-add-PCIe2-support.patch @@ -0,0 +1,200 @@ +From b14fea6eb11e6e11c1747e54110c7223d102b0ed Mon Sep 17 00:00:00 2001 +From: Sebastian Reichel +Date: Mon, 17 Apr 2023 20:03:08 +0200 +Subject: [PATCH] arm64: dts: rockchip: rk3588: add PCIe2 support + +Add all three PCIe2 IP blocks to the RK3588 DT. Note, that RK3588 +also has two PCIe3 IP blocks, that will be handled separately. + +TODO: FIXME: this is not compliant with the DT binding. There is +one additional clock ("pipe"), one additional reset line, the +interrupt-names do not match + +Signed-off-by: Kever Yang +Co-developed-by: Kever Yang +Signed-off-by: Sebastian Reichel +--- + arch/arm64/boot/dts/rockchip/rk3588.dtsi | 54 +++++++++++ + arch/arm64/boot/dts/rockchip/rk3588s.dtsi | 108 ++++++++++++++++++++++ + 2 files changed, 162 insertions(+) + +--- a/arch/arm64/boot/dts/rockchip/rk3588.dtsi ++++ b/arch/arm64/boot/dts/rockchip/rk3588.dtsi +@@ -80,6 +80,60 @@ + status = "disabled"; + }; + ++ pcie2x1l0: pcie@fe170000 { ++ compatible = "rockchip,rk3588-pcie", "rockchip,rk3568-pcie"; ++ #address-cells = <3>; ++ #size-cells = <2>; ++ bus-range = <0x20 0x2f>; ++ clocks = <&cru ACLK_PCIE_1L0_MSTR>, <&cru ACLK_PCIE_1L0_SLV>, ++ <&cru ACLK_PCIE_1L0_DBI>, <&cru PCLK_PCIE_1L0>, ++ <&cru CLK_PCIE_AUX2>, <&cru CLK_PCIE1L0_PIPE>; ++ clock-names = "aclk_mst", "aclk_slv", ++ "aclk_dbi", "pclk", ++ "aux", "pipe"; ++ device_type = "pci"; ++ interrupts = , ++ , ++ , ++ , ++ ; ++ interrupt-names = "sys", "pmc", "msg", "legacy", "err"; ++ #interrupt-cells = <1>; ++ interrupt-map-mask = <0 0 0 7>; ++ interrupt-map = <0 0 0 1 &pcie2x1l0_intc 0>, ++ <0 0 0 2 &pcie2x1l0_intc 1>, ++ <0 0 0 3 &pcie2x1l0_intc 2>, ++ <0 0 0 4 &pcie2x1l0_intc 3>; ++ linux,pci-domain = <2>; ++ num-ib-windows = <8>; ++ num-ob-windows = <8>; ++ num-viewport = <4>; ++ max-link-speed = <2>; ++ msi-map = <0x2000 &its0 0x2000 0x1000>; ++ num-lanes = <1>; ++ phys = <&combphy1_ps PHY_TYPE_PCIE>; ++ phy-names = "pcie-phy"; ++ power-domains = <&power RK3588_PD_PCIE>; ++ ranges = <0x01000000 0x0 0xf2100000 0x0 0xf2100000 0x0 0x00100000>, ++ <0x02000000 0x0 0xf2200000 0x0 0xf2200000 0x0 0x00e00000>, ++ <0x03000000 0x9 0x80000000 0x9 0x80000000 0x0 0x40000000>; ++ reg = <0xa 0x40800000 0x0 0x00400000>, ++ <0x0 0xfe170000 0x0 0x00010000>, ++ <0x0 0xf2000000 0x0 0x00100000>; ++ reg-names = "dbi", "apb", "config"; ++ resets = <&cru SRST_PCIE2_POWER_UP>, <&cru SRST_P_PCIE2>; ++ reset-names = "pwr", "pipe"; ++ status = "disabled"; ++ ++ pcie2x1l0_intc: legacy-interrupt-controller { ++ interrupt-controller; ++ #address-cells = <0>; ++ #interrupt-cells = <1>; ++ interrupt-parent = <&gic>; ++ interrupts = ; ++ }; ++ }; ++ + gmac0: ethernet@fe1b0000 { + compatible = "rockchip,rk3588-gmac", "snps,dwmac-4.20a"; + reg = <0x0 0xfe1b0000 0x0 0x10000>; +--- a/arch/arm64/boot/dts/rockchip/rk3588s.dtsi ++++ b/arch/arm64/boot/dts/rockchip/rk3588s.dtsi +@@ -1670,6 +1670,114 @@ + reg = <0x0 0xfdf82200 0x0 0x20>; + }; + ++ pcie2x1l1: pcie@fe180000 { ++ compatible = "rockchip,rk3588-pcie", "rockchip,rk3568-pcie"; ++ #address-cells = <3>; ++ #size-cells = <2>; ++ bus-range = <0x30 0x3f>; ++ clocks = <&cru ACLK_PCIE_1L1_MSTR>, <&cru ACLK_PCIE_1L1_SLV>, ++ <&cru ACLK_PCIE_1L1_DBI>, <&cru PCLK_PCIE_1L1>, ++ <&cru CLK_PCIE_AUX3>, <&cru CLK_PCIE1L1_PIPE>; ++ clock-names = "aclk_mst", "aclk_slv", ++ "aclk_dbi", "pclk", ++ "aux", "pipe"; ++ device_type = "pci"; ++ interrupts = , ++ , ++ , ++ , ++ ; ++ interrupt-names = "sys", "pmc", "msg", "legacy", "err"; ++ #interrupt-cells = <1>; ++ interrupt-map-mask = <0 0 0 7>; ++ interrupt-map = <0 0 0 1 &pcie2x1l1_intc 0>, ++ <0 0 0 2 &pcie2x1l1_intc 1>, ++ <0 0 0 3 &pcie2x1l1_intc 2>, ++ <0 0 0 4 &pcie2x1l1_intc 3>; ++ linux,pci-domain = <3>; ++ num-ib-windows = <8>; ++ num-ob-windows = <8>; ++ num-viewport = <4>; ++ max-link-speed = <2>; ++ msi-map = <0x3000 &its0 0x3000 0x1000>; ++ num-lanes = <1>; ++ phys = <&combphy2_psu PHY_TYPE_PCIE>; ++ phy-names = "pcie-phy"; ++ power-domains = <&power RK3588_PD_PCIE>; ++ ranges = <0x01000000 0x0 0xf3100000 0x0 0xf3100000 0x0 0x00100000>, ++ <0x02000000 0x0 0xf3200000 0x0 0xf3200000 0x0 0x00e00000>, ++ <0x03000000 0x9 0xc0000000 0x9 0xc0000000 0x0 0x40000000>; ++ reg = <0xa 0x40c00000 0x0 0x00400000>, ++ <0x0 0xfe180000 0x0 0x00010000>, ++ <0x0 0xf3000000 0x0 0x00100000>; ++ reg-names = "dbi", "apb", "config"; ++ resets = <&cru SRST_PCIE3_POWER_UP>, <&cru SRST_P_PCIE3>; ++ reset-names = "pwr", "pipe"; ++ status = "disabled"; ++ ++ pcie2x1l1_intc: legacy-interrupt-controller { ++ interrupt-controller; ++ #address-cells = <0>; ++ #interrupt-cells = <1>; ++ interrupt-parent = <&gic>; ++ interrupts = ; ++ }; ++ }; ++ ++ pcie2x1l2: pcie@fe190000 { ++ compatible = "rockchip,rk3588-pcie", "rockchip,rk3568-pcie"; ++ #address-cells = <3>; ++ #size-cells = <2>; ++ bus-range = <0x40 0x4f>; ++ clocks = <&cru ACLK_PCIE_1L2_MSTR>, <&cru ACLK_PCIE_1L2_SLV>, ++ <&cru ACLK_PCIE_1L2_DBI>, <&cru PCLK_PCIE_1L2>, ++ <&cru CLK_PCIE_AUX4>, <&cru CLK_PCIE1L2_PIPE>; ++ clock-names = "aclk_mst", "aclk_slv", ++ "aclk_dbi", "pclk", ++ "aux", "pipe"; ++ device_type = "pci"; ++ interrupts = , ++ , ++ , ++ , ++ ; ++ interrupt-names = "sys", "pmc", "msg", "legacy", "err"; ++ #interrupt-cells = <1>; ++ interrupt-map-mask = <0 0 0 7>; ++ interrupt-map = <0 0 0 1 &pcie2x1l2_intc 0>, ++ <0 0 0 2 &pcie2x1l2_intc 1>, ++ <0 0 0 3 &pcie2x1l2_intc 2>, ++ <0 0 0 4 &pcie2x1l2_intc 3>; ++ linux,pci-domain = <4>; ++ num-ib-windows = <8>; ++ num-ob-windows = <8>; ++ num-viewport = <4>; ++ max-link-speed = <2>; ++ msi-map = <0x4000 &its0 0x4000 0x1000>; ++ num-lanes = <1>; ++ phys = <&combphy0_ps PHY_TYPE_PCIE>; ++ phy-names = "pcie-phy"; ++ power-domains = <&power RK3588_PD_PCIE>; ++ ranges = <0x01000000 0x0 0xf4100000 0x0 0xf4100000 0x0 0x00100000>, ++ <0x02000000 0x0 0xf4200000 0x0 0xf4200000 0x0 0x00e00000>, ++ <0x03000000 0xa 0x00000000 0xa 0x00000000 0x0 0x40000000>; ++ reg = <0xa 0x41000000 0x0 0x00400000>, ++ <0x0 0xfe190000 0x0 0x00010000>, ++ <0x0 0xf4000000 0x0 0x00100000>; ++ reg-names = "dbi", "apb", "config"; ++ resets = <&cru SRST_PCIE4_POWER_UP>, <&cru SRST_P_PCIE4>; ++ reset-names = "pwr", "pipe"; ++ status = "disabled"; ++ ++ pcie2x1l2_intc: legacy-interrupt-controller { ++ interrupt-controller; ++ #address-cells = <0>; ++ #interrupt-cells = <1>; ++ interrupt-parent = <&gic>; ++ interrupts = ; ++ }; ++ }; ++ + gmac1: ethernet@fe1c0000 { + compatible = "rockchip,rk3588-gmac", "snps,dwmac-4.20a"; + reg = <0x0 0xfe1c0000 0x0 0x10000>; diff --git a/target/linux/rockchip/patches-6.1/115-02-arm64-dts-rockchip-rk3588-evb1-add-PCIe2-support.patch b/target/linux/rockchip/patches-6.1/115-02-arm64-dts-rockchip-rk3588-evb1-add-PCIe2-support.patch new file mode 100644 index 0000000000..b7f2444dd0 --- /dev/null +++ b/target/linux/rockchip/patches-6.1/115-02-arm64-dts-rockchip-rk3588-evb1-add-PCIe2-support.patch @@ -0,0 +1,73 @@ +From 871085534221b58ff5ed26c5852618decd83a1a4 Mon Sep 17 00:00:00 2001 +From: Sebastian Reichel +Date: Mon, 17 Apr 2023 21:13:03 +0200 +Subject: [PATCH] arm64: dts: rockchip: rk3588-evb1: add PCIe2 support + +The RK3588 EVB1 has a second network card, which is connected +via a PCIe2 block. This adds support for that. + +The patch also enables the first PCIe2 block. I did not test +its functionality, but the board boots up properly. + +Signed-off-by: Sebastian Reichel +--- + .../boot/dts/rockchip/rk3588-evb1-v10.dts | 37 +++++++++++++++++++ + 1 file changed, 37 insertions(+) + +--- a/arch/arm64/boot/dts/rockchip/rk3588-evb1-v10.dts ++++ b/arch/arm64/boot/dts/rockchip/rk3588-evb1-v10.dts +@@ -81,6 +81,26 @@ + pinctrl-names = "default"; + pinctrl-0 = <&vcc5v0_host_en>; + }; ++ ++ pcie20_avdd0v85: pcie20-avdd0v85 { ++ compatible = "regulator-fixed"; ++ regulator-name = "pcie20_avdd0v85"; ++ regulator-boot-on; ++ regulator-always-on; ++ regulator-min-microvolt = <850000>; ++ regulator-max-microvolt = <850000>; ++ vin-supply = <&avdd_0v85_s0>; ++ }; ++ ++ pcie20_avdd1v8: pcie20-avdd1v8 { ++ compatible = "regulator-fixed"; ++ regulator-name = "pcie20_avdd1v8"; ++ regulator-boot-on; ++ regulator-always-on; ++ regulator-min-microvolt = <1800000>; ++ regulator-max-microvolt = <1800000>; ++ vin-supply = <&avcc_1v8_s0>; ++ }; + }; + + &cpu_l0 { +@@ -963,10 +983,27 @@ + status = "okay"; + }; + ++&pcie2x1l1 { ++ reset-gpios = <&gpio4 RK_PA2 GPIO_ACTIVE_HIGH>; ++ pinctrl-names = "default"; ++ pinctrl-0 = <&rtl8111_isolate>; ++ status = "okay"; ++}; ++ + &pinctrl { ++ rtl8111 { ++ rtl8111_isolate: rtl8111-isolate { ++ rockchip,pins = <1 RK_PA4 RK_FUNC_GPIO &pcfg_pull_up>; ++ }; ++ }; ++ + usb { + vcc5v0_host_en: vcc5v0-host-en { + rockchip,pins = <4 RK_PB0 RK_FUNC_GPIO &pcfg_pull_none>; + }; + }; + }; ++ ++&combphy2_psu { ++ status = "okay"; ++}; diff --git a/target/linux/rockchip/patches-6.1/115-03-arm64-dts-rockchip-RK3588s-Enable-PCIE2-0x1-fe190000.patch b/target/linux/rockchip/patches-6.1/115-03-arm64-dts-rockchip-RK3588s-Enable-PCIE2-0x1-fe190000.patch new file mode 100644 index 0000000000..2a689e243a --- /dev/null +++ b/target/linux/rockchip/patches-6.1/115-03-arm64-dts-rockchip-RK3588s-Enable-PCIE2-0x1-fe190000.patch @@ -0,0 +1,46 @@ +From 43227cd535520a31510c9db45e96686575bfb1e1 Mon Sep 17 00:00:00 2001 +From: Lucas Tanure +Date: Tue, 28 Feb 2023 14:40:59 +0000 +Subject: [PATCH] arm64: dts: rockchip: RK3588s: Enable PCIE2.0x1 @fe190000 + +Enable PCIE2.0x1 @fe190000 for RTL8125 network controller in +Rock 5B board. + +Signed-off-by: Lucas Tanure +--- + .../boot/dts/rockchip/rk3588-rock-5b.dts | 20 +++++++++++++++++++ + 1 file changed, 20 insertions(+) + +--- a/arch/arm64/boot/dts/rockchip/rk3588-rock-5b.dts ++++ b/arch/arm64/boot/dts/rockchip/rk3588-rock-5b.dts +@@ -66,6 +66,15 @@ + pinctrl-0 = <&vcc5v0_host_en>; + vin-supply = <&vcc5v0_sys>; + }; ++ ++ vcc3v3_pcie2x1l2: vcc3v3-pcie2x1l2 { ++ compatible = "regulator-fixed"; ++ regulator-name = "vcc3v3_pcie2x1l2"; ++ regulator-min-microvolt = <3300000>; ++ regulator-max-microvolt = <3300000>; ++ startup-delay-us = <5000>; ++ vin-supply = <&vcc_3v3_s3>; ++ }; + }; + + &cpu_b0 { +@@ -252,3 +261,14 @@ + }; + }; + }; ++ ++&combphy0_ps { ++ status = "okay"; ++}; ++ ++&pcie2x1l2 { ++ reset-gpios = <&gpio3 RK_PB0 GPIO_ACTIVE_HIGH>; ++ vpcie3v3-supply = <&vcc3v3_pcie2x1l2>; ++ status = "okay"; ++ ++}; diff --git a/target/linux/rockchip/patches-6.1/116-01-arm64-dts-rockchip-Add-RK806-regulator-config.patch b/target/linux/rockchip/patches-6.1/116-01-arm64-dts-rockchip-Add-RK806-regulator-config.patch new file mode 100644 index 0000000000..700fde25e1 --- /dev/null +++ b/target/linux/rockchip/patches-6.1/116-01-arm64-dts-rockchip-Add-RK806-regulator-config.patch @@ -0,0 +1,196 @@ +From 4007f264822a4dc2528e9612900699d59616e00e Mon Sep 17 00:00:00 2001 +From: Lucas Tanure +Date: Mon, 9 Jan 2023 16:37:23 +0000 +Subject: [PATCH] arm64: dts: rockchip: Add RK806 regulator config + +Add support for rk806 single configuration PMIC in Rock Pi 5A and 5B. + +Signed-off-by: Lucas Tanure +Signed-off-by: Sebastian Reichel +--- + .../dts/rockchip/rk3588-rk806-single.dtsi | 179 ++++++++++++++++++ + 1 file changed, 179 insertions(+) + create mode 100644 arch/arm64/boot/dts/rockchip/rk3588-rk806-single.dtsi + +--- /dev/null ++++ b/arch/arm64/boot/dts/rockchip/rk3588-rk806-single.dtsi +@@ -0,0 +1,179 @@ ++// SPDX-License-Identifier: (GPL-2.0+ OR MIT) ++/* ++ * Copyright (c) 2021 Rockchip Electronics Co., Ltd. ++ * ++ */ ++ ++#include ++#include ++ ++&spi2 { ++ status = "okay"; ++ assigned-clocks = <&cru CLK_SPI2>; ++ assigned-clock-rates = <200000000>; ++ pinctrl-names = "default"; ++ pinctrl-0 = <&spi2m2_cs0 &spi2m2_pins>; ++ num-cs = <1>; ++ ++ rk806single: rk806single@0 { ++ compatible = "rockchip,rk806"; ++ spi-max-frequency = <1000000>; ++ reg = <0x0>; ++ ++ interrupt-parent = <&gpio0>; ++ interrupts = <7 IRQ_TYPE_LEVEL_LOW>; ++ ++ pinctrl-names = "default"; ++ pinctrl-0 = <&pmic_pins>, <&rk806_dvs1_null>, <&rk806_dvs2_null>, <&rk806_dvs3_null>; ++ ++ vcc1-supply = <&vcc5v0_sys>; ++ vcc2-supply = <&vcc5v0_sys>; ++ vcc3-supply = <&vcc5v0_sys>; ++ vcc4-supply = <&vcc5v0_sys>; ++ vcc5-supply = <&vcc5v0_sys>; ++ vcc6-supply = <&vcc5v0_sys>; ++ vcc7-supply = <&vcc5v0_sys>; ++ vcc8-supply = <&vcc5v0_sys>; ++ vcc9-supply = <&vcc5v0_sys>; ++ vcc10-supply = <&vcc5v0_sys>; ++ vcc11-supply = <&vcc_2v0_pldo_s3>; ++ vcc12-supply = <&vcc5v0_sys>; ++ vcc13-supply = <&vcc_1v1_nldo_s3>; ++ vcc14-supply = <&vcc_1v1_nldo_s3>; ++ vcca-supply = <&vcc5v0_sys>; ++ ++ gpio-controller; ++ #gpio-cells = <2>; ++ ++ rk806_dvs1_null: dvs1-null-pins { ++ pins = "gpio_pwrctrl2"; ++ function = "pin_fun0"; ++ }; ++ ++ rk806_dvs1_slp: dvs1-slp-pins { ++ pins = "gpio_pwrctrl1"; ++ function = "pin_fun1"; ++ }; ++ ++ rk806_dvs1_pwrdn: dvs1-pwrdn-pins { ++ pins = "gpio_pwrctrl1"; ++ function = "pin_fun2"; ++ }; ++ ++ rk806_dvs1_rst: dvs1-rst-pins { ++ pins = "gpio_pwrctrl1"; ++ function = "pin_fun3"; ++ }; ++ ++ rk806_dvs2_null: dvs2-null-pins { ++ pins = "gpio_pwrctrl2"; ++ function = "pin_fun0"; ++ }; ++ ++ rk806_dvs2_slp: dvs2-slp-pins { ++ pins = "gpio_pwrctrl2"; ++ function = "pin_fun1"; ++ }; ++ ++ rk806_dvs2_pwrdn: dvs2-pwrdn-pins { ++ pins = "gpio_pwrctrl2"; ++ function = "pin_fun2"; ++ }; ++ ++ rk806_dvs2_rst: dvs2-rst-pins { ++ pins = "gpio_pwrctrl2"; ++ function = "pin_fun3"; ++ }; ++ ++ rk806_dvs2_dvs: dvs2-dvs-pins { ++ pins = "gpio_pwrctrl2"; ++ function = "pin_fun4"; ++ }; ++ ++ rk806_dvs2_gpio: dvs2-gpio-pins { ++ pins = "gpio_pwrctrl2"; ++ function = "pin_fun5"; ++ }; ++ ++ rk806_dvs3_null: dvs3-null-pins { ++ pins = "gpio_pwrctrl3"; ++ function = "pin_fun0"; ++ }; ++ ++ rk806_dvs3_slp: dvs3-slp-pins { ++ pins = "gpio_pwrctrl3"; ++ function = "pin_fun1"; ++ }; ++ ++ rk806_dvs3_pwrdn: dvs3-pwrdn-pins { ++ pins = "gpio_pwrctrl3"; ++ function = "pin_fun2"; ++ }; ++ ++ rk806_dvs3_rst: dvs3-rst-pins { ++ pins = "gpio_pwrctrl3"; ++ function = "pin_fun3"; ++ }; ++ ++ rk806_dvs3_dvs: dvs3-dvs-pins { ++ pins = "gpio_pwrctrl3"; ++ function = "pin_fun4"; ++ }; ++ ++ rk806_dvs3_gpio: dvs3-gpio-pins { ++ pins = "gpio_pwrctrl3"; ++ function = "pin_fun5"; ++ }; ++ ++ regulators { ++ vcc_2v0_pldo_s3: dcdc-reg7 { ++ regulator-always-on; ++ regulator-boot-on; ++ regulator-min-microvolt = <2000000>; ++ regulator-max-microvolt = <2000000>; ++ regulator-ramp-delay = <12500>; ++ regulator-name = "vdd_2v0_pldo_s3"; ++ regulator-state-mem { ++ regulator-on-in-suspend; ++ regulator-suspend-microvolt = <2000000>; ++ }; ++ }; ++ ++ vcc_3v3_s3: dcdc-reg8 { ++ regulator-always-on; ++ regulator-boot-on; ++ regulator-min-microvolt = <3300000>; ++ regulator-max-microvolt = <3300000>; ++ regulator-name = "vcc_3v3_s3"; ++ regulator-state-mem { ++ regulator-on-in-suspend; ++ regulator-suspend-microvolt = <3300000>; ++ }; ++ }; ++ ++ vcc_3v3_s0: pldo-reg4 { ++ regulator-always-on; ++ regulator-boot-on; ++ regulator-min-microvolt = <3300000>; ++ regulator-max-microvolt = <3300000>; ++ regulator-ramp-delay = <12500>; ++ regulator-name = "vcc_3v3_s0"; ++ regulator-state-mem { ++ regulator-off-in-suspend; ++ }; ++ }; ++ ++ vccio_sd_s0: pldo-reg5 { ++ regulator-always-on; ++ regulator-boot-on; ++ regulator-min-microvolt = <1800000>; ++ regulator-max-microvolt = <3300000>; ++ regulator-ramp-delay = <12500>; ++ regulator-name = "vccio_sd_s0"; ++ regulator-state-mem { ++ regulator-off-in-suspend; ++ }; ++ }; ++ }; ++ }; ++}; diff --git a/target/linux/rockchip/patches-6.1/116-02-arm64-dts-rockchip-rock-5a-Add-SD-card-support.patch b/target/linux/rockchip/patches-6.1/116-02-arm64-dts-rockchip-rock-5a-Add-SD-card-support.patch new file mode 100644 index 0000000000..981cb21034 --- /dev/null +++ b/target/linux/rockchip/patches-6.1/116-02-arm64-dts-rockchip-rock-5a-Add-SD-card-support.patch @@ -0,0 +1,79 @@ +From 5e3ab74c5fa048982925574f0e6d4628bad2be7e Mon Sep 17 00:00:00 2001 +From: Lucas Tanure +Date: Tue, 13 Dec 2022 09:30:20 +0000 +Subject: [PATCH] arm64: dts: rockchip: rock-5a: Add SD card support + +Add sdmmc support for Rock Pi 5A board. + +Signed-off-by: Lucas Tanure +Signed-off-by: Sebastian Reichel +--- + .../boot/dts/rockchip/rk3588s-rock-5a.dts | 46 +++++++++++++++++++ + 1 file changed, 46 insertions(+) + +--- a/arch/arm64/boot/dts/rockchip/rk3588s-rock-5a.dts ++++ b/arch/arm64/boot/dts/rockchip/rk3588s-rock-5a.dts +@@ -5,6 +5,7 @@ + #include + #include + #include "rk3588s.dtsi" ++#include "rk3588-rk806-single.dtsi" + + / { + model = "Radxa ROCK 5 Model A"; +@@ -18,6 +19,35 @@ + chosen { + stdout-path = "serial2:1500000n8"; + }; ++ ++ vcc12v_dcin: vcc12v-dcin { ++ compatible = "regulator-fixed"; ++ regulator-name = "vcc12v_dcin"; ++ regulator-always-on; ++ regulator-boot-on; ++ regulator-min-microvolt = <12000000>; ++ regulator-max-microvolt = <12000000>; ++ }; ++ ++ vcc5v0_sys: vcc5v0-sys { ++ compatible = "regulator-fixed"; ++ regulator-name = "vcc5v0_sys"; ++ regulator-always-on; ++ regulator-boot-on; ++ regulator-min-microvolt = <5000000>; ++ regulator-max-microvolt = <5000000>; ++ vin-supply = <&vcc12v_dcin>; ++ }; ++ ++ vcc_1v1_nldo_s3: vcc-1v1-nldo-s3 { ++ compatible = "regulator-fixed"; ++ regulator-name = "vcc_1v1_nldo_s3"; ++ regulator-always-on; ++ regulator-boot-on; ++ regulator-min-microvolt = <1100000>; ++ regulator-max-microvolt = <1100000>; ++ vin-supply = <&vcc5v0_sys>; ++ }; + }; + + &gmac1 { +@@ -72,3 +102,19 @@ + pinctrl-0 = <&uart2m0_xfer>; + status = "okay"; + }; ++ ++&sdmmc { ++ max-frequency = <150000000>; ++ no-sdio; ++ no-mmc; ++ bus-width = <4>; ++ cap-mmc-highspeed; ++ cap-sd-highspeed; ++ disable-wp; ++ sd-uhs-sdr104; ++ vmmc-supply = <&vcc_3v3_s0>; ++ vqmmc-supply = <&vccio_sd_s0>; ++ pinctrl-names = "default"; ++ pinctrl-0 = <&sdmmc_bus4 &sdmmc_clk &sdmmc_cmd &sdmmc_det>; ++ status = "okay"; ++}; diff --git a/target/linux/rockchip/patches-6.1/116-03-arm64-dts-rockchip-rock-5b-Add-SD-card-support.patch b/target/linux/rockchip/patches-6.1/116-03-arm64-dts-rockchip-rock-5b-Add-SD-card-support.patch new file mode 100644 index 0000000000..20d56eb253 --- /dev/null +++ b/target/linux/rockchip/patches-6.1/116-03-arm64-dts-rockchip-rock-5b-Add-SD-card-support.patch @@ -0,0 +1,63 @@ +From 80b7c355e8db615dcdfec83ad0412761f3078279 Mon Sep 17 00:00:00 2001 +From: Lucas Tanure +Date: Tue, 21 Feb 2023 16:17:19 +0000 +Subject: [PATCH] arm64: dts: rockchip: rock-5b: Add SD card support + +Add sdmmc node and it's regulators for sd card support + +Signed-off-by: Lucas Tanure +Signed-off-by: Sebastian Reichel +--- + .../boot/dts/rockchip/rk3588-rock-5b.dts | 27 +++++++++++++++++++ + 1 file changed, 27 insertions(+) + +--- a/arch/arm64/boot/dts/rockchip/rk3588-rock-5b.dts ++++ b/arch/arm64/boot/dts/rockchip/rk3588-rock-5b.dts +@@ -5,6 +5,7 @@ + #include + #include + #include "rk3588.dtsi" ++#include "rk3588-rk806-single.dtsi" + + / { + model = "Radxa ROCK 5 Model B"; +@@ -75,6 +76,16 @@ + startup-delay-us = <5000>; + vin-supply = <&vcc_3v3_s3>; + }; ++ ++ vcc_1v1_nldo_s3: vcc-1v1-nldo-s3 { ++ compatible = "regulator-fixed"; ++ regulator-name = "vcc_1v1_nldo_s3"; ++ regulator-always-on; ++ regulator-boot-on; ++ regulator-min-microvolt = <1100000>; ++ regulator-max-microvolt = <1100000>; ++ vin-supply = <&vcc5v0_sys>; ++ }; + }; + + &cpu_b0 { +@@ -214,6 +225,22 @@ + status = "okay"; + }; + ++&sdmmc { ++ max-frequency = <200000000>; ++ no-sdio; ++ no-mmc; ++ bus-width = <4>; ++ cap-mmc-highspeed; ++ cap-sd-highspeed; ++ disable-wp; ++ sd-uhs-sdr104; ++ vmmc-supply = <&vcc_3v3_s3>; ++ vqmmc-supply = <&vccio_sd_s0>; ++ pinctrl-names = "default"; ++ pinctrl-0 = <&sdmmc_bus4 &sdmmc_clk &sdmmc_cmd &sdmmc_det>; ++ status = "okay"; ++}; ++ + &uart2 { + pinctrl-0 = <&uart2m0_xfer>; + status = "okay"; diff --git a/target/linux/rockchip/patches-6.1/116-04-arm64-dts-rockchip-Add-missing-regulator-config.patch b/target/linux/rockchip/patches-6.1/116-04-arm64-dts-rockchip-Add-missing-regulator-config.patch new file mode 100644 index 0000000000..1ac1c9bf29 --- /dev/null +++ b/target/linux/rockchip/patches-6.1/116-04-arm64-dts-rockchip-Add-missing-regulator-config.patch @@ -0,0 +1,21 @@ +--- a/arch/arm64/boot/dts/rockchip/rk3588-rk806-single.dtsi ++++ b/arch/arm64/boot/dts/rockchip/rk3588-rk806-single.dtsi +@@ -126,6 +126,18 @@ + }; + + regulators { ++ vdd_cpu_lit_s0: vdd_cpu_lit_mem_s0: dcdc-reg2 { ++ regulator-always-on; ++ regulator-boot-on; ++ regulator-min-microvolt = <550000>; ++ regulator-max-microvolt = <950000>; ++ regulator-ramp-delay = <12500>; ++ regulator-name = "vdd_cpu_lit_s0"; ++ regulator-state-mem { ++ regulator-off-in-suspend; ++ }; ++ }; ++ + vcc_2v0_pldo_s3: dcdc-reg7 { + regulator-always-on; + regulator-boot-on; diff --git a/target/linux/rockchip/patches-6.1/117-01-clk-divider-Fix-handling-of-rates-UINT_MAX.patch b/target/linux/rockchip/patches-6.1/117-01-clk-divider-Fix-handling-of-rates-UINT_MAX.patch new file mode 100644 index 0000000000..36b85c54b8 --- /dev/null +++ b/target/linux/rockchip/patches-6.1/117-01-clk-divider-Fix-handling-of-rates-UINT_MAX.patch @@ -0,0 +1,43 @@ +From cb57f471ea551d1d19bdd3a6f2a82fbf84287a1b Mon Sep 17 00:00:00 2001 +From: Sebastian Reichel +Date: Thu, 18 May 2023 05:19:48 +0200 +Subject: [PATCH] clk: divider: Fix handling of rates > UINT_MAX + +Fix handling of rates that exceed UINT_MAX (4.29 GHz) to do something +reasonably sensible. Right now asking for UINT_MAX+1 will effectively +return the smallest rate available instead of the biggest one. + +Signed-off-by: Sebastian Reichel +--- + drivers/clk/clk-divider.c | 6 +++--- + 1 file changed, 3 insertions(+), 3 deletions(-) + +--- a/drivers/clk/clk-divider.c ++++ b/drivers/clk/clk-divider.c +@@ -220,7 +220,7 @@ static int _div_round_up(const struct cl + unsigned long parent_rate, unsigned long rate, + unsigned long flags) + { +- int div = DIV_ROUND_UP_ULL((u64)parent_rate, rate); ++ int div = DIV_ROUND_UP_ULL((u64)parent_rate, rate > UINT_MAX ? UINT_MAX : rate); + + if (flags & CLK_DIVIDER_POWER_OF_TWO) + div = __roundup_pow_of_two(div); +@@ -237,7 +237,7 @@ static int _div_round_closest(const stru + int up, down; + unsigned long up_rate, down_rate; + +- up = DIV_ROUND_UP_ULL((u64)parent_rate, rate); ++ up = DIV_ROUND_UP_ULL((u64)parent_rate, rate > UINT_MAX ? UINT_MAX : rate); + down = parent_rate / rate; + + if (flags & CLK_DIVIDER_POWER_OF_TWO) { +@@ -473,7 +473,7 @@ int divider_get_val(unsigned long rate, + { + unsigned int div, value; + +- div = DIV_ROUND_UP_ULL((u64)parent_rate, rate); ++ div = DIV_ROUND_UP_ULL((u64)parent_rate, rate > UINT_MAX ? UINT_MAX : rate); + + if (!_is_valid_div(table, div, flags)) + return -EINVAL; diff --git a/target/linux/rockchip/patches-6.1/117-02-clk-composite-Fix-handling-of-high-clock-rates.patch b/target/linux/rockchip/patches-6.1/117-02-clk-composite-Fix-handling-of-high-clock-rates.patch new file mode 100644 index 0000000000..6aa081045d --- /dev/null +++ b/target/linux/rockchip/patches-6.1/117-02-clk-composite-Fix-handling-of-high-clock-rates.patch @@ -0,0 +1,45 @@ +From 823c6a55a620892fb8a284b880d9d5d40e1c2375 Mon Sep 17 00:00:00 2001 +From: Sebastian Reichel +Date: Thu, 18 May 2023 05:28:17 +0200 +Subject: [PATCH] clk: composite: Fix handling of high clock rates + +If clk_round_rate(clk, ULONG_MAX) is called to acquire the highest +available clock rate and the highest available clock rate is smaller +than ULONG_MAX/2, the result of "req->rate - tmp_req.rate" has the +highest bit set. Since the input to abs() is signed, that means the +number will be miss-interpreted. + +This results in the logic being reverted and the worst choice being +selected as the best one. For example this has been observed on RK3588 +for the eMMC clock: + +GPLL: abs(18446744073709551615 - 1188000000) = 1188000001 +CPLL: abs(18446744073709551615 - 1500000000) = 1500000001 +XIN24M: abs(18446744073709551615 - 24000000) = 24000001 + +With the updated logic any casting between signed and unsigned is +avoided and the numbers look like this instead: + +GPLL: 18446744073709551615 - 1188000000 = 18446744072521551615 +CPLL: 18446744073709551615 - 1500000000 = 18446744072209551615 +XIN24M: 18446744073709551615 - 24000000 = 18446744073685551615 + +As a result the parent with the highest acceptable rate is chosen +instead of the parent clock with the lowest one. + +Signed-off-by: Sebastian Reichel +--- + drivers/clk/clk-composite.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +--- a/drivers/clk/clk-composite.c ++++ b/drivers/clk/clk-composite.c +@@ -119,7 +119,7 @@ static int clk_composite_determine_rate( + if (ret) + continue; + +- rate_diff = abs(req->rate - tmp_req.rate); ++ rate_diff = req->rate > tmp_req.rate ? req->rate - tmp_req.rate : tmp_req.rate - req->rate; + + if (!rate_diff || !req->best_parent_hw + || best_rate_diff > rate_diff) { diff --git a/target/linux/rockchip/patches-6.1/118-01-iio-adc-rockchip_saradc-Add-support-for-RK3588.patch b/target/linux/rockchip/patches-6.1/118-01-iio-adc-rockchip_saradc-Add-support-for-RK3588.patch new file mode 100644 index 0000000000..4b56c304a8 --- /dev/null +++ b/target/linux/rockchip/patches-6.1/118-01-iio-adc-rockchip_saradc-Add-support-for-RK3588.patch @@ -0,0 +1,224 @@ +From: Shreeya Patel +To: jic23@kernel.org, lars@metafoo.de, heiko@sntech.de, + robh+dt@kernel.org, krzysztof.kozlowski+dt@linaro.org, + sebastian.reichel@collabora.com +Cc: linux-iio@vger.kernel.org, devicetree@vger.kernel.org, + linux-arm-kernel@lists.infradead.org, + linux-rockchip@lists.infradead.org, linux-kernel@vger.kernel.org, + kernel@collabora.com, gustavo.padovan@collabora.com, + serge.broslavsky@collabora.com, + Shreeya Patel , + Simon Xue +Subject: [PATCH 1/7] iio: adc: rockchip_saradc: Add support for RK3588 +Date: Wed, 17 May 2023 04:30:45 +0530 [thread overview] +Message-ID: <20230516230051.14846-2-shreeya.patel@collabora.com> (raw) +In-Reply-To: <20230516230051.14846-1-shreeya.patel@collabora.com> + +Refactor conversion operation to support rk3588 saradc and +add separate start, read, powerdown in respective hooks. + +Signed-off-by: Simon Xue +Signed-off-by: Shreeya Patel +--- + drivers/iio/adc/rockchip_saradc.c | 127 +++++++++++++++++++++++++++--- + 1 file changed, 115 insertions(+), 12 deletions(-) + +--- a/drivers/iio/adc/rockchip_saradc.c ++++ b/drivers/iio/adc/rockchip_saradc.c +@@ -37,10 +37,29 @@ + #define SARADC_TIMEOUT msecs_to_jiffies(100) + #define SARADC_MAX_CHANNELS 8 + ++/* v2 registers */ ++#define SARADC2_CONV_CON 0x0 ++#define SARADC_T_PD_SOC 0x4 ++#define SARADC_T_DAS_SOC 0xc ++#define SARADC2_END_INT_EN 0x104 ++#define SARADC2_ST_CON 0x108 ++#define SARADC2_STATUS 0x10c ++#define SARADC2_END_INT_ST 0x110 ++#define SARADC2_DATA_BASE 0x120 ++ ++#define SARADC2_EN_END_INT BIT(0) ++#define SARADC2_START BIT(4) ++#define SARADC2_SINGLE_MODE BIT(5) ++ ++struct rockchip_saradc; ++ + struct rockchip_saradc_data { + const struct iio_chan_spec *channels; + int num_channels; + unsigned long clk_rate; ++ void (*start)(struct rockchip_saradc *info, int chn); ++ int (*read)(struct rockchip_saradc *info); ++ void (*power_down)(struct rockchip_saradc *info); + }; + + struct rockchip_saradc { +@@ -57,27 +76,77 @@ struct rockchip_saradc { + struct notifier_block nb; + }; + +-static void rockchip_saradc_power_down(struct rockchip_saradc *info) ++static void rockchip_saradc_reset_controller(struct reset_control *reset); ++ ++static void rockchip_saradc_start_v1(struct rockchip_saradc *info, int chn) ++{ ++ /* 8 clock periods as delay between power up and start cmd */ ++ writel_relaxed(8, info->regs + SARADC_DLY_PU_SOC); ++ /* Select the channel to be used and trigger conversion */ ++ writel(SARADC_CTRL_POWER_CTRL | (chn & SARADC_CTRL_CHN_MASK) | ++ SARADC_CTRL_IRQ_ENABLE, info->regs + SARADC_CTRL); ++} ++ ++static void rockchip_saradc_start_v2(struct rockchip_saradc *info, int chn) ++{ ++ int val; ++ ++ if (info->reset) ++ rockchip_saradc_reset_controller(info->reset); ++ ++ writel_relaxed(0xc, info->regs + SARADC_T_DAS_SOC); ++ writel_relaxed(0x20, info->regs + SARADC_T_PD_SOC); ++ val = SARADC2_EN_END_INT << 16 | SARADC2_EN_END_INT; ++ writel_relaxed(val, info->regs + SARADC2_END_INT_EN); ++ val = SARADC2_START | SARADC2_SINGLE_MODE | chn; ++ writel(val << 16 | val, info->regs + SARADC2_CONV_CON); ++} ++ ++static void rockchip_saradc_start(struct rockchip_saradc *info, int chn) ++{ ++ info->data->start(info, chn); ++} ++ ++static int rockchip_saradc_read_v1(struct rockchip_saradc *info) ++{ ++ return readl_relaxed(info->regs + SARADC_DATA); ++} ++ ++static int rockchip_saradc_read_v2(struct rockchip_saradc *info) ++{ ++ int offset; ++ ++ /* Clear irq */ ++ writel_relaxed(0x1, info->regs + SARADC2_END_INT_ST); ++ ++ offset = SARADC2_DATA_BASE + info->last_chan->channel * 0x4; ++ ++ return readl_relaxed(info->regs + offset); ++} ++ ++static int rockchip_saradc_read(struct rockchip_saradc *info) ++{ ++ return info->data->read(info); ++} ++ ++static void rockchip_saradc_power_down_v1(struct rockchip_saradc *info) + { +- /* Clear irq & power down adc */ + writel_relaxed(0, info->regs + SARADC_CTRL); + } + ++static void rockchip_saradc_power_down(struct rockchip_saradc *info) ++{ ++ if (info->data->power_down) ++ info->data->power_down(info); ++} ++ + static int rockchip_saradc_conversion(struct rockchip_saradc *info, + struct iio_chan_spec const *chan) + { + reinit_completion(&info->completion); + +- /* 8 clock periods as delay between power up and start cmd */ +- writel_relaxed(8, info->regs + SARADC_DLY_PU_SOC); +- + info->last_chan = chan; +- +- /* Select the channel to be used and trigger conversion */ +- writel(SARADC_CTRL_POWER_CTRL +- | (chan->channel & SARADC_CTRL_CHN_MASK) +- | SARADC_CTRL_IRQ_ENABLE, +- info->regs + SARADC_CTRL); ++ rockchip_saradc_start(info, chan->channel); + + if (!wait_for_completion_timeout(&info->completion, SARADC_TIMEOUT)) + return -ETIMEDOUT; +@@ -120,7 +189,7 @@ static irqreturn_t rockchip_saradc_isr(i + struct rockchip_saradc *info = dev_id; + + /* Read value */ +- info->last_val = readl_relaxed(info->regs + SARADC_DATA); ++ info->last_val = rockchip_saradc_read(info); + info->last_val &= GENMASK(info->last_chan->scan_type.realbits - 1, 0); + + rockchip_saradc_power_down(info); +@@ -160,6 +229,9 @@ static const struct rockchip_saradc_data + .channels = rockchip_saradc_iio_channels, + .num_channels = ARRAY_SIZE(rockchip_saradc_iio_channels), + .clk_rate = 1000000, ++ .start = rockchip_saradc_start_v1, ++ .read = rockchip_saradc_read_v1, ++ .power_down = rockchip_saradc_power_down_v1, + }; + + static const struct iio_chan_spec rockchip_rk3066_tsadc_iio_channels[] = { +@@ -171,6 +243,9 @@ static const struct rockchip_saradc_data + .channels = rockchip_rk3066_tsadc_iio_channels, + .num_channels = ARRAY_SIZE(rockchip_rk3066_tsadc_iio_channels), + .clk_rate = 50000, ++ .start = rockchip_saradc_start_v1, ++ .read = rockchip_saradc_read_v1, ++ .power_down = rockchip_saradc_power_down_v1, + }; + + static const struct iio_chan_spec rockchip_rk3399_saradc_iio_channels[] = { +@@ -186,6 +261,9 @@ static const struct rockchip_saradc_data + .channels = rockchip_rk3399_saradc_iio_channels, + .num_channels = ARRAY_SIZE(rockchip_rk3399_saradc_iio_channels), + .clk_rate = 1000000, ++ .start = rockchip_saradc_start_v1, ++ .read = rockchip_saradc_read_v1, ++ .power_down = rockchip_saradc_power_down_v1, + }; + + static const struct iio_chan_spec rockchip_rk3568_saradc_iio_channels[] = { +@@ -203,6 +281,28 @@ static const struct rockchip_saradc_data + .channels = rockchip_rk3568_saradc_iio_channels, + .num_channels = ARRAY_SIZE(rockchip_rk3568_saradc_iio_channels), + .clk_rate = 1000000, ++ .start = rockchip_saradc_start_v1, ++ .read = rockchip_saradc_read_v1, ++ .power_down = rockchip_saradc_power_down_v1, ++}; ++ ++static const struct iio_chan_spec rockchip_rk3588_saradc_iio_channels[] = { ++ SARADC_CHANNEL(0, "adc0", 12), ++ SARADC_CHANNEL(1, "adc1", 12), ++ SARADC_CHANNEL(2, "adc2", 12), ++ SARADC_CHANNEL(3, "adc3", 12), ++ SARADC_CHANNEL(4, "adc4", 12), ++ SARADC_CHANNEL(5, "adc5", 12), ++ SARADC_CHANNEL(6, "adc6", 12), ++ SARADC_CHANNEL(7, "adc7", 12), ++}; ++ ++static const struct rockchip_saradc_data rk3588_saradc_data = { ++ .channels = rockchip_rk3588_saradc_iio_channels, ++ .num_channels = ARRAY_SIZE(rockchip_rk3588_saradc_iio_channels), ++ .clk_rate = 1000000, ++ .start = rockchip_saradc_start_v2, ++ .read = rockchip_saradc_read_v2, + }; + + static const struct of_device_id rockchip_saradc_match[] = { +@@ -218,6 +318,9 @@ static const struct of_device_id rockchi + }, { + .compatible = "rockchip,rk3568-saradc", + .data = &rk3568_saradc_data, ++ }, { ++ .compatible = "rockchip,rk3588-saradc", ++ .data = &rk3588_saradc_data, + }, + {}, + }; diff --git a/target/linux/rockchip/patches-6.1/118-02-iio-adc-rockchip_saradc-Make-use-of-devm_clk_get_enabled.patch b/target/linux/rockchip/patches-6.1/118-02-iio-adc-rockchip_saradc-Make-use-of-devm_clk_get_enabled.patch new file mode 100644 index 0000000000..87829689aa --- /dev/null +++ b/target/linux/rockchip/patches-6.1/118-02-iio-adc-rockchip_saradc-Make-use-of-devm_clk_get_enabled.patch @@ -0,0 +1,145 @@ +From: Shreeya Patel +To: jic23@kernel.org, lars@metafoo.de, heiko@sntech.de, + robh+dt@kernel.org, krzysztof.kozlowski+dt@linaro.org, + sebastian.reichel@collabora.com +Cc: linux-iio@vger.kernel.org, devicetree@vger.kernel.org, + linux-arm-kernel@lists.infradead.org, + linux-rockchip@lists.infradead.org, linux-kernel@vger.kernel.org, + kernel@collabora.com, gustavo.padovan@collabora.com, + serge.broslavsky@collabora.com, + Shreeya Patel +Subject: [PATCH 2/7] iio: adc: rockchip_saradc: Make use of devm_clk_get_enabled +Date: Wed, 17 May 2023 04:30:46 +0530 [thread overview] +Message-ID: <20230516230051.14846-3-shreeya.patel@collabora.com> (raw) +In-Reply-To: <20230516230051.14846-1-shreeya.patel@collabora.com> + +Use devm_clk_get_enabled() to avoid manually disabling the +clock. + +Signed-off-by: Shreeya Patel +--- + drivers/iio/adc/rockchip_saradc.c | 77 +++++-------------------------- + 1 file changed, 11 insertions(+), 66 deletions(-) + +--- a/drivers/iio/adc/rockchip_saradc.c ++++ b/drivers/iio/adc/rockchip_saradc.c +@@ -336,20 +336,6 @@ static void rockchip_saradc_reset_contro + reset_control_deassert(reset); + } + +-static void rockchip_saradc_clk_disable(void *data) +-{ +- struct rockchip_saradc *info = data; +- +- clk_disable_unprepare(info->clk); +-} +- +-static void rockchip_saradc_pclk_disable(void *data) +-{ +- struct rockchip_saradc *info = data; +- +- clk_disable_unprepare(info->pclk); +-} +- + static void rockchip_saradc_regulator_disable(void *data) + { + struct rockchip_saradc *info = data; +@@ -483,16 +469,6 @@ static int rockchip_saradc_probe(struct + return ret; + } + +- info->pclk = devm_clk_get(&pdev->dev, "apb_pclk"); +- if (IS_ERR(info->pclk)) +- return dev_err_probe(&pdev->dev, PTR_ERR(info->pclk), +- "failed to get pclk\n"); +- +- info->clk = devm_clk_get(&pdev->dev, "saradc"); +- if (IS_ERR(info->clk)) +- return dev_err_probe(&pdev->dev, PTR_ERR(info->clk), +- "failed to get adc clock\n"); +- + info->vref = devm_regulator_get(&pdev->dev, "vref"); + if (IS_ERR(info->vref)) + return dev_err_probe(&pdev->dev, PTR_ERR(info->vref), +@@ -501,6 +477,16 @@ static int rockchip_saradc_probe(struct + if (info->reset) + rockchip_saradc_reset_controller(info->reset); + ++ info->pclk = devm_clk_get_enabled(&pdev->dev, "apb_pclk"); ++ if (IS_ERR(info->pclk)) ++ return dev_err_probe(&pdev->dev, PTR_ERR(info->pclk), ++ "failed to get pclk\n"); ++ ++ info->clk = devm_clk_get_enabled(&pdev->dev, "saradc"); ++ if (IS_ERR(info->clk)) ++ return dev_err_probe(&pdev->dev, PTR_ERR(info->clk), ++ "failed to get adc clock\n"); ++ + /* + * Use a default value for the converter clock. + * This may become user-configurable in the future. +@@ -530,32 +516,6 @@ static int rockchip_saradc_probe(struct + + info->uv_vref = ret; + +- ret = clk_prepare_enable(info->pclk); +- if (ret < 0) { +- dev_err(&pdev->dev, "failed to enable pclk\n"); +- return ret; +- } +- ret = devm_add_action_or_reset(&pdev->dev, +- rockchip_saradc_pclk_disable, info); +- if (ret) { +- dev_err(&pdev->dev, "failed to register devm action, %d\n", +- ret); +- return ret; +- } +- +- ret = clk_prepare_enable(info->clk); +- if (ret < 0) { +- dev_err(&pdev->dev, "failed to enable converter clock\n"); +- return ret; +- } +- ret = devm_add_action_or_reset(&pdev->dev, +- rockchip_saradc_clk_disable, info); +- if (ret) { +- dev_err(&pdev->dev, "failed to register devm action, %d\n", +- ret); +- return ret; +- } +- + platform_set_drvdata(pdev, indio_dev); + + indio_dev->name = dev_name(&pdev->dev); +@@ -589,8 +549,6 @@ static int rockchip_saradc_suspend(struc + struct iio_dev *indio_dev = dev_get_drvdata(dev); + struct rockchip_saradc *info = iio_priv(indio_dev); + +- clk_disable_unprepare(info->clk); +- clk_disable_unprepare(info->pclk); + regulator_disable(info->vref); + + return 0; +@@ -600,21 +558,8 @@ static int rockchip_saradc_resume(struct + { + struct iio_dev *indio_dev = dev_get_drvdata(dev); + struct rockchip_saradc *info = iio_priv(indio_dev); +- int ret; +- +- ret = regulator_enable(info->vref); +- if (ret) +- return ret; +- +- ret = clk_prepare_enable(info->pclk); +- if (ret) +- return ret; +- +- ret = clk_prepare_enable(info->clk); +- if (ret) +- clk_disable_unprepare(info->pclk); + +- return ret; ++ return regulator_enable(info->vref); + } + + static DEFINE_SIMPLE_DEV_PM_OPS(rockchip_saradc_pm_ops, diff --git a/target/linux/rockchip/patches-6.1/118-03-iio-adc-rockchip_saradc-Use-of_device_get_match_data.patch b/target/linux/rockchip/patches-6.1/118-03-iio-adc-rockchip_saradc-Use-of_device_get_match_data.patch new file mode 100644 index 0000000000..c3bafb1ee2 --- /dev/null +++ b/target/linux/rockchip/patches-6.1/118-03-iio-adc-rockchip_saradc-Use-of_device_get_match_data.patch @@ -0,0 +1,53 @@ +From: Shreeya Patel +To: jic23@kernel.org, lars@metafoo.de, heiko@sntech.de, + robh+dt@kernel.org, krzysztof.kozlowski+dt@linaro.org, + sebastian.reichel@collabora.com +Cc: linux-iio@vger.kernel.org, devicetree@vger.kernel.org, + linux-arm-kernel@lists.infradead.org, + linux-rockchip@lists.infradead.org, linux-kernel@vger.kernel.org, + kernel@collabora.com, gustavo.padovan@collabora.com, + serge.broslavsky@collabora.com, + Shreeya Patel +Subject: [PATCH 3/7] iio: adc: rockchip_saradc: Use of_device_get_match_data +Date: Wed, 17 May 2023 04:30:47 +0530 [thread overview] +Message-ID: <20230516230051.14846-4-shreeya.patel@collabora.com> (raw) +In-Reply-To: <20230516230051.14846-1-shreeya.patel@collabora.com> + +Use of_device_get_match_data() to simplify the code. + +Signed-off-by: Shreeya Patel +--- + drivers/iio/adc/rockchip_saradc.c | 8 ++++---- + 1 file changed, 4 insertions(+), 4 deletions(-) + +--- a/drivers/iio/adc/rockchip_saradc.c ++++ b/drivers/iio/adc/rockchip_saradc.c +@@ -405,10 +405,10 @@ static void rockchip_saradc_regulator_un + + static int rockchip_saradc_probe(struct platform_device *pdev) + { ++ const struct rockchip_saradc_data *match_data; + struct rockchip_saradc *info = NULL; + struct device_node *np = pdev->dev.of_node; + struct iio_dev *indio_dev = NULL; +- const struct of_device_id *match; + int ret; + int irq; + +@@ -422,13 +422,13 @@ static int rockchip_saradc_probe(struct + } + info = iio_priv(indio_dev); + +- match = of_match_device(rockchip_saradc_match, &pdev->dev); +- if (!match) { ++ match_data = of_device_get_match_data(&pdev->dev); ++ if (!match_data) { + dev_err(&pdev->dev, "failed to match device\n"); + return -ENODEV; + } + +- info->data = match->data; ++ info->data = match_data; + + /* Sanity check for possible later IP variants with more channels */ + if (info->data->num_channels > SARADC_MAX_CHANNELS) { diff --git a/target/linux/rockchip/patches-6.1/118-04-iio-adc-rockchip_saradc-Match-alignment-with-open-parenth.patch b/target/linux/rockchip/patches-6.1/118-04-iio-adc-rockchip_saradc-Match-alignment-with-open-parenth.patch new file mode 100644 index 0000000000..cc9c746e5a --- /dev/null +++ b/target/linux/rockchip/patches-6.1/118-04-iio-adc-rockchip_saradc-Match-alignment-with-open-parenth.patch @@ -0,0 +1,44 @@ +From: Shreeya Patel +To: jic23@kernel.org, lars@metafoo.de, heiko@sntech.de, + robh+dt@kernel.org, krzysztof.kozlowski+dt@linaro.org, + sebastian.reichel@collabora.com +Cc: linux-iio@vger.kernel.org, devicetree@vger.kernel.org, + linux-arm-kernel@lists.infradead.org, + linux-rockchip@lists.infradead.org, linux-kernel@vger.kernel.org, + kernel@collabora.com, gustavo.padovan@collabora.com, + serge.broslavsky@collabora.com, + Shreeya Patel +Subject: [PATCH 4/7] iio: adc: rockchip_saradc: Match alignment with open parenthesis +Date: Wed, 17 May 2023 04:30:48 +0530 [thread overview] +Message-ID: <20230516230051.14846-5-shreeya.patel@collabora.com> (raw) +In-Reply-To: <20230516230051.14846-1-shreeya.patel@collabora.com> + +Match alignment with open parenthesis for improving the code +readability. + +Signed-off-by: Shreeya Patel +--- + drivers/iio/adc/rockchip_saradc.c | 5 ++--- + 1 file changed, 2 insertions(+), 3 deletions(-) + +--- a/drivers/iio/adc/rockchip_saradc.c ++++ b/drivers/iio/adc/rockchip_saradc.c +@@ -141,7 +141,7 @@ static void rockchip_saradc_power_down(s + } + + static int rockchip_saradc_conversion(struct rockchip_saradc *info, +- struct iio_chan_spec const *chan) ++ struct iio_chan_spec const *chan) + { + reinit_completion(&info->completion); + +@@ -384,8 +384,7 @@ out: + } + + static int rockchip_saradc_volt_notify(struct notifier_block *nb, +- unsigned long event, +- void *data) ++ unsigned long event, void *data) + { + struct rockchip_saradc *info = + container_of(nb, struct rockchip_saradc, nb); diff --git a/target/linux/rockchip/patches-6.1/118-05-iio-adc-rockchip_saradc-Use-dev_err_probe.patch b/target/linux/rockchip/patches-6.1/118-05-iio-adc-rockchip_saradc-Use-dev_err_probe.patch new file mode 100644 index 0000000000..b4842944f6 --- /dev/null +++ b/target/linux/rockchip/patches-6.1/118-05-iio-adc-rockchip_saradc-Use-dev_err_probe.patch @@ -0,0 +1,96 @@ +From: Shreeya Patel +To: jic23@kernel.org, lars@metafoo.de, heiko@sntech.de, + robh+dt@kernel.org, krzysztof.kozlowski+dt@linaro.org, + sebastian.reichel@collabora.com +Cc: linux-iio@vger.kernel.org, devicetree@vger.kernel.org, + linux-arm-kernel@lists.infradead.org, + linux-rockchip@lists.infradead.org, linux-kernel@vger.kernel.org, + kernel@collabora.com, gustavo.padovan@collabora.com, + serge.broslavsky@collabora.com, + Shreeya Patel +Subject: [PATCH 5/7] iio: adc: rockchip_saradc: Use dev_err_probe +Date: Wed, 17 May 2023 04:30:49 +0530 [thread overview] +Message-ID: <20230516230051.14846-6-shreeya.patel@collabora.com> (raw) +In-Reply-To: <20230516230051.14846-1-shreeya.patel@collabora.com> + +Use dev_err_probe instead of dev_err in probe function, +which simplifies code a little bit and prints the error +code. + +Signed-off-by: Shreeya Patel +--- + drivers/iio/adc/rockchip_saradc.c | 45 ++++++++++++++----------------- + 1 file changed, 20 insertions(+), 25 deletions(-) + +--- a/drivers/iio/adc/rockchip_saradc.c ++++ b/drivers/iio/adc/rockchip_saradc.c +@@ -415,25 +415,23 @@ static int rockchip_saradc_probe(struct + return -ENODEV; + + indio_dev = devm_iio_device_alloc(&pdev->dev, sizeof(*info)); +- if (!indio_dev) { +- dev_err(&pdev->dev, "failed allocating iio device\n"); +- return -ENOMEM; +- } ++ if (!indio_dev) ++ return dev_err_probe(&pdev->dev, -ENOMEM, ++ "failed allocating iio device\n"); ++ + info = iio_priv(indio_dev); + + match_data = of_device_get_match_data(&pdev->dev); +- if (!match_data) { +- dev_err(&pdev->dev, "failed to match device\n"); +- return -ENODEV; +- } ++ if (!match_data) ++ return dev_err_probe(&pdev->dev, -ENODEV, ++ "failed to match device\n"); + + info->data = match_data; + + /* Sanity check for possible later IP variants with more channels */ +- if (info->data->num_channels > SARADC_MAX_CHANNELS) { +- dev_err(&pdev->dev, "max channels exceeded"); +- return -EINVAL; +- } ++ if (info->data->num_channels > SARADC_MAX_CHANNELS) ++ return dev_err_probe(&pdev->dev, -EINVAL, ++ "max channels exceeded"); + + info->regs = devm_platform_ioremap_resource(pdev, 0); + if (IS_ERR(info->regs)) +@@ -491,23 +489,20 @@ static int rockchip_saradc_probe(struct + * This may become user-configurable in the future. + */ + ret = clk_set_rate(info->clk, info->data->clk_rate); +- if (ret < 0) { +- dev_err(&pdev->dev, "failed to set adc clk rate, %d\n", ret); +- return ret; +- } ++ if (ret < 0) ++ return dev_err_probe(&pdev->dev, ret, ++ "failed to set adc clk rate\n"); + + ret = regulator_enable(info->vref); +- if (ret < 0) { +- dev_err(&pdev->dev, "failed to enable vref regulator\n"); +- return ret; +- } ++ if (ret < 0) ++ return dev_err_probe(&pdev->dev, ret, ++ "failed to enable vref regulator\n"); ++ + ret = devm_add_action_or_reset(&pdev->dev, + rockchip_saradc_regulator_disable, info); +- if (ret) { +- dev_err(&pdev->dev, "failed to register devm action, %d\n", +- ret); +- return ret; +- } ++ if (ret) ++ return dev_err_probe(&pdev->dev, ret, ++ "failed to register devm action\n"); + + ret = regulator_get_voltage(info->vref); + if (ret < 0) diff --git a/target/linux/rockchip/patches-6.1/118-06-arm64-dts-rockchip-Add-DT-node-for-ADC-support-in-RK3588.patch b/target/linux/rockchip/patches-6.1/118-06-arm64-dts-rockchip-Add-DT-node-for-ADC-support-in-RK3588.patch new file mode 100644 index 0000000000..248e3318c5 --- /dev/null +++ b/target/linux/rockchip/patches-6.1/118-06-arm64-dts-rockchip-Add-DT-node-for-ADC-support-in-RK3588.patch @@ -0,0 +1,43 @@ +From: Shreeya Patel +To: jic23@kernel.org, lars@metafoo.de, heiko@sntech.de, + robh+dt@kernel.org, krzysztof.kozlowski+dt@linaro.org, + sebastian.reichel@collabora.com +Cc: linux-iio@vger.kernel.org, devicetree@vger.kernel.org, + linux-arm-kernel@lists.infradead.org, + linux-rockchip@lists.infradead.org, linux-kernel@vger.kernel.org, + kernel@collabora.com, gustavo.padovan@collabora.com, + serge.broslavsky@collabora.com, + Shreeya Patel +Subject: [PATCH 6/7] arm64: dts: rockchip: Add DT node for ADC support in RK3588 +Date: Wed, 17 May 2023 04:30:50 +0530 [thread overview] +Message-ID: <20230516230051.14846-7-shreeya.patel@collabora.com> (raw) +In-Reply-To: <20230516230051.14846-1-shreeya.patel@collabora.com> + +Add DT node for ADC support in RK3588. + +Signed-off-by: Shreeya Patel +--- + arch/arm64/boot/dts/rockchip/rk3588s.dtsi | 12 ++++++++++++ + 1 file changed, 12 insertions(+) + +--- a/arch/arm64/boot/dts/rockchip/rk3588s.dtsi ++++ b/arch/arm64/boot/dts/rockchip/rk3588s.dtsi +@@ -2648,6 +2648,18 @@ + status = "disabled"; + }; + ++ saradc: saradc@fec10000 { ++ compatible = "rockchip,rk3588-saradc"; ++ reg = <0x0 0xfec10000 0x0 0x10000>; ++ interrupts = ; ++ #io-channel-cells = <1>; ++ clocks = <&cru CLK_SARADC>, <&cru PCLK_SARADC>; ++ clock-names = "saradc", "apb_pclk"; ++ resets = <&cru SRST_P_SARADC>; ++ reset-names = "saradc-apb"; ++ status = "disabled"; ++ }; ++ + system_sram2: sram@ff001000 { + compatible = "mmio-sram"; + reg = <0x0 0xff001000 0x0 0xef000>; diff --git a/target/linux/rockchip/patches-6.1/119-01-phy-rockchip-add-usbdp-combo-phy-driver.patch b/target/linux/rockchip/patches-6.1/119-01-phy-rockchip-add-usbdp-combo-phy-driver.patch new file mode 100644 index 0000000000..c7d2616926 --- /dev/null +++ b/target/linux/rockchip/patches-6.1/119-01-phy-rockchip-add-usbdp-combo-phy-driver.patch @@ -0,0 +1,1779 @@ +From 7575bee7ee718cae56720eb1cd137df3aea65c73 Mon Sep 17 00:00:00 2001 +From: Frank Wang +Date: Tue, 25 Apr 2023 15:55:54 +0200 +Subject: [PATCH 80/85] phy: rockchip: add usbdp combo phy driver + +This adds a new USBDP combo PHY with Samsung IP block driver. + +The driver get lane mux and mapping info in 2 ways, supporting +DisplayPort alternate mode or parsing from DT. When parsing from DT, +the property "rockchip,dp-lane-mux" provide the DP mux and mapping info. + +When do DP link training, need to set lane number, link rate, swing, and +pre-emphasis via PHY configure interface. + +Co-Developed-by: Zhang Yubing +Signed-off-by: Zhang Yubing +Co-Developed-by: Frank Wang +Signed-off-by: Frank Wang +Signed-off-by: Sebastian Reichel +--- + drivers/phy/rockchip/Kconfig | 9 + + drivers/phy/rockchip/Makefile | 1 + + drivers/phy/rockchip/phy-rockchip-usbdp.c | 1728 +++++++++++++++++++++ + 3 files changed, 1738 insertions(+) + create mode 100644 drivers/phy/rockchip/phy-rockchip-usbdp.c + +--- a/drivers/phy/rockchip/Kconfig ++++ b/drivers/phy/rockchip/Kconfig +@@ -107,3 +107,12 @@ config PHY_ROCKCHIP_USB + select GENERIC_PHY + help + Enable this to support the Rockchip USB 2.0 PHY. ++ ++config PHY_ROCKCHIP_USBDP ++ tristate "Rockchip USBDP COMBO PHY Driver" ++ depends on ARCH_ROCKCHIP && OF ++ select GENERIC_PHY ++ select TYPEC ++ help ++ Enable this to support the Rockchip USB3.0/DP ++ combo PHY with Samsung IP block. +--- a/drivers/phy/rockchip/Makefile ++++ b/drivers/phy/rockchip/Makefile +@@ -11,3 +11,4 @@ obj-$(CONFIG_PHY_ROCKCHIP_PCIE) += phy- + obj-$(CONFIG_PHY_ROCKCHIP_SNPS_PCIE3) += phy-rockchip-snps-pcie3.o + obj-$(CONFIG_PHY_ROCKCHIP_TYPEC) += phy-rockchip-typec.o + obj-$(CONFIG_PHY_ROCKCHIP_USB) += phy-rockchip-usb.o ++obj-$(CONFIG_PHY_ROCKCHIP_USBDP) += phy-rockchip-usbdp.o +--- /dev/null ++++ b/drivers/phy/rockchip/phy-rockchip-usbdp.c +@@ -0,0 +1,1728 @@ ++// SPDX-License-Identifier: GPL-2.0-or-later ++/* ++ * Rockchip USBDP Combo PHY with Samsung IP block driver ++ * ++ * Copyright (C) 2021 Rockchip Electronics Co., Ltd ++ */ ++ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++/* RK3588 USBDP PHY Register Definitions */ ++ ++#define UDPHY_PCS 0x4000 ++#define UDPHY_PMA 0x8000 ++ ++/* VO0 GRF Registers */ ++#define RK3588_GRF_VO0_CON0 0x0000 ++#define RK3588_GRF_VO0_CON2 0x0008 ++#define DP_SINK_HPD_CFG BIT(11) ++#define DP_SINK_HPD_SEL BIT(10) ++#define DP_AUX_DIN_SEL BIT(9) ++#define DP_AUX_DOUT_SEL BIT(8) ++#define DP_LANE_SEL_N(n) GENMASK(2 * (n) + 1, 2 * (n)) ++#define DP_LANE_SEL_ALL GENMASK(7, 0) ++#define PHY_AUX_DP_DATA_POL_NORMAL 0 ++#define PHY_AUX_DP_DATA_POL_INVERT 1 ++ ++/* PMA CMN Registers */ ++#define CMN_LANE_MUX_AND_EN_OFFSET 0x0288 /* cmn_reg00A2 */ ++#define CMN_DP_LANE_MUX_N(n) BIT((n) + 4) ++#define CMN_DP_LANE_EN_N(n) BIT(n) ++#define CMN_DP_LANE_MUX_ALL GENMASK(7, 4) ++#define CMN_DP_LANE_EN_ALL GENMASK(3, 0) ++#define PHY_LANE_MUX_USB 0 ++#define PHY_LANE_MUX_DP 1 ++ ++#define CMN_DP_LINK_OFFSET 0x28c /*cmn_reg00A3 */ ++#define CMN_DP_TX_LINK_BW GENMASK(6, 5) ++#define CMN_DP_TX_LANE_SWAP_EN BIT(2) ++ ++#define CMN_SSC_EN_OFFSET 0x2d0 /* cmn_reg00B4 */ ++#define CMN_ROPLL_SSC_EN BIT(1) ++#define CMN_LCPLL_SSC_EN BIT(0) ++ ++#define CMN_ANA_LCPLL_DONE_OFFSET 0x0350 /* cmn_reg00D4 */ ++#define CMN_ANA_LCPLL_LOCK_DONE BIT(7) ++#define CMN_ANA_LCPLL_AFC_DONE BIT(6) ++ ++#define CMN_ANA_ROPLL_DONE_OFFSET 0x0354 /* cmn_reg00D5 */ ++#define CMN_ANA_ROPLL_LOCK_DONE BIT(1) ++#define CMN_ANA_ROPLL_AFC_DONE BIT(0) ++ ++#define CMN_DP_RSTN_OFFSET 0x038c /* cmn_reg00E3 */ ++#define CMN_DP_INIT_RSTN BIT(3) ++#define CMN_DP_CMN_RSTN BIT(2) ++#define CMN_CDR_WTCHDG_EN BIT(1) ++#define CMN_CDR_WTCHDG_MSK_CDR_EN BIT(0) ++ ++#define TRSV_ANA_TX_CLK_OFFSET_N(n) (0x854 + (n) * 0x800) /* trsv_reg0215 */ ++#define LN_ANA_TX_SER_TXCLK_INV BIT(1) ++ ++#define TRSV_LN0_MON_RX_CDR_DONE_OFFSET 0x0b84 /* trsv_reg02E1 */ ++#define TRSV_LN0_MON_RX_CDR_LOCK_DONE BIT(0) ++ ++#define TRSV_LN2_MON_RX_CDR_DONE_OFFSET 0x1b84 /* trsv_reg06E1 */ ++#define TRSV_LN2_MON_RX_CDR_LOCK_DONE BIT(0) ++ ++ ++#define BIT_WRITEABLE_SHIFT 16 ++ ++enum { ++ DP_BW_RBR, ++ DP_BW_HBR, ++ DP_BW_HBR2, ++ DP_BW_HBR3, ++}; ++ ++enum { ++ UDPHY_MODE_NONE = 0, ++ UDPHY_MODE_USB = BIT(0), ++ UDPHY_MODE_DP = BIT(1), ++ UDPHY_MODE_DP_USB = BIT(1) | BIT(0), ++}; ++ ++struct udphy_grf_reg { ++ unsigned int offset; ++ unsigned int bitend; ++ unsigned int bitstart; ++ unsigned int disable; ++ unsigned int enable; ++}; ++ ++struct udphy_grf_cfg { ++ /* u2phy-grf */ ++ struct udphy_grf_reg bvalid_phy_con; ++ struct udphy_grf_reg bvalid_grf_con; ++ ++ /* usb-grf */ ++ struct udphy_grf_reg usb3otg0_cfg; ++ struct udphy_grf_reg usb3otg1_cfg; ++ ++ /* usbdpphy-grf */ ++ struct udphy_grf_reg low_pwrn; ++ struct udphy_grf_reg rx_lfps; ++}; ++ ++struct udphy_vogrf_cfg { ++ /* vo-grf */ ++ struct udphy_grf_reg hpd_trigger; ++}; ++ ++struct dp_tx_drv_ctrl { ++ u32 trsv_reg0204; ++ u32 trsv_reg0205; ++ u32 trsv_reg0206; ++ u32 trsv_reg0207; ++}; ++ ++struct rockchip_udphy; ++ ++struct rockchip_udphy_cfg { ++ /* resets to be requested */ ++ const char * const *rst_list; ++ int num_rsts; ++ ++ struct udphy_grf_cfg grfcfg; ++ struct udphy_vogrf_cfg vogrfcfg[2]; ++ const struct dp_tx_drv_ctrl (*dp_tx_ctrl_cfg[4])[4]; ++ const struct dp_tx_drv_ctrl (*dp_tx_ctrl_cfg_typec[4])[4]; ++ int (*combophy_init)(struct rockchip_udphy *udphy); ++ int (*dp_phy_set_rate)(struct rockchip_udphy *udphy, ++ struct phy_configure_opts_dp *dp); ++ int (*dp_phy_set_voltages)(struct rockchip_udphy *udphy, ++ struct phy_configure_opts_dp *dp); ++ int (*hpd_event_trigger)(struct rockchip_udphy *udphy, bool hpd); ++ int (*dplane_enable)(struct rockchip_udphy *udphy, int dp_lanes); ++ int (*dplane_select)(struct rockchip_udphy *udphy); ++}; ++ ++struct rockchip_udphy { ++ struct device *dev; ++ struct regmap *pma_regmap; ++ struct regmap *u2phygrf; ++ struct regmap *udphygrf; ++ struct regmap *usbgrf; ++ struct regmap *vogrf; ++ struct typec_switch_dev *sw; ++ struct typec_mux_dev *mux; ++ struct mutex mutex; /* mutex to protect access to individual PHYs */ ++ ++ /* clocks and rests */ ++ int num_clks; ++ struct clk_bulk_data *clks; ++ struct clk *refclk; ++ struct reset_control **rsts; ++ ++ /* PHY status management */ ++ bool flip; ++ bool mode_change; ++ u8 mode; ++ u8 status; ++ ++ /* utilized for USB */ ++ bool hs; /* flag for high-speed */ ++ ++ /* utilized for DP */ ++ struct gpio_desc *sbu1_dc_gpio; ++ struct gpio_desc *sbu2_dc_gpio; ++ u32 lane_mux_sel[4]; ++ u32 dp_lane_sel[4]; ++ u32 dp_aux_dout_sel; ++ u32 dp_aux_din_sel; ++ bool dp_sink_hpd_sel; ++ bool dp_sink_hpd_cfg; ++ u8 bw; ++ int id; ++ ++ /* PHY const config */ ++ const struct rockchip_udphy_cfg *cfgs; ++}; ++ ++static const struct dp_tx_drv_ctrl rk3588_dp_tx_drv_ctrl_rbr_hbr[4][4] = { ++ /* voltage swing 0, pre-emphasis 0->3 */ ++ { ++ { 0x20, 0x10, 0x42, 0xe5 }, ++ { 0x26, 0x14, 0x42, 0xe5 }, ++ { 0x29, 0x18, 0x42, 0xe5 }, ++ { 0x2b, 0x1c, 0x43, 0xe7 }, ++ }, ++ ++ /* voltage swing 1, pre-emphasis 0->2 */ ++ { ++ { 0x23, 0x10, 0x42, 0xe7 }, ++ { 0x2a, 0x17, 0x43, 0xe7 }, ++ { 0x2b, 0x1a, 0x43, 0xe7 }, ++ }, ++ ++ /* voltage swing 2, pre-emphasis 0->1 */ ++ { ++ { 0x27, 0x10, 0x42, 0xe7 }, ++ { 0x2b, 0x17, 0x43, 0xe7 }, ++ }, ++ ++ /* voltage swing 3, pre-emphasis 0 */ ++ { ++ { 0x29, 0x10, 0x43, 0xe7 }, ++ }, ++}; ++ ++static const struct dp_tx_drv_ctrl rk3588_dp_tx_drv_ctrl_rbr_hbr_typec[4][4] = { ++ /* voltage swing 0, pre-emphasis 0->3 */ ++ { ++ { 0x20, 0x10, 0x42, 0xe5 }, ++ { 0x26, 0x14, 0x42, 0xe5 }, ++ { 0x29, 0x18, 0x42, 0xe5 }, ++ { 0x2b, 0x1c, 0x43, 0xe7 }, ++ }, ++ ++ /* voltage swing 1, pre-emphasis 0->2 */ ++ { ++ { 0x23, 0x10, 0x42, 0xe7 }, ++ { 0x2a, 0x17, 0x43, 0xe7 }, ++ { 0x2b, 0x1a, 0x43, 0xe7 }, ++ }, ++ ++ /* voltage swing 2, pre-emphasis 0->1 */ ++ { ++ { 0x27, 0x10, 0x43, 0x67 }, ++ { 0x2b, 0x17, 0x43, 0xe7 }, ++ }, ++ ++ /* voltage swing 3, pre-emphasis 0 */ ++ { ++ { 0x29, 0x10, 0x43, 0xe7 }, ++ }, ++}; ++ ++static const struct dp_tx_drv_ctrl rk3588_dp_tx_drv_ctrl_hbr2[4][4] = { ++ /* voltage swing 0, pre-emphasis 0->3 */ ++ { ++ { 0x21, 0x10, 0x42, 0xe5 }, ++ { 0x26, 0x14, 0x42, 0xe5 }, ++ { 0x26, 0x16, 0x43, 0xe5 }, ++ { 0x2a, 0x19, 0x43, 0xe7 }, ++ }, ++ ++ /* voltage swing 1, pre-emphasis 0->2 */ ++ { ++ { 0x24, 0x10, 0x42, 0xe7 }, ++ { 0x2a, 0x17, 0x43, 0xe7 }, ++ { 0x2b, 0x1a, 0x43, 0xe7 }, ++ }, ++ ++ /* voltage swing 2, pre-emphasis 0->1 */ ++ { ++ { 0x28, 0x10, 0x42, 0xe7 }, ++ { 0x2b, 0x17, 0x43, 0xe7 }, ++ }, ++ ++ /* voltage swing 3, pre-emphasis 0 */ ++ { ++ { 0x28, 0x10, 0x43, 0xe7 }, ++ }, ++}; ++ ++static const struct dp_tx_drv_ctrl rk3588_dp_tx_drv_ctrl_hbr3[4][4] = { ++ /* voltage swing 0, pre-emphasis 0->3 */ ++ { ++ { 0x21, 0x10, 0x42, 0xe5 }, ++ { 0x26, 0x14, 0x42, 0xe5 }, ++ { 0x26, 0x16, 0x43, 0xe5 }, ++ { 0x29, 0x18, 0x43, 0xe7 }, ++ }, ++ ++ /* voltage swing 1, pre-emphasis 0->2 */ ++ { ++ { 0x24, 0x10, 0x42, 0xe7 }, ++ { 0x2a, 0x18, 0x43, 0xe7 }, ++ { 0x2b, 0x1b, 0x43, 0xe7 } ++ }, ++ ++ /* voltage swing 2, pre-emphasis 0->1 */ ++ { ++ { 0x27, 0x10, 0x42, 0xe7 }, ++ { 0x2b, 0x18, 0x43, 0xe7 } ++ }, ++ ++ /* voltage swing 3, pre-emphasis 0 */ ++ { ++ { 0x28, 0x10, 0x43, 0xe7 }, ++ }, ++}; ++ ++static const struct reg_sequence rk3588_udphy_24m_refclk_cfg[] = { ++ {0x0090, 0x68}, {0x0094, 0x68}, ++ {0x0128, 0x24}, {0x012c, 0x44}, ++ {0x0130, 0x3f}, {0x0134, 0x44}, ++ {0x015c, 0xa9}, {0x0160, 0x71}, ++ {0x0164, 0x71}, {0x0168, 0xa9}, ++ {0x0174, 0xa9}, {0x0178, 0x71}, ++ {0x017c, 0x71}, {0x0180, 0xa9}, ++ {0x018c, 0x41}, {0x0190, 0x00}, ++ {0x0194, 0x05}, {0x01ac, 0x2a}, ++ {0x01b0, 0x17}, {0x01b4, 0x17}, ++ {0x01b8, 0x2a}, {0x01c8, 0x04}, ++ {0x01cc, 0x08}, {0x01d0, 0x08}, ++ {0x01d4, 0x04}, {0x01d8, 0x20}, ++ {0x01dc, 0x01}, {0x01e0, 0x09}, ++ {0x01e4, 0x03}, {0x01f0, 0x29}, ++ {0x01f4, 0x02}, {0x01f8, 0x02}, ++ {0x01fc, 0x29}, {0x0208, 0x2a}, ++ {0x020c, 0x17}, {0x0210, 0x17}, ++ {0x0214, 0x2a}, {0x0224, 0x20}, ++ {0x03f0, 0x0a}, {0x03f4, 0x07}, ++ {0x03f8, 0x07}, {0x03fc, 0x0c}, ++ {0x0404, 0x12}, {0x0408, 0x1a}, ++ {0x040c, 0x1a}, {0x0410, 0x3f}, ++ {0x0ce0, 0x68}, {0x0ce8, 0xd0}, ++ {0x0cf0, 0x87}, {0x0cf8, 0x70}, ++ {0x0d00, 0x70}, {0x0d08, 0xa9}, ++ {0x1ce0, 0x68}, {0x1ce8, 0xd0}, ++ {0x1cf0, 0x87}, {0x1cf8, 0x70}, ++ {0x1d00, 0x70}, {0x1d08, 0xa9}, ++ {0x0a3c, 0xd0}, {0x0a44, 0xd0}, ++ {0x0a48, 0x01}, {0x0a4c, 0x0d}, ++ {0x0a54, 0xe0}, {0x0a5c, 0xe0}, ++ {0x0a64, 0xa8}, {0x1a3c, 0xd0}, ++ {0x1a44, 0xd0}, {0x1a48, 0x01}, ++ {0x1a4c, 0x0d}, {0x1a54, 0xe0}, ++ {0x1a5c, 0xe0}, {0x1a64, 0xa8} ++}; ++ ++static const struct reg_sequence rk3588_udphy_26m_refclk_cfg[] = { ++ {0x0830, 0x07}, {0x085c, 0x80}, ++ {0x1030, 0x07}, {0x105c, 0x80}, ++ {0x1830, 0x07}, {0x185c, 0x80}, ++ {0x2030, 0x07}, {0x205c, 0x80}, ++ {0x0228, 0x38}, {0x0104, 0x44}, ++ {0x0248, 0x44}, {0x038C, 0x02}, ++ {0x0878, 0x04}, {0x1878, 0x04}, ++ {0x0898, 0x77}, {0x1898, 0x77}, ++ {0x0054, 0x01}, {0x00e0, 0x38}, ++ {0x0060, 0x24}, {0x0064, 0x77}, ++ {0x0070, 0x76}, {0x0234, 0xE8}, ++ {0x0AF4, 0x15}, {0x1AF4, 0x15}, ++ {0x081C, 0xE5}, {0x181C, 0xE5}, ++ {0x099C, 0x48}, {0x199C, 0x48}, ++ {0x09A4, 0x07}, {0x09A8, 0x22}, ++ {0x19A4, 0x07}, {0x19A8, 0x22}, ++ {0x09B8, 0x3E}, {0x19B8, 0x3E}, ++ {0x09E4, 0x02}, {0x19E4, 0x02}, ++ {0x0A34, 0x1E}, {0x1A34, 0x1E}, ++ {0x0A98, 0x2F}, {0x1A98, 0x2F}, ++ {0x0c30, 0x0E}, {0x0C48, 0x06}, ++ {0x1C30, 0x0E}, {0x1C48, 0x06}, ++ {0x028C, 0x18}, {0x0AF0, 0x00}, ++ {0x1AF0, 0x00} ++}; ++ ++static const struct reg_sequence rk3588_udphy_init_sequence[] = { ++ {0x0104, 0x44}, {0x0234, 0xE8}, ++ {0x0248, 0x44}, {0x028C, 0x18}, ++ {0x081C, 0xE5}, {0x0878, 0x00}, ++ {0x0994, 0x1C}, {0x0AF0, 0x00}, ++ {0x181C, 0xE5}, {0x1878, 0x00}, ++ {0x1994, 0x1C}, {0x1AF0, 0x00}, ++ {0x0428, 0x60}, {0x0D58, 0x33}, ++ {0x1D58, 0x33}, {0x0990, 0x74}, ++ {0x0D64, 0x17}, {0x08C8, 0x13}, ++ {0x1990, 0x74}, {0x1D64, 0x17}, ++ {0x18C8, 0x13}, {0x0D90, 0x40}, ++ {0x0DA8, 0x40}, {0x0DC0, 0x40}, ++ {0x0DD8, 0x40}, {0x1D90, 0x40}, ++ {0x1DA8, 0x40}, {0x1DC0, 0x40}, ++ {0x1DD8, 0x40}, {0x03C0, 0x30}, ++ {0x03C4, 0x06}, {0x0E10, 0x00}, ++ {0x1E10, 0x00}, {0x043C, 0x0F}, ++ {0x0D2C, 0xFF}, {0x1D2C, 0xFF}, ++ {0x0D34, 0x0F}, {0x1D34, 0x0F}, ++ {0x08FC, 0x2A}, {0x0914, 0x28}, ++ {0x0A30, 0x03}, {0x0E38, 0x05}, ++ {0x0ECC, 0x27}, {0x0ED0, 0x22}, ++ {0x0ED4, 0x26}, {0x18FC, 0x2A}, ++ {0x1914, 0x28}, {0x1A30, 0x03}, ++ {0x1E38, 0x05}, {0x1ECC, 0x27}, ++ {0x1ED0, 0x22}, {0x1ED4, 0x26}, ++ {0x0048, 0x0F}, {0x0060, 0x3C}, ++ {0x0064, 0xF7}, {0x006C, 0x20}, ++ {0x0070, 0x7D}, {0x0074, 0x68}, ++ {0x0AF4, 0x1A}, {0x1AF4, 0x1A}, ++ {0x0440, 0x3F}, {0x10D4, 0x08}, ++ {0x20D4, 0x08}, {0x00D4, 0x30}, ++ {0x0024, 0x6e}, ++}; ++ ++static inline int grfreg_write(struct regmap *base, ++ const struct udphy_grf_reg *reg, bool en) ++{ ++ u32 val, mask, tmp; ++ ++ tmp = en ? reg->enable : reg->disable; ++ mask = GENMASK(reg->bitend, reg->bitstart); ++ val = (tmp << reg->bitstart) | (mask << BIT_WRITEABLE_SHIFT); ++ ++ return regmap_write(base, reg->offset, val); ++} ++ ++static int udphy_clk_init(struct rockchip_udphy *udphy, struct device *dev) ++{ ++ int i; ++ ++ udphy->num_clks = devm_clk_bulk_get_all(dev, &udphy->clks); ++ if (udphy->num_clks < 1) ++ return -ENODEV; ++ ++ /* used for configure phy reference clock frequency */ ++ for (i = 0; i < udphy->num_clks; i++) { ++ if (!strncmp(udphy->clks[i].id, "refclk", 6)) { ++ udphy->refclk = udphy->clks[i].clk; ++ break; ++ } ++ } ++ ++ if (!udphy->refclk) ++ dev_warn(udphy->dev, "no refclk found\n"); ++ ++ return 0; ++} ++ ++static int udphy_reset_init(struct rockchip_udphy *udphy, struct device *dev) ++{ ++ const struct rockchip_udphy_cfg *cfg = udphy->cfgs; ++ int idx; ++ ++ udphy->rsts = devm_kcalloc(dev, cfg->num_rsts, ++ sizeof(*udphy->rsts), GFP_KERNEL); ++ if (!udphy->rsts) ++ return -ENOMEM; ++ ++ for (idx = 0; idx < cfg->num_rsts; idx++) { ++ struct reset_control *rst; ++ const char *name = cfg->rst_list[idx]; ++ ++ rst = devm_reset_control_get(dev, name); ++ if (IS_ERR(rst)) { ++ dev_err(dev, "failed to get %s reset\n", name); ++ devm_kfree(dev, (void *)udphy->rsts); ++ return PTR_ERR(rst); ++ } ++ ++ udphy->rsts[idx] = rst; ++ } ++ ++ return 0; ++} ++ ++static int udphy_get_rst_idx(const char * const *list, int num, char *name) ++{ ++ int idx; ++ ++ for (idx = 0; idx < num; idx++) { ++ if (!strcmp(list[idx], name)) ++ return idx; ++ } ++ ++ return -EINVAL; ++} ++ ++static int udphy_reset_assert(struct rockchip_udphy *udphy, char *name) ++{ ++ const struct rockchip_udphy_cfg *cfg = udphy->cfgs; ++ int idx; ++ ++ idx = udphy_get_rst_idx(cfg->rst_list, cfg->num_rsts, name); ++ if (idx < 0) ++ return idx; ++ ++ return reset_control_assert(udphy->rsts[idx]); ++} ++ ++static int udphy_reset_deassert(struct rockchip_udphy *udphy, char *name) ++{ ++ const struct rockchip_udphy_cfg *cfg = udphy->cfgs; ++ int idx; ++ ++ idx = udphy_get_rst_idx(cfg->rst_list, cfg->num_rsts, name); ++ if (idx < 0) ++ return idx; ++ ++ return reset_control_deassert(udphy->rsts[idx]); ++} ++ ++static void udphy_u3_port_disable(struct rockchip_udphy *udphy, u8 disable) ++{ ++ const struct rockchip_udphy_cfg *cfg = udphy->cfgs; ++ const struct udphy_grf_reg *preg; ++ ++ preg = udphy->id ? &cfg->grfcfg.usb3otg1_cfg : &cfg->grfcfg.usb3otg0_cfg; ++ grfreg_write(udphy->usbgrf, preg, disable); ++} ++ ++static void udphy_usb_bvalid_enable(struct rockchip_udphy *udphy, u8 enable) ++{ ++ const struct rockchip_udphy_cfg *cfg = udphy->cfgs; ++ ++ grfreg_write(udphy->u2phygrf, &cfg->grfcfg.bvalid_phy_con, enable); ++ grfreg_write(udphy->u2phygrf, &cfg->grfcfg.bvalid_grf_con, enable); ++} ++ ++/* ++ * In usb/dp combo phy driver, here are 2 ways to mapping lanes. ++ * ++ * 1 Type-C Mapping table (DP_Alt_Mode V1.0b remove ABF pin mapping) ++ * --------------------------------------------------------------------------- ++ * Type-C Pin B11-B10 A2-A3 A11-A10 B2-B3 ++ * PHY Pad ln0(tx/rx) ln1(tx) ln2(tx/rx) ln3(tx) ++ * C/E(Normal) dpln3 dpln2 dpln0 dpln1 ++ * C/E(Flip ) dpln0 dpln1 dpln3 dpln2 ++ * D/F(Normal) usbrx usbtx dpln0 dpln1 ++ * D/F(Flip ) dpln0 dpln1 usbrx usbtx ++ * A(Normal ) dpln3 dpln1 dpln2 dpln0 ++ * A(Flip ) dpln2 dpln0 dpln3 dpln1 ++ * B(Normal ) usbrx usbtx dpln1 dpln0 ++ * B(Flip ) dpln1 dpln0 usbrx usbtx ++ * --------------------------------------------------------------------------- ++ * ++ * 2 Mapping the lanes in dtsi ++ * if all 4 lane assignment for dp function, define rockchip,dp-lane-mux = ; ++ * sample as follow: ++ * --------------------------------------------------------------------------- ++ * B11-B10 A2-A3 A11-A10 B2-B3 ++ * rockchip,dp-lane-mux ln0(tx/rx) ln1(tx) ln2(tx/rx) ln3(tx) ++ * <0 1 2 3> dpln0 dpln1 dpln2 dpln3 ++ * <2 3 0 1> dpln2 dpln3 dpln0 dpln1 ++ * --------------------------------------------------------------------------- ++ * if 2 lane for dp function, 2 lane for usb function, define rockchip,dp-lane-mux = ; ++ * sample as follow: ++ * --------------------------------------------------------------------------- ++ * B11-B10 A2-A3 A11-A10 B2-B3 ++ * rockchip,dp-lane-mux ln0(tx/rx) ln1(tx) ln2(tx/rx) ln3(tx) ++ * <0 1> dpln0 dpln1 usbrx usbtx ++ * <2 3> usbrx usbtx dpln0 dpln1 ++ * --------------------------------------------------------------------------- ++ */ ++ ++static int udphy_dplane_select(struct rockchip_udphy *udphy) ++{ ++ const struct rockchip_udphy_cfg *cfg = udphy->cfgs; ++ ++ if (cfg->dplane_select) ++ return cfg->dplane_select(udphy); ++ ++ return 0; ++} ++ ++static int udphy_dplane_get(struct rockchip_udphy *udphy) ++{ ++ int dp_lanes; ++ ++ switch (udphy->mode) { ++ case UDPHY_MODE_DP: ++ dp_lanes = 4; ++ break; ++ case UDPHY_MODE_DP_USB: ++ dp_lanes = 2; ++ break; ++ case UDPHY_MODE_USB: ++ fallthrough; ++ default: ++ dp_lanes = 0; ++ break; ++ } ++ ++ return dp_lanes; ++} ++ ++static int udphy_dplane_enable(struct rockchip_udphy *udphy, int dp_lanes) ++{ ++ const struct rockchip_udphy_cfg *cfg = udphy->cfgs; ++ int ret = 0; ++ ++ if (cfg->dplane_enable) ++ ret = cfg->dplane_enable(udphy, dp_lanes); ++ ++ return ret; ++} ++ ++static int upphy_set_typec_default_mapping(struct rockchip_udphy *udphy) ++{ ++ if (udphy->flip) { ++ udphy->dp_lane_sel[0] = 0; ++ udphy->dp_lane_sel[1] = 1; ++ udphy->dp_lane_sel[2] = 3; ++ udphy->dp_lane_sel[3] = 2; ++ udphy->lane_mux_sel[0] = PHY_LANE_MUX_DP; ++ udphy->lane_mux_sel[1] = PHY_LANE_MUX_DP; ++ udphy->lane_mux_sel[2] = PHY_LANE_MUX_USB; ++ udphy->lane_mux_sel[3] = PHY_LANE_MUX_USB; ++ udphy->dp_aux_dout_sel = PHY_AUX_DP_DATA_POL_INVERT; ++ udphy->dp_aux_din_sel = PHY_AUX_DP_DATA_POL_INVERT; ++ gpiod_set_value_cansleep(udphy->sbu1_dc_gpio, 1); ++ gpiod_set_value_cansleep(udphy->sbu2_dc_gpio, 0); ++ } else { ++ udphy->dp_lane_sel[0] = 2; ++ udphy->dp_lane_sel[1] = 3; ++ udphy->dp_lane_sel[2] = 1; ++ udphy->dp_lane_sel[3] = 0; ++ udphy->lane_mux_sel[0] = PHY_LANE_MUX_USB; ++ udphy->lane_mux_sel[1] = PHY_LANE_MUX_USB; ++ udphy->lane_mux_sel[2] = PHY_LANE_MUX_DP; ++ udphy->lane_mux_sel[3] = PHY_LANE_MUX_DP; ++ udphy->dp_aux_dout_sel = PHY_AUX_DP_DATA_POL_NORMAL; ++ udphy->dp_aux_din_sel = PHY_AUX_DP_DATA_POL_NORMAL; ++ gpiod_set_value_cansleep(udphy->sbu1_dc_gpio, 0); ++ gpiod_set_value_cansleep(udphy->sbu2_dc_gpio, 1); ++ } ++ ++ udphy->mode = UDPHY_MODE_DP_USB; ++ ++ return 0; ++} ++ ++static int udphy_orien_sw_set(struct typec_switch_dev *sw, ++ enum typec_orientation orien) ++{ ++ struct rockchip_udphy *udphy = typec_switch_get_drvdata(sw); ++ ++ mutex_lock(&udphy->mutex); ++ ++ if (orien == TYPEC_ORIENTATION_NONE) { ++ gpiod_set_value_cansleep(udphy->sbu1_dc_gpio, 0); ++ gpiod_set_value_cansleep(udphy->sbu2_dc_gpio, 0); ++ /* unattached */ ++ udphy_usb_bvalid_enable(udphy, false); ++ goto unlock_ret; ++ } ++ ++ udphy->flip = (orien == TYPEC_ORIENTATION_REVERSE) ? true : false; ++ upphy_set_typec_default_mapping(udphy); ++ udphy_usb_bvalid_enable(udphy, true); ++ ++unlock_ret: ++ mutex_unlock(&udphy->mutex); ++ return 0; ++} ++ ++static int udphy_setup_orien_switch(struct rockchip_udphy *udphy) ++{ ++ struct typec_switch_desc sw_desc = { }; ++ ++ sw_desc.drvdata = udphy; ++ sw_desc.fwnode = dev_fwnode(udphy->dev); ++ sw_desc.set = udphy_orien_sw_set; ++ ++ udphy->sw = typec_switch_register(udphy->dev, &sw_desc); ++ if (IS_ERR(udphy->sw)) { ++ dev_err(udphy->dev, "Error register typec orientation switch: %ld\n", ++ PTR_ERR(udphy->sw)); ++ return PTR_ERR(udphy->sw); ++ } ++ ++ return 0; ++} ++ ++static void udphy_orien_switch_unregister(void *data) ++{ ++ struct rockchip_udphy *udphy = data; ++ ++ typec_switch_unregister(udphy->sw); ++} ++ ++static int udphy_setup(struct rockchip_udphy *udphy) ++{ ++ const struct rockchip_udphy_cfg *cfg = udphy->cfgs; ++ int ret = 0; ++ ++ ret = clk_bulk_prepare_enable(udphy->num_clks, udphy->clks); ++ if (ret) { ++ dev_err(udphy->dev, "failed to enable clk\n"); ++ return ret; ++ } ++ ++ if (cfg->combophy_init) { ++ ret = cfg->combophy_init(udphy); ++ if (ret) { ++ dev_err(udphy->dev, "failed to init combophy\n"); ++ clk_bulk_disable_unprepare(udphy->num_clks, udphy->clks); ++ return ret; ++ } ++ } ++ ++ return 0; ++} ++ ++static int udphy_disable(struct rockchip_udphy *udphy) ++{ ++ const struct rockchip_udphy_cfg *cfg = udphy->cfgs; ++ int i; ++ ++ clk_bulk_disable_unprepare(udphy->num_clks, udphy->clks); ++ ++ for (i = 0; i < cfg->num_rsts; i++) ++ reset_control_assert(udphy->rsts[i]); ++ ++ return 0; ++} ++ ++static int udphy_parse_lane_mux_data(struct rockchip_udphy *udphy, struct device_node *np) ++{ ++ struct property *prop; ++ int ret, i, len, num_lanes; ++ ++ prop = of_find_property(np, "rockchip,dp-lane-mux", &len); ++ if (!prop) { ++ dev_dbg(udphy->dev, "failed to find dp lane mux, following dp alt mode\n"); ++ udphy->mode = UDPHY_MODE_USB; ++ return 0; ++ } ++ ++ num_lanes = len / sizeof(u32); ++ ++ if (num_lanes != 2 && num_lanes != 4) { ++ dev_err(udphy->dev, "invalid number of lane mux\n"); ++ return -EINVAL; ++ } ++ ++ ret = of_property_read_u32_array(np, "rockchip,dp-lane-mux", udphy->dp_lane_sel, num_lanes); ++ if (ret) { ++ dev_err(udphy->dev, "get dp lane mux failed\n"); ++ return -EINVAL; ++ } ++ ++ for (i = 0; i < num_lanes; i++) { ++ int j; ++ ++ if (udphy->dp_lane_sel[i] > 3) { ++ dev_err(udphy->dev, "lane mux between 0 and 3, exceeding the range\n"); ++ return -EINVAL; ++ } ++ ++ udphy->lane_mux_sel[udphy->dp_lane_sel[i]] = PHY_LANE_MUX_DP; ++ ++ for (j = i + 1; j < num_lanes; j++) { ++ if (udphy->dp_lane_sel[i] == udphy->dp_lane_sel[j]) { ++ dev_err(udphy->dev, "set repeat lane mux value\n"); ++ return -EINVAL; ++ } ++ } ++ } ++ ++ udphy->mode = UDPHY_MODE_DP; ++ if (num_lanes == 2) ++ udphy->mode |= UDPHY_MODE_USB; ++ ++ return 0; ++} ++ ++static int udphy_get_initial_status(struct rockchip_udphy *udphy) ++{ ++ const struct rockchip_udphy_cfg *cfg = udphy->cfgs; ++ int ret, i; ++ u32 value; ++ ++ ret = clk_bulk_prepare_enable(udphy->num_clks, udphy->clks); ++ if (ret) { ++ dev_err(udphy->dev, "failed to enable clk\n"); ++ return ret; ++ } ++ ++ for (i = 0; i < cfg->num_rsts; i++) ++ reset_control_deassert(udphy->rsts[i]); ++ ++ regmap_read(udphy->pma_regmap, CMN_LANE_MUX_AND_EN_OFFSET, &value); ++ if (FIELD_GET(CMN_DP_LANE_MUX_ALL, value) && FIELD_GET(CMN_DP_LANE_EN_ALL, value)) ++ udphy->status = UDPHY_MODE_DP; ++ else ++ udphy_disable(udphy); ++ ++ return 0; ++} ++ ++static int udphy_parse_dt(struct rockchip_udphy *udphy, struct device *dev) ++{ ++ struct device_node *np = dev->of_node; ++ enum usb_device_speed maximum_speed; ++ int ret; ++ ++ udphy->u2phygrf = syscon_regmap_lookup_by_phandle(np, "rockchip,u2phy-grf"); ++ if (IS_ERR(udphy->u2phygrf)) { ++ if (PTR_ERR(udphy->u2phygrf) == -ENODEV) { ++ dev_warn(dev, "missing u2phy-grf dt node\n"); ++ udphy->u2phygrf = NULL; ++ } else { ++ return PTR_ERR(udphy->u2phygrf); ++ } ++ } ++ ++ udphy->udphygrf = syscon_regmap_lookup_by_phandle(np, "rockchip,usbdpphy-grf"); ++ if (IS_ERR(udphy->udphygrf)) { ++ if (PTR_ERR(udphy->udphygrf) == -ENODEV) { ++ dev_warn(dev, "missing usbdpphy-grf dt node\n"); ++ udphy->udphygrf = NULL; ++ } else { ++ return PTR_ERR(udphy->udphygrf); ++ } ++ } ++ ++ udphy->usbgrf = syscon_regmap_lookup_by_phandle(np, "rockchip,usb-grf"); ++ if (IS_ERR(udphy->usbgrf)) { ++ if (PTR_ERR(udphy->usbgrf) == -ENODEV) { ++ dev_warn(dev, "missing usb-grf dt node\n"); ++ udphy->usbgrf = NULL; ++ } else { ++ return PTR_ERR(udphy->usbgrf); ++ } ++ } ++ ++ udphy->vogrf = syscon_regmap_lookup_by_phandle(np, "rockchip,vo-grf"); ++ if (IS_ERR(udphy->vogrf)) { ++ if (PTR_ERR(udphy->vogrf) == -ENODEV) { ++ dev_warn(dev, "missing vo-grf dt node\n"); ++ udphy->vogrf = NULL; ++ } else { ++ return PTR_ERR(udphy->vogrf); ++ } ++ } ++ ++ ret = udphy_parse_lane_mux_data(udphy, np); ++ if (ret) ++ return ret; ++ ++ udphy->sbu1_dc_gpio = devm_gpiod_get_optional(dev, "sbu1-dc", GPIOD_OUT_LOW); ++ if (IS_ERR(udphy->sbu1_dc_gpio)) ++ return PTR_ERR(udphy->sbu1_dc_gpio); ++ ++ udphy->sbu2_dc_gpio = devm_gpiod_get_optional(dev, "sbu2-dc", GPIOD_OUT_LOW); ++ if (IS_ERR(udphy->sbu2_dc_gpio)) ++ return PTR_ERR(udphy->sbu2_dc_gpio); ++ ++ if (device_property_present(dev, "maximum-speed")) { ++ maximum_speed = usb_get_maximum_speed(dev); ++ udphy->hs = maximum_speed <= USB_SPEED_HIGH ? true : false; ++ } ++ ++ ret = udphy_clk_init(udphy, dev); ++ if (ret) ++ return ret; ++ ++ ret = udphy_reset_init(udphy, dev); ++ if (ret) ++ return ret; ++ ++ return 0; ++} ++ ++static int udphy_power_on(struct rockchip_udphy *udphy, u8 mode) ++{ ++ int ret; ++ ++ if (!(udphy->mode & mode)) { ++ dev_info(udphy->dev, "mode 0x%02x is not support\n", mode); ++ return 0; ++ } ++ ++ if (udphy->status == UDPHY_MODE_NONE) { ++ udphy->mode_change = false; ++ ret = udphy_setup(udphy); ++ if (ret) ++ return ret; ++ ++ if (udphy->mode & UDPHY_MODE_USB) ++ udphy_u3_port_disable(udphy, false); ++ } else if (udphy->mode_change) { ++ udphy->mode_change = false; ++ udphy->status = UDPHY_MODE_NONE; ++ if (udphy->mode == UDPHY_MODE_DP) ++ udphy_u3_port_disable(udphy, true); ++ ++ ret = udphy_disable(udphy); ++ if (ret) ++ return ret; ++ ret = udphy_setup(udphy); ++ if (ret) ++ return ret; ++ } ++ ++ udphy->status |= mode; ++ ++ return 0; ++} ++ ++static int udphy_power_off(struct rockchip_udphy *udphy, u8 mode) ++{ ++ int ret; ++ ++ if (!(udphy->mode & mode)) { ++ dev_info(udphy->dev, "mode 0x%02x is not support\n", mode); ++ return 0; ++ } ++ ++ if (!udphy->status) ++ return 0; ++ ++ udphy->status &= ~mode; ++ ++ if (udphy->status == UDPHY_MODE_NONE) { ++ ret = udphy_disable(udphy); ++ if (ret) ++ return ret; ++ } ++ ++ return 0; ++} ++ ++static int rockchip_dp_phy_power_on(struct phy *phy) ++{ ++ struct rockchip_udphy *udphy = phy_get_drvdata(phy); ++ int ret, dp_lanes; ++ ++ mutex_lock(&udphy->mutex); ++ ++ dp_lanes = udphy_dplane_get(udphy); ++ phy_set_bus_width(phy, dp_lanes); ++ ++ ret = udphy_power_on(udphy, UDPHY_MODE_DP); ++ if (ret) ++ goto unlock; ++ ++ ret = udphy_dplane_enable(udphy, dp_lanes); ++ if (ret) ++ goto unlock; ++ ++ ret = udphy_dplane_select(udphy); ++ ++unlock: ++ mutex_unlock(&udphy->mutex); ++ /* ++ * If data send by aux channel too fast after phy power on, ++ * the aux may be not ready which will cause aux error. Adding ++ * delay to avoid this issue. ++ */ ++ usleep_range(10000, 11000); ++ return ret; ++} ++ ++static int rockchip_dp_phy_power_off(struct phy *phy) ++{ ++ struct rockchip_udphy *udphy = phy_get_drvdata(phy); ++ int ret; ++ ++ mutex_lock(&udphy->mutex); ++ ret = udphy_dplane_enable(udphy, 0); ++ if (ret) ++ goto unlock; ++ ++ ret = udphy_power_off(udphy, UDPHY_MODE_DP); ++ ++unlock: ++ mutex_unlock(&udphy->mutex); ++ return ret; ++} ++ ++static int rockchip_dp_phy_verify_link_rate(unsigned int link_rate) ++{ ++ switch (link_rate) { ++ case 1620: ++ case 2700: ++ case 5400: ++ case 8100: ++ break; ++ default: ++ return -EINVAL; ++ } ++ ++ return 0; ++} ++ ++static int rockchip_dp_phy_verify_config(struct rockchip_udphy *udphy, ++ struct phy_configure_opts_dp *dp) ++{ ++ int i, ret; ++ ++ /* If changing link rate was required, verify it's supported. */ ++ ret = rockchip_dp_phy_verify_link_rate(dp->link_rate); ++ if (ret) ++ return ret; ++ ++ /* Verify lane count. */ ++ switch (dp->lanes) { ++ case 1: ++ case 2: ++ case 4: ++ /* valid lane count. */ ++ break; ++ default: ++ return -EINVAL; ++ } ++ ++ /* ++ * If changing voltages is required, check swing and pre-emphasis ++ * levels, per-lane. ++ */ ++ if (dp->set_voltages) { ++ /* Lane count verified previously. */ ++ for (i = 0; i < dp->lanes; i++) { ++ if (dp->voltage[i] > 3 || dp->pre[i] > 3) ++ return -EINVAL; ++ ++ /* ++ * Sum of voltage swing and pre-emphasis levels cannot ++ * exceed 3. ++ */ ++ if (dp->voltage[i] + dp->pre[i] > 3) ++ return -EINVAL; ++ } ++ } ++ ++ return 0; ++} ++ ++static int rockchip_dp_phy_configure(struct phy *phy, ++ union phy_configure_opts *opts) ++{ ++ struct rockchip_udphy *udphy = phy_get_drvdata(phy); ++ const struct rockchip_udphy_cfg *cfg = udphy->cfgs; ++ int ret; ++ ++ ret = rockchip_dp_phy_verify_config(udphy, &opts->dp); ++ if (ret) ++ return ret; ++ ++ if (opts->dp.set_rate && cfg->dp_phy_set_rate) { ++ ret = cfg->dp_phy_set_rate(udphy, &opts->dp); ++ if (ret) { ++ dev_err(udphy->dev, ++ "rockchip_hdptx_phy_set_rate failed\n"); ++ return ret; ++ } ++ } ++ ++ if (opts->dp.set_voltages && cfg->dp_phy_set_voltages) { ++ ret = cfg->dp_phy_set_voltages(udphy, &opts->dp); ++ if (ret) { ++ dev_err(udphy->dev, ++ "rockchip_dp_phy_set_voltages failed\n"); ++ return ret; ++ } ++ } ++ ++ return 0; ++} ++ ++static const struct phy_ops rockchip_dp_phy_ops = { ++ .power_on = rockchip_dp_phy_power_on, ++ .power_off = rockchip_dp_phy_power_off, ++ .configure = rockchip_dp_phy_configure, ++ .owner = THIS_MODULE, ++}; ++ ++static int rockchip_u3phy_init(struct phy *phy) ++{ ++ struct rockchip_udphy *udphy = phy_get_drvdata(phy); ++ int ret = 0; ++ ++ mutex_lock(&udphy->mutex); ++ /* DP only or high-speed, disable U3 port */ ++ if (!(udphy->mode & UDPHY_MODE_USB) || udphy->hs) { ++ udphy_u3_port_disable(udphy, true); ++ goto unlock; ++ } ++ ++ ret = udphy_power_on(udphy, UDPHY_MODE_USB); ++ ++unlock: ++ mutex_unlock(&udphy->mutex); ++ return ret; ++} ++ ++static int rockchip_u3phy_exit(struct phy *phy) ++{ ++ struct rockchip_udphy *udphy = phy_get_drvdata(phy); ++ int ret = 0; ++ ++ mutex_lock(&udphy->mutex); ++ /* DP only or high-speed */ ++ if (!(udphy->mode & UDPHY_MODE_USB) || udphy->hs) ++ goto unlock; ++ ++ ret = udphy_power_off(udphy, UDPHY_MODE_USB); ++ ++unlock: ++ mutex_unlock(&udphy->mutex); ++ return ret; ++} ++ ++static const struct phy_ops rockchip_u3phy_ops = { ++ .init = rockchip_u3phy_init, ++ .exit = rockchip_u3phy_exit, ++ .owner = THIS_MODULE, ++}; ++ ++static int usbdp_typec_mux_set(struct typec_mux_dev *mux, ++ struct typec_mux_state *state) ++{ ++ struct rockchip_udphy *udphy = typec_mux_get_drvdata(mux); ++ const struct rockchip_udphy_cfg *cfg = udphy->cfgs; ++ u8 mode; ++ ++ mutex_lock(&udphy->mutex); ++ ++ switch (state->mode) { ++ case TYPEC_DP_STATE_C: ++ fallthrough; ++ case TYPEC_DP_STATE_E: ++ udphy->lane_mux_sel[0] = PHY_LANE_MUX_DP; ++ udphy->lane_mux_sel[1] = PHY_LANE_MUX_DP; ++ udphy->lane_mux_sel[2] = PHY_LANE_MUX_DP; ++ udphy->lane_mux_sel[3] = PHY_LANE_MUX_DP; ++ mode = UDPHY_MODE_DP; ++ break; ++ case TYPEC_DP_STATE_D: ++ fallthrough; ++ default: ++ if (udphy->flip) { ++ udphy->lane_mux_sel[0] = PHY_LANE_MUX_DP; ++ udphy->lane_mux_sel[1] = PHY_LANE_MUX_DP; ++ udphy->lane_mux_sel[2] = PHY_LANE_MUX_USB; ++ udphy->lane_mux_sel[3] = PHY_LANE_MUX_USB; ++ } else { ++ udphy->lane_mux_sel[0] = PHY_LANE_MUX_USB; ++ udphy->lane_mux_sel[1] = PHY_LANE_MUX_USB; ++ udphy->lane_mux_sel[2] = PHY_LANE_MUX_DP; ++ udphy->lane_mux_sel[3] = PHY_LANE_MUX_DP; ++ } ++ mode = UDPHY_MODE_DP_USB; ++ break; ++ } ++ ++ if (state->alt && state->alt->svid == USB_TYPEC_DP_SID) { ++ struct typec_displayport_data *data = state->data; ++ ++ if (!data) { ++ if (cfg->hpd_event_trigger) ++ cfg->hpd_event_trigger(udphy, false); ++ } else if (data->status & DP_STATUS_IRQ_HPD) { ++ if (cfg->hpd_event_trigger) { ++ cfg->hpd_event_trigger(udphy, false); ++ usleep_range(750, 800); ++ cfg->hpd_event_trigger(udphy, true); ++ } ++ } else if (data->status & DP_STATUS_HPD_STATE) { ++ if (udphy->mode != mode) { ++ udphy->mode = mode; ++ udphy->mode_change = true; ++ } ++ if (cfg->hpd_event_trigger) ++ cfg->hpd_event_trigger(udphy, true); ++ } else { ++ if (cfg->hpd_event_trigger) ++ cfg->hpd_event_trigger(udphy, false); ++ } ++ } ++ ++ mutex_unlock(&udphy->mutex); ++ return 0; ++} ++ ++static int udphy_setup_typec_mux(struct rockchip_udphy *udphy) ++{ ++ struct typec_mux_desc mux_desc = {}; ++ ++ mux_desc.drvdata = udphy; ++ mux_desc.fwnode = dev_fwnode(udphy->dev); ++ mux_desc.set = usbdp_typec_mux_set; ++ ++ udphy->mux = typec_mux_register(udphy->dev, &mux_desc); ++ if (IS_ERR(udphy->mux)) { ++ dev_err(udphy->dev, "Error register typec mux: %ld\n", ++ PTR_ERR(udphy->mux)); ++ return PTR_ERR(udphy->mux); ++ } ++ ++ return 0; ++} ++ ++static void udphy_typec_mux_unregister(void *data) ++{ ++ struct rockchip_udphy *udphy = data; ++ ++ typec_mux_unregister(udphy->mux); ++} ++ ++static u32 udphy_dp_get_max_link_rate(struct rockchip_udphy *udphy, struct device_node *np) ++{ ++ u32 max_link_rate; ++ int ret; ++ ++ ret = of_property_read_u32(np, "max-link-rate", &max_link_rate); ++ if (ret) ++ return 8100; ++ ++ ret = rockchip_dp_phy_verify_link_rate(max_link_rate); ++ if (ret) { ++ dev_warn(udphy->dev, "invalid max-link-rate value:%d\n", max_link_rate); ++ max_link_rate = 8100; ++ } ++ ++ return max_link_rate; ++} ++ ++static const struct regmap_config rockchip_udphy_pma_regmap_cfg = { ++ .reg_bits = 32, ++ .reg_stride = 4, ++ .val_bits = 32, ++ .fast_io = true, ++ .max_register = 0x20dc, ++}; ++ ++static int rockchip_udphy_probe(struct platform_device *pdev) ++{ ++ struct device *dev = &pdev->dev; ++ struct device_node *np = dev->of_node; ++ struct device_node *child_np; ++ struct phy_provider *phy_provider; ++ struct resource *res; ++ struct rockchip_udphy *udphy; ++ const struct rockchip_udphy_cfg *phy_cfgs; ++ void __iomem *base; ++ int id, ret; ++ ++ udphy = devm_kzalloc(dev, sizeof(*udphy), GFP_KERNEL); ++ if (!udphy) ++ return -ENOMEM; ++ ++ id = of_alias_get_id(dev->of_node, "usbdp"); ++ if (id < 0) ++ id = 0; ++ udphy->id = id; ++ ++ phy_cfgs = of_device_get_match_data(dev); ++ if (!phy_cfgs) { ++ dev_err(dev, "no OF data can be matched with %p node\n", np); ++ return -EINVAL; ++ } ++ ++ udphy->cfgs = phy_cfgs; ++ ++ base = devm_platform_get_and_ioremap_resource(pdev, 0, &res); ++ if (IS_ERR(base)) ++ return PTR_ERR(base); ++ ++ udphy->pma_regmap = devm_regmap_init_mmio(dev, base + UDPHY_PMA, ++ &rockchip_udphy_pma_regmap_cfg); ++ if (IS_ERR(udphy->pma_regmap)) ++ return PTR_ERR(udphy->pma_regmap); ++ ++ ret = udphy_parse_dt(udphy, dev); ++ if (ret) ++ return ret; ++ ++ ret = udphy_get_initial_status(udphy); ++ if (ret) ++ return ret; ++ ++ mutex_init(&udphy->mutex); ++ udphy->dev = dev; ++ platform_set_drvdata(pdev, udphy); ++ ++ if (device_property_present(dev, "orientation-switch")) { ++ ret = udphy_setup_orien_switch(udphy); ++ if (ret) ++ return ret; ++ ++ ret = devm_add_action_or_reset(dev, udphy_orien_switch_unregister, udphy); ++ if (ret) ++ return ret; ++ } ++ ++ if (device_property_present(dev, "svid")) { ++ ret = udphy_setup_typec_mux(udphy); ++ if (ret) ++ return ret; ++ ++ ret = devm_add_action_or_reset(dev, udphy_typec_mux_unregister, udphy); ++ if (ret) ++ return ret; ++ } ++ ++ for_each_available_child_of_node(np, child_np) { ++ struct phy *phy; ++ ++ if (of_node_name_eq(child_np, "dp-port")) { ++ phy = devm_phy_create(dev, child_np, &rockchip_dp_phy_ops); ++ if (IS_ERR(phy)) { ++ dev_err(dev, "failed to create dp phy: %pOFn\n", child_np); ++ goto put_child; ++ } ++ ++ phy_set_bus_width(phy, udphy_dplane_get(udphy)); ++ phy->attrs.max_link_rate = udphy_dp_get_max_link_rate(udphy, child_np); ++ } else if (of_node_name_eq(child_np, "usb3-port")) { ++ phy = devm_phy_create(dev, child_np, &rockchip_u3phy_ops); ++ if (IS_ERR(phy)) { ++ dev_err(dev, "failed to create usb phy: %pOFn\n", child_np); ++ goto put_child; ++ } ++ } else ++ continue; ++ ++ phy_set_drvdata(phy, udphy); ++ } ++ ++ phy_provider = devm_of_phy_provider_register(dev, of_phy_simple_xlate); ++ if (IS_ERR(phy_provider)) { ++ dev_err(dev, "failed to register phy provider\n"); ++ goto put_child; ++ } ++ ++ return 0; ++ ++put_child: ++ of_node_put(child_np); ++ return ret; ++} ++ ++static int rk3588_udphy_refclk_set(struct rockchip_udphy *udphy) ++{ ++ unsigned long rate; ++ int ret; ++ ++ /* configure phy reference clock */ ++ rate = clk_get_rate(udphy->refclk); ++ dev_dbg(udphy->dev, "refclk freq %ld\n", rate); ++ ++ switch (rate) { ++ case 24000000: ++ ret = regmap_multi_reg_write(udphy->pma_regmap, rk3588_udphy_24m_refclk_cfg, ++ ARRAY_SIZE(rk3588_udphy_24m_refclk_cfg)); ++ if (ret) ++ return ret; ++ break; ++ case 26000000: ++ /* register default is 26MHz */ ++ ret = regmap_multi_reg_write(udphy->pma_regmap, rk3588_udphy_26m_refclk_cfg, ++ ARRAY_SIZE(rk3588_udphy_26m_refclk_cfg)); ++ if (ret) ++ return ret; ++ break; ++ default: ++ dev_err(udphy->dev, "unsupported refclk freq %ld\n", rate); ++ return -EINVAL; ++ } ++ ++ return 0; ++} ++ ++static int rk3588_udphy_status_check(struct rockchip_udphy *udphy) ++{ ++ unsigned int val; ++ int ret; ++ ++ /* LCPLL check */ ++ if (udphy->mode & UDPHY_MODE_USB) { ++ ret = regmap_read_poll_timeout(udphy->pma_regmap, CMN_ANA_LCPLL_DONE_OFFSET, ++ val, (val & CMN_ANA_LCPLL_AFC_DONE) && ++ (val & CMN_ANA_LCPLL_LOCK_DONE), 200, 100000); ++ if (ret) { ++ dev_err(udphy->dev, "cmn ana lcpll lock timeout\n"); ++ return ret; ++ } ++ } ++ ++ if (udphy->mode & UDPHY_MODE_USB) { ++ if (!udphy->flip) { ++ ret = regmap_read_poll_timeout(udphy->pma_regmap, ++ TRSV_LN0_MON_RX_CDR_DONE_OFFSET, val, ++ val & TRSV_LN0_MON_RX_CDR_LOCK_DONE, ++ 200, 100000); ++ if (ret) ++ dev_err(udphy->dev, "trsv ln0 mon rx cdr lock timeout\n"); ++ } else { ++ ret = regmap_read_poll_timeout(udphy->pma_regmap, ++ TRSV_LN2_MON_RX_CDR_DONE_OFFSET, val, ++ val & TRSV_LN2_MON_RX_CDR_LOCK_DONE, ++ 200, 100000); ++ if (ret) ++ dev_err(udphy->dev, "trsv ln2 mon rx cdr lock timeout\n"); ++ } ++ } ++ ++ return 0; ++} ++ ++static int rk3588_udphy_init(struct rockchip_udphy *udphy) ++{ ++ const struct rockchip_udphy_cfg *cfg = udphy->cfgs; ++ int ret; ++ ++ /* enable rx lfps for usb */ ++ if (udphy->mode & UDPHY_MODE_USB) ++ grfreg_write(udphy->udphygrf, &cfg->grfcfg.rx_lfps, true); ++ ++ /* Step 1: power on pma and deassert apb rstn */ ++ grfreg_write(udphy->udphygrf, &cfg->grfcfg.low_pwrn, true); ++ ++ udphy_reset_deassert(udphy, "pma_apb"); ++ udphy_reset_deassert(udphy, "pcs_apb"); ++ ++ /* Step 2: set init sequence and phy refclk */ ++ ret = regmap_multi_reg_write(udphy->pma_regmap, rk3588_udphy_init_sequence, ++ ARRAY_SIZE(rk3588_udphy_init_sequence)); ++ if (ret) { ++ dev_err(udphy->dev, "init sequence set error %d\n", ret); ++ goto assert_apb; ++ } ++ ++ ret = rk3588_udphy_refclk_set(udphy); ++ if (ret) { ++ dev_err(udphy->dev, "refclk set error %d\n", ret); ++ goto assert_apb; ++ } ++ ++ /* Step 3: configure lane mux */ ++ regmap_update_bits(udphy->pma_regmap, CMN_LANE_MUX_AND_EN_OFFSET, ++ CMN_DP_LANE_MUX_ALL | CMN_DP_LANE_EN_ALL, ++ FIELD_PREP(CMN_DP_LANE_MUX_N(3), udphy->lane_mux_sel[3]) | ++ FIELD_PREP(CMN_DP_LANE_MUX_N(2), udphy->lane_mux_sel[2]) | ++ FIELD_PREP(CMN_DP_LANE_MUX_N(1), udphy->lane_mux_sel[1]) | ++ FIELD_PREP(CMN_DP_LANE_MUX_N(0), udphy->lane_mux_sel[0]) | ++ FIELD_PREP(CMN_DP_LANE_EN_ALL, 0)); ++ ++ /* Step 4: deassert init rstn and wait for 200ns from datasheet */ ++ if (udphy->mode & UDPHY_MODE_USB) ++ udphy_reset_deassert(udphy, "init"); ++ ++ if (udphy->mode & UDPHY_MODE_DP) { ++ regmap_update_bits(udphy->pma_regmap, CMN_DP_RSTN_OFFSET, ++ CMN_DP_INIT_RSTN, ++ FIELD_PREP(CMN_DP_INIT_RSTN, 0x1)); ++ } ++ ++ udelay(1); ++ ++ /* Step 5: deassert cmn/lane rstn */ ++ if (udphy->mode & UDPHY_MODE_USB) { ++ udphy_reset_deassert(udphy, "cmn"); ++ udphy_reset_deassert(udphy, "lane"); ++ } ++ ++ /* Step 6: wait for lock done of pll */ ++ ret = rk3588_udphy_status_check(udphy); ++ if (ret) ++ goto assert_phy; ++ ++ return 0; ++ ++assert_phy: ++ udphy_reset_assert(udphy, "init"); ++ udphy_reset_assert(udphy, "cmn"); ++ udphy_reset_assert(udphy, "lane"); ++ ++assert_apb: ++ udphy_reset_assert(udphy, "pma_apb"); ++ udphy_reset_assert(udphy, "pcs_apb"); ++ return ret; ++} ++ ++static int rk3588_udphy_hpd_event_trigger(struct rockchip_udphy *udphy, bool hpd) ++{ ++ const struct rockchip_udphy_cfg *cfg = udphy->cfgs; ++ ++ udphy->dp_sink_hpd_sel = true; ++ udphy->dp_sink_hpd_cfg = hpd; ++ ++ grfreg_write(udphy->vogrf, &cfg->vogrfcfg[udphy->id].hpd_trigger, hpd); ++ ++ return 0; ++} ++ ++static int rk3588_udphy_dplane_enable(struct rockchip_udphy *udphy, int dp_lanes) ++{ ++ int i; ++ u32 val = 0; ++ ++ for (i = 0; i < dp_lanes; i++) ++ val |= BIT(udphy->dp_lane_sel[i]); ++ ++ regmap_update_bits(udphy->pma_regmap, CMN_LANE_MUX_AND_EN_OFFSET, CMN_DP_LANE_EN_ALL, ++ FIELD_PREP(CMN_DP_LANE_EN_ALL, val)); ++ ++ if (!dp_lanes) ++ regmap_update_bits(udphy->pma_regmap, CMN_DP_RSTN_OFFSET, ++ CMN_DP_CMN_RSTN, FIELD_PREP(CMN_DP_CMN_RSTN, 0x0)); ++ ++ return 0; ++} ++ ++static int rk3588_udphy_dplane_select(struct rockchip_udphy *udphy) ++{ ++ u32 value = 0; ++ ++ switch (udphy->mode) { ++ case UDPHY_MODE_DP: ++ value |= 2 << udphy->dp_lane_sel[2] * 2; ++ value |= 3 << udphy->dp_lane_sel[3] * 2; ++ fallthrough; ++ case UDPHY_MODE_DP_USB: ++ value |= 0 << udphy->dp_lane_sel[0] * 2; ++ value |= 1 << udphy->dp_lane_sel[1] * 2; ++ break; ++ case UDPHY_MODE_USB: ++ break; ++ default: ++ break; ++ } ++ ++ regmap_write(udphy->vogrf, udphy->id ? RK3588_GRF_VO0_CON2 : RK3588_GRF_VO0_CON0, ++ ((DP_AUX_DIN_SEL | DP_AUX_DOUT_SEL | DP_LANE_SEL_ALL) << 16) | ++ FIELD_PREP(DP_AUX_DIN_SEL, udphy->dp_aux_din_sel) | ++ FIELD_PREP(DP_AUX_DOUT_SEL, udphy->dp_aux_dout_sel) | value); ++ ++ return 0; ++} ++ ++static int rk3588_dp_phy_set_rate(struct rockchip_udphy *udphy, ++ struct phy_configure_opts_dp *dp) ++{ ++ u32 val; ++ int ret; ++ ++ regmap_update_bits(udphy->pma_regmap, CMN_DP_RSTN_OFFSET, ++ CMN_DP_CMN_RSTN, FIELD_PREP(CMN_DP_CMN_RSTN, 0x0)); ++ ++ switch (dp->link_rate) { ++ case 1620: ++ udphy->bw = DP_BW_RBR; ++ break; ++ case 2700: ++ udphy->bw = DP_BW_HBR; ++ break; ++ case 5400: ++ udphy->bw = DP_BW_HBR2; ++ break; ++ case 8100: ++ udphy->bw = DP_BW_HBR3; ++ break; ++ default: ++ return -EINVAL; ++ } ++ ++ regmap_update_bits(udphy->pma_regmap, CMN_DP_LINK_OFFSET, CMN_DP_TX_LINK_BW, ++ FIELD_PREP(CMN_DP_TX_LINK_BW, udphy->bw)); ++ regmap_update_bits(udphy->pma_regmap, CMN_SSC_EN_OFFSET, CMN_ROPLL_SSC_EN, ++ FIELD_PREP(CMN_ROPLL_SSC_EN, dp->ssc)); ++ regmap_update_bits(udphy->pma_regmap, CMN_DP_RSTN_OFFSET, CMN_DP_CMN_RSTN, ++ FIELD_PREP(CMN_DP_CMN_RSTN, 0x1)); ++ ++ ret = regmap_read_poll_timeout(udphy->pma_regmap, CMN_ANA_ROPLL_DONE_OFFSET, val, ++ FIELD_GET(CMN_ANA_ROPLL_LOCK_DONE, val) && ++ FIELD_GET(CMN_ANA_ROPLL_AFC_DONE, val), ++ 0, 1000); ++ if (ret) { ++ dev_err(udphy->dev, "ROPLL is not lock\n"); ++ return ret; ++ } ++ ++ return 0; ++} ++ ++static void rk3588_dp_phy_set_voltage(struct rockchip_udphy *udphy, u8 bw, ++ u32 voltage, u32 pre, u32 lane) ++{ ++ u32 offset = 0x800 * lane; ++ u32 val; ++ const struct rockchip_udphy_cfg *cfg = udphy->cfgs; ++ const struct dp_tx_drv_ctrl (*dp_ctrl)[4]; ++ ++ dp_ctrl = udphy->mux ? cfg->dp_tx_ctrl_cfg_typec[bw] : cfg->dp_tx_ctrl_cfg[bw]; ++ val = dp_ctrl[voltage][pre].trsv_reg0204; ++ regmap_write(udphy->pma_regmap, 0x0810 + offset, val); ++ ++ val = dp_ctrl[voltage][pre].trsv_reg0205; ++ regmap_write(udphy->pma_regmap, 0x0814 + offset, val); ++ ++ val = dp_ctrl[voltage][pre].trsv_reg0206; ++ regmap_write(udphy->pma_regmap, 0x0818 + offset, val); ++ ++ val = dp_ctrl[voltage][pre].trsv_reg0207; ++ regmap_write(udphy->pma_regmap, 0x081c + offset, val); ++} ++ ++static int rk3588_dp_phy_set_voltages(struct rockchip_udphy *udphy, ++ struct phy_configure_opts_dp *dp) ++{ ++ u32 i, lane; ++ ++ for (i = 0; i < dp->lanes; i++) { ++ lane = udphy->dp_lane_sel[i]; ++ switch (dp->link_rate) { ++ case 1620: ++ case 2700: ++ regmap_update_bits(udphy->pma_regmap, TRSV_ANA_TX_CLK_OFFSET_N(lane), ++ LN_ANA_TX_SER_TXCLK_INV, ++ FIELD_PREP(LN_ANA_TX_SER_TXCLK_INV, ++ udphy->lane_mux_sel[lane])); ++ break; ++ case 5400: ++ case 8100: ++ regmap_update_bits(udphy->pma_regmap, TRSV_ANA_TX_CLK_OFFSET_N(lane), ++ LN_ANA_TX_SER_TXCLK_INV, ++ FIELD_PREP(LN_ANA_TX_SER_TXCLK_INV, 0x0)); ++ break; ++ } ++ ++ rk3588_dp_phy_set_voltage(udphy, udphy->bw, dp->voltage[i], dp->pre[i], lane); ++ } ++ ++ return 0; ++} ++ ++static int __maybe_unused udphy_resume(struct device *dev) ++{ ++ struct rockchip_udphy *udphy = dev_get_drvdata(dev); ++ const struct rockchip_udphy_cfg *cfg = udphy->cfgs; ++ ++ if (udphy->dp_sink_hpd_sel) ++ cfg->hpd_event_trigger(udphy, udphy->dp_sink_hpd_cfg); ++ ++ return 0; ++} ++ ++static const struct dev_pm_ops udphy_pm_ops = { ++ SET_LATE_SYSTEM_SLEEP_PM_OPS(NULL, udphy_resume) ++}; ++ ++static const char * const rk3588_udphy_rst_l[] = { ++ "init", "cmn", "lane", "pcs_apb", "pma_apb" ++}; ++ ++static const struct rockchip_udphy_cfg rk3588_udphy_cfgs = { ++ .num_rsts = ARRAY_SIZE(rk3588_udphy_rst_l), ++ .rst_list = rk3588_udphy_rst_l, ++ .grfcfg = { ++ /* u2phy-grf */ ++ .bvalid_phy_con = { 0x0008, 1, 0, 0x2, 0x3 }, ++ .bvalid_grf_con = { 0x0010, 3, 2, 0x2, 0x3 }, ++ ++ /* usb-grf */ ++ .usb3otg0_cfg = { 0x001c, 15, 0, 0x1100, 0x0188 }, ++ .usb3otg1_cfg = { 0x0034, 15, 0, 0x1100, 0x0188 }, ++ ++ /* usbdpphy-grf */ ++ .low_pwrn = { 0x0004, 13, 13, 0, 1 }, ++ .rx_lfps = { 0x0004, 14, 14, 0, 1 }, ++ }, ++ .vogrfcfg = { ++ { ++ .hpd_trigger = { 0x0000, 11, 10, 1, 3 }, ++ }, ++ { ++ .hpd_trigger = { 0x0008, 11, 10, 1, 3 }, ++ }, ++ }, ++ .dp_tx_ctrl_cfg = { ++ rk3588_dp_tx_drv_ctrl_rbr_hbr, ++ rk3588_dp_tx_drv_ctrl_rbr_hbr, ++ rk3588_dp_tx_drv_ctrl_hbr2, ++ rk3588_dp_tx_drv_ctrl_hbr3, ++ }, ++ .dp_tx_ctrl_cfg_typec = { ++ rk3588_dp_tx_drv_ctrl_rbr_hbr_typec, ++ rk3588_dp_tx_drv_ctrl_rbr_hbr_typec, ++ rk3588_dp_tx_drv_ctrl_hbr2, ++ rk3588_dp_tx_drv_ctrl_hbr3, ++ }, ++ .combophy_init = rk3588_udphy_init, ++ .dp_phy_set_rate = rk3588_dp_phy_set_rate, ++ .dp_phy_set_voltages = rk3588_dp_phy_set_voltages, ++ .hpd_event_trigger = rk3588_udphy_hpd_event_trigger, ++ .dplane_enable = rk3588_udphy_dplane_enable, ++ .dplane_select = rk3588_udphy_dplane_select, ++}; ++ ++static const struct of_device_id rockchip_udphy_dt_match[] = { ++ { ++ .compatible = "rockchip,rk3588-usbdp-phy", ++ .data = &rk3588_udphy_cfgs ++ }, ++ { /* sentinel */ } ++}; ++ ++MODULE_DEVICE_TABLE(of, rockchip_udphy_dt_match); ++ ++static struct platform_driver rockchip_udphy_driver = { ++ .probe = rockchip_udphy_probe, ++ .driver = { ++ .name = "rockchip-usbdp-phy", ++ .of_match_table = rockchip_udphy_dt_match, ++ .pm = &udphy_pm_ops, ++ }, ++}; ++ ++module_platform_driver(rockchip_udphy_driver); ++ ++MODULE_AUTHOR("Frank Wang "); ++MODULE_AUTHOR("Zhang Yubing "); ++MODULE_DESCRIPTION("Rockchip USBDP Combo PHY driver"); ++MODULE_LICENSE("GPL v2"); diff --git a/target/linux/rockchip/patches-6.1/119-02-arm64-dts-rockchip-rk3588s-Add-USBDP-phy-nodes.patch b/target/linux/rockchip/patches-6.1/119-02-arm64-dts-rockchip-rk3588s-Add-USBDP-phy-nodes.patch new file mode 100644 index 0000000000..5f1d174a2c --- /dev/null +++ b/target/linux/rockchip/patches-6.1/119-02-arm64-dts-rockchip-rk3588s-Add-USBDP-phy-nodes.patch @@ -0,0 +1,196 @@ +From 131f987dd64516874607913481c8b124e129c3a3 Mon Sep 17 00:00:00 2001 +From: Sebastian Reichel +Date: Tue, 25 Apr 2023 17:49:04 +0200 +Subject: [PATCH 81/85] arm64: dts: rockchip: rk3588s: Add USBDP phy nodes + +Add both USB3-Displayport PHYs from RK3588. + +Signed-off-by: Sebastian Reichel +--- + arch/arm64/boot/dts/rockchip/rk3588.dtsi | 63 +++++++++++++++++++ + arch/arm64/boot/dts/rockchip/rk3588s.dtsi | 74 +++++++++++++++++++++++ + 2 files changed, 137 insertions(+) + +--- a/arch/arm64/boot/dts/rockchip/rk3588.dtsi ++++ b/arch/arm64/boot/dts/rockchip/rk3588.dtsi +@@ -12,6 +12,38 @@ + reg = <0x0 0xfd5c0000 0x0 0x100>; + }; + ++ usbdpphy1_grf: syscon@fd5cc000 { ++ compatible = "rockchip,rk3588-usbdpphy-grf", "syscon"; ++ reg = <0x0 0xfd5cc000 0x0 0x4000>; ++ }; ++ ++ usb2phy1_grf: syscon@fd5d4000 { ++ compatible = "rockchip,rk3588-usb2phy-grf", "syscon", ++ "simple-mfd"; ++ reg = <0x0 0xfd5d4000 0x0 0x4000>; ++ #address-cells = <1>; ++ #size-cells = <1>; ++ ++ u2phy1: usb2-phy@4000 { ++ compatible = "rockchip,rk3588-usb2phy"; ++ reg = <0x4000 0x10>; ++ interrupts = ; ++ resets = <&cru SRST_OTGPHY_U3_1>, <&cru SRST_P_USB2PHY_U3_1_GRF0>; ++ reset-names = "phy", "apb"; ++ clocks = <&cru CLK_USB2PHY_HDPTXRXPHY_REF>; ++ clock-names = "phyclk"; ++ clock-output-names = "usb480m_phy1"; ++ #clock-cells = <0>; ++ rockchip,usbctrl-grf = <&usb_grf>; ++ status = "disabled"; ++ ++ u2phy1_otg: otg-port { ++ #phy-cells = <0>; ++ status = "disabled"; ++ }; ++ }; ++ }; ++ + i2s8_8ch: i2s@fddc8000 { + compatible = "rockchip,rk3588-i2s-tdm"; + reg = <0x0 0xfddc8000 0x0 0x1000>; +@@ -206,6 +238,37 @@ + }; + }; + ++ usbdp_phy1: phy@fed90000 { ++ compatible = "rockchip,rk3588-usbdp-phy"; ++ reg = <0x0 0xfed90000 0x0 0x10000>; ++ rockchip,u2phy-grf = <&usb2phy1_grf>; ++ rockchip,usb-grf = <&usb_grf>; ++ rockchip,usbdpphy-grf = <&usbdpphy1_grf>; ++ rockchip,vo-grf = <&vo0_grf>; ++ clocks = <&cru CLK_USBDPPHY_MIPIDCPPHY_REF>, ++ <&cru CLK_USBDP_PHY1_IMMORTAL>, ++ <&cru PCLK_USBDPPHY1>, ++ <&u2phy1>; ++ clock-names = "refclk", "immortal", "pclk", "utmi"; ++ resets = <&cru SRST_USBDP_COMBO_PHY1_INIT>, ++ <&cru SRST_USBDP_COMBO_PHY1_CMN>, ++ <&cru SRST_USBDP_COMBO_PHY1_LANE>, ++ <&cru SRST_USBDP_COMBO_PHY1_PCS>, ++ <&cru SRST_P_USBDPPHY1>; ++ reset-names = "init", "cmn", "lane", "pcs_apb", "pma_apb"; ++ status = "disabled"; ++ ++ usbdp_phy1_dp: dp-port { ++ #phy-cells = <0>; ++ status = "disabled"; ++ }; ++ ++ usbdp_phy1_u3: usb3-port { ++ #phy-cells = <0>; ++ status = "disabled"; ++ }; ++ }; ++ + combphy1_ps: phy@fee10000 { + compatible = "rockchip,rk3588-naneng-combphy"; + reg = <0x0 0xfee10000 0x0 0x100>; +--- a/arch/arm64/boot/dts/rockchip/rk3588s.dtsi ++++ b/arch/arm64/boot/dts/rockchip/rk3588s.dtsi +@@ -881,6 +881,33 @@ + reg = <0x0 0xfd58c000 0x0 0x1000>; + }; + ++ usb2phy0_grf: syscon@fd5d0000 { ++ compatible = "rockchip,rk3588-usb2phy-grf", "syscon", ++ "simple-mfd"; ++ reg = <0x0 0xfd5d0000 0x0 0x4000>; ++ #address-cells = <1>; ++ #size-cells = <1>; ++ ++ u2phy0: usb2-phy@0 { ++ compatible = "rockchip,rk3588-usb2phy"; ++ reg = <0x0 0x10>; ++ interrupts = ; ++ resets = <&cru SRST_OTGPHY_U3_0>, <&cru SRST_P_USB2PHY_U3_0_GRF0>; ++ reset-names = "phy", "apb"; ++ clocks = <&cru CLK_USB2PHY_HDPTXRXPHY_REF>; ++ clock-names = "phyclk"; ++ clock-output-names = "usb480m_phy0"; ++ #clock-cells = <0>; ++ rockchip,usbctrl-grf = <&usb_grf>; ++ status = "disabled"; ++ ++ u2phy0_otg: otg-port { ++ #phy-cells = <0>; ++ status = "disabled"; ++ }; ++ }; ++ }; ++ + usb2phy2_grf: syscon@fd5d8000 { + compatible = "rockchip,rk3588-usb2phy-grf", "syscon", "simple-mfd"; + reg = <0x0 0xfd5d8000 0x0 0x4000>; +@@ -906,6 +933,17 @@ + }; + }; + ++ vo0_grf: syscon@fd5a6000 { ++ compatible = "rockchip,rk3588-vo-grf", "syscon"; ++ reg = <0x0 0xfd5a6000 0x0 0x2000>; ++ clocks = <&cru PCLK_VO0GRF>; ++ }; ++ ++ usb_grf: syscon@fd5ac000 { ++ compatible = "rockchip,rk3588-usb-grf", "syscon"; ++ reg = <0x0 0xfd5ac000 0x0 0x4000>; ++ }; ++ + usb2phy3_grf: syscon@fd5dc000 { + compatible = "rockchip,rk3588-usb2phy-grf", "syscon", "simple-mfd"; + reg = <0x0 0xfd5dc000 0x0 0x4000>; +@@ -956,6 +994,11 @@ + reg = <0x0 0xfd5c4000 0x0 0x100>; + }; + ++ usbdpphy0_grf: syscon@fd5c8000 { ++ compatible = "rockchip,rk3588-usbdpphy-grf", "syscon"; ++ reg = <0x0 0xfd5c8000 0x0 0x4000>; ++ }; ++ + ioc: syscon@fd5f0000 { + compatible = "rockchip,rk3588-ioc", "syscon"; + reg = <0x0 0xfd5f0000 0x0 0x10000>; +@@ -2616,6 +2659,37 @@ + #dma-cells = <1>; + }; + ++ usbdp_phy0: phy@fed80000 { ++ compatible = "rockchip,rk3588-usbdp-phy"; ++ reg = <0x0 0xfed80000 0x0 0x10000>; ++ rockchip,u2phy-grf = <&usb2phy0_grf>; ++ rockchip,usb-grf = <&usb_grf>; ++ rockchip,usbdpphy-grf = <&usbdpphy0_grf>; ++ rockchip,vo-grf = <&vo0_grf>; ++ clocks = <&cru CLK_USBDPPHY_MIPIDCPPHY_REF>, ++ <&cru CLK_USBDP_PHY0_IMMORTAL>, ++ <&cru PCLK_USBDPPHY0>, ++ <&u2phy0>; ++ clock-names = "refclk", "immortal", "pclk", "utmi"; ++ resets = <&cru SRST_USBDP_COMBO_PHY0_INIT>, ++ <&cru SRST_USBDP_COMBO_PHY0_CMN>, ++ <&cru SRST_USBDP_COMBO_PHY0_LANE>, ++ <&cru SRST_USBDP_COMBO_PHY0_PCS>, ++ <&cru SRST_P_USBDPPHY0>; ++ reset-names = "init", "cmn", "lane", "pcs_apb", "pma_apb"; ++ status = "disabled"; ++ ++ usbdp_phy0_dp: dp-port { ++ #phy-cells = <0>; ++ status = "disabled"; ++ }; ++ ++ usbdp_phy0_u3: usb3-port { ++ #phy-cells = <0>; ++ status = "disabled"; ++ }; ++ }; ++ + combphy0_ps: phy@fee00000 { + compatible = "rockchip,rk3588-naneng-combphy"; + reg = <0x0 0xfee00000 0x0 0x100>; diff --git a/target/linux/rockchip/patches-6.1/119-03-arm64-dts-rockchip-rk3588s-Add-USB3-controllers.patch b/target/linux/rockchip/patches-6.1/119-03-arm64-dts-rockchip-rk3588s-Add-USB3-controllers.patch new file mode 100644 index 0000000000..595a4b3b21 --- /dev/null +++ b/target/linux/rockchip/patches-6.1/119-03-arm64-dts-rockchip-rk3588s-Add-USB3-controllers.patch @@ -0,0 +1,129 @@ +From 05f5bff9db6d1c8a8513ccd588102a758d13ec37 Mon Sep 17 00:00:00 2001 +From: Sebastian Reichel +Date: Tue, 25 Apr 2023 18:17:19 +0200 +Subject: [PATCH 82/85] arm64: dts: rockchip: rk3588s: Add USB3 controllers + +Add all USB3 controllers. + +Signed-off-by: Sebastian Reichel +--- + arch/arm64/boot/dts/rockchip/rk3588.dtsi | 29 +++++++++++ + arch/arm64/boot/dts/rockchip/rk3588s.dtsi | 62 +++++++++++++++++++++++ + 2 files changed, 91 insertions(+) + +--- a/arch/arm64/boot/dts/rockchip/rk3588.dtsi ++++ b/arch/arm64/boot/dts/rockchip/rk3588.dtsi +@@ -7,6 +7,35 @@ + #include "rk3588-pinctrl.dtsi" + + / { ++ usbdrd3_1: usbdrd3_1 { ++ compatible = "rockchip,rk3588-dwc3", "rockchip,rk3399-dwc3"; ++ clocks = <&cru REF_CLK_USB3OTG1>, <&cru SUSPEND_CLK_USB3OTG1>, ++ <&cru ACLK_USB3OTG1>; ++ clock-names = "ref", "suspend", "bus"; ++ #address-cells = <2>; ++ #size-cells = <2>; ++ ranges; ++ status = "disabled"; ++ ++ usbdrd_dwc3_1: usb@fc400000 { ++ compatible = "snps,dwc3"; ++ reg = <0x0 0xfc400000 0x0 0x400000>; ++ interrupts = ; ++ power-domains = <&power RK3588_PD_USB>; ++ resets = <&cru SRST_A_USB3OTG1>; ++ reset-names = "usb3-otg"; ++ dr_mode = "host"; ++ phys = <&u2phy1_otg>, <&usbdp_phy1_u3>; ++ phy-names = "usb2-phy", "usb3-phy"; ++ phy_type = "utmi_wide"; ++ snps,dis_enblslpm_quirk; ++ snps,dis-u2-freeclk-exists-quirk; ++ snps,dis-del-phy-power-chg-quirk; ++ snps,dis-tx-ipgap-linecheck-quirk; ++ status = "disabled"; ++ }; ++ }; ++ + pipe_phy1_grf: syscon@fd5c0000 { + compatible = "rockchip,rk3588-pipe-phy-grf", "syscon"; + reg = <0x0 0xfd5c0000 0x0 0x100>; +--- a/arch/arm64/boot/dts/rockchip/rk3588s.dtsi ++++ b/arch/arm64/boot/dts/rockchip/rk3588s.dtsi +@@ -832,6 +832,38 @@ + }; + }; + ++ usbdrd3_0: usbdrd3_0 { ++ compatible = "rockchip,rk3588-dwc3", "rockchip,rk3399-dwc3"; ++ clocks = <&cru REF_CLK_USB3OTG0>, <&cru SUSPEND_CLK_USB3OTG0>, ++ <&cru ACLK_USB3OTG0>; ++ clock-names = "ref", "suspend", "bus"; ++ #address-cells = <2>; ++ #size-cells = <2>; ++ ranges; ++ status = "disabled"; ++ ++ usbdrd_dwc3_0: usb@fc000000 { ++ compatible = "snps,dwc3"; ++ reg = <0x0 0xfc000000 0x0 0x400000>; ++ interrupts = ; ++ power-domains = <&power RK3588_PD_USB>; ++ resets = <&cru SRST_A_USB3OTG0>; ++ reset-names = "usb3-otg"; ++ dr_mode = "otg"; ++ phys = <&u2phy0_otg>, <&usbdp_phy0_u3>; ++ phy-names = "usb2-phy", "usb3-phy"; ++ phy_type = "utmi_wide"; ++ snps,dis_enblslpm_quirk; ++ snps,dis-u1-entry-quirk; ++ snps,dis-u2-entry-quirk; ++ snps,dis-u2-freeclk-exists-quirk; ++ snps,dis-del-phy-power-chg-quirk; ++ snps,dis-tx-ipgap-linecheck-quirk; ++ quirk-skip-phy-init; ++ status = "disabled"; ++ }; ++ }; ++ + usb_host0_ehci: usb@fc800000 { + compatible = "rockchip,rk3588-ehci", "generic-ehci"; + reg = <0x0 0xfc800000 0x0 0x40000>; +@@ -876,6 +908,36 @@ + status = "disabled"; + }; + ++ usbhost3_0: usbhost3_0 { ++ compatible = "rockchip,rk3588-dwc3", "rockchip,rk3399-dwc3"; ++ clocks = <&cru REF_CLK_USB3OTG2>, <&cru SUSPEND_CLK_USB3OTG2>, ++ <&cru ACLK_USB3OTG2>, <&cru CLK_UTMI_OTG2>, ++ <&cru PCLK_PHP_ROOT>, <&cru CLK_PIPEPHY2_PIPE_U3_G>; ++ clock-names = "ref", "suspend", "bus", "utmi", "php", "pipe"; ++ #address-cells = <2>; ++ #size-cells = <2>; ++ ranges; ++ status = "disabled"; ++ ++ usbhost_dwc3_0: usb@fcd00000 { ++ compatible = "snps,dwc3"; ++ reg = <0x0 0xfcd00000 0x0 0x400000>; ++ interrupts = ; ++ resets = <&cru SRST_A_USB3OTG2>; ++ reset-names = "usb3-host"; ++ dr_mode = "host"; ++ phys = <&combphy2_psu PHY_TYPE_USB3>; ++ phy-names = "usb3-phy"; ++ phy_type = "utmi_wide"; ++ snps,dis_enblslpm_quirk; ++ snps,dis-u2-freeclk-exists-quirk; ++ snps,dis-del-phy-power-chg-quirk; ++ snps,dis-tx-ipgap-linecheck-quirk; ++ snps,dis_rxdet_inp3_quirk; ++ status = "disabled"; ++ }; ++ }; ++ + sys_grf: syscon@fd58c000 { + compatible = "rockchip,rk3588-sys-grf", "syscon"; + reg = <0x0 0xfd58c000 0x0 0x1000>; diff --git a/target/linux/rockchip/patches-6.1/801-05-arm64-dts-rockchip-rk3588s-add-rng-node.patch b/target/linux/rockchip/patches-6.1/801-05-arm64-dts-rockchip-rk3588s-add-rng-node.patch new file mode 100644 index 0000000000..01e8561d3f --- /dev/null +++ b/target/linux/rockchip/patches-6.1/801-05-arm64-dts-rockchip-rk3588s-add-rng-node.patch @@ -0,0 +1,31 @@ +From b56b10f0075e78c72b0ab5bfe9ce64714be48151 Mon Sep 17 00:00:00 2001 +From: Lin Jinhan +Date: Sat, 18 Sep 2021 16:24:23 +0800 +Subject: [PATCH] arm64: dts: rockchip: rk3588s: add rng node + +Signed-off-by: Lin Jinhan +Change-Id: Ifb8964053daa6b593dd2c2c6a3b8caab8526e56d +--- + arch/arm64/boot/dts/rockchip/rk3588s.dtsi | 11 +++++++++++ + 1 file changed, 11 insertions(+) + +--- a/arch/arm64/boot/dts/rockchip/rk3588s.dtsi ++++ b/arch/arm64/boot/dts/rockchip/rk3588s.dtsi +@@ -2011,6 +2011,17 @@ + status = "disabled"; + }; + ++ rng: rng@fe378000 { ++ compatible = "rockchip,trngv1"; ++ reg = <0x0 0xfe378000 0x0 0x200>; ++ interrupts = ; ++ clocks = <&cru SCMI_HCLK_SECURE_NS>; ++ clock-names = "hclk_trng"; ++ resets = <&scmi_reset SRST_H_TRNG_NS>; ++ reset-names = "reset"; ++ status = "disabled"; ++ }; ++ + i2s0_8ch: i2s@fe470000 { + compatible = "rockchip,rk3588-i2s-tdm"; + reg = <0x0 0xfe470000 0x0 0x1000>; diff --git a/target/linux/rockchip/patches-6.1/801-06-arm64-dts-rockchip-rk3588s-rng-use-scmi_clk.patch b/target/linux/rockchip/patches-6.1/801-06-arm64-dts-rockchip-rk3588s-rng-use-scmi_clk.patch new file mode 100644 index 0000000000..ef666de482 --- /dev/null +++ b/target/linux/rockchip/patches-6.1/801-06-arm64-dts-rockchip-rk3588s-rng-use-scmi_clk.patch @@ -0,0 +1,25 @@ +From 8f3ec330491d807e613c40fe83f85a28ad8d5f6c Mon Sep 17 00:00:00 2001 +From: Lin Jinhan +Date: Wed, 17 Nov 2021 14:51:34 +0800 +Subject: [PATCH] arm64: dts: rockchip: rk3588s: rng: use scmi_clk + +rng module should use scmi_clk rather than cru. + +Fixes: b56b10f0075e ("arm64: dts: rockchip: rk3588s: add rng node") +Signed-off-by: Lin Jinhan +Change-Id: I49994529fcc209c2bc173c1abc497536fb920302 +--- + arch/arm64/boot/dts/rockchip/rk3588s.dtsi | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +--- a/arch/arm64/boot/dts/rockchip/rk3588s.dtsi ++++ b/arch/arm64/boot/dts/rockchip/rk3588s.dtsi +@@ -2015,7 +2015,7 @@ + compatible = "rockchip,trngv1"; + reg = <0x0 0xfe378000 0x0 0x200>; + interrupts = ; +- clocks = <&cru SCMI_HCLK_SECURE_NS>; ++ clocks = <&scmi_clk SCMI_HCLK_SECURE_NS>; + clock-names = "hclk_trng"; + resets = <&scmi_reset SRST_H_TRNG_NS>; + reset-names = "reset"; diff --git a/target/linux/rockchip/patches-6.1/801-05-arm64-dts-rockchip-enable-hwrng-for-rockchip-boards.patch b/target/linux/rockchip/patches-6.1/801-07-arm64-dts-rockchip-enable-hwrng-for-rockchip-boards.patch similarity index 100% rename from target/linux/rockchip/patches-6.1/801-05-arm64-dts-rockchip-enable-hwrng-for-rockchip-boards.patch rename to target/linux/rockchip/patches-6.1/801-07-arm64-dts-rockchip-enable-hwrng-for-rockchip-boards.patch diff --git a/target/linux/rockchip/patches-6.1/994-rockchip-rk3588-unlock-2.4-GHz.patch b/target/linux/rockchip/patches-6.1/994-rockchip-rk3588-unlock-2.4-GHz.patch new file mode 100644 index 0000000000..d14c98df5e --- /dev/null +++ b/target/linux/rockchip/patches-6.1/994-rockchip-rk3588-unlock-2.4-GHz.patch @@ -0,0 +1,28 @@ +--- a/arch/arm64/boot/dts/rockchip/rk3588s.dtsi ++++ b/arch/arm64/boot/dts/rockchip/rk3588s.dtsi +@@ -149,6 +149,12 @@ + <925000 925000 1000000>; + clock-latency-ns = <40000>; + }; ++ opp-2400000000 { ++ opp-hz = /bits/ 64 <2400000000>; ++ opp-microvolt = <1000000 1000000 1000000>, ++ <1000000 1000000 1000000>; ++ clock-latency-ns = <40000>; ++ }; + }; + + cluster2_opp_table: opp-table-cluster2 { +@@ -226,6 +232,12 @@ + <925000 925000 1000000>; + clock-latency-ns = <40000>; + }; ++ opp-2400000000 { ++ opp-hz = /bits/ 64 <2400000000>; ++ opp-microvolt = <1000000 1000000 1000000>, ++ <1000000 1000000 1000000>; ++ clock-latency-ns = <40000>; ++ }; + }; + + cpus {