1/* 2 * Copyright 2013 Freescale Semiconductor, Inc. 3 * 4 * CPU Frequency Scaling driver for Freescale QorIQ SoCs. 5 * 6 * This program is free software; you can redistribute it and/or modify 7 * it under the terms of the GNU General Public License version 2 as 8 * published by the Free Software Foundation. 9 */ 10 11#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt 12 13#include <linux/clk.h> 14#include <linux/cpufreq.h> 15#include <linux/errno.h> 16#include <linux/init.h> 17#include <linux/kernel.h> 18#include <linux/module.h> 19#include <linux/mutex.h> 20#include <linux/of.h> 21#include <linux/slab.h> 22#include <linux/smp.h> 23 24#if !defined(CONFIG_ARM) 25#include <asm/smp.h> /* for get_hard_smp_processor_id() in UP configs */ 26#endif 27 28/** 29 * struct cpu_data 30 * @pclk: the parent clock of cpu 31 * @table: frequency table 32 */ 33struct cpu_data { 34 struct clk **pclk; 35 struct cpufreq_frequency_table *table; 36}; 37 38/** 39 * struct soc_data - SoC specific data 40 * @freq_mask: mask the disallowed frequencies 41 * @flag: unique flags 42 */ 43struct soc_data { 44 u32 freq_mask[4]; 45 u32 flag; 46}; 47 48#define FREQ_MASK 1 49/* see hardware specification for the allowed frqeuencies */ 50static const struct soc_data sdata[] = { 51 { /* used by p2041 and p3041 */ 52 .freq_mask = {0x8, 0x8, 0x2, 0x2}, 53 .flag = FREQ_MASK, 54 }, 55 { /* used by p5020 */ 56 .freq_mask = {0x8, 0x2}, 57 .flag = FREQ_MASK, 58 }, 59 { /* used by p4080, p5040 */ 60 .freq_mask = {0}, 61 .flag = 0, 62 }, 63}; 64 65/* 66 * the minimum allowed core frequency, in Hz 67 * for chassis v1.0, >= platform frequency 68 * for chassis v2.0, >= platform frequency / 2 69 */ 70static u32 min_cpufreq; 71static const u32 *fmask; 72 73#if defined(CONFIG_ARM) 74static int get_cpu_physical_id(int cpu) 75{ 76 return topology_core_id(cpu); 77} 78#else 79static int get_cpu_physical_id(int cpu) 80{ 81 return get_hard_smp_processor_id(cpu); 82} 83#endif 84 85static u32 get_bus_freq(void) 86{ 87 struct device_node *soc; 88 u32 sysfreq; 89 90 soc = of_find_node_by_type(NULL, "soc"); 91 if (!soc) 92 return 0; 93 94 if (of_property_read_u32(soc, "bus-frequency", &sysfreq)) 95 sysfreq = 0; 96 97 of_node_put(soc); 98 99 return sysfreq; 100} 101 102static struct device_node *cpu_to_clk_node(int cpu) 103{ 104 struct device_node *np, *clk_np; 105 106 if (!cpu_present(cpu)) 107 return NULL; 108 109 np = of_get_cpu_node(cpu, NULL); 110 if (!np) 111 return NULL; 112 113 clk_np = of_parse_phandle(np, "clocks", 0); 114 if (!clk_np) 115 return NULL; 116 117 of_node_put(np); 118 119 return clk_np; 120} 121 122/* traverse cpu nodes to get cpu mask of sharing clock wire */ 123static void set_affected_cpus(struct cpufreq_policy *policy) 124{ 125 struct device_node *np, *clk_np; 126 struct cpumask *dstp = policy->cpus; 127 int i; 128 129 np = cpu_to_clk_node(policy->cpu); 130 if (!np) 131 return; 132 133 for_each_present_cpu(i) { 134 clk_np = cpu_to_clk_node(i); 135 if (!clk_np) 136 continue; 137 138 if (clk_np == np) 139 cpumask_set_cpu(i, dstp); 140 141 of_node_put(clk_np); 142 } 143 of_node_put(np); 144} 145 146/* reduce the duplicated frequencies in frequency table */ 147static void freq_table_redup(struct cpufreq_frequency_table *freq_table, 148 int count) 149{ 150 int i, j; 151 152 for (i = 1; i < count; i++) { 153 for (j = 0; j < i; j++) { 154 if (freq_table[j].frequency == CPUFREQ_ENTRY_INVALID || 155 freq_table[j].frequency != 156 freq_table[i].frequency) 157 continue; 158 159 freq_table[i].frequency = CPUFREQ_ENTRY_INVALID; 160 break; 161 } 162 } 163} 164 165/* sort the frequencies in frequency table in descenting order */ 166static void freq_table_sort(struct cpufreq_frequency_table *freq_table, 167 int count) 168{ 169 int i, j, ind; 170 unsigned int freq, max_freq; 171 struct cpufreq_frequency_table table; 172 173 for (i = 0; i < count - 1; i++) { 174 max_freq = freq_table[i].frequency; 175 ind = i; 176 for (j = i + 1; j < count; j++) { 177 freq = freq_table[j].frequency; 178 if (freq == CPUFREQ_ENTRY_INVALID || 179 freq <= max_freq) 180 continue; 181 ind = j; 182 max_freq = freq; 183 } 184 185 if (ind != i) { 186 /* exchange the frequencies */ 187 table.driver_data = freq_table[i].driver_data; 188 table.frequency = freq_table[i].frequency; 189 freq_table[i].driver_data = freq_table[ind].driver_data; 190 freq_table[i].frequency = freq_table[ind].frequency; 191 freq_table[ind].driver_data = table.driver_data; 192 freq_table[ind].frequency = table.frequency; 193 } 194 } 195} 196 197static int qoriq_cpufreq_cpu_init(struct cpufreq_policy *policy) 198{ 199 struct device_node *np, *pnode; 200 int i, count, ret; 201 u32 freq, mask; 202 struct clk *clk; 203 struct cpufreq_frequency_table *table; 204 struct cpu_data *data; 205 unsigned int cpu = policy->cpu; 206 u64 u64temp; 207 208 np = of_get_cpu_node(cpu, NULL); 209 if (!np) 210 return -ENODEV; 211 212 data = kzalloc(sizeof(*data), GFP_KERNEL); 213 if (!data) 214 goto err_np; 215 216 policy->clk = of_clk_get(np, 0); 217 if (IS_ERR(policy->clk)) { 218 pr_err("%s: no clock information\n", __func__); 219 goto err_nomem2; 220 } 221 222 pnode = of_parse_phandle(np, "clocks", 0); 223 if (!pnode) { 224 pr_err("%s: could not get clock information\n", __func__); 225 goto err_nomem2; 226 } 227 228 count = of_property_count_strings(pnode, "clock-names"); 229 data->pclk = kcalloc(count, sizeof(struct clk *), GFP_KERNEL); 230 if (!data->pclk) { 231 pr_err("%s: no memory\n", __func__); 232 goto err_node; 233 } 234 235 table = kcalloc(count + 1, sizeof(*table), GFP_KERNEL); 236 if (!table) { 237 pr_err("%s: no memory\n", __func__); 238 goto err_pclk; 239 } 240 241 if (fmask) 242 mask = fmask[get_cpu_physical_id(cpu)]; 243 else 244 mask = 0x0; 245 246 for (i = 0; i < count; i++) { 247 clk = of_clk_get(pnode, i); 248 data->pclk[i] = clk; 249 freq = clk_get_rate(clk); 250 /* 251 * the clock is valid if its frequency is not masked 252 * and large than minimum allowed frequency. 253 */ 254 if (freq < min_cpufreq || (mask & (1 << i))) 255 table[i].frequency = CPUFREQ_ENTRY_INVALID; 256 else 257 table[i].frequency = freq / 1000; 258 table[i].driver_data = i; 259 } 260 freq_table_redup(table, count); 261 freq_table_sort(table, count); 262 table[i].frequency = CPUFREQ_TABLE_END; 263 264 /* set the min and max frequency properly */ 265 ret = cpufreq_table_validate_and_show(policy, table); 266 if (ret) { 267 pr_err("invalid frequency table: %d\n", ret); 268 goto err_nomem1; 269 } 270 271 data->table = table; 272 273 /* update ->cpus if we have cluster, no harm if not */ 274 set_affected_cpus(policy); 275 policy->driver_data = data; 276 277 /* Minimum transition latency is 12 platform clocks */ 278 u64temp = 12ULL * NSEC_PER_SEC; 279 do_div(u64temp, get_bus_freq()); 280 policy->cpuinfo.transition_latency = u64temp + 1; 281 282 of_node_put(np); 283 of_node_put(pnode); 284 285 return 0; 286 287err_nomem1: 288 kfree(table); 289err_pclk: 290 kfree(data->pclk); 291err_node: 292 of_node_put(pnode); 293err_nomem2: 294 policy->driver_data = NULL; 295 kfree(data); 296err_np: 297 of_node_put(np); 298 299 return -ENODEV; 300} 301 302static int __exit qoriq_cpufreq_cpu_exit(struct cpufreq_policy *policy) 303{ 304 struct cpu_data *data = policy->driver_data; 305 306 kfree(data->pclk); 307 kfree(data->table); 308 kfree(data); 309 policy->driver_data = NULL; 310 311 return 0; 312} 313 314static int qoriq_cpufreq_target(struct cpufreq_policy *policy, 315 unsigned int index) 316{ 317 struct clk *parent; 318 struct cpu_data *data = policy->driver_data; 319 320 parent = data->pclk[data->table[index].driver_data]; 321 return clk_set_parent(policy->clk, parent); 322} 323 324static struct cpufreq_driver qoriq_cpufreq_driver = { 325 .name = "qoriq_cpufreq", 326 .flags = CPUFREQ_CONST_LOOPS, 327 .init = qoriq_cpufreq_cpu_init, 328 .exit = __exit_p(qoriq_cpufreq_cpu_exit), 329 .verify = cpufreq_generic_frequency_table_verify, 330 .target_index = qoriq_cpufreq_target, 331 .get = cpufreq_generic_get, 332 .attr = cpufreq_generic_attr, 333}; 334 335static const struct of_device_id node_matches[] __initconst = { 336 { .compatible = "fsl,p2041-clockgen", .data = &sdata[0], }, 337 { .compatible = "fsl,p3041-clockgen", .data = &sdata[0], }, 338 { .compatible = "fsl,p5020-clockgen", .data = &sdata[1], }, 339 { .compatible = "fsl,p4080-clockgen", .data = &sdata[2], }, 340 { .compatible = "fsl,p5040-clockgen", .data = &sdata[2], }, 341 { .compatible = "fsl,qoriq-clockgen-2.0", }, 342 {} 343}; 344 345static int __init qoriq_cpufreq_init(void) 346{ 347 int ret; 348 struct device_node *np; 349 const struct of_device_id *match; 350 const struct soc_data *data; 351 352 np = of_find_matching_node(NULL, node_matches); 353 if (!np) 354 return -ENODEV; 355 356 match = of_match_node(node_matches, np); 357 data = match->data; 358 if (data) { 359 if (data->flag) 360 fmask = data->freq_mask; 361 min_cpufreq = get_bus_freq(); 362 } else { 363 min_cpufreq = get_bus_freq() / 2; 364 } 365 366 of_node_put(np); 367 368 ret = cpufreq_register_driver(&qoriq_cpufreq_driver); 369 if (!ret) 370 pr_info("Freescale QorIQ CPU frequency scaling driver\n"); 371 372 return ret; 373} 374module_init(qoriq_cpufreq_init); 375 376static void __exit qoriq_cpufreq_exit(void) 377{ 378 cpufreq_unregister_driver(&qoriq_cpufreq_driver); 379} 380module_exit(qoriq_cpufreq_exit); 381 382MODULE_LICENSE("GPL"); 383MODULE_AUTHOR("Tang Yuantian <Yuantian.Tang@freescale.com>"); 384MODULE_DESCRIPTION("cpufreq driver for Freescale QorIQ series SoCs"); 385