Loading drivers/cpufreq/qcom-cpufreq-hw.c +21 −30 Original line number Diff line number Diff line Loading @@ -23,8 +23,7 @@ #define CORE_COUNT_VAL(val) (((val) & (GENMASK(18, 16))) >> 16) #define LUT_ROW_SIZE 32 #define CLK_HW_DIV 2 #define EQ_IRQ_STATUS BIT(0) #define LT_IRQ_STATUS BIT(1) #define GT_IRQ_STATUS BIT(2) #define MAX_FN_SIZE 12 #define LIMITS_POLLING_DELAY_MS 10 Loading @@ -37,7 +36,7 @@ enum { REG_VOLT_LUT_TABLE, REG_PERF_STATE, REG_CYCLE_CNTR, REG_LLM_DCVS_VC_VOTE, REG_DOMAIN_STATE, REG_INTR_EN, REG_INTR_CLR, REG_INTR_STATUS, Loading Loading @@ -86,7 +85,7 @@ static const u16 cpufreq_qcom_epss_std_offsets[REG_ARRAY_SIZE] = { [REG_VOLT_LUT_TABLE] = 0x200, [REG_PERF_STATE] = 0x320, [REG_CYCLE_CNTR] = 0x3c4, [REG_LLM_DCVS_VC_VOTE] = 0x024, [REG_DOMAIN_STATE] = 0x020, [REG_INTR_EN] = 0x304, [REG_INTR_CLR] = 0x308, [REG_INTR_STATUS] = 0x30C, Loading @@ -95,6 +94,8 @@ static const u16 cpufreq_qcom_epss_std_offsets[REG_ARRAY_SIZE] = { static struct cpufreq_counter qcom_cpufreq_counter[NR_CPUS]; static struct cpufreq_qcom *qcom_freq_domain_map[NR_CPUS]; static unsigned int qcom_cpufreq_hw_get(unsigned int cpu); static ssize_t dcvsh_freq_limit_show(struct device *dev, struct device_attribute *attr, char *buf) { Loading @@ -105,48 +106,40 @@ static ssize_t dcvsh_freq_limit_show(struct device *dev, static unsigned long limits_mitigation_notify(struct cpufreq_qcom *c) { int i; u32 max_vc; unsigned long freq; max_vc = readl_relaxed(c->reg_bases[REG_LLM_DCVS_VC_VOTE]) & GENMASK(13, 8); freq = readl_relaxed(c->reg_bases[REG_DOMAIN_STATE]) & GENMASK(7, 0); freq = DIV_ROUND_CLOSEST_ULL(freq * c->xo_rate, 1000); for (i = 0; i < lut_max_entries; i++) { if (c->table[i].driver_data != max_vc) continue; else { sched_update_cpu_freq_min_max(&c->related_cpus, 0, c->table[i].frequency); trace_dcvsh_freq(cpumask_first(&c->related_cpus), c->table[i].frequency); c->dcvsh_freq_limit = c->table[i].frequency; return c->table[i].frequency; } } sched_update_cpu_freq_min_max(&c->related_cpus, 0, freq); trace_dcvsh_freq(cpumask_first(&c->related_cpus), freq); c->dcvsh_freq_limit = freq; return 0; return freq; } static void limits_dcvsh_poll(struct work_struct *work) { struct cpufreq_qcom *c = container_of(work, struct cpufreq_qcom, freq_poll_work.work); struct cpufreq_policy *policy; unsigned long freq_limit; unsigned long freq_limit, dcvsh_freq; u32 regval, cpu; mutex_lock(&c->dcvsh_lock); cpu = cpumask_first(&c->related_cpus); policy = cpufreq_cpu_get_raw(cpu); freq_limit = limits_mitigation_notify(c); if (freq_limit != policy->cpuinfo.max_freq || !freq_limit) { dcvsh_freq = qcom_cpufreq_hw_get(cpu); if (freq_limit != dcvsh_freq) { mod_delayed_work(system_highpri_wq, &c->freq_poll_work, msecs_to_jiffies(LIMITS_POLLING_DELAY_MS)); } else { regval = readl_relaxed(c->reg_bases[REG_INTR_CLR]); regval &= ~LT_IRQ_STATUS; regval |= GT_IRQ_STATUS; writel_relaxed(regval, c->reg_bases[REG_INTR_CLR]); c->is_irq_enabled = true; Loading @@ -162,7 +155,7 @@ static irqreturn_t dcvsh_handle_isr(int irq, void *data) u32 regval; regval = readl_relaxed(c->reg_bases[REG_INTR_STATUS]); if (!(regval & LT_IRQ_STATUS)) if (!(regval & GT_IRQ_STATUS)) return IRQ_HANDLED; mutex_lock(&c->dcvsh_lock); Loading Loading @@ -301,7 +294,7 @@ static int qcom_cpufreq_hw_cpu_init(struct cpufreq_policy *policy) "dcvsh-irq-%d", policy->cpu); ret = devm_request_threaded_irq(cpu_dev, c->dcvsh_irq, NULL, dcvsh_handle_isr, IRQF_TRIGGER_HIGH | IRQF_ONESHOT | IRQF_NO_SUSPEND | IRQF_SHARED, c->dcvsh_irq_name, c); IRQF_NO_SUSPEND, c->dcvsh_irq_name, c); if (ret) { dev_err(cpu_dev, "Failed to register irq %d\n", ret); return ret; Loading @@ -309,7 +302,6 @@ static int qcom_cpufreq_hw_cpu_init(struct cpufreq_policy *policy) c->is_irq_requested = true; c->is_irq_enabled = true; writel_relaxed(LT_IRQ_STATUS, c->reg_bases[REG_INTR_EN]); c->freq_limit_attr.attr.name = "dcvsh_freq_limit"; c->freq_limit_attr.show = dcvsh_freq_limit_show; c->freq_limit_attr.attr.mode = 0444; Loading Loading @@ -401,7 +393,6 @@ static int qcom_cpufreq_hw_read_lut(struct platform_device *pdev, else c->table[i].frequency = c->cpu_hw_rate / 1000; c->table[i].driver_data = vc; cur_freq = c->table[i].frequency; dev_dbg(dev, "index=%d freq=%d, core_count %d\n", Loading Loading
drivers/cpufreq/qcom-cpufreq-hw.c +21 −30 Original line number Diff line number Diff line Loading @@ -23,8 +23,7 @@ #define CORE_COUNT_VAL(val) (((val) & (GENMASK(18, 16))) >> 16) #define LUT_ROW_SIZE 32 #define CLK_HW_DIV 2 #define EQ_IRQ_STATUS BIT(0) #define LT_IRQ_STATUS BIT(1) #define GT_IRQ_STATUS BIT(2) #define MAX_FN_SIZE 12 #define LIMITS_POLLING_DELAY_MS 10 Loading @@ -37,7 +36,7 @@ enum { REG_VOLT_LUT_TABLE, REG_PERF_STATE, REG_CYCLE_CNTR, REG_LLM_DCVS_VC_VOTE, REG_DOMAIN_STATE, REG_INTR_EN, REG_INTR_CLR, REG_INTR_STATUS, Loading Loading @@ -86,7 +85,7 @@ static const u16 cpufreq_qcom_epss_std_offsets[REG_ARRAY_SIZE] = { [REG_VOLT_LUT_TABLE] = 0x200, [REG_PERF_STATE] = 0x320, [REG_CYCLE_CNTR] = 0x3c4, [REG_LLM_DCVS_VC_VOTE] = 0x024, [REG_DOMAIN_STATE] = 0x020, [REG_INTR_EN] = 0x304, [REG_INTR_CLR] = 0x308, [REG_INTR_STATUS] = 0x30C, Loading @@ -95,6 +94,8 @@ static const u16 cpufreq_qcom_epss_std_offsets[REG_ARRAY_SIZE] = { static struct cpufreq_counter qcom_cpufreq_counter[NR_CPUS]; static struct cpufreq_qcom *qcom_freq_domain_map[NR_CPUS]; static unsigned int qcom_cpufreq_hw_get(unsigned int cpu); static ssize_t dcvsh_freq_limit_show(struct device *dev, struct device_attribute *attr, char *buf) { Loading @@ -105,48 +106,40 @@ static ssize_t dcvsh_freq_limit_show(struct device *dev, static unsigned long limits_mitigation_notify(struct cpufreq_qcom *c) { int i; u32 max_vc; unsigned long freq; max_vc = readl_relaxed(c->reg_bases[REG_LLM_DCVS_VC_VOTE]) & GENMASK(13, 8); freq = readl_relaxed(c->reg_bases[REG_DOMAIN_STATE]) & GENMASK(7, 0); freq = DIV_ROUND_CLOSEST_ULL(freq * c->xo_rate, 1000); for (i = 0; i < lut_max_entries; i++) { if (c->table[i].driver_data != max_vc) continue; else { sched_update_cpu_freq_min_max(&c->related_cpus, 0, c->table[i].frequency); trace_dcvsh_freq(cpumask_first(&c->related_cpus), c->table[i].frequency); c->dcvsh_freq_limit = c->table[i].frequency; return c->table[i].frequency; } } sched_update_cpu_freq_min_max(&c->related_cpus, 0, freq); trace_dcvsh_freq(cpumask_first(&c->related_cpus), freq); c->dcvsh_freq_limit = freq; return 0; return freq; } static void limits_dcvsh_poll(struct work_struct *work) { struct cpufreq_qcom *c = container_of(work, struct cpufreq_qcom, freq_poll_work.work); struct cpufreq_policy *policy; unsigned long freq_limit; unsigned long freq_limit, dcvsh_freq; u32 regval, cpu; mutex_lock(&c->dcvsh_lock); cpu = cpumask_first(&c->related_cpus); policy = cpufreq_cpu_get_raw(cpu); freq_limit = limits_mitigation_notify(c); if (freq_limit != policy->cpuinfo.max_freq || !freq_limit) { dcvsh_freq = qcom_cpufreq_hw_get(cpu); if (freq_limit != dcvsh_freq) { mod_delayed_work(system_highpri_wq, &c->freq_poll_work, msecs_to_jiffies(LIMITS_POLLING_DELAY_MS)); } else { regval = readl_relaxed(c->reg_bases[REG_INTR_CLR]); regval &= ~LT_IRQ_STATUS; regval |= GT_IRQ_STATUS; writel_relaxed(regval, c->reg_bases[REG_INTR_CLR]); c->is_irq_enabled = true; Loading @@ -162,7 +155,7 @@ static irqreturn_t dcvsh_handle_isr(int irq, void *data) u32 regval; regval = readl_relaxed(c->reg_bases[REG_INTR_STATUS]); if (!(regval & LT_IRQ_STATUS)) if (!(regval & GT_IRQ_STATUS)) return IRQ_HANDLED; mutex_lock(&c->dcvsh_lock); Loading Loading @@ -301,7 +294,7 @@ static int qcom_cpufreq_hw_cpu_init(struct cpufreq_policy *policy) "dcvsh-irq-%d", policy->cpu); ret = devm_request_threaded_irq(cpu_dev, c->dcvsh_irq, NULL, dcvsh_handle_isr, IRQF_TRIGGER_HIGH | IRQF_ONESHOT | IRQF_NO_SUSPEND | IRQF_SHARED, c->dcvsh_irq_name, c); IRQF_NO_SUSPEND, c->dcvsh_irq_name, c); if (ret) { dev_err(cpu_dev, "Failed to register irq %d\n", ret); return ret; Loading @@ -309,7 +302,6 @@ static int qcom_cpufreq_hw_cpu_init(struct cpufreq_policy *policy) c->is_irq_requested = true; c->is_irq_enabled = true; writel_relaxed(LT_IRQ_STATUS, c->reg_bases[REG_INTR_EN]); c->freq_limit_attr.attr.name = "dcvsh_freq_limit"; c->freq_limit_attr.show = dcvsh_freq_limit_show; c->freq_limit_attr.attr.mode = 0444; Loading Loading @@ -401,7 +393,6 @@ static int qcom_cpufreq_hw_read_lut(struct platform_device *pdev, else c->table[i].frequency = c->cpu_hw_rate / 1000; c->table[i].driver_data = vc; cur_freq = c->table[i].frequency; dev_dbg(dev, "index=%d freq=%d, core_count %d\n", Loading