Loading drivers/clk/qcom/clock-cpu-8994.c +129 −16 Original line number Diff line number Diff line Loading @@ -1178,11 +1178,39 @@ static void perform_v1_fixup(void) __cpu_mux_set_sel(&a53_lf_mux, 1); } static int add_opp(struct clk *c, struct device *dev, unsigned long max_rate) static long corner_to_voltage(unsigned long corner, struct device *dev) { struct opp *oppl; long uv; rcu_read_lock(); oppl = dev_pm_opp_find_freq_exact(dev, corner, true); rcu_read_unlock(); if (IS_ERR_OR_NULL(oppl)) return -EINVAL; rcu_read_lock(); uv = dev_pm_opp_get_voltage(oppl); rcu_read_unlock(); return uv; } static int add_opp(struct clk *c, struct device *cpudev, struct device *vregdev, unsigned long max_rate) { unsigned long rate = 0; int level; long ret; long ret, uv, corner; bool use_voltages = false; struct opp *oppl; rcu_read_lock(); /* Check if the regulator driver has already populated OPP tables */ oppl = dev_pm_opp_find_freq_exact(vregdev, 2, true); rcu_read_unlock(); if (!IS_ERR_OR_NULL(oppl)) use_voltages = true; while (1) { ret = clk_round_rate(c, rate + 1); Loading @@ -1196,11 +1224,43 @@ static int add_opp(struct clk *c, struct device *dev, unsigned long max_rate) pr_warn("clock-cpu: no uv for %lu.\n", rate); return -EINVAL; } ret = dev_pm_opp_add(dev, rate, c->vdd_class->vdd_uv[level]); uv = corner = c->vdd_class->vdd_uv[level]; /* * If corner to voltage mapping is available, populate the OPP * table with the voltages rather than corners. */ if (use_voltages) { uv = corner_to_voltage(corner, vregdev); if (uv < 0) { pr_warn("clock-cpu: no uv for corner %lu\n", corner); return uv; } ret = dev_pm_opp_add(cpudev, rate, uv); if (ret) { pr_warn("clock-cpu: couldn't add OPP for %lu\n", rate); return ret; } } else { /* * Populate both CPU and regulator devices with the * freq-to-corner OPP table to maintain backward * compatibility. */ ret = dev_pm_opp_add(cpudev, rate, corner); if (ret) { pr_warn("clock-cpu: couldn't add OPP for %lu\n", rate); return ret; } ret = dev_pm_opp_add(vregdev, rate, corner); if (ret) { pr_warn("clock-cpu: failed to add OPP for %lu\n", rate); pr_warn("clock-cpu: couldn't add OPP for %lu\n", rate); return ret; } } if (rate >= max_rate) break; } Loading @@ -1208,20 +1268,52 @@ static int add_opp(struct clk *c, struct device *dev, unsigned long max_rate) return 0; } static void print_opp_table(int a53_cpu, int a57_cpu) { struct opp *oppfmax, *oppfmin; unsigned long apc0_fmax = a53_clk.c.fmax[a53_clk.c.num_fmax - 1]; unsigned long apc1_fmax = a57_clk.c.fmax[a57_clk.c.num_fmax - 1]; unsigned long apc0_fmin = a53_clk.c.fmax[1]; unsigned long apc1_fmin = a57_clk.c.fmax[1]; rcu_read_lock(); oppfmax = dev_pm_opp_find_freq_exact(get_cpu_device(a53_cpu), apc0_fmax, true); oppfmin = dev_pm_opp_find_freq_exact(get_cpu_device(a53_cpu), apc0_fmin, true); /* * One time information during boot. Important to know that this looks * sane since it can eventually make its way to the scheduler. */ pr_info("clock_cpu: a53: OPP voltage for %lu: %ld\n", apc0_fmin, dev_pm_opp_get_voltage(oppfmin)); pr_info("clock_cpu: a53: OPP voltage for %lu: %ld\n", apc0_fmax, dev_pm_opp_get_voltage(oppfmax)); oppfmax = dev_pm_opp_find_freq_exact(get_cpu_device(a57_cpu), apc1_fmax, true); oppfmin = dev_pm_opp_find_freq_exact(get_cpu_device(a57_cpu), apc1_fmin, true); pr_info("clock_cpu: a57: OPP voltage for %lu: %lu\n", apc1_fmin, dev_pm_opp_get_voltage(oppfmin)); pr_info("clock_cpu: a57: OPP voltage for %lu: %lu\n", apc1_fmax, dev_pm_opp_get_voltage(oppfmax)); rcu_read_unlock(); } static void populate_opp_table(struct platform_device *pdev) { struct platform_device *apc0_dev, *apc1_dev; struct device_node *apc0_node, *apc1_node; unsigned long apc0_fmax, apc1_fmax; int cpu, a53_cpu, a57_cpu; apc0_node = of_parse_phandle(pdev->dev.of_node, "vdd-a53-supply", 0); apc1_node = of_parse_phandle(pdev->dev.of_node, "vdd-a57-supply", 0); if (!apc0_node) { pr_err("can't find the apc0 dt node.\n"); return; } if (!apc1_node) { pr_err("can't find the apc1 dt node.\n"); return; Loading @@ -1229,12 +1321,10 @@ static void populate_opp_table(struct platform_device *pdev) apc0_dev = of_find_device_by_node(apc0_node); apc1_dev = of_find_device_by_node(apc1_node); if (!apc0_dev) { pr_err("can't find the apc0 device node.\n"); return; } if (!apc1_dev) { pr_err("can't find the apc1 device node.\n"); return; Loading @@ -1243,16 +1333,30 @@ static void populate_opp_table(struct platform_device *pdev) apc0_fmax = a53_clk.c.fmax[a53_clk.c.num_fmax - 1]; apc1_fmax = a57_clk.c.fmax[a57_clk.c.num_fmax - 1]; WARN(add_opp(&a53_clk.c, &apc0_dev->dev, apc0_fmax), for_each_possible_cpu(cpu) { if (logical_cpu_to_clk(cpu) == &a53_clk.c) { a53_cpu = cpu; WARN(add_opp(&a53_clk.c, get_cpu_device(cpu), &apc0_dev->dev, apc0_fmax), "Failed to add OPP levels for A53\n"); WARN(add_opp(&a57_clk.c, &apc1_dev->dev, apc1_fmax), } if (logical_cpu_to_clk(cpu) == &a57_clk.c) { a57_cpu = cpu; WARN(add_opp(&a57_clk.c, get_cpu_device(cpu), &apc1_dev->dev, apc1_fmax), "Failed to add OPP levels for A57\n"); } } /* One time print during bootup */ pr_info("clock-cpu-8994: OPP tables populated.\n"); pr_info("clock-cpu-8994: OPP tables populated (cpu %d and %d)", a53_cpu, a57_cpu); print_opp_table(a53_cpu, a57_cpu); } static int a57speedbin; struct platform_device *cpu_clock_8994_dev; static int cpu_clock_8994_driver_probe(struct platform_device *pdev) { Loading @@ -1264,6 +1368,7 @@ static int cpu_clock_8994_driver_probe(struct platform_device *pdev) char a57speedbinstr[] = "qcom,a57-speedbinXX-vXX"; v2 = msm8994_v2; cpu_clock_8994_dev = pdev; a53_pll0_main.c.flags = CLKFLAG_NO_RATE_CACHE; a57_pll0_main.c.flags = CLKFLAG_NO_RATE_CACHE; Loading Loading @@ -1395,7 +1500,6 @@ static int cpu_clock_8994_driver_probe(struct platform_device *pdev) clk_set_rate(&cci_clk.c, 300000000); } populate_opp_table(pdev); put_online_cpus(); Loading @@ -1417,6 +1521,15 @@ static struct platform_driver cpu_clock_8994_driver = { }, }; /* CPU devices are not currently available in arch_initcall */ static int __init cpu_clock_8994_init_opp(void) { if (cpu_clock_8994_dev) populate_opp_table(cpu_clock_8994_dev); return 0; } module_init(cpu_clock_8994_init_opp); static int __init cpu_clock_8994_init(void) { return platform_driver_register(&cpu_clock_8994_driver); Loading Loading
drivers/clk/qcom/clock-cpu-8994.c +129 −16 Original line number Diff line number Diff line Loading @@ -1178,11 +1178,39 @@ static void perform_v1_fixup(void) __cpu_mux_set_sel(&a53_lf_mux, 1); } static int add_opp(struct clk *c, struct device *dev, unsigned long max_rate) static long corner_to_voltage(unsigned long corner, struct device *dev) { struct opp *oppl; long uv; rcu_read_lock(); oppl = dev_pm_opp_find_freq_exact(dev, corner, true); rcu_read_unlock(); if (IS_ERR_OR_NULL(oppl)) return -EINVAL; rcu_read_lock(); uv = dev_pm_opp_get_voltage(oppl); rcu_read_unlock(); return uv; } static int add_opp(struct clk *c, struct device *cpudev, struct device *vregdev, unsigned long max_rate) { unsigned long rate = 0; int level; long ret; long ret, uv, corner; bool use_voltages = false; struct opp *oppl; rcu_read_lock(); /* Check if the regulator driver has already populated OPP tables */ oppl = dev_pm_opp_find_freq_exact(vregdev, 2, true); rcu_read_unlock(); if (!IS_ERR_OR_NULL(oppl)) use_voltages = true; while (1) { ret = clk_round_rate(c, rate + 1); Loading @@ -1196,11 +1224,43 @@ static int add_opp(struct clk *c, struct device *dev, unsigned long max_rate) pr_warn("clock-cpu: no uv for %lu.\n", rate); return -EINVAL; } ret = dev_pm_opp_add(dev, rate, c->vdd_class->vdd_uv[level]); uv = corner = c->vdd_class->vdd_uv[level]; /* * If corner to voltage mapping is available, populate the OPP * table with the voltages rather than corners. */ if (use_voltages) { uv = corner_to_voltage(corner, vregdev); if (uv < 0) { pr_warn("clock-cpu: no uv for corner %lu\n", corner); return uv; } ret = dev_pm_opp_add(cpudev, rate, uv); if (ret) { pr_warn("clock-cpu: couldn't add OPP for %lu\n", rate); return ret; } } else { /* * Populate both CPU and regulator devices with the * freq-to-corner OPP table to maintain backward * compatibility. */ ret = dev_pm_opp_add(cpudev, rate, corner); if (ret) { pr_warn("clock-cpu: couldn't add OPP for %lu\n", rate); return ret; } ret = dev_pm_opp_add(vregdev, rate, corner); if (ret) { pr_warn("clock-cpu: failed to add OPP for %lu\n", rate); pr_warn("clock-cpu: couldn't add OPP for %lu\n", rate); return ret; } } if (rate >= max_rate) break; } Loading @@ -1208,20 +1268,52 @@ static int add_opp(struct clk *c, struct device *dev, unsigned long max_rate) return 0; } static void print_opp_table(int a53_cpu, int a57_cpu) { struct opp *oppfmax, *oppfmin; unsigned long apc0_fmax = a53_clk.c.fmax[a53_clk.c.num_fmax - 1]; unsigned long apc1_fmax = a57_clk.c.fmax[a57_clk.c.num_fmax - 1]; unsigned long apc0_fmin = a53_clk.c.fmax[1]; unsigned long apc1_fmin = a57_clk.c.fmax[1]; rcu_read_lock(); oppfmax = dev_pm_opp_find_freq_exact(get_cpu_device(a53_cpu), apc0_fmax, true); oppfmin = dev_pm_opp_find_freq_exact(get_cpu_device(a53_cpu), apc0_fmin, true); /* * One time information during boot. Important to know that this looks * sane since it can eventually make its way to the scheduler. */ pr_info("clock_cpu: a53: OPP voltage for %lu: %ld\n", apc0_fmin, dev_pm_opp_get_voltage(oppfmin)); pr_info("clock_cpu: a53: OPP voltage for %lu: %ld\n", apc0_fmax, dev_pm_opp_get_voltage(oppfmax)); oppfmax = dev_pm_opp_find_freq_exact(get_cpu_device(a57_cpu), apc1_fmax, true); oppfmin = dev_pm_opp_find_freq_exact(get_cpu_device(a57_cpu), apc1_fmin, true); pr_info("clock_cpu: a57: OPP voltage for %lu: %lu\n", apc1_fmin, dev_pm_opp_get_voltage(oppfmin)); pr_info("clock_cpu: a57: OPP voltage for %lu: %lu\n", apc1_fmax, dev_pm_opp_get_voltage(oppfmax)); rcu_read_unlock(); } static void populate_opp_table(struct platform_device *pdev) { struct platform_device *apc0_dev, *apc1_dev; struct device_node *apc0_node, *apc1_node; unsigned long apc0_fmax, apc1_fmax; int cpu, a53_cpu, a57_cpu; apc0_node = of_parse_phandle(pdev->dev.of_node, "vdd-a53-supply", 0); apc1_node = of_parse_phandle(pdev->dev.of_node, "vdd-a57-supply", 0); if (!apc0_node) { pr_err("can't find the apc0 dt node.\n"); return; } if (!apc1_node) { pr_err("can't find the apc1 dt node.\n"); return; Loading @@ -1229,12 +1321,10 @@ static void populate_opp_table(struct platform_device *pdev) apc0_dev = of_find_device_by_node(apc0_node); apc1_dev = of_find_device_by_node(apc1_node); if (!apc0_dev) { pr_err("can't find the apc0 device node.\n"); return; } if (!apc1_dev) { pr_err("can't find the apc1 device node.\n"); return; Loading @@ -1243,16 +1333,30 @@ static void populate_opp_table(struct platform_device *pdev) apc0_fmax = a53_clk.c.fmax[a53_clk.c.num_fmax - 1]; apc1_fmax = a57_clk.c.fmax[a57_clk.c.num_fmax - 1]; WARN(add_opp(&a53_clk.c, &apc0_dev->dev, apc0_fmax), for_each_possible_cpu(cpu) { if (logical_cpu_to_clk(cpu) == &a53_clk.c) { a53_cpu = cpu; WARN(add_opp(&a53_clk.c, get_cpu_device(cpu), &apc0_dev->dev, apc0_fmax), "Failed to add OPP levels for A53\n"); WARN(add_opp(&a57_clk.c, &apc1_dev->dev, apc1_fmax), } if (logical_cpu_to_clk(cpu) == &a57_clk.c) { a57_cpu = cpu; WARN(add_opp(&a57_clk.c, get_cpu_device(cpu), &apc1_dev->dev, apc1_fmax), "Failed to add OPP levels for A57\n"); } } /* One time print during bootup */ pr_info("clock-cpu-8994: OPP tables populated.\n"); pr_info("clock-cpu-8994: OPP tables populated (cpu %d and %d)", a53_cpu, a57_cpu); print_opp_table(a53_cpu, a57_cpu); } static int a57speedbin; struct platform_device *cpu_clock_8994_dev; static int cpu_clock_8994_driver_probe(struct platform_device *pdev) { Loading @@ -1264,6 +1368,7 @@ static int cpu_clock_8994_driver_probe(struct platform_device *pdev) char a57speedbinstr[] = "qcom,a57-speedbinXX-vXX"; v2 = msm8994_v2; cpu_clock_8994_dev = pdev; a53_pll0_main.c.flags = CLKFLAG_NO_RATE_CACHE; a57_pll0_main.c.flags = CLKFLAG_NO_RATE_CACHE; Loading Loading @@ -1395,7 +1500,6 @@ static int cpu_clock_8994_driver_probe(struct platform_device *pdev) clk_set_rate(&cci_clk.c, 300000000); } populate_opp_table(pdev); put_online_cpus(); Loading @@ -1417,6 +1521,15 @@ static struct platform_driver cpu_clock_8994_driver = { }, }; /* CPU devices are not currently available in arch_initcall */ static int __init cpu_clock_8994_init_opp(void) { if (cpu_clock_8994_dev) populate_opp_table(cpu_clock_8994_dev); return 0; } module_init(cpu_clock_8994_init_opp); static int __init cpu_clock_8994_init(void) { return platform_driver_register(&cpu_clock_8994_driver); Loading