Lines Matching +full:cpufreq +full:- +full:hw
1 // SPDX-License-Identifier: GPL-2.0
7 #include <linux/cpufreq.h>
44 * Mutex to synchronize between de-init sequence and re-starting LMh
65 dev = get_cpu_device(policy->cpu); in qcom_cpufreq_set_bw()
67 return -ENODEV; in qcom_cpufreq_set_bw()
101 struct qcom_cpufreq_data *data = policy->driver_data; in qcom_cpufreq_hw_target_index()
102 const struct qcom_cpufreq_soc_data *soc_data = data->soc_data; in qcom_cpufreq_hw_target_index()
103 unsigned long freq = policy->freq_table[index].frequency; in qcom_cpufreq_hw_target_index()
105 writel_relaxed(index, data->base + soc_data->reg_perf_state); in qcom_cpufreq_hw_target_index()
124 data = policy->driver_data; in qcom_cpufreq_hw_get()
125 soc_data = data->soc_data; in qcom_cpufreq_hw_get()
127 index = readl_relaxed(data->base + soc_data->reg_perf_state); in qcom_cpufreq_hw_get()
128 index = min(index, LUT_MAX_ENTRIES - 1); in qcom_cpufreq_hw_get()
130 return policy->freq_table[index].frequency; in qcom_cpufreq_hw_get()
136 struct qcom_cpufreq_data *data = policy->driver_data; in qcom_cpufreq_hw_fast_switch()
137 const struct qcom_cpufreq_soc_data *soc_data = data->soc_data; in qcom_cpufreq_hw_fast_switch()
140 index = policy->cached_resolved_idx; in qcom_cpufreq_hw_fast_switch()
141 writel_relaxed(index, data->base + soc_data->reg_perf_state); in qcom_cpufreq_hw_fast_switch()
143 return policy->freq_table[index].frequency; in qcom_cpufreq_hw_fast_switch()
155 struct qcom_cpufreq_data *drv_data = policy->driver_data; in qcom_cpufreq_hw_read_lut()
156 const struct qcom_cpufreq_soc_data *soc_data = drv_data->soc_data; in qcom_cpufreq_hw_read_lut()
160 return -ENOMEM; in qcom_cpufreq_hw_read_lut()
164 /* Disable all opps and cross-validate against LUT later */ in qcom_cpufreq_hw_read_lut()
174 } else if (ret != -ENODEV) { in qcom_cpufreq_hw_read_lut()
178 policy->fast_switch_possible = true; in qcom_cpufreq_hw_read_lut()
183 data = readl_relaxed(drv_data->base + soc_data->reg_freq_lut + in qcom_cpufreq_hw_read_lut()
184 i * soc_data->lut_row_size); in qcom_cpufreq_hw_read_lut()
189 data = readl_relaxed(drv_data->base + soc_data->reg_volt_lut + in qcom_cpufreq_hw_read_lut()
190 i * soc_data->lut_row_size); in qcom_cpufreq_hw_read_lut()
217 struct cpufreq_frequency_table *prev = &table[i - 1]; in qcom_cpufreq_hw_read_lut()
223 if (prev->frequency == CPUFREQ_ENTRY_INVALID) { in qcom_cpufreq_hw_read_lut()
225 prev->frequency = prev_freq; in qcom_cpufreq_hw_read_lut()
226 prev->flags = CPUFREQ_BOOST_FREQ; in qcom_cpufreq_hw_read_lut()
240 policy->freq_table = table; in qcom_cpufreq_hw_read_lut()
241 dev_pm_opp_set_sharing_cpus(cpu_dev, policy->cpus); in qcom_cpufreq_hw_read_lut()
257 ret = of_parse_phandle_with_args(cpu_np, "qcom,freq-domain", in qcom_get_related_cpus()
258 "#freq-domain-cells", 0, in qcom_get_related_cpus()
271 unsigned int val = readl_relaxed(data->base + data->soc_data->reg_current_vote); in qcom_lmh_get_throttle_freq()
279 struct cpufreq_policy *policy = data->policy; in qcom_lmh_dcvs_notify()
280 int cpu = cpumask_first(policy->cpus); in qcom_lmh_dcvs_notify()
293 if (IS_ERR(opp) && PTR_ERR(opp) == -ERANGE) in qcom_lmh_dcvs_notify()
301 capacity = mult_frac(max_capacity, throttled_freq, policy->cpuinfo.max_freq); in qcom_lmh_dcvs_notify()
307 arch_set_thermal_pressure(policy->cpus, max_capacity - capacity); in qcom_lmh_dcvs_notify()
313 mutex_lock(&data->throttle_lock); in qcom_lmh_dcvs_notify()
314 if (data->cancel_throttle) in qcom_lmh_dcvs_notify()
318 * If h/w throttled frequency is higher than what cpufreq has requested in qcom_lmh_dcvs_notify()
322 enable_irq(data->throttle_irq); in qcom_lmh_dcvs_notify()
324 mod_delayed_work(system_highpri_wq, &data->throttle_work, in qcom_lmh_dcvs_notify()
328 mutex_unlock(&data->throttle_lock); in qcom_lmh_dcvs_notify()
344 disable_irq_nosync(c_data->throttle_irq); in qcom_lmh_dcvs_handle_irq()
368 { .compatible = "qcom,cpufreq-hw", .data = &qcom_soc_data },
369 { .compatible = "qcom,cpufreq-epss", .data = &epss_soc_data },
376 struct qcom_cpufreq_data *data = policy->driver_data; in qcom_cpufreq_hw_lmh_init()
383 * if there is an error, allow cpufreq to be enabled as usual. in qcom_cpufreq_hw_lmh_init()
385 data->throttle_irq = platform_get_irq(pdev, index); in qcom_cpufreq_hw_lmh_init()
386 if (data->throttle_irq <= 0) in qcom_cpufreq_hw_lmh_init()
387 return data->throttle_irq == -EPROBE_DEFER ? -EPROBE_DEFER : 0; in qcom_cpufreq_hw_lmh_init()
389 data->cancel_throttle = false; in qcom_cpufreq_hw_lmh_init()
390 data->policy = policy; in qcom_cpufreq_hw_lmh_init()
392 mutex_init(&data->throttle_lock); in qcom_cpufreq_hw_lmh_init()
393 INIT_DEFERRABLE_WORK(&data->throttle_work, qcom_lmh_dcvs_poll); in qcom_cpufreq_hw_lmh_init()
395 snprintf(irq_name, sizeof(irq_name), "dcvsh-irq-%u", policy->cpu); in qcom_cpufreq_hw_lmh_init()
396 ret = request_threaded_irq(data->throttle_irq, NULL, qcom_lmh_dcvs_handle_irq, in qcom_cpufreq_hw_lmh_init()
399 dev_err(&pdev->dev, "Error registering %s: %d\n", irq_name, ret); in qcom_cpufreq_hw_lmh_init()
408 if (data->throttle_irq <= 0) in qcom_cpufreq_hw_lmh_exit()
411 mutex_lock(&data->throttle_lock); in qcom_cpufreq_hw_lmh_exit()
412 data->cancel_throttle = true; in qcom_cpufreq_hw_lmh_exit()
413 mutex_unlock(&data->throttle_lock); in qcom_cpufreq_hw_lmh_exit()
415 cancel_delayed_work_sync(&data->throttle_work); in qcom_cpufreq_hw_lmh_exit()
416 free_irq(data->throttle_irq, data); in qcom_cpufreq_hw_lmh_exit()
422 struct device *dev = &pdev->dev; in qcom_cpufreq_hw_cpu_init()
431 cpu_dev = get_cpu_device(policy->cpu); in qcom_cpufreq_hw_cpu_init()
434 policy->cpu); in qcom_cpufreq_hw_cpu_init()
435 return -ENODEV; in qcom_cpufreq_hw_cpu_init()
438 cpu_np = of_cpu_device_node_get(policy->cpu); in qcom_cpufreq_hw_cpu_init()
440 return -EINVAL; in qcom_cpufreq_hw_cpu_init()
442 ret = of_parse_phandle_with_args(cpu_np, "qcom,freq-domain", in qcom_cpufreq_hw_cpu_init()
443 "#freq-domain-cells", 0, &args); in qcom_cpufreq_hw_cpu_init()
453 return -ENODEV; in qcom_cpufreq_hw_cpu_init()
456 if (!request_mem_region(res->start, resource_size(res), res->name)) { in qcom_cpufreq_hw_cpu_init()
458 return -EBUSY; in qcom_cpufreq_hw_cpu_init()
461 base = ioremap(res->start, resource_size(res)); in qcom_cpufreq_hw_cpu_init()
464 ret = -ENOMEM; in qcom_cpufreq_hw_cpu_init()
470 ret = -ENOMEM; in qcom_cpufreq_hw_cpu_init()
474 data->soc_data = of_device_get_match_data(&pdev->dev); in qcom_cpufreq_hw_cpu_init()
475 data->base = base; in qcom_cpufreq_hw_cpu_init()
476 data->res = res; in qcom_cpufreq_hw_cpu_init()
478 /* HW should be in enabled state to proceed */ in qcom_cpufreq_hw_cpu_init()
479 if (!(readl_relaxed(base + data->soc_data->reg_enable) & 0x1)) { in qcom_cpufreq_hw_cpu_init()
480 dev_err(dev, "Domain-%d cpufreq hardware not enabled\n", index); in qcom_cpufreq_hw_cpu_init()
481 ret = -ENODEV; in qcom_cpufreq_hw_cpu_init()
485 qcom_get_related_cpus(index, policy->cpus); in qcom_cpufreq_hw_cpu_init()
486 if (!cpumask_weight(policy->cpus)) { in qcom_cpufreq_hw_cpu_init()
487 dev_err(dev, "Domain-%d failed to get related CPUs\n", index); in qcom_cpufreq_hw_cpu_init()
488 ret = -ENOENT; in qcom_cpufreq_hw_cpu_init()
492 policy->driver_data = data; in qcom_cpufreq_hw_cpu_init()
493 policy->dvfs_possible_from_any_cpu = true; in qcom_cpufreq_hw_cpu_init()
497 dev_err(dev, "Domain-%d failed to read LUT\n", index); in qcom_cpufreq_hw_cpu_init()
504 ret = -ENODEV; in qcom_cpufreq_hw_cpu_init()
524 release_mem_region(res->start, resource_size(res)); in qcom_cpufreq_hw_cpu_init()
530 struct device *cpu_dev = get_cpu_device(policy->cpu); in qcom_cpufreq_hw_cpu_exit()
531 struct qcom_cpufreq_data *data = policy->driver_data; in qcom_cpufreq_hw_cpu_exit()
532 struct resource *res = data->res; in qcom_cpufreq_hw_cpu_exit()
533 void __iomem *base = data->base; in qcom_cpufreq_hw_cpu_exit()
536 dev_pm_opp_of_cpumask_remove_table(policy->related_cpus); in qcom_cpufreq_hw_cpu_exit()
538 kfree(policy->freq_table); in qcom_cpufreq_hw_cpu_exit()
541 release_mem_region(res->start, resource_size(res)); in qcom_cpufreq_hw_cpu_exit()
563 .name = "qcom-cpufreq-hw",
573 clk = clk_get(&pdev->dev, "xo"); in qcom_cpufreq_hw_driver_probe()
580 clk = clk_get(&pdev->dev, "alternate"); in qcom_cpufreq_hw_driver_probe()
592 return -EPROBE_DEFER; in qcom_cpufreq_hw_driver_probe()
600 dev_err(&pdev->dev, "CPUFreq HW driver failed to register\n"); in qcom_cpufreq_hw_driver_probe()
602 dev_dbg(&pdev->dev, "QCOM CPUFreq HW driver initialized\n"); in qcom_cpufreq_hw_driver_probe()
616 .name = "qcom-cpufreq-hw",
633 MODULE_DESCRIPTION("QCOM CPUFREQ HW Driver");