Lines Matching +full:opp +full:- +full:table +full:- +full:2
1 // SPDX-License-Identifier: GPL-2.0
7 #include <linux/clk-provider.h>
26 #define CLK_HW_DIV 2
29 #define GT_IRQ_STATUS BIT(2)
49 * Mutex to synchronize between de-init sequence and re-starting LMh
75 struct dev_pm_opp *opp; in qcom_cpufreq_set_bw() local
79 dev = get_cpu_device(policy->cpu); in qcom_cpufreq_set_bw()
81 return -ENODEV; in qcom_cpufreq_set_bw()
83 opp = dev_pm_opp_find_freq_exact(dev, freq_hz, true); in qcom_cpufreq_set_bw()
84 if (IS_ERR(opp)) in qcom_cpufreq_set_bw()
85 return PTR_ERR(opp); in qcom_cpufreq_set_bw()
87 ret = dev_pm_opp_set_opp(dev, opp); in qcom_cpufreq_set_bw()
88 dev_pm_opp_put(opp); in qcom_cpufreq_set_bw()
99 /* Skip voltage update if the opp table is not available */ in qcom_cpufreq_update_opp()
115 struct qcom_cpufreq_data *data = policy->driver_data; in qcom_cpufreq_hw_target_index()
117 unsigned long freq = policy->freq_table[index].frequency; in qcom_cpufreq_hw_target_index()
120 writel_relaxed(index, data->base + soc_data->reg_perf_state); in qcom_cpufreq_hw_target_index()
122 if (data->per_core_dcvs) in qcom_cpufreq_hw_target_index()
123 for (i = 1; i < cpumask_weight(policy->related_cpus); i++) in qcom_cpufreq_hw_target_index()
124 writel_relaxed(index, data->base + soc_data->reg_perf_state + i * 4); in qcom_cpufreq_hw_target_index()
136 if (qcom_cpufreq.soc_data->reg_current_vote) in qcom_lmh_get_throttle_freq()
137 lval = readl_relaxed(data->base + qcom_cpufreq.soc_data->reg_current_vote) & 0x3ff; in qcom_lmh_get_throttle_freq()
139 lval = readl_relaxed(data->base + qcom_cpufreq.soc_data->reg_domain_state) & 0xff; in qcom_lmh_get_throttle_freq()
156 data = policy->driver_data; in qcom_cpufreq_get_freq()
159 index = readl_relaxed(data->base + soc_data->reg_perf_state); in qcom_cpufreq_get_freq()
160 index = min(index, LUT_MAX_ENTRIES - 1); in qcom_cpufreq_get_freq()
162 return policy->freq_table[index].frequency; in qcom_cpufreq_get_freq()
174 data = policy->driver_data; in qcom_cpufreq_hw_get()
176 if (data->throttle_irq >= 0) in qcom_cpufreq_hw_get()
185 struct qcom_cpufreq_data *data = policy->driver_data; in qcom_cpufreq_hw_fast_switch()
190 index = policy->cached_resolved_idx; in qcom_cpufreq_hw_fast_switch()
191 writel_relaxed(index, data->base + soc_data->reg_perf_state); in qcom_cpufreq_hw_fast_switch()
193 if (data->per_core_dcvs) in qcom_cpufreq_hw_fast_switch()
194 for (i = 1; i < cpumask_weight(policy->related_cpus); i++) in qcom_cpufreq_hw_fast_switch()
195 writel_relaxed(index, data->base + soc_data->reg_perf_state + i * 4); in qcom_cpufreq_hw_fast_switch()
197 return policy->freq_table[index].frequency; in qcom_cpufreq_hw_fast_switch()
205 struct cpufreq_frequency_table *table; in qcom_cpufreq_hw_read_lut() local
206 struct dev_pm_opp *opp; in qcom_cpufreq_hw_read_lut() local
209 struct qcom_cpufreq_data *drv_data = policy->driver_data; in qcom_cpufreq_hw_read_lut()
212 table = kcalloc(LUT_MAX_ENTRIES + 1, sizeof(*table), GFP_KERNEL); in qcom_cpufreq_hw_read_lut()
213 if (!table) in qcom_cpufreq_hw_read_lut()
214 return -ENOMEM; in qcom_cpufreq_hw_read_lut()
218 /* Disable all opps and cross-validate against LUT later */ in qcom_cpufreq_hw_read_lut()
221 opp = dev_pm_opp_find_freq_ceil(cpu_dev, &rate); in qcom_cpufreq_hw_read_lut()
222 if (IS_ERR(opp)) in qcom_cpufreq_hw_read_lut()
225 dev_pm_opp_put(opp); in qcom_cpufreq_hw_read_lut()
228 } else if (ret != -ENODEV) { in qcom_cpufreq_hw_read_lut()
229 dev_err(cpu_dev, "Invalid opp table in device tree\n"); in qcom_cpufreq_hw_read_lut()
230 kfree(table); in qcom_cpufreq_hw_read_lut()
233 policy->fast_switch_possible = true; in qcom_cpufreq_hw_read_lut()
238 data = readl_relaxed(drv_data->base + soc_data->reg_freq_lut + in qcom_cpufreq_hw_read_lut()
239 i * soc_data->lut_row_size); in qcom_cpufreq_hw_read_lut()
244 data = readl_relaxed(drv_data->base + soc_data->reg_volt_lut + in qcom_cpufreq_hw_read_lut()
245 i * soc_data->lut_row_size); in qcom_cpufreq_hw_read_lut()
255 table[i].frequency = freq; in qcom_cpufreq_hw_read_lut()
259 dev_warn(cpu_dev, "failed to update OPP for freq=%d\n", freq); in qcom_cpufreq_hw_read_lut()
260 table[i].frequency = CPUFREQ_ENTRY_INVALID; in qcom_cpufreq_hw_read_lut()
264 table[i].frequency = CPUFREQ_ENTRY_INVALID; in qcom_cpufreq_hw_read_lut()
269 * end of table in qcom_cpufreq_hw_read_lut()
272 struct cpufreq_frequency_table *prev = &table[i - 1]; in qcom_cpufreq_hw_read_lut()
278 if (prev->frequency == CPUFREQ_ENTRY_INVALID) { in qcom_cpufreq_hw_read_lut()
280 prev->frequency = prev_freq; in qcom_cpufreq_hw_read_lut()
281 prev->flags = CPUFREQ_BOOST_FREQ; in qcom_cpufreq_hw_read_lut()
283 dev_warn(cpu_dev, "failed to update OPP for freq=%d\n", in qcom_cpufreq_hw_read_lut()
294 table[i].frequency = CPUFREQ_TABLE_END; in qcom_cpufreq_hw_read_lut()
295 policy->freq_table = table; in qcom_cpufreq_hw_read_lut()
296 dev_pm_opp_set_sharing_cpus(cpu_dev, policy->cpus); in qcom_cpufreq_hw_read_lut()
312 ret = of_parse_phandle_with_args(cpu_np, "qcom,freq-domain", in qcom_get_related_cpus()
313 "#freq-domain-cells", 0, in qcom_get_related_cpus()
326 struct cpufreq_policy *policy = data->policy; in qcom_lmh_dcvs_notify()
327 int cpu = cpumask_first(policy->related_cpus); in qcom_lmh_dcvs_notify()
330 struct dev_pm_opp *opp; in qcom_lmh_dcvs_notify() local
334 * registered opp table and use it to calculate thermal pressure. in qcom_lmh_dcvs_notify()
338 opp = dev_pm_opp_find_freq_floor(dev, &freq_hz); in qcom_lmh_dcvs_notify()
339 if (IS_ERR(opp) && PTR_ERR(opp) == -ERANGE) in qcom_lmh_dcvs_notify()
340 opp = dev_pm_opp_find_freq_ceil(dev, &freq_hz); in qcom_lmh_dcvs_notify()
342 if (IS_ERR(opp)) { in qcom_lmh_dcvs_notify()
343 dev_warn(dev, "Can't find the OPP for throttling: %pe!\n", opp); in qcom_lmh_dcvs_notify()
345 dev_pm_opp_put(opp); in qcom_lmh_dcvs_notify()
351 arch_update_thermal_pressure(policy->related_cpus, throttled_freq); in qcom_lmh_dcvs_notify()
357 mutex_lock(&data->throttle_lock); in qcom_lmh_dcvs_notify()
358 if (data->cancel_throttle) in qcom_lmh_dcvs_notify()
366 enable_irq(data->throttle_irq); in qcom_lmh_dcvs_notify()
368 mod_delayed_work(system_highpri_wq, &data->throttle_work, in qcom_lmh_dcvs_notify()
372 mutex_unlock(&data->throttle_lock); in qcom_lmh_dcvs_notify()
388 disable_irq_nosync(c_data->throttle_irq); in qcom_lmh_dcvs_handle_irq()
389 schedule_delayed_work(&c_data->throttle_work, 0); in qcom_lmh_dcvs_handle_irq()
391 if (qcom_cpufreq.soc_data->reg_intr_clr) in qcom_lmh_dcvs_handle_irq()
393 c_data->base + qcom_cpufreq.soc_data->reg_intr_clr); in qcom_lmh_dcvs_handle_irq()
420 { .compatible = "qcom,cpufreq-hw", .data = &qcom_soc_data },
421 { .compatible = "qcom,cpufreq-epss", .data = &epss_soc_data },
428 struct qcom_cpufreq_data *data = policy->driver_data; in qcom_cpufreq_hw_lmh_init()
436 data->throttle_irq = platform_get_irq_optional(pdev, index); in qcom_cpufreq_hw_lmh_init()
437 if (data->throttle_irq == -ENXIO) in qcom_cpufreq_hw_lmh_init()
439 if (data->throttle_irq < 0) in qcom_cpufreq_hw_lmh_init()
440 return data->throttle_irq; in qcom_cpufreq_hw_lmh_init()
442 data->cancel_throttle = false; in qcom_cpufreq_hw_lmh_init()
443 data->policy = policy; in qcom_cpufreq_hw_lmh_init()
445 mutex_init(&data->throttle_lock); in qcom_cpufreq_hw_lmh_init()
446 INIT_DEFERRABLE_WORK(&data->throttle_work, qcom_lmh_dcvs_poll); in qcom_cpufreq_hw_lmh_init()
448 snprintf(data->irq_name, sizeof(data->irq_name), "dcvsh-irq-%u", policy->cpu); in qcom_cpufreq_hw_lmh_init()
449 ret = request_threaded_irq(data->throttle_irq, NULL, qcom_lmh_dcvs_handle_irq, in qcom_cpufreq_hw_lmh_init()
450 IRQF_ONESHOT | IRQF_NO_AUTOEN, data->irq_name, data); in qcom_cpufreq_hw_lmh_init()
452 dev_err(&pdev->dev, "Error registering %s: %d\n", data->irq_name, ret); in qcom_cpufreq_hw_lmh_init()
456 ret = irq_set_affinity_and_hint(data->throttle_irq, policy->cpus); in qcom_cpufreq_hw_lmh_init()
458 dev_err(&pdev->dev, "Failed to set CPU affinity of %s[%d]\n", in qcom_cpufreq_hw_lmh_init()
459 data->irq_name, data->throttle_irq); in qcom_cpufreq_hw_lmh_init()
466 struct qcom_cpufreq_data *data = policy->driver_data; in qcom_cpufreq_hw_cpu_online()
470 if (data->throttle_irq <= 0) in qcom_cpufreq_hw_cpu_online()
473 mutex_lock(&data->throttle_lock); in qcom_cpufreq_hw_cpu_online()
474 data->cancel_throttle = false; in qcom_cpufreq_hw_cpu_online()
475 mutex_unlock(&data->throttle_lock); in qcom_cpufreq_hw_cpu_online()
477 ret = irq_set_affinity_and_hint(data->throttle_irq, policy->cpus); in qcom_cpufreq_hw_cpu_online()
479 dev_err(&pdev->dev, "Failed to set CPU affinity of %s[%d]\n", in qcom_cpufreq_hw_cpu_online()
480 data->irq_name, data->throttle_irq); in qcom_cpufreq_hw_cpu_online()
487 struct qcom_cpufreq_data *data = policy->driver_data; in qcom_cpufreq_hw_cpu_offline()
489 if (data->throttle_irq <= 0) in qcom_cpufreq_hw_cpu_offline()
492 mutex_lock(&data->throttle_lock); in qcom_cpufreq_hw_cpu_offline()
493 data->cancel_throttle = true; in qcom_cpufreq_hw_cpu_offline()
494 mutex_unlock(&data->throttle_lock); in qcom_cpufreq_hw_cpu_offline()
496 cancel_delayed_work_sync(&data->throttle_work); in qcom_cpufreq_hw_cpu_offline()
497 irq_set_affinity_and_hint(data->throttle_irq, NULL); in qcom_cpufreq_hw_cpu_offline()
498 disable_irq_nosync(data->throttle_irq); in qcom_cpufreq_hw_cpu_offline()
505 if (data->throttle_irq <= 0) in qcom_cpufreq_hw_lmh_exit()
508 free_irq(data->throttle_irq, data); in qcom_cpufreq_hw_lmh_exit()
514 struct device *dev = &pdev->dev; in qcom_cpufreq_hw_cpu_init()
521 cpu_dev = get_cpu_device(policy->cpu); in qcom_cpufreq_hw_cpu_init()
524 policy->cpu); in qcom_cpufreq_hw_cpu_init()
525 return -ENODEV; in qcom_cpufreq_hw_cpu_init()
528 cpu_np = of_cpu_device_node_get(policy->cpu); in qcom_cpufreq_hw_cpu_init()
530 return -EINVAL; in qcom_cpufreq_hw_cpu_init()
532 ret = of_parse_phandle_with_args(cpu_np, "qcom,freq-domain", in qcom_cpufreq_hw_cpu_init()
533 "#freq-domain-cells", 0, &args); in qcom_cpufreq_hw_cpu_init()
542 if (!(readl_relaxed(data->base + qcom_cpufreq.soc_data->reg_enable) & 0x1)) { in qcom_cpufreq_hw_cpu_init()
543 dev_err(dev, "Domain-%d cpufreq hardware not enabled\n", index); in qcom_cpufreq_hw_cpu_init()
544 return -ENODEV; in qcom_cpufreq_hw_cpu_init()
547 if (readl_relaxed(data->base + qcom_cpufreq.soc_data->reg_dcvs_ctrl) & 0x1) in qcom_cpufreq_hw_cpu_init()
548 data->per_core_dcvs = true; in qcom_cpufreq_hw_cpu_init()
550 qcom_get_related_cpus(index, policy->cpus); in qcom_cpufreq_hw_cpu_init()
552 policy->driver_data = data; in qcom_cpufreq_hw_cpu_init()
553 policy->dvfs_possible_from_any_cpu = true; in qcom_cpufreq_hw_cpu_init()
557 dev_err(dev, "Domain-%d failed to read LUT\n", index); in qcom_cpufreq_hw_cpu_init()
564 return -ENODEV; in qcom_cpufreq_hw_cpu_init()
578 struct device *cpu_dev = get_cpu_device(policy->cpu); in qcom_cpufreq_hw_cpu_exit()
579 struct qcom_cpufreq_data *data = policy->driver_data; in qcom_cpufreq_hw_cpu_exit()
582 dev_pm_opp_of_cpumask_remove_table(policy->related_cpus); in qcom_cpufreq_hw_cpu_exit()
584 kfree(policy->freq_table); in qcom_cpufreq_hw_cpu_exit()
592 struct qcom_cpufreq_data *data = policy->driver_data; in qcom_cpufreq_ready()
594 if (data->throttle_irq >= 0) in qcom_cpufreq_ready()
595 enable_irq(data->throttle_irq); in qcom_cpufreq_ready()
617 .name = "qcom-cpufreq-hw",
636 struct device *dev = &pdev->dev; in qcom_cpufreq_hw_driver_probe()
660 return -EPROBE_DEFER; in qcom_cpufreq_hw_driver_probe()
673 return -ENOMEM; in qcom_cpufreq_hw_driver_probe()
677 return -ENODEV; in qcom_cpufreq_hw_driver_probe()
681 return -ENOMEM; in qcom_cpufreq_hw_driver_probe()
683 clk_data->num = num_domains; in qcom_cpufreq_hw_driver_probe()
696 data->base = base; in qcom_cpufreq_hw_driver_probe()
701 return -ENOMEM; in qcom_cpufreq_hw_driver_probe()
705 data->cpu_clk.init = &clk_init; in qcom_cpufreq_hw_driver_probe()
707 ret = devm_clk_hw_register(dev, &data->cpu_clk); in qcom_cpufreq_hw_driver_probe()
714 clk_data->hws[i] = &data->cpu_clk; in qcom_cpufreq_hw_driver_probe()
742 .name = "qcom-cpufreq-hw",