From f023f8dd59bf93e29e9b9bd98a92eeef43b1a32a Mon Sep 17 00:00:00 2001 From: Viresh Kumar Date: Thu, 4 Apr 2013 12:54:15 +0000 Subject: cpufreq: s3c24xx: move cpufreq driver to drivers/cpufreq This patch moves cpufreq driver of Samsung's ARM based s3c24xx platform to drivers/cpufreq. Signed-off-by: Viresh Kumar Acked-by: Arnd Bergmann Acked-by: Rafael J. Wysocki Signed-off-by: Kukjin Kim --- drivers/cpufreq/s3c2410-cpufreq.c | 160 ++++++++++++++++++++++++++++++++++++++ 1 file changed, 160 insertions(+) create mode 100644 drivers/cpufreq/s3c2410-cpufreq.c (limited to 'drivers/cpufreq/s3c2410-cpufreq.c') diff --git a/drivers/cpufreq/s3c2410-cpufreq.c b/drivers/cpufreq/s3c2410-cpufreq.c new file mode 100644 index 000000000000..cfa0dd8723ec --- /dev/null +++ b/drivers/cpufreq/s3c2410-cpufreq.c @@ -0,0 +1,160 @@ +/* + * Copyright (c) 2006-2008 Simtec Electronics + * http://armlinux.simtec.co.uk/ + * Ben Dooks + * + * S3C2410 CPU Frequency scaling + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. +*/ + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include + +#include + +#include +#include +#include + +/* Note, 2410A has an extra mode for 1:4:4 ratio, bit 2 of CLKDIV */ + +static void s3c2410_cpufreq_setdivs(struct s3c_cpufreq_config *cfg) +{ + u32 clkdiv = 0; + + if (cfg->divs.h_divisor == 2) + clkdiv |= S3C2410_CLKDIVN_HDIVN; + + if (cfg->divs.p_divisor != cfg->divs.h_divisor) + clkdiv |= S3C2410_CLKDIVN_PDIVN; + + __raw_writel(clkdiv, S3C2410_CLKDIVN); +} + +static int s3c2410_cpufreq_calcdivs(struct s3c_cpufreq_config *cfg) +{ + unsigned long hclk, fclk, pclk; + unsigned int hdiv, pdiv; + unsigned long hclk_max; + + fclk = cfg->freq.fclk; + hclk_max = cfg->max.hclk; + + cfg->freq.armclk = fclk; + + s3c_freq_dbg("%s: fclk is %lu, max hclk %lu\n", + __func__, fclk, hclk_max); + + hdiv = (fclk > cfg->max.hclk) ? 2 : 1; + hclk = fclk / hdiv; + + if (hclk > cfg->max.hclk) { + s3c_freq_dbg("%s: hclk too big\n", __func__); + return -EINVAL; + } + + pdiv = (hclk > cfg->max.pclk) ? 2 : 1; + pclk = hclk / pdiv; + + if (pclk > cfg->max.pclk) { + s3c_freq_dbg("%s: pclk too big\n", __func__); + return -EINVAL; + } + + pdiv *= hdiv; + + /* record the result */ + cfg->divs.p_divisor = pdiv; + cfg->divs.h_divisor = hdiv; + + return 0; +} + +static struct s3c_cpufreq_info s3c2410_cpufreq_info = { + .max = { + .fclk = 200000000, + .hclk = 100000000, + .pclk = 50000000, + }, + + /* transition latency is about 5ms worst-case, so + * set 10ms to be sure */ + .latency = 10000000, + + .locktime_m = 150, + .locktime_u = 150, + .locktime_bits = 12, + + .need_pll = 1, + + .name = "s3c2410", + .calc_iotiming = s3c2410_iotiming_calc, + .set_iotiming = s3c2410_iotiming_set, + .get_iotiming = s3c2410_iotiming_get, + .resume_clocks = s3c2410_setup_clocks, + + .set_fvco = s3c2410_set_fvco, + .set_refresh = s3c2410_cpufreq_setrefresh, + .set_divs = s3c2410_cpufreq_setdivs, + .calc_divs = s3c2410_cpufreq_calcdivs, + + .debug_io_show = s3c_cpufreq_debugfs_call(s3c2410_iotiming_debugfs), +}; + +static int s3c2410_cpufreq_add(struct device *dev, + struct subsys_interface *sif) +{ + return s3c_cpufreq_register(&s3c2410_cpufreq_info); +} + +static struct subsys_interface s3c2410_cpufreq_interface = { + .name = "s3c2410_cpufreq", + .subsys = &s3c2410_subsys, + .add_dev = s3c2410_cpufreq_add, +}; + +static int __init s3c2410_cpufreq_init(void) +{ + return subsys_interface_register(&s3c2410_cpufreq_interface); +} +arch_initcall(s3c2410_cpufreq_init); + +static int s3c2410a_cpufreq_add(struct device *dev, + struct subsys_interface *sif) +{ + /* alter the maximum freq settings for S3C2410A. If a board knows + * it only has a maximum of 200, then it should register its own + * limits. */ + + s3c2410_cpufreq_info.max.fclk = 266000000; + s3c2410_cpufreq_info.max.hclk = 133000000; + s3c2410_cpufreq_info.max.pclk = 66500000; + s3c2410_cpufreq_info.name = "s3c2410a"; + + return s3c2410_cpufreq_add(dev, sif); +} + +static struct subsys_interface s3c2410a_cpufreq_interface = { + .name = "s3c2410a_cpufreq", + .subsys = &s3c2410a_subsys, + .add_dev = s3c2410a_cpufreq_add, +}; + +static int __init s3c2410a_cpufreq_init(void) +{ + return subsys_interface_register(&s3c2410a_cpufreq_interface); +} +arch_initcall(s3c2410a_cpufreq_init); -- cgit v1.2.3