Skip to content

Commit 3ceb546

Browse files
committed
cpufreq: rockchip: handle -EPROBE_DEFER for late PMIC initialization
On boards like Youyeetoo YY3588 where the RK806 PMIC initializes late, the cpufreq driver would fail to get the CPU regulator and abort probe. This caused CPU frequency scaling to be unavailable. Handle -EPROBE_DEFER from regulator_get_optional() to allow the driver to retry when the PMIC becomes available.
1 parent cce4bd7 commit 3ceb546

File tree

1 file changed

+49
-2
lines changed

1 file changed

+49
-2
lines changed

drivers/cpufreq/rockchip-cpufreq.c

Lines changed: 49 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@
1717
#include <linux/cpu.h>
1818
#include <linux/cpufreq.h>
1919
#include <linux/cpuidle.h>
20+
#include <linux/delay.h>
2021
#include <linux/err.h>
2122
#include <linux/init.h>
2223
#include <linux/kernel.h>
@@ -33,6 +34,7 @@
3334
#include <linux/regmap.h>
3435
#include <linux/regulator/consumer.h>
3536
#include <linux/rockchip/cpu.h>
37+
#include <linux/workqueue.h>
3638
#include <soc/rockchip/rockchip_opp_select.h>
3739
#include <soc/rockchip/rockchip_system_monitor.h>
3840

@@ -54,6 +56,11 @@ struct cluster_info {
5456
};
5557
static LIST_HEAD(cluster_info_list);
5658

59+
#define CPUFREQ_DEFER_DELAY_MS 100
60+
#define CPUFREQ_DEFER_RETRIES 50
61+
static struct delayed_work cpufreq_defer_work;
62+
static int cpufreq_defer_retry_count;
63+
5764
static struct cluster_info *rockchip_cluster_info_lookup(int cpu);
5865

5966
static int px30_get_soc_info(struct device *dev, struct device_node *np,
@@ -861,7 +868,7 @@ static struct notifier_block rockchip_cpufreq_panic_notifier_block = {
861868
.notifier_call = rockchip_cpufreq_panic_notifier,
862869
};
863870

864-
static int __init rockchip_cpufreq_driver_init(void)
871+
static int rockchip_cpufreq_do_init(void)
865872
{
866873
struct cluster_info *cluster, *pos;
867874
struct cpufreq_dt_platform_data pdata = {0};
@@ -881,6 +888,9 @@ static int __init rockchip_cpufreq_driver_init(void)
881888

882889
ret = rockchip_cpufreq_cluster_init(cpu, cluster);
883890
if (ret) {
891+
kfree(cluster);
892+
if (ret == -EPROBE_DEFER)
893+
goto release_cluster_info;
884894
pr_err("Failed to initialize dvfs info cpu%d\n", cpu);
885895
goto release_cluster_info;
886896
}
@@ -929,7 +939,44 @@ static int __init rockchip_cpufreq_driver_init(void)
929939
}
930940
return ret;
931941
}
932-
module_init(rockchip_cpufreq_driver_init);
942+
943+
static void rockchip_cpufreq_defer_work_func(struct work_struct *work)
944+
{
945+
int ret;
946+
947+
ret = rockchip_cpufreq_do_init();
948+
if (ret == -EPROBE_DEFER) {
949+
if (++cpufreq_defer_retry_count < CPUFREQ_DEFER_RETRIES) {
950+
pr_debug("cpufreq: regulator not ready, retry %d/%d\n",
951+
cpufreq_defer_retry_count, CPUFREQ_DEFER_RETRIES);
952+
schedule_delayed_work(&cpufreq_defer_work,
953+
msecs_to_jiffies(CPUFREQ_DEFER_DELAY_MS));
954+
} else {
955+
pr_err("cpufreq: gave up waiting for regulator after %d retries\n",
956+
CPUFREQ_DEFER_RETRIES);
957+
}
958+
} else if (ret) {
959+
pr_err("cpufreq: initialization failed with error %d\n", ret);
960+
}
961+
}
962+
963+
static int __init rockchip_cpufreq_driver_init(void)
964+
{
965+
int ret;
966+
967+
ret = rockchip_cpufreq_do_init();
968+
if (ret == -EPROBE_DEFER) {
969+
pr_info("cpufreq: regulator not ready, deferring initialization\n");
970+
INIT_DELAYED_WORK(&cpufreq_defer_work,
971+
rockchip_cpufreq_defer_work_func);
972+
schedule_delayed_work(&cpufreq_defer_work,
973+
msecs_to_jiffies(CPUFREQ_DEFER_DELAY_MS));
974+
return 0;
975+
}
976+
977+
return ret;
978+
}
979+
late_initcall(rockchip_cpufreq_driver_init);
933980

934981
MODULE_AUTHOR("Finley Xiao <finley.xiao@rock-chips.com>");
935982
MODULE_DESCRIPTION("Rockchip cpufreq driver");

0 commit comments

Comments
 (0)