Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

cpufreq: qoriq: Don't look at clock implementation details

Get the CPU clock's potential parent clocks from the clock interface
itself, rather than manually parsing the clocks property to find a
phandle, looking at the clock-names property of that, and assuming that
those are valid parent clocks for the cpu clock.

This is necessary now that the clocks are generated based on the clock
driver's knowledge of the chip rather than a fragile device-tree
description of the mux options.

We can now rely on the clock driver to ensure that the mux only exposes
options that are valid. The cpufreq driver was currently being overly
conservative in some cases -- for example, the "min_cpufreq =
get_bus_freq()" restriction only applies to chips with erratum
A-004510, and whether the freq_mask used on p5020 is needed depends on
the actual frequencies of the PLLs (FWIW, p5040 has a similar
limitation but its .freq_mask was zero) -- and the frequency mask
mechanism made assumptions about particular parent clock indices that
are no longer valid.

Signed-off-by: Scott Wood <scottwood@nxp.com>
Signed-off-by: Tang Yuantian <yuantian.tang@nxp.com>
Acked-by: Viresh Kumar <viresh.kumar@linaro.org>
Signed-off-by: Rafael J. Wysocki <rafael.j.wysocki@intel.com>

authored by

Tang Yuantian and committed by
Rafael J. Wysocki
b1e9a649 5026ac23

