From b7b4e785520ff87383ab5131f903544a261e83a1 Mon Sep 17 00:00:00 2001 From: Jon Hunter Date: Wed, 2 Dec 2020 09:14:16 +0000 Subject: cpufreq: tegra186: Fix sparse 'incorrect type in assignment' warning Sparse warns that the incorrect type is being assigned to the CPUFREQ driver_data variable in the Tegra186 CPUFREQ driver. The Tegra186 CPUFREQ driver is assigned a type of 'void __iomem *' to a pointer of type 'void *' ... drivers/cpufreq/tegra186-cpufreq.c:72:37: sparse: sparse: incorrect type in assignment (different address spaces) @@ expected void *driver_data @@ got void [noderef] __iomem * @@ ... drivers/cpufreq/tegra186-cpufreq.c:87:40: sparse: sparse: incorrect type in initializer (different address spaces) @@ expected void [noderef] __iomem *edvd_reg @@ got void *driver_data @@ The Tegra186 CPUFREQ driver is using the policy->driver_data variable to store and iomem pointer to a Tegra186 CPU register that is used to set the clock speed for the CPU. This is not necessary because the register base address is already stored in the driver data and the offset of the register for each CPU is static. Therefore, fix this by adding a new structure with the register offsets for each CPU and store this in the main driver data structure along with the register base address. Please note that a new structure has been added for storing the register offsets rather than a simple array, because this will permit further clean-ups and simplification of the driver. Signed-off-by: Jon Hunter Signed-off-by: Viresh Kumar --- drivers/cpufreq/tegra186-cpufreq.c | 61 ++++++++++++++++++++++++++++---------- 1 file changed, 46 insertions(+), 15 deletions(-) (limited to 'drivers/cpufreq/tegra186-cpufreq.c') diff --git a/drivers/cpufreq/tegra186-cpufreq.c b/drivers/cpufreq/tegra186-cpufreq.c index 7eb2c56c65de..98b5f32eb0be 100644 --- a/drivers/cpufreq/tegra186-cpufreq.c +++ b/drivers/cpufreq/tegra186-cpufreq.c @@ -12,13 +12,45 @@ #include #include -#define EDVD_CORE_VOLT_FREQ(core) (0x20 + (core) * 0x4) -#define EDVD_CORE_VOLT_FREQ_F_SHIFT 0 -#define EDVD_CORE_VOLT_FREQ_F_MASK 0xffff -#define EDVD_CORE_VOLT_FREQ_V_SHIFT 16 +#define EDVD_OFFSET_A57(core) ((SZ_64K * 6) + (0x20 + (core) * 0x4)) +#define EDVD_OFFSET_DENVER(core) ((SZ_64K * 7) + (0x20 + (core) * 0x4)) +#define EDVD_CORE_VOLT_FREQ_F_SHIFT 0 +#define EDVD_CORE_VOLT_FREQ_F_MASK 0xffff +#define EDVD_CORE_VOLT_FREQ_V_SHIFT 16 + +struct tegra186_cpufreq_cpu { + unsigned int edvd_offset; +}; + +static const struct tegra186_cpufreq_cpu tegra186_cpus[] = { + /* CPU0 - A57 Cluster */ + { + .edvd_offset = EDVD_OFFSET_A57(0) + }, + /* CPU1 - Denver Cluster */ + { + .edvd_offset = EDVD_OFFSET_DENVER(0) + }, + /* CPU2 - Denver Cluster */ + { + .edvd_offset = EDVD_OFFSET_DENVER(1) + }, + /* CPU3 - A57 Cluster */ + { + .edvd_offset = EDVD_OFFSET_A57(1) + }, + /* CPU4 - A57 Cluster */ + { + .edvd_offset = EDVD_OFFSET_A57(2) + }, + /* CPU5 - A57 Cluster */ + { + .edvd_offset = EDVD_OFFSET_A57(3) + }, + +}; struct tegra186_cpufreq_cluster_info { - unsigned long offset; int cpus[4]; unsigned int bpmp_cluster_id; }; @@ -27,13 +59,11 @@ struct tegra186_cpufreq_cluster_info { static const struct tegra186_cpufreq_cluster_info tegra186_clusters[] = { /* Denver cluster */ { - .offset = SZ_64K * 7, .cpus = { 1, 2, NO_CPU, NO_CPU }, .bpmp_cluster_id = 0, }, /* A57 cluster */ { - .offset = SZ_64K * 6, .cpus = { 0, 3, 4, 5 }, .bpmp_cluster_id = 1, }, @@ -51,6 +81,7 @@ struct tegra186_cpufreq_data { size_t num_clusters; struct tegra186_cpufreq_cluster *clusters; + const struct tegra186_cpufreq_cpu *cpus; }; static int tegra186_cpufreq_init(struct cpufreq_policy *policy) @@ -71,13 +102,12 @@ static int tegra186_cpufreq_init(struct cpufreq_policy *policy) if (core == ARRAY_SIZE(info->cpus)) continue; - policy->driver_data = - data->regs + info->offset + EDVD_CORE_VOLT_FREQ(core); policy->freq_table = cluster->table; break; } policy->cpuinfo.transition_latency = 300 * 1000; + policy->driver_data = NULL; return 0; } @@ -85,11 +115,12 @@ static int tegra186_cpufreq_init(struct cpufreq_policy *policy) static int tegra186_cpufreq_set_target(struct cpufreq_policy *policy, unsigned int index) { + struct tegra186_cpufreq_data *data = cpufreq_get_driver_data(); struct cpufreq_frequency_table *tbl = policy->freq_table + index; - void __iomem *edvd_reg = policy->driver_data; + unsigned int edvd_offset = data->cpus[policy->cpu].edvd_offset; u32 edvd_val = tbl->driver_data; - writel(edvd_val, edvd_reg); + writel(edvd_val, data->regs + edvd_offset); return 0; } @@ -98,16 +129,15 @@ static unsigned int tegra186_cpufreq_get(unsigned int cpu) { struct tegra186_cpufreq_data *data = cpufreq_get_driver_data(); struct cpufreq_policy *policy; - void __iomem *edvd_reg; - unsigned int i, freq = 0; + unsigned int i, edvd_offset, freq = 0; u32 ndiv; policy = cpufreq_cpu_get(cpu); if (!policy) return 0; - edvd_reg = policy->driver_data; - ndiv = readl(edvd_reg) & EDVD_CORE_VOLT_FREQ_F_MASK; + edvd_offset = data->cpus[policy->cpu].edvd_offset; + ndiv = readl(data->regs + edvd_offset) & EDVD_CORE_VOLT_FREQ_F_MASK; for (i = 0; i < data->num_clusters; i++) { struct tegra186_cpufreq_cluster *cluster = &data->clusters[i]; @@ -240,6 +270,7 @@ static int tegra186_cpufreq_probe(struct platform_device *pdev) return -ENOMEM; data->num_clusters = ARRAY_SIZE(tegra186_clusters); + data->cpus = tegra186_cpus; bpmp = tegra_bpmp_get(&pdev->dev); if (IS_ERR(bpmp)) -- cgit v1.2.3 From cfef4bcaccf35f0b80acc5c79967996b2eb88ba6 Mon Sep 17 00:00:00 2001 From: Jon Hunter Date: Wed, 2 Dec 2020 09:14:17 +0000 Subject: cpufreq: tegra186: Simplify cluster information lookup The CPUFREQ driver framework references each individual CPUs when getting and setting the speed. Tegra186 has 3 clusters of A57 CPUs and 1 cluster of Denver CPUs. Hence, the Tegra186 CPUFREQ driver need to know which cluster a given CPU belongs to. The logic in the Tegra186 driver can be greatly simplified by storing the cluster ID associated with each CPU in the tegra186_cpufreq_cpu structure. This allow us to completely remove the Tegra cluster info structure from the driver and simplifiy the code. Signed-off-by: Jon Hunter Signed-off-by: Viresh Kumar --- drivers/cpufreq/tegra186-cpufreq.c | 85 +++++++++----------------------------- 1 file changed, 20 insertions(+), 65 deletions(-) (limited to 'drivers/cpufreq/tegra186-cpufreq.c') diff --git a/drivers/cpufreq/tegra186-cpufreq.c b/drivers/cpufreq/tegra186-cpufreq.c index 98b5f32eb0be..e566ea298b59 100644 --- a/drivers/cpufreq/tegra186-cpufreq.c +++ b/drivers/cpufreq/tegra186-cpufreq.c @@ -12,6 +12,7 @@ #include #include +#define TEGRA186_NUM_CLUSTERS 2 #define EDVD_OFFSET_A57(core) ((SZ_64K * 6) + (0x20 + (core) * 0x4)) #define EDVD_OFFSET_DENVER(core) ((SZ_64K * 7) + (0x20 + (core) * 0x4)) #define EDVD_CORE_VOLT_FREQ_F_SHIFT 0 @@ -19,58 +20,44 @@ #define EDVD_CORE_VOLT_FREQ_V_SHIFT 16 struct tegra186_cpufreq_cpu { + unsigned int bpmp_cluster_id; unsigned int edvd_offset; }; static const struct tegra186_cpufreq_cpu tegra186_cpus[] = { /* CPU0 - A57 Cluster */ { + .bpmp_cluster_id = 1, .edvd_offset = EDVD_OFFSET_A57(0) }, /* CPU1 - Denver Cluster */ { + .bpmp_cluster_id = 0, .edvd_offset = EDVD_OFFSET_DENVER(0) }, /* CPU2 - Denver Cluster */ { + .bpmp_cluster_id = 0, .edvd_offset = EDVD_OFFSET_DENVER(1) }, /* CPU3 - A57 Cluster */ { + .bpmp_cluster_id = 1, .edvd_offset = EDVD_OFFSET_A57(1) }, /* CPU4 - A57 Cluster */ { + .bpmp_cluster_id = 1, .edvd_offset = EDVD_OFFSET_A57(2) }, /* CPU5 - A57 Cluster */ { - .edvd_offset = EDVD_OFFSET_A57(3) - }, - -}; - -struct tegra186_cpufreq_cluster_info { - int cpus[4]; - unsigned int bpmp_cluster_id; -}; - -#define NO_CPU -1 -static const struct tegra186_cpufreq_cluster_info tegra186_clusters[] = { - /* Denver cluster */ - { - .cpus = { 1, 2, NO_CPU, NO_CPU }, - .bpmp_cluster_id = 0, - }, - /* A57 cluster */ - { - .cpus = { 0, 3, 4, 5 }, .bpmp_cluster_id = 1, + .edvd_offset = EDVD_OFFSET_A57(3) }, }; struct tegra186_cpufreq_cluster { - const struct tegra186_cpufreq_cluster_info *info; struct cpufreq_frequency_table *table; u32 ref_clk_khz; u32 div; @@ -78,8 +65,6 @@ struct tegra186_cpufreq_cluster { struct tegra186_cpufreq_data { void __iomem *regs; - - size_t num_clusters; struct tegra186_cpufreq_cluster *clusters; const struct tegra186_cpufreq_cpu *cpus; }; @@ -87,25 +72,9 @@ struct tegra186_cpufreq_data { static int tegra186_cpufreq_init(struct cpufreq_policy *policy) { struct tegra186_cpufreq_data *data = cpufreq_get_driver_data(); - unsigned int i; - - for (i = 0; i < data->num_clusters; i++) { - struct tegra186_cpufreq_cluster *cluster = &data->clusters[i]; - const struct tegra186_cpufreq_cluster_info *info = - cluster->info; - int core; - - for (core = 0; core < ARRAY_SIZE(info->cpus); core++) { - if (info->cpus[core] == policy->cpu) - break; - } - if (core == ARRAY_SIZE(info->cpus)) - continue; - - policy->freq_table = cluster->table; - break; - } + unsigned int cluster = data->cpus[policy->cpu].bpmp_cluster_id; + policy->freq_table = data->clusters[cluster].table; policy->cpuinfo.transition_latency = 300 * 1000; policy->driver_data = NULL; @@ -128,8 +97,9 @@ static int tegra186_cpufreq_set_target(struct cpufreq_policy *policy, static unsigned int tegra186_cpufreq_get(unsigned int cpu) { struct tegra186_cpufreq_data *data = cpufreq_get_driver_data(); + struct tegra186_cpufreq_cluster *cluster; struct cpufreq_policy *policy; - unsigned int i, edvd_offset, freq = 0; + unsigned int edvd_offset, cluster_id; u32 ndiv; policy = cpufreq_cpu_get(cpu); @@ -138,24 +108,11 @@ static unsigned int tegra186_cpufreq_get(unsigned int cpu) edvd_offset = data->cpus[policy->cpu].edvd_offset; ndiv = readl(data->regs + edvd_offset) & EDVD_CORE_VOLT_FREQ_F_MASK; - - for (i = 0; i < data->num_clusters; i++) { - struct tegra186_cpufreq_cluster *cluster = &data->clusters[i]; - int core; - - for (core = 0; core < ARRAY_SIZE(cluster->info->cpus); core++) { - if (cluster->info->cpus[core] != policy->cpu) - continue; - - freq = (cluster->ref_clk_khz * ndiv) / cluster->div; - goto out; - } - } - -out: + cluster_id = data->cpus[policy->cpu].bpmp_cluster_id; + cluster = &data->clusters[cluster_id]; cpufreq_cpu_put(policy); - return freq; + return (cluster->ref_clk_khz * ndiv) / cluster->div; } static struct cpufreq_driver tegra186_cpufreq_driver = { @@ -171,7 +128,7 @@ static struct cpufreq_driver tegra186_cpufreq_driver = { static struct cpufreq_frequency_table *init_vhint_table( struct platform_device *pdev, struct tegra_bpmp *bpmp, - struct tegra186_cpufreq_cluster *cluster) + struct tegra186_cpufreq_cluster *cluster, unsigned int cluster_id) { struct cpufreq_frequency_table *table; struct mrq_cpu_vhint_request req; @@ -190,7 +147,7 @@ static struct cpufreq_frequency_table *init_vhint_table( memset(&req, 0, sizeof(req)); req.addr = phys; - req.cluster_id = cluster->info->bpmp_cluster_id; + req.cluster_id = cluster_id; memset(&msg, 0, sizeof(msg)); msg.mrq = MRQ_CPU_VHINT; @@ -264,12 +221,11 @@ static int tegra186_cpufreq_probe(struct platform_device *pdev) if (!data) return -ENOMEM; - data->clusters = devm_kcalloc(&pdev->dev, ARRAY_SIZE(tegra186_clusters), + data->clusters = devm_kcalloc(&pdev->dev, TEGRA186_NUM_CLUSTERS, sizeof(*data->clusters), GFP_KERNEL); if (!data->clusters) return -ENOMEM; - data->num_clusters = ARRAY_SIZE(tegra186_clusters); data->cpus = tegra186_cpus; bpmp = tegra_bpmp_get(&pdev->dev); @@ -282,11 +238,10 @@ static int tegra186_cpufreq_probe(struct platform_device *pdev) goto put_bpmp; } - for (i = 0; i < data->num_clusters; i++) { + for (i = 0; i < TEGRA186_NUM_CLUSTERS; i++) { struct tegra186_cpufreq_cluster *cluster = &data->clusters[i]; - cluster->info = &tegra186_clusters[i]; - cluster->table = init_vhint_table(pdev, bpmp, cluster); + cluster->table = init_vhint_table(pdev, bpmp, cluster, i); if (IS_ERR(cluster->table)) { err = PTR_ERR(cluster->table); goto put_bpmp; -- cgit v1.2.3