From 71821a2fe9d250fcd93bb9c140e4eda5ebd49ba0 Mon Sep 17 00:00:00 2001 From: Taniya Das Date: Mon, 3 Aug 2020 23:52:57 +0530 Subject: [PATCH] cpufreq: qcom: Add support for performance lock feature In the case where the 'qcom,perf-lock-support' feature is enabled the memory region bases would be required to be provided from the device node. Any DCVS request requires the shared memory region to be updated before the cpufreq-hw perf desired register is updated. Change-Id: I16d068d3311edf8e32654ab29070d4721a7c1493 Signed-off-by: Taniya Das --- drivers/cpufreq/qcom-cpufreq-hw.c | 30 +++++++++++++++++++++++++++++- 1 file changed, 29 insertions(+), 1 deletion(-) diff --git a/drivers/cpufreq/qcom-cpufreq-hw.c b/drivers/cpufreq/qcom-cpufreq-hw.c index 2585e0bc3c93..9ecc76b23d5f 100644 --- a/drivers/cpufreq/qcom-cpufreq-hw.c +++ b/drivers/cpufreq/qcom-cpufreq-hw.c @@ -29,7 +29,7 @@ #define LUT_ROW_SIZE 32 #define CLK_HW_DIV 2 #define GT_IRQ_STATUS BIT(2) -#define MAX_FN_SIZE 12 +#define MAX_FN_SIZE 20 #define LIMITS_POLLING_DELAY_MS 10 #define CYCLE_CNTR_OFFSET(c, m, acc_count) \ @@ -54,10 +54,12 @@ static const u16 *offsets; static unsigned int lut_row_size = LUT_ROW_SIZE; static unsigned int lut_max_entries = LUT_MAX_ENTRIES; static bool accumulative_counter; +static bool perf_lock_support; struct cpufreq_qcom { struct cpufreq_frequency_table *table; void __iomem *base; + void __iomem *pdmem_base; cpumask_t related_cpus; unsigned long dcvsh_freq_limit; struct delayed_work freq_poll_work; @@ -234,6 +236,14 @@ static int qcom_cpufreq_hw_target_index(struct cpufreq_policy *policy, unsigned int index) { + struct cpufreq_qcom *c; + + if (perf_lock_support) { + c = qcom_freq_domain_map[policy->cpu]; + if (c->pdmem_base) + writel_relaxed(index, c->pdmem_base); + } + writel_relaxed(index, policy->driver_data + offsets[REG_PERF_STATE]); arch_set_freq_scale(policy->related_cpus, policy->freq_table[index].frequency, @@ -469,6 +479,7 @@ static int qcom_cpu_resources_init(struct platform_device *pdev, struct resource *res; struct device *dev = &pdev->dev; void __iomem *base; + char pdmem_name[MAX_FN_SIZE] = {}; int ret, cpu_r; c = devm_kzalloc(dev, sizeof(*c), GFP_KERNEL); @@ -509,6 +520,23 @@ static int qcom_cpu_resources_init(struct platform_device *pdev, return ret; } + perf_lock_support = of_property_read_bool(dev->of_node, + "qcom,perf-lock-support"); + if (perf_lock_support) { + snprintf(pdmem_name, sizeof(pdmem_name), "pdmem-domain%d", + index); + res = platform_get_resource_byname(pdev, IORESOURCE_MEM, + pdmem_name); + if (!res) + dev_err(dev, "PDMEM domain-%d failed\n", index); + + base = devm_ioremap_resource(dev, res); + if (IS_ERR(base)) + dev_err(dev, "Failed to map PDMEM domain-%d\n", index); + else + c->pdmem_base = base; + } + if (of_find_property(dev->of_node, "interrupts", NULL)) { c->dcvsh_irq = of_irq_get(dev->of_node, index); if (c->dcvsh_irq > 0) {