+49 -99
+49 -99
drivers/cpufreq/qoriq-cpufreq.c
··· 11 11 #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt 12 12 13 13 #include <linux/clk.h> 14 + #include <linux/clk-provider.h> 14 15 #include <linux/cpufreq.h> 15 16 #include <linux/cpu_cooling.h> 16 17 #include <linux/errno.h> ··· 38 37 struct thermal_cooling_device *cdev; 39 38 }; 40 39 40 + /* 41 + * Don't use cpufreq on this SoC -- used when the SoC would have otherwise 42 + * matched a more generic compatible. 43 + */ 44 + #define SOC_BLACKLIST 1 45 + 41 46 /** 42 47 * struct soc_data - SoC specific data 43 - * @freq_mask: mask the disallowed frequencies 44 - * @flag: unique flags 48 + * @flags: SOC_xxx 45 49 */ 46 50 struct soc_data { 47 - u32 freq_mask[4]; 48 - u32 flag; 51 + u32 flags; 49 52 }; 50 - 51 - #define FREQ_MASK 1 52 - /* see hardware specification for the allowed frqeuencies */ 53 - static const struct soc_data sdata[] = { 54 - { /* used by p2041 and p3041 */ 55 - .freq_mask = {0x8, 0x8, 0x2, 0x2}, 56 - .flag = FREQ_MASK, 57 - }, 58 - { /* used by p5020 */ 59 - .freq_mask = {0x8, 0x2}, 60 - .flag = FREQ_MASK, 61 - }, 62 - { /* used by p4080, p5040 */ 63 - .freq_mask = {0}, 64 - .flag = 0, 65 - }, 66 - }; 67 - 68 - /* 69 - * the minimum allowed core frequency, in Hz 70 - * for chassis v1.0, >= platform frequency 71 - * for chassis v2.0, >= platform frequency / 2 72 - */ 73 - static u32 min_cpufreq; 74 - static const u32 *fmask; 75 - 76 - #if defined(CONFIG_ARM) 77 - static int get_cpu_physical_id(int cpu) 78 - { 79 - return topology_core_id(cpu); 80 - } 81 - #else 82 - static int get_cpu_physical_id(int cpu) 83 - { 84 - return get_hard_smp_processor_id(cpu); 85 - } 86 - #endif 87 53 88 54 static u32 get_bus_freq(void) 89 55 { ··· 69 101 return sysfreq; 70 102 } 71 103 72 - static struct device_node *cpu_to_clk_node(int cpu) 104 + static struct clk *cpu_to_clk(int cpu) 73 105 { 74 - struct device_node *np, *clk_np; 106 + struct device_node *np; 107 + struct clk *clk; 75 108 76 109 if (!cpu_present(cpu)) 77 110 return NULL; ··· 81 112 if (!np) 82 113 return NULL; 83 114 84 - clk_np = of_parse_phandle(np, "clocks", 0); 85 - if (!clk_np) 86 - return NULL; 87 - 115 + clk = of_clk_get(np, 0); 88 116 of_node_put(np); 89 - 90 - return clk_np; 117 + return clk; 91 118 } 92 119 93 120 /* traverse cpu nodes to get cpu mask of sharing clock wire */ 94 121 static void set_affected_cpus(struct cpufreq_policy *policy) 95 122 { 96 - struct device_node *np, *clk_np; 97 123 struct cpumask *dstp = policy->cpus; 124 + struct clk *clk; 98 125 int i; 99 126 100 - np = cpu_to_clk_node(policy->cpu); 101 - if (!np) 102 - return; 103 - 104 127 for_each_present_cpu(i) { 105 - clk_np = cpu_to_clk_node(i); 106 - if (!clk_np) 128 + clk = cpu_to_clk(i); 129 + if (IS_ERR(clk)) { 130 + pr_err("%s: no clock for cpu %d\n", __func__, i); 107 131 continue; 132 + } 108 133 109 - if (clk_np == np) 134 + if (clk_is_match(policy->clk, clk)) 110 135 cpumask_set_cpu(i, dstp); 111 - 112 - of_node_put(clk_np); 113 136 } 114 - of_node_put(np); 115 137 } 116 138 117 139 /* reduce the duplicated frequencies in frequency table */ ··· 158 198 159 199 static int qoriq_cpufreq_cpu_init(struct cpufreq_policy *policy) 160 200 { 161 - struct device_node *np, *pnode; 201 + struct device_node *np; 162 202 int i, count, ret; 163 - u32 freq, mask; 203 + u32 freq; 164 204 struct clk *clk; 205 + const struct clk_hw *hwclk; 165 206 struct cpufreq_frequency_table *table; 166 207 struct cpu_data *data; 167 208 unsigned int cpu = policy->cpu; ··· 182 221 goto err_nomem2; 183 222 } 184 223 185 - pnode = of_parse_phandle(np, "clocks", 0); 186 - if (!pnode) { 187 - pr_err("%s: could not get clock information\n", __func__); 188 - goto err_nomem2; 189 - } 224 + hwclk = __clk_get_hw(policy->clk); 225 + count = clk_hw_get_num_parents(hwclk); 190 226 191 - count = of_property_count_strings(pnode, "clock-names"); 192 227 data->pclk = kcalloc(count, sizeof(struct clk *), GFP_KERNEL); 193 228 if (!data->pclk) { 194 229 pr_err("%s: no memory\n", __func__); 195 - goto err_node; 230 + goto err_nomem2; 196 231 } 197 232 198 233 table = kcalloc(count + 1, sizeof(*table), GFP_KERNEL); ··· 197 240 goto err_pclk; 198 241 } 199 242 200 - if (fmask) 201 - mask = fmask[get_cpu_physical_id(cpu)]; 202 - else 203 - mask = 0x0; 204 - 205 243 for (i = 0; i < count; i++) { 206 - clk = of_clk_get(pnode, i); 244 + clk = clk_hw_get_parent_by_index(hwclk, i)->clk; 207 245 data->pclk[i] = clk; 208 246 freq = clk_get_rate(clk); 209 - /* 210 - * the clock is valid if its frequency is not masked 211 - * and large than minimum allowed frequency. 212 - */ 213 - if (freq < min_cpufreq || (mask & (1 << i))) 214 - table[i].frequency = CPUFREQ_ENTRY_INVALID; 215 - else 216 - table[i].frequency = freq / 1000; 247 + table[i].frequency = freq / 1000; 217 248 table[i].driver_data = i; 218 249 } 219 250 freq_table_redup(table, count); ··· 227 282 policy->cpuinfo.transition_latency = u64temp + 1; 228 283 229 284 of_node_put(np); 230 - of_node_put(pnode); 231 285 232 286 return 0; 233 287 ··· 234 290 kfree(table); 235 291 err_pclk: 236 292 kfree(data->pclk); 237 - err_node: 238 - of_node_put(pnode); 239 293 err_nomem2: 240 - policy->driver_data = NULL; 241 294 kfree(data); 242 295 err_np: 243 296 of_node_put(np); ··· 298 357 .attr = cpufreq_generic_attr, 299 358 }; 300 359 360 + static const struct soc_data blacklist = { 361 + .flags = SOC_BLACKLIST, 362 + }; 363 + 301 364 static const struct of_device_id node_matches[] __initconst = { 302 - { .compatible = "fsl,p2041-clockgen", .data = &sdata[0], }, 303 - { .compatible = "fsl,p3041-clockgen", .data = &sdata[0], }, 304 - { .compatible = "fsl,p5020-clockgen", .data = &sdata[1], }, 305 - { .compatible = "fsl,p4080-clockgen", .data = &sdata[2], }, 306 - { .compatible = "fsl,p5040-clockgen", .data = &sdata[2], }, 365 + /* e6500 cannot use cpufreq due to erratum A-008083 */ 366 + { .compatible = "fsl,b4420-clockgen", &blacklist }, 367 + { .compatible = "fsl,b4860-clockgen", &blacklist }, 368 + { .compatible = "fsl,t2080-clockgen", &blacklist }, 369 + { .compatible = "fsl,t4240-clockgen", &blacklist }, 370 + 371 + { .compatible = "fsl,ls1012a-clockgen", }, 372 + { .compatible = "fsl,ls1021a-clockgen", }, 373 + { .compatible = "fsl,ls1043a-clockgen", }, 374 + { .compatible = "fsl,ls1046a-clockgen", }, 375 + { .compatible = "fsl,ls1088a-clockgen", }, 376 + { .compatible = "fsl,ls2080a-clockgen", }, 377 + { .compatible = "fsl,p4080-clockgen", }, 378 + { .compatible = "fsl,qoriq-clockgen-1.0", }, 307 379 { .compatible = "fsl,qoriq-clockgen-2.0", }, 308 380 {} 309 381 }; ··· 334 380 335 381 match = of_match_node(node_matches, np); 336 382 data = match->data; 337 - if (data) { 338 - if (data->flag) 339 - fmask = data->freq_mask; 340 - min_cpufreq = get_bus_freq(); 341 - } else { 342 - min_cpufreq = get_bus_freq() / 2; 343 - } 344 383 345 384 of_node_put(np); 385 + 386 + if (data && data->flags & SOC_BLACKLIST) 387 + return -ENODEV; 346 388 347 389 ret = cpufreq_register_driver(&qoriq_cpufreq_driver); 348 390 if (!ret)