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 * @parent: the parent node of cpu clock 31 * @table: frequency table 32 */ 33 struct cpu_data { 34 struct device_node *parent; 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 */ 43 struct 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 */ 50 static 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 */ 70 static u32 min_cpufreq; 71 static const u32 *fmask; 72 73 #if defined(CONFIG_ARM) 74 static int get_cpu_physical_id(int cpu) 75 { 76 return topology_core_id(cpu); 77 } 78 #else 79 static int get_cpu_physical_id(int cpu) 80 { 81 return get_hard_smp_processor_id(cpu); 82 } 83 #endif 84 85 static 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 102 static 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 */ 123 static 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 */ 147 static 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 */ 166 static 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 197 static int qoriq_cpufreq_cpu_init(struct cpufreq_policy *policy) 198 { 199 struct device_node *np; 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 data->parent = of_parse_phandle(np, "clocks", 0); 223 if (!data->parent) { 224 pr_err("%s: could not get clock information\n", __func__); 225 goto err_nomem2; 226 } 227 228 count = of_property_count_strings(data->parent, "clock-names"); 229 table = kcalloc(count + 1, sizeof(*table), GFP_KERNEL); 230 if (!table) { 231 pr_err("%s: no memory\n", __func__); 232 goto err_node; 233 } 234 235 if (fmask) 236 mask = fmask[get_cpu_physical_id(cpu)]; 237 else 238 mask = 0x0; 239 240 for (i = 0; i < count; i++) { 241 clk = of_clk_get(data->parent, i); 242 freq = clk_get_rate(clk); 243 /* 244 * the clock is valid if its frequency is not masked 245 * and large than minimum allowed frequency. 246 */ 247 if (freq < min_cpufreq || (mask & (1 << i))) 248 table[i].frequency = CPUFREQ_ENTRY_INVALID; 249 else 250 table[i].frequency = freq / 1000; 251 table[i].driver_data = i; 252 } 253 freq_table_redup(table, count); 254 freq_table_sort(table, count); 255 table[i].frequency = CPUFREQ_TABLE_END; 256 257 /* set the min and max frequency properly */ 258 ret = cpufreq_table_validate_and_show(policy, table); 259 if (ret) { 260 pr_err("invalid frequency table: %d\n", ret); 261 goto err_nomem1; 262 } 263 264 data->table = table; 265 266 /* update ->cpus if we have cluster, no harm if not */ 267 set_affected_cpus(policy); 268 policy->driver_data = data; 269 270 /* Minimum transition latency is 12 platform clocks */ 271 u64temp = 12ULL * NSEC_PER_SEC; 272 do_div(u64temp, get_bus_freq()); 273 policy->cpuinfo.transition_latency = u64temp + 1; 274 275 of_node_put(np); 276 277 return 0; 278 279 err_nomem1: 280 kfree(table); 281 err_node: 282 of_node_put(data->parent); 283 err_nomem2: 284 policy->driver_data = NULL; 285 kfree(data); 286 err_np: 287 of_node_put(np); 288 289 return -ENODEV; 290 } 291 292 static int __exit qoriq_cpufreq_cpu_exit(struct cpufreq_policy *policy) 293 { 294 struct cpu_data *data = policy->driver_data; 295 296 of_node_put(data->parent); 297 kfree(data->table); 298 kfree(data); 299 policy->driver_data = NULL; 300 301 return 0; 302 } 303 304 static int qoriq_cpufreq_target(struct cpufreq_policy *policy, 305 unsigned int index) 306 { 307 struct clk *parent; 308 struct cpu_data *data = policy->driver_data; 309 310 parent = of_clk_get(data->parent, data->table[index].driver_data); 311 return clk_set_parent(policy->clk, parent); 312 } 313 314 static struct cpufreq_driver qoriq_cpufreq_driver = { 315 .name = "qoriq_cpufreq", 316 .flags = CPUFREQ_CONST_LOOPS, 317 .init = qoriq_cpufreq_cpu_init, 318 .exit = __exit_p(qoriq_cpufreq_cpu_exit), 319 .verify = cpufreq_generic_frequency_table_verify, 320 .target_index = qoriq_cpufreq_target, 321 .get = cpufreq_generic_get, 322 .attr = cpufreq_generic_attr, 323 }; 324 325 static const struct of_device_id node_matches[] __initconst = { 326 { .compatible = "fsl,p2041-clockgen", .data = &sdata[0], }, 327 { .compatible = "fsl,p3041-clockgen", .data = &sdata[0], }, 328 { .compatible = "fsl,p5020-clockgen", .data = &sdata[1], }, 329 { .compatible = "fsl,p4080-clockgen", .data = &sdata[2], }, 330 { .compatible = "fsl,p5040-clockgen", .data = &sdata[2], }, 331 { .compatible = "fsl,qoriq-clockgen-2.0", }, 332 {} 333 }; 334 335 static int __init qoriq_cpufreq_init(void) 336 { 337 int ret; 338 struct device_node *np; 339 const struct of_device_id *match; 340 const struct soc_data *data; 341 342 np = of_find_matching_node(NULL, node_matches); 343 if (!np) 344 return -ENODEV; 345 346 match = of_match_node(node_matches, np); 347 data = match->data; 348 if (data) { 349 if (data->flag) 350 fmask = data->freq_mask; 351 min_cpufreq = get_bus_freq(); 352 } else { 353 min_cpufreq = get_bus_freq() / 2; 354 } 355 356 of_node_put(np); 357 358 ret = cpufreq_register_driver(&qoriq_cpufreq_driver); 359 if (!ret) 360 pr_info("Freescale QorIQ CPU frequency scaling driver\n"); 361 362 return ret; 363 } 364 module_init(qoriq_cpufreq_init); 365 366 static void __exit qoriq_cpufreq_exit(void) 367 { 368 cpufreq_unregister_driver(&qoriq_cpufreq_driver); 369 } 370 module_exit(qoriq_cpufreq_exit); 371 372 MODULE_LICENSE("GPL"); 373 MODULE_AUTHOR("Tang Yuantian <Yuantian.Tang@freescale.com>"); 374 MODULE_DESCRIPTION("cpufreq driver for Freescale QorIQ series SoCs"); 375