/* cpufreq transisition latency */
 #define TEGRA_CPUFREQ_TRANSITION_LATENCY (300 * 1000) /* unit in nanoseconds */
 
+struct tegra_cpu_data {
+       u32 cpuid;
+       u32 clusterid;
+       void __iomem *freq_core_reg;
+};
+
 struct tegra_cpu_ctr {
        u32 cpu;
        u32 coreclk_cnt, last_coreclk_cnt;
        struct cpufreq_frequency_table **bpmp_luts;
        const struct tegra_cpufreq_soc *soc;
        bool icc_dram_bw_scaling;
+       struct tegra_cpu_data *cpu_data;
 };
 
 static struct workqueue_struct *read_counters_wq;
 static int tegra234_get_cpu_ndiv(u32 cpu, u32 cpuid, u32 clusterid, u64 *ndiv)
 {
        struct tegra194_cpufreq_data *data = cpufreq_get_driver_data();
-       void __iomem *freq_core_reg;
-       u64 mpidr_id;
-
-       /* use physical id to get address of per core frequency register */
-       mpidr_id = (clusterid * data->soc->maxcpus_per_cluster) + cpuid;
-       freq_core_reg = SCRATCH_FREQ_CORE_REG(data, mpidr_id);
 
-       *ndiv = readl(freq_core_reg) & NDIV_MASK;
+       *ndiv = readl(data->cpu_data[cpu].freq_core_reg) & NDIV_MASK;
 
        return 0;
 }
 static void tegra234_set_cpu_ndiv(struct cpufreq_policy *policy, u64 ndiv)
 {
        struct tegra194_cpufreq_data *data = cpufreq_get_driver_data();
-       void __iomem *freq_core_reg;
-       u32 cpu, cpuid, clusterid;
-       u64 mpidr_id;
-
-       for_each_cpu_and(cpu, policy->cpus, cpu_online_mask) {
-               data->soc->ops->get_cpu_cluster_id(cpu, &cpuid, &clusterid);
-
-               /* use physical id to get address of per core frequency register */
-               mpidr_id = (clusterid * data->soc->maxcpus_per_cluster) + cpuid;
-               freq_core_reg = SCRATCH_FREQ_CORE_REG(data, mpidr_id);
+       u32 cpu;
 
-               writel(ndiv, freq_core_reg);
-       }
+       for_each_cpu_and(cpu, policy->cpus, cpu_online_mask)
+               writel(ndiv, data->cpu_data[cpu].freq_core_reg);
 }
 
 /*
 {
        struct tegra194_cpufreq_data *data = cpufreq_get_driver_data();
        void __iomem *actmon_reg;
-       u32 cpuid, clusterid;
        u64 val;
 
-       data->soc->ops->get_cpu_cluster_id(c->cpu, &cpuid, &clusterid);
-       actmon_reg = CORE_ACTMON_CNTR_REG(data, clusterid, cpuid);
+       actmon_reg = CORE_ACTMON_CNTR_REG(data, data->cpu_data[c->cpu].clusterid,
+                                         data->cpu_data[c->cpu].cpuid);
 
        val = readq(actmon_reg);
        c->last_refclk_cnt = upper_32_bits(val);
 static unsigned int tegra194_get_speed(u32 cpu)
 {
        struct tegra194_cpufreq_data *data = cpufreq_get_driver_data();
+       u32 clusterid = data->cpu_data[cpu].clusterid;
        struct cpufreq_frequency_table *pos;
-       u32 cpuid, clusterid;
        unsigned int rate;
        u64 ndiv;
        int ret;
 
-       data->soc->ops->get_cpu_cluster_id(cpu, &cpuid, &clusterid);
-
        /* reconstruct actual cpu freq using counters */
        rate = tegra194_calculate_speed(cpu);
 
        /* get last written ndiv value */
-       ret = data->soc->ops->get_cpu_ndiv(cpu, cpuid, clusterid, &ndiv);
+       ret = data->soc->ops->get_cpu_ndiv(cpu, data->cpu_data[cpu].cpuid, clusterid, &ndiv);
        if (WARN_ON_ONCE(ret))
                return rate;
 
 {
        struct tegra194_cpufreq_data *data = cpufreq_get_driver_data();
        int maxcpus_per_cluster = data->soc->maxcpus_per_cluster;
+       u32 clusterid = data->cpu_data[policy->cpu].clusterid;
        struct cpufreq_frequency_table *freq_table;
        struct cpufreq_frequency_table *bpmp_lut;
        u32 start_cpu, cpu;
-       u32 clusterid;
        int ret;
 
-       data->soc->ops->get_cpu_cluster_id(policy->cpu, NULL, &clusterid);
        if (clusterid >= data->soc->num_clusters || !data->bpmp_luts[clusterid])
                return -EINVAL;
 
        return freq_table;
 }
 
+static int tegra194_cpufreq_store_physids(unsigned int cpu, struct tegra194_cpufreq_data *data)
+{
+       int num_cpus = data->soc->maxcpus_per_cluster * data->soc->num_clusters;
+       u32 cpuid, clusterid;
+       u64 mpidr_id;
+
+       if (cpu > (num_cpus - 1)) {
+               pr_err("cpufreq: wrong num of cpus or clusters in soc data\n");
+               return -EINVAL;
+       }
+
+       data->soc->ops->get_cpu_cluster_id(cpu, &cpuid, &clusterid);
+
+       mpidr_id = (clusterid * data->soc->maxcpus_per_cluster) + cpuid;
+
+       data->cpu_data[cpu].cpuid = cpuid;
+       data->cpu_data[cpu].clusterid = clusterid;
+       data->cpu_data[cpu].freq_core_reg = SCRATCH_FREQ_CORE_REG(data, mpidr_id);
+
+       return 0;
+}
+
 static int tegra194_cpufreq_probe(struct platform_device *pdev)
 {
        const struct tegra_cpufreq_soc *soc;
        struct tegra_bpmp *bpmp;
        struct device *cpu_dev;
        int err, i;
+       u32 cpu;
 
        data = devm_kzalloc(&pdev->dev, sizeof(*data), GFP_KERNEL);
        if (!data)
                        return PTR_ERR(data->regs);
        }
 
+       data->cpu_data = devm_kcalloc(&pdev->dev, data->soc->num_clusters *
+                                     data->soc->maxcpus_per_cluster,
+                                     sizeof(*data->cpu_data), GFP_KERNEL);
+       if (!data->cpu_data)
+               return -ENOMEM;
+
        platform_set_drvdata(pdev, data);
 
        bpmp = tegra_bpmp_get(&pdev->dev);
                }
        }
 
+       for_each_possible_cpu(cpu) {
+               err = tegra194_cpufreq_store_physids(cpu, data);
+               if (err)
+                       goto err_free_res;
+       }
+
        tegra194_cpufreq_driver.driver_data = data;
 
        /* Check for optional OPPv2 and interconnect paths on CPU0 to enable ICC scaling */