0001
0002
0003
0004
0005
0006
0007
0008 #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
0009
0010 #include <linux/clk.h>
0011 #include <linux/clk-provider.h>
0012 #include <linux/cpufreq.h>
0013 #include <linux/errno.h>
0014 #include <linux/init.h>
0015 #include <linux/kernel.h>
0016 #include <linux/module.h>
0017 #include <linux/mutex.h>
0018 #include <linux/of.h>
0019 #include <linux/slab.h>
0020 #include <linux/smp.h>
0021 #include <linux/platform_device.h>
0022
0023
0024
0025
0026
0027
0028 struct cpu_data {
0029 struct clk **pclk;
0030 struct cpufreq_frequency_table *table;
0031 };
0032
0033
0034
0035
0036
0037 struct soc_data {
0038 u32 flags;
0039 };
0040
0041 static u32 get_bus_freq(void)
0042 {
0043 struct device_node *soc;
0044 u32 sysfreq;
0045 struct clk *pltclk;
0046 int ret;
0047
0048
0049 soc = of_find_node_by_type(NULL, "soc");
0050 if (soc) {
0051 ret = of_property_read_u32(soc, "bus-frequency", &sysfreq);
0052 of_node_put(soc);
0053 if (!ret)
0054 return sysfreq;
0055 }
0056
0057
0058 pltclk = clk_get(NULL, "cg-pll0-div1");
0059 if (IS_ERR(pltclk)) {
0060 pr_err("%s: can't get bus frequency %ld\n",
0061 __func__, PTR_ERR(pltclk));
0062 return PTR_ERR(pltclk);
0063 }
0064
0065 return clk_get_rate(pltclk);
0066 }
0067
0068 static struct clk *cpu_to_clk(int cpu)
0069 {
0070 struct device_node *np;
0071 struct clk *clk;
0072
0073 if (!cpu_present(cpu))
0074 return NULL;
0075
0076 np = of_get_cpu_node(cpu, NULL);
0077 if (!np)
0078 return NULL;
0079
0080 clk = of_clk_get(np, 0);
0081 of_node_put(np);
0082 return clk;
0083 }
0084
0085
0086 static void set_affected_cpus(struct cpufreq_policy *policy)
0087 {
0088 struct cpumask *dstp = policy->cpus;
0089 struct clk *clk;
0090 int i;
0091
0092 for_each_present_cpu(i) {
0093 clk = cpu_to_clk(i);
0094 if (IS_ERR(clk)) {
0095 pr_err("%s: no clock for cpu %d\n", __func__, i);
0096 continue;
0097 }
0098
0099 if (clk_is_match(policy->clk, clk))
0100 cpumask_set_cpu(i, dstp);
0101 }
0102 }
0103
0104
0105 static void freq_table_redup(struct cpufreq_frequency_table *freq_table,
0106 int count)
0107 {
0108 int i, j;
0109
0110 for (i = 1; i < count; i++) {
0111 for (j = 0; j < i; j++) {
0112 if (freq_table[j].frequency == CPUFREQ_ENTRY_INVALID ||
0113 freq_table[j].frequency !=
0114 freq_table[i].frequency)
0115 continue;
0116
0117 freq_table[i].frequency = CPUFREQ_ENTRY_INVALID;
0118 break;
0119 }
0120 }
0121 }
0122
0123
0124 static void freq_table_sort(struct cpufreq_frequency_table *freq_table,
0125 int count)
0126 {
0127 int i, j, ind;
0128 unsigned int freq, max_freq;
0129 struct cpufreq_frequency_table table;
0130
0131 for (i = 0; i < count - 1; i++) {
0132 max_freq = freq_table[i].frequency;
0133 ind = i;
0134 for (j = i + 1; j < count; j++) {
0135 freq = freq_table[j].frequency;
0136 if (freq == CPUFREQ_ENTRY_INVALID ||
0137 freq <= max_freq)
0138 continue;
0139 ind = j;
0140 max_freq = freq;
0141 }
0142
0143 if (ind != i) {
0144
0145 table.driver_data = freq_table[i].driver_data;
0146 table.frequency = freq_table[i].frequency;
0147 freq_table[i].driver_data = freq_table[ind].driver_data;
0148 freq_table[i].frequency = freq_table[ind].frequency;
0149 freq_table[ind].driver_data = table.driver_data;
0150 freq_table[ind].frequency = table.frequency;
0151 }
0152 }
0153 }
0154
0155 static int qoriq_cpufreq_cpu_init(struct cpufreq_policy *policy)
0156 {
0157 struct device_node *np;
0158 int i, count;
0159 u32 freq;
0160 struct clk *clk;
0161 const struct clk_hw *hwclk;
0162 struct cpufreq_frequency_table *table;
0163 struct cpu_data *data;
0164 unsigned int cpu = policy->cpu;
0165 u64 u64temp;
0166
0167 np = of_get_cpu_node(cpu, NULL);
0168 if (!np)
0169 return -ENODEV;
0170
0171 data = kzalloc(sizeof(*data), GFP_KERNEL);
0172 if (!data)
0173 goto err_np;
0174
0175 policy->clk = of_clk_get(np, 0);
0176 if (IS_ERR(policy->clk)) {
0177 pr_err("%s: no clock information\n", __func__);
0178 goto err_nomem2;
0179 }
0180
0181 hwclk = __clk_get_hw(policy->clk);
0182 count = clk_hw_get_num_parents(hwclk);
0183
0184 data->pclk = kcalloc(count, sizeof(struct clk *), GFP_KERNEL);
0185 if (!data->pclk)
0186 goto err_nomem2;
0187
0188 table = kcalloc(count + 1, sizeof(*table), GFP_KERNEL);
0189 if (!table)
0190 goto err_pclk;
0191
0192 for (i = 0; i < count; i++) {
0193 clk = clk_hw_get_parent_by_index(hwclk, i)->clk;
0194 data->pclk[i] = clk;
0195 freq = clk_get_rate(clk);
0196 table[i].frequency = freq / 1000;
0197 table[i].driver_data = i;
0198 }
0199 freq_table_redup(table, count);
0200 freq_table_sort(table, count);
0201 table[i].frequency = CPUFREQ_TABLE_END;
0202 policy->freq_table = table;
0203 data->table = table;
0204
0205
0206 set_affected_cpus(policy);
0207 policy->driver_data = data;
0208
0209
0210 u64temp = 12ULL * NSEC_PER_SEC;
0211 do_div(u64temp, get_bus_freq());
0212 policy->cpuinfo.transition_latency = u64temp + 1;
0213
0214 of_node_put(np);
0215
0216 return 0;
0217
0218 err_pclk:
0219 kfree(data->pclk);
0220 err_nomem2:
0221 kfree(data);
0222 err_np:
0223 of_node_put(np);
0224
0225 return -ENODEV;
0226 }
0227
0228 static int qoriq_cpufreq_cpu_exit(struct cpufreq_policy *policy)
0229 {
0230 struct cpu_data *data = policy->driver_data;
0231
0232 kfree(data->pclk);
0233 kfree(data->table);
0234 kfree(data);
0235 policy->driver_data = NULL;
0236
0237 return 0;
0238 }
0239
0240 static int qoriq_cpufreq_target(struct cpufreq_policy *policy,
0241 unsigned int index)
0242 {
0243 struct clk *parent;
0244 struct cpu_data *data = policy->driver_data;
0245
0246 parent = data->pclk[data->table[index].driver_data];
0247 return clk_set_parent(policy->clk, parent);
0248 }
0249
0250 static struct cpufreq_driver qoriq_cpufreq_driver = {
0251 .name = "qoriq_cpufreq",
0252 .flags = CPUFREQ_CONST_LOOPS |
0253 CPUFREQ_IS_COOLING_DEV,
0254 .init = qoriq_cpufreq_cpu_init,
0255 .exit = qoriq_cpufreq_cpu_exit,
0256 .verify = cpufreq_generic_frequency_table_verify,
0257 .target_index = qoriq_cpufreq_target,
0258 .get = cpufreq_generic_get,
0259 .attr = cpufreq_generic_attr,
0260 };
0261
0262 static const struct of_device_id qoriq_cpufreq_blacklist[] = {
0263
0264 { .compatible = "fsl,b4420-clockgen", },
0265 { .compatible = "fsl,b4860-clockgen", },
0266 { .compatible = "fsl,t2080-clockgen", },
0267 { .compatible = "fsl,t4240-clockgen", },
0268 {}
0269 };
0270
0271 static int qoriq_cpufreq_probe(struct platform_device *pdev)
0272 {
0273 int ret;
0274 struct device_node *np;
0275
0276 np = of_find_matching_node(NULL, qoriq_cpufreq_blacklist);
0277 if (np) {
0278 of_node_put(np);
0279 dev_info(&pdev->dev, "Disabling due to erratum A-008083");
0280 return -ENODEV;
0281 }
0282
0283 ret = cpufreq_register_driver(&qoriq_cpufreq_driver);
0284 if (ret)
0285 return ret;
0286
0287 dev_info(&pdev->dev, "Freescale QorIQ CPU frequency scaling driver\n");
0288 return 0;
0289 }
0290
0291 static int qoriq_cpufreq_remove(struct platform_device *pdev)
0292 {
0293 cpufreq_unregister_driver(&qoriq_cpufreq_driver);
0294
0295 return 0;
0296 }
0297
0298 static struct platform_driver qoriq_cpufreq_platform_driver = {
0299 .driver = {
0300 .name = "qoriq-cpufreq",
0301 },
0302 .probe = qoriq_cpufreq_probe,
0303 .remove = qoriq_cpufreq_remove,
0304 };
0305 module_platform_driver(qoriq_cpufreq_platform_driver);
0306
0307 MODULE_ALIAS("platform:qoriq-cpufreq");
0308 MODULE_LICENSE("GPL");
0309 MODULE_AUTHOR("Tang Yuantian <Yuantian.Tang@freescale.com>");
0310 MODULE_DESCRIPTION("cpufreq driver for Freescale QorIQ series SoCs");