brintos

brintos / linux-shallow public Read only

0
0
Text · 8.7 KiB · ed1ae06 Raw
322 lines · c
1// SPDX-License-Identifier: GPL-2.0-or-later2/*3 *  Copyright (C) 2002,2003 Intrinsyc Software4 *5 * History:6 *   31-Jul-2002 : Initial version [FB]7 *   29-Jan-2003 : added PXA255 support [FB]8 *   20-Apr-2003 : ported to v2.5 (Dustin McIntire, Sensoria Corp.)9 *10 * Note:11 *   This driver may change the memory bus clock rate, but will not do any12 *   platform specific access timing changes... for example if you have flash13 *   memory connected to CS0, you will need to register a platform specific14 *   notifier which will adjust the memory access strobes to maintain a15 *   minimum strobe width.16 */17 18#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt19 20#include <linux/kernel.h>21#include <linux/module.h>22#include <linux/sched.h>23#include <linux/init.h>24#include <linux/cpufreq.h>25#include <linux/err.h>26#include <linux/regulator/consumer.h>27#include <linux/soc/pxa/cpu.h>28#include <linux/io.h>29 30#ifdef DEBUG31static unsigned int freq_debug;32module_param(freq_debug, uint, 0);33MODULE_PARM_DESC(freq_debug, "Set the debug messages to on=1/off=0");34#else35#define freq_debug  036#endif37 38static struct regulator *vcc_core;39 40static unsigned int pxa27x_maxfreq;41module_param(pxa27x_maxfreq, uint, 0);42MODULE_PARM_DESC(pxa27x_maxfreq, "Set the pxa27x maxfreq in MHz"43		 "(typically 624=>pxa270, 416=>pxa271, 520=>pxa272)");44 45struct pxa_cpufreq_data {46	struct clk *clk_core;47};48static struct pxa_cpufreq_data  pxa_cpufreq_data;49 50struct pxa_freqs {51	unsigned int khz;52	int vmin;53	int vmax;54};55 56/*57 * PXA255 definitions58 */59static const struct pxa_freqs pxa255_run_freqs[] =60{61	/* CPU   MEMBUS		   run  turbo PXbus SDRAM */62	{ 99500, -1, -1},	/*  99,   99,   50,   50  */63	{132700, -1, -1},	/* 133,  133,   66,   66  */64	{199100, -1, -1},	/* 199,  199,   99,   99  */65	{265400, -1, -1},	/* 265,  265,  133,   66  */66	{331800, -1, -1},	/* 331,  331,  166,   83  */67	{398100, -1, -1},	/* 398,  398,  196,   99  */68};69 70/* Use the turbo mode frequencies for the CPUFREQ_POLICY_POWERSAVE policy */71static const struct pxa_freqs pxa255_turbo_freqs[] =72{73	/* CPU			   run  turbo PXbus SDRAM */74	{ 99500, -1, -1},	/*  99,   99,   50,   50  */75	{199100, -1, -1},	/*  99,  199,   50,   99  */76	{298500, -1, -1},	/*  99,  287,   50,   99  */77	{298600, -1, -1},	/* 199,  287,   99,   99  */78	{398100, -1, -1},	/* 199,  398,   99,   99  */79};80 81#define NUM_PXA25x_RUN_FREQS ARRAY_SIZE(pxa255_run_freqs)82#define NUM_PXA25x_TURBO_FREQS ARRAY_SIZE(pxa255_turbo_freqs)83 84static struct cpufreq_frequency_table85	pxa255_run_freq_table[NUM_PXA25x_RUN_FREQS+1];86static struct cpufreq_frequency_table87	pxa255_turbo_freq_table[NUM_PXA25x_TURBO_FREQS+1];88 89static unsigned int pxa255_turbo_table;90module_param(pxa255_turbo_table, uint, 0);91MODULE_PARM_DESC(pxa255_turbo_table, "Selects the frequency table (0 = run table, !0 = turbo table)");92 93static struct pxa_freqs pxa27x_freqs[] = {94	{104000,  900000, 1705000 },95	{156000, 1000000, 1705000 },96	{208000, 1180000, 1705000 },97	{312000, 1250000, 1705000 },98	{416000, 1350000, 1705000 },99	{520000, 1450000, 1705000 },100	{624000, 1550000, 1705000 }101};102 103#define NUM_PXA27x_FREQS ARRAY_SIZE(pxa27x_freqs)104static struct cpufreq_frequency_table105	pxa27x_freq_table[NUM_PXA27x_FREQS+1];106 107#ifdef CONFIG_REGULATOR108 109static int pxa_cpufreq_change_voltage(const struct pxa_freqs *pxa_freq)110{111	int ret = 0;112	int vmin, vmax;113 114	if (!cpu_is_pxa27x())115		return 0;116 117	vmin = pxa_freq->vmin;118	vmax = pxa_freq->vmax;119	if ((vmin == -1) || (vmax == -1))120		return 0;121 122	ret = regulator_set_voltage(vcc_core, vmin, vmax);123	if (ret)124		pr_err("Failed to set vcc_core in [%dmV..%dmV]\n", vmin, vmax);125	return ret;126}127 128static void pxa_cpufreq_init_voltages(void)129{130	vcc_core = regulator_get(NULL, "vcc_core");131	if (IS_ERR(vcc_core)) {132		pr_info("Didn't find vcc_core regulator\n");133		vcc_core = NULL;134	} else {135		pr_info("Found vcc_core regulator\n");136	}137}138#else139static int pxa_cpufreq_change_voltage(const struct pxa_freqs *pxa_freq)140{141	return 0;142}143 144static void pxa_cpufreq_init_voltages(void) { }145#endif146 147static void find_freq_tables(struct cpufreq_frequency_table **freq_table,148			     const struct pxa_freqs **pxa_freqs)149{150	if (cpu_is_pxa25x()) {151		if (!pxa255_turbo_table) {152			*pxa_freqs = pxa255_run_freqs;153			*freq_table = pxa255_run_freq_table;154		} else {155			*pxa_freqs = pxa255_turbo_freqs;156			*freq_table = pxa255_turbo_freq_table;157		}158	} else if (cpu_is_pxa27x()) {159		*pxa_freqs = pxa27x_freqs;160		*freq_table = pxa27x_freq_table;161	} else {162		BUG();163	}164}165 166static void pxa27x_guess_max_freq(void)167{168	if (!pxa27x_maxfreq) {169		pxa27x_maxfreq = 416000;170		pr_info("PXA CPU 27x max frequency not defined (pxa27x_maxfreq), assuming pxa271 with %dkHz maxfreq\n",171			pxa27x_maxfreq);172	} else {173		pxa27x_maxfreq *= 1000;174	}175}176 177static unsigned int pxa_cpufreq_get(unsigned int cpu)178{179	struct pxa_cpufreq_data *data = cpufreq_get_driver_data();180 181	return (unsigned int) clk_get_rate(data->clk_core) / 1000;182}183 184static int pxa_set_target(struct cpufreq_policy *policy, unsigned int idx)185{186	struct cpufreq_frequency_table *pxa_freqs_table;187	const struct pxa_freqs *pxa_freq_settings;188	struct pxa_cpufreq_data *data = cpufreq_get_driver_data();189	unsigned int new_freq_cpu;190	int ret = 0;191 192	/* Get the current policy */193	find_freq_tables(&pxa_freqs_table, &pxa_freq_settings);194 195	new_freq_cpu = pxa_freq_settings[idx].khz;196 197	if (freq_debug)198		pr_debug("Changing CPU frequency from %d Mhz to %d Mhz\n",199			 policy->cur / 1000,  new_freq_cpu / 1000);200 201	if (vcc_core && new_freq_cpu > policy->cur) {202		ret = pxa_cpufreq_change_voltage(&pxa_freq_settings[idx]);203		if (ret)204			return ret;205	}206 207	clk_set_rate(data->clk_core, new_freq_cpu * 1000);208 209	/*210	 * Even if voltage setting fails, we don't report it, as the frequency211	 * change succeeded. The voltage reduction is not a critical failure,212	 * only power savings will suffer from this.213	 *214	 * Note: if the voltage change fails, and a return value is returned, a215	 * bug is triggered (seems a deadlock). Should anybody find out where,216	 * the "return 0" should become a "return ret".217	 */218	if (vcc_core && new_freq_cpu < policy->cur)219		ret = pxa_cpufreq_change_voltage(&pxa_freq_settings[idx]);220 221	return 0;222}223 224static int pxa_cpufreq_init(struct cpufreq_policy *policy)225{226	int i;227	unsigned int freq;228	struct cpufreq_frequency_table *pxa255_freq_table;229	const struct pxa_freqs *pxa255_freqs;230 231	/* try to guess pxa27x cpu */232	if (cpu_is_pxa27x())233		pxa27x_guess_max_freq();234 235	pxa_cpufreq_init_voltages();236 237	/* set default policy and cpuinfo */238	policy->cpuinfo.transition_latency = 1000; /* FIXME: 1 ms, assumed */239 240	/* Generate pxa25x the run cpufreq_frequency_table struct */241	for (i = 0; i < NUM_PXA25x_RUN_FREQS; i++) {242		pxa255_run_freq_table[i].frequency = pxa255_run_freqs[i].khz;243		pxa255_run_freq_table[i].driver_data = i;244	}245	pxa255_run_freq_table[i].frequency = CPUFREQ_TABLE_END;246 247	/* Generate pxa25x the turbo cpufreq_frequency_table struct */248	for (i = 0; i < NUM_PXA25x_TURBO_FREQS; i++) {249		pxa255_turbo_freq_table[i].frequency =250			pxa255_turbo_freqs[i].khz;251		pxa255_turbo_freq_table[i].driver_data = i;252	}253	pxa255_turbo_freq_table[i].frequency = CPUFREQ_TABLE_END;254 255	pxa255_turbo_table = !!pxa255_turbo_table;256 257	/* Generate the pxa27x cpufreq_frequency_table struct */258	for (i = 0; i < NUM_PXA27x_FREQS; i++) {259		freq = pxa27x_freqs[i].khz;260		if (freq > pxa27x_maxfreq)261			break;262		pxa27x_freq_table[i].frequency = freq;263		pxa27x_freq_table[i].driver_data = i;264	}265	pxa27x_freq_table[i].driver_data = i;266	pxa27x_freq_table[i].frequency = CPUFREQ_TABLE_END;267 268	/*269	 * Set the policy's minimum and maximum frequencies from the tables270	 * just constructed.  This sets cpuinfo.mxx_freq, min and max.271	 */272	if (cpu_is_pxa25x()) {273		find_freq_tables(&pxa255_freq_table, &pxa255_freqs);274		pr_info("using %s frequency table\n",275			pxa255_turbo_table ? "turbo" : "run");276 277		policy->freq_table = pxa255_freq_table;278	}279	else if (cpu_is_pxa27x()) {280		policy->freq_table = pxa27x_freq_table;281	}282 283	pr_info("frequency change support initialized\n");284 285	return 0;286}287 288static struct cpufreq_driver pxa_cpufreq_driver = {289	.flags	= CPUFREQ_NEED_INITIAL_FREQ_CHECK,290	.verify	= cpufreq_generic_frequency_table_verify,291	.target_index = pxa_set_target,292	.init	= pxa_cpufreq_init,293	.get	= pxa_cpufreq_get,294	.name	= "PXA2xx",295	.driver_data = &pxa_cpufreq_data,296};297 298static int __init pxa_cpu_init(void)299{300	int ret = -ENODEV;301 302	pxa_cpufreq_data.clk_core = clk_get_sys(NULL, "core");303	if (IS_ERR(pxa_cpufreq_data.clk_core))304		return PTR_ERR(pxa_cpufreq_data.clk_core);305 306	if (cpu_is_pxa25x() || cpu_is_pxa27x())307		ret = cpufreq_register_driver(&pxa_cpufreq_driver);308	return ret;309}310 311static void __exit pxa_cpu_exit(void)312{313	cpufreq_unregister_driver(&pxa_cpufreq_driver);314}315 316 317MODULE_AUTHOR("Intrinsyc Software Inc.");318MODULE_DESCRIPTION("CPU frequency changing driver for the PXA architecture");319MODULE_LICENSE("GPL");320module_init(pxa_cpu_init);321module_exit(pxa_cpu_exit);322