summaryrefslogtreecommitdiff
path: root/arch/arm
diff options
context:
space:
mode:
Diffstat (limited to 'arch/arm')
-rw-r--r--arch/arm/Kconfig25
-rw-r--r--arch/arm/mach-davinci/Makefile1
-rw-r--r--arch/arm/mach-davinci/cpufreq.c248
-rw-r--r--arch/arm/mach-exynos/Kconfig2
-rw-r--r--arch/arm/mach-imx/cpufreq.c8
-rw-r--r--arch/arm/mach-integrator/Makefile1
-rw-r--r--arch/arm/mach-integrator/cpu.c224
-rw-r--r--arch/arm/mach-omap2/pm.c9
-rw-r--r--arch/arm/mach-pxa/Makefile6
-rw-r--r--arch/arm/mach-pxa/cpufreq-pxa2xx.c494
-rw-r--r--arch/arm/mach-pxa/cpufreq-pxa3xx.c258
-rw-r--r--arch/arm/mach-pxa/include/mach/generic.h1
-rw-r--r--arch/arm/mach-s3c24xx/cpufreq.c8
-rw-r--r--arch/arm/mach-sa1100/Kconfig26
-rw-r--r--arch/arm/mach-sa1100/Makefile3
-rw-r--r--arch/arm/mach-sa1100/cpu-sa1100.c249
-rw-r--r--arch/arm/mach-sa1100/cpu-sa1110.c408
-rw-r--r--arch/arm/mach-sa1100/include/mach/generic.h1
-rw-r--r--arch/arm/mach-tegra/Makefile1
-rw-r--r--arch/arm/mach-tegra/cpu-tegra.c293
20 files changed, 30 insertions, 2236 deletions
diff --git a/arch/arm/Kconfig b/arch/arm/Kconfig
index 1cacda4..cdb8322 100644
--- a/arch/arm/Kconfig
+++ b/arch/arm/Kconfig
@@ -2160,7 +2160,6 @@ endmenu
menu "CPU Power Management"
if ARCH_HAS_CPUFREQ
-
source "drivers/cpufreq/Kconfig"
config CPU_FREQ_IMX
@@ -2170,30 +2169,6 @@ config CPU_FREQ_IMX
help
This enables the CPUfreq driver for i.MX CPUs.
-config CPU_FREQ_SA1100
- bool
-
-config CPU_FREQ_SA1110
- bool
-
-config CPU_FREQ_INTEGRATOR
- tristate "CPUfreq driver for ARM Integrator CPUs"
- depends on ARCH_INTEGRATOR && CPU_FREQ
- default y
- help
- This enables the CPUfreq driver for ARM Integrator CPUs.
-
- For details, take a look at <file:Documentation/cpu-freq>.
-
- If in doubt, say Y.
-
-config CPU_FREQ_PXA
- bool
- depends on CPU_FREQ && ARCH_PXA && PXA25x
- default y
- select CPU_FREQ_DEFAULT_GOV_USERSPACE
- select CPU_FREQ_TABLE
-
config CPU_FREQ_S3C
bool
help
diff --git a/arch/arm/mach-davinci/Makefile b/arch/arm/mach-davinci/Makefile
index fb5c1aa..dd1ffcc 100644
--- a/arch/arm/mach-davinci/Makefile
+++ b/arch/arm/mach-davinci/Makefile
@@ -37,7 +37,6 @@ obj-$(CONFIG_MACH_MITYOMAPL138) += board-mityomapl138.o
obj-$(CONFIG_MACH_OMAPL138_HAWKBOARD) += board-omapl138-hawk.o
# Power Management
-obj-$(CONFIG_CPU_FREQ) += cpufreq.o
obj-$(CONFIG_CPU_IDLE) += cpuidle.o
obj-$(CONFIG_SUSPEND) += pm.o sleep.o
obj-$(CONFIG_HAVE_CLK) += pm_domain.o
diff --git a/arch/arm/mach-davinci/cpufreq.c b/arch/arm/mach-davinci/cpufreq.c
deleted file mode 100644
index 4729eaa..0000000
--- a/arch/arm/mach-davinci/cpufreq.c
+++ /dev/null
@@ -1,248 +0,0 @@
-/*
- * CPU frequency scaling for DaVinci
- *
- * Copyright (C) 2009 Texas Instruments Incorporated - http://www.ti.com/
- *
- * Based on linux/arch/arm/plat-omap/cpu-omap.c. Original Copyright follows:
- *
- * Copyright (C) 2005 Nokia Corporation
- * Written by Tony Lindgren <tony@atomide.com>
- *
- * Based on cpu-sa1110.c, Copyright (C) 2001 Russell King
- *
- * Copyright (C) 2007-2008 Texas Instruments, Inc.
- * Updated to support OMAP3
- * Rajendra Nayak <rnayak@ti.com>
- *
- * 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 <linux/types.h>
-#include <linux/cpufreq.h>
-#include <linux/init.h>
-#include <linux/err.h>
-#include <linux/clk.h>
-#include <linux/platform_device.h>
-#include <linux/export.h>
-
-#include <mach/hardware.h>
-#include <mach/cpufreq.h>
-#include <mach/common.h>
-
-#include "clock.h"
-
-struct davinci_cpufreq {
- struct device *dev;
- struct clk *armclk;
- struct clk *asyncclk;
- unsigned long asyncrate;
-};
-static struct davinci_cpufreq cpufreq;
-
-static int davinci_verify_speed(struct cpufreq_policy *policy)
-{
- struct davinci_cpufreq_config *pdata = cpufreq.dev->platform_data;
- struct cpufreq_frequency_table *freq_table = pdata->freq_table;
- struct clk *armclk = cpufreq.armclk;
-
- if (freq_table)
- return cpufreq_frequency_table_verify(policy, freq_table);
-
- if (policy->cpu)
- return -EINVAL;
-
- cpufreq_verify_within_limits(policy, policy->cpuinfo.min_freq,
- policy->cpuinfo.max_freq);
-
- policy->min = clk_round_rate(armclk, policy->min * 1000) / 1000;
- policy->max = clk_round_rate(armclk, policy->max * 1000) / 1000;
- cpufreq_verify_within_limits(policy, policy->cpuinfo.min_freq,
- policy->cpuinfo.max_freq);
- return 0;
-}
-
-static unsigned int davinci_getspeed(unsigned int cpu)
-{
- if (cpu)
- return 0;
-
- return clk_get_rate(cpufreq.armclk) / 1000;
-}
-
-static int davinci_target(struct cpufreq_policy *policy,
- unsigned int target_freq, unsigned int relation)
-{
- int ret = 0;
- unsigned int idx;
- struct cpufreq_freqs freqs;
- struct davinci_cpufreq_config *pdata = cpufreq.dev->platform_data;
- struct clk *armclk = cpufreq.armclk;
-
- /*
- * Ensure desired rate is within allowed range. Some govenors
- * (ondemand) will just pass target_freq=0 to get the minimum.
- */
- if (target_freq < policy->cpuinfo.min_freq)
- target_freq = policy->cpuinfo.min_freq;
- if (target_freq > policy->cpuinfo.max_freq)
- target_freq = policy->cpuinfo.max_freq;
-
- freqs.old = davinci_getspeed(0);
- freqs.new = clk_round_rate(armclk, target_freq * 1000) / 1000;
- freqs.cpu = 0;
-
- if (freqs.old == freqs.new)
- return ret;
-
- dev_dbg(cpufreq.dev, "transition: %u --> %u\n", freqs.old, freqs.new);
-
- ret = cpufreq_frequency_table_target(policy, pdata->freq_table,
- freqs.new, relation, &idx);
- if (ret)
- return -EINVAL;
-
- cpufreq_notify_transition(&freqs, CPUFREQ_PRECHANGE);
-
- /* if moving to higher frequency, up the voltage beforehand */
- if (pdata->set_voltage && freqs.new > freqs.old) {
- ret = pdata->set_voltage(idx);
- if (ret)
- goto out;
- }
-
- ret = clk_set_rate(armclk, idx);
- if (ret)
- goto out;
-
- if (cpufreq.asyncclk) {
- ret = clk_set_rate(cpufreq.asyncclk, cpufreq.asyncrate);
- if (ret)
- goto out;
- }
-
- /* if moving to lower freq, lower the voltage after lowering freq */
- if (pdata->set_voltage && freqs.new < freqs.old)
- pdata->set_voltage(idx);
-
-out:
- cpufreq_notify_transition(&freqs, CPUFREQ_POSTCHANGE);
-
- return ret;
-}
-
-static int davinci_cpu_init(struct cpufreq_policy *policy)
-{
- int result = 0;
- struct davinci_cpufreq_config *pdata = cpufreq.dev->platform_data;
- struct cpufreq_frequency_table *freq_table = pdata->freq_table;
-
- if (policy->cpu != 0)
- return -EINVAL;
-
- /* Finish platform specific initialization */
- if (pdata->init) {
- result = pdata->init();
- if (result)
- return result;
- }
-
- policy->cur = policy->min = policy->max = davinci_getspeed(0);
-
- if (freq_table) {
- result = cpufreq_frequency_table_cpuinfo(policy, freq_table);
- if (!result)
- cpufreq_frequency_table_get_attr(freq_table,
- policy->cpu);
- } else {
- policy->cpuinfo.min_freq = policy->min;
- policy->cpuinfo.max_freq = policy->max;
- }
-
- policy->min = policy->cpuinfo.min_freq;
- policy->max = policy->cpuinfo.max_freq;
- policy->cur = davinci_getspeed(0);
-
- /*
- * Time measurement across the target() function yields ~1500-1800us
- * time taken with no drivers on notification list.
- * Setting the latency to 2000 us to accommodate addition of drivers
- * to pre/post change notification list.
- */
- policy->cpuinfo.transition_latency = 2000 * 1000;
- return 0;
-}
-
-static int davinci_cpu_exit(struct cpufreq_policy *policy)
-{
- cpufreq_frequency_table_put_attr(policy->cpu);
- return 0;
-}
-
-static struct freq_attr *davinci_cpufreq_attr[] = {
- &cpufreq_freq_attr_scaling_available_freqs,
- NULL,
-};
-
-static struct cpufreq_driver davinci_driver = {
- .flags = CPUFREQ_STICKY,
- .verify = davinci_verify_speed,
- .target = davinci_target,
- .get = davinci_getspeed,
- .init = davinci_cpu_init,
- .exit = davinci_cpu_exit,
- .name = "davinci",
- .attr = davinci_cpufreq_attr,
-};
-
-static int __init davinci_cpufreq_probe(struct platform_device *pdev)
-{
- struct davinci_cpufreq_config *pdata = pdev->dev.platform_data;
- struct clk *asyncclk;
-
- if (!pdata)
- return -EINVAL;
- if (!pdata->freq_table)
- return -EINVAL;
-
- cpufreq.dev = &pdev->dev;
-
- cpufreq.armclk = clk_get(NULL, "arm");
- if (IS_ERR(cpufreq.armclk)) {
- dev_err(cpufreq.dev, "Unable to get ARM clock\n");
- return PTR_ERR(cpufreq.armclk);
- }
-
- asyncclk = clk_get(cpufreq.dev, "async");
- if (!IS_ERR(asyncclk)) {
- cpufreq.asyncclk = asyncclk;
- cpufreq.asyncrate = clk_get_rate(asyncclk);
- }
-
- return cpufreq_register_driver(&davinci_driver);
-}
-
-static int __exit davinci_cpufreq_remove(struct platform_device *pdev)
-{
- clk_put(cpufreq.armclk);
-
- if (cpufreq.asyncclk)
- clk_put(cpufreq.asyncclk);
-
- return cpufreq_unregister_driver(&davinci_driver);
-}
-
-static struct platform_driver davinci_cpufreq_driver = {
- .driver = {
- .name = "cpufreq-davinci",
- .owner = THIS_MODULE,
- },
- .remove = __exit_p(davinci_cpufreq_remove),
-};
-
-int __init davinci_cpufreq_init(void)
-{
- return platform_driver_probe(&davinci_cpufreq_driver,
- davinci_cpufreq_probe);
-}
-
diff --git a/arch/arm/mach-exynos/Kconfig b/arch/arm/mach-exynos/Kconfig
index 70f94c8..d5dde07 100644
--- a/arch/arm/mach-exynos/Kconfig
+++ b/arch/arm/mach-exynos/Kconfig
@@ -72,10 +72,12 @@ config SOC_EXYNOS5440
bool "SAMSUNG EXYNOS5440"
default y
depends on ARCH_EXYNOS5
+ select ARCH_HAS_OPP
select ARM_ARCH_TIMER
select AUTO_ZRELADDR
select PINCTRL
select PINCTRL_EXYNOS5440
+ select PM_OPP
help
Enable EXYNOS5440 SoC support
diff --git a/arch/arm/mach-imx/cpufreq.c b/arch/arm/mach-imx/cpufreq.c
index d8c75c3..387dc4c 100644
--- a/arch/arm/mach-imx/cpufreq.c
+++ b/arch/arm/mach-imx/cpufreq.c
@@ -87,13 +87,12 @@ static int mxc_set_target(struct cpufreq_policy *policy,
freqs.old = clk_get_rate(cpu_clk) / 1000;
freqs.new = freq_Hz / 1000;
- freqs.cpu = 0;
freqs.flags = 0;
- cpufreq_notify_transition(&freqs, CPUFREQ_PRECHANGE);
+ cpufreq_notify_transition(policy, &freqs, CPUFREQ_PRECHANGE);
ret = set_cpu_freq(freq_Hz);
- cpufreq_notify_transition(&freqs, CPUFREQ_POSTCHANGE);
+ cpufreq_notify_transition(policy, &freqs, CPUFREQ_POSTCHANGE);
return ret;
}
@@ -145,14 +144,11 @@ static int mxc_cpufreq_init(struct cpufreq_policy *policy)
imx_freq_table[i].frequency = CPUFREQ_TABLE_END;
policy->cur = clk_get_rate(cpu_clk) / 1000;
- policy->min = policy->cpuinfo.min_freq = cpu_freq_khz_min;
- policy->max = policy->cpuinfo.max_freq = cpu_freq_khz_max;
/* Manual states, that PLL stabilizes in two CLK32 periods */
policy->cpuinfo.transition_latency = 2 * NANOSECOND / CLK32_FREQ;
ret = cpufreq_frequency_table_cpuinfo(policy, imx_freq_table);
-
if (ret < 0) {
printk(KERN_ERR "%s: failed to register i.MXC CPUfreq with error code %d\n",
__func__, ret);
diff --git a/arch/arm/mach-integrator/Makefile b/arch/arm/mach-integrator/Makefile
index 5521d18..d14d6b7 100644
--- a/arch/arm/mach-integrator/Makefile
+++ b/arch/arm/mach-integrator/Makefile
@@ -9,5 +9,4 @@ obj-$(CONFIG_ARCH_INTEGRATOR_AP) += integrator_ap.o
obj-$(CONFIG_ARCH_INTEGRATOR_CP) += integrator_cp.o
obj-$(CONFIG_PCI) += pci_v3.o pci.o
-obj-$(CONFIG_CPU_FREQ_INTEGRATOR) += cpu.o
obj-$(CONFIG_INTEGRATOR_IMPD1) += impd1.o
diff --git a/arch/arm/mach-integrator/cpu.c b/arch/arm/mach-integrator/cpu.c
deleted file mode 100644
index 590c192..0000000
--- a/arch/arm/mach-integrator/cpu.c
+++ /dev/null
@@ -1,224 +0,0 @@
-/*
- * linux/arch/arm/mach-integrator/cpu.c
- *
- * Copyright (C) 2001-2002 Deep Blue Solutions Ltd.
- *
- * 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.
- *
- * CPU support functions
- */
-#include <linux/module.h>
-#include <linux/types.h>
-#include <linux/kernel.h>
-#include <linux/cpufreq.h>
-#include <linux/sched.h>
-#include <linux/smp.h>
-#include <linux/init.h>
-#include <linux/io.h>
-
-#include <mach/hardware.h>
-#include <mach/platform.h>
-#include <asm/mach-types.h>
-#include <asm/hardware/icst.h>
-
-static struct cpufreq_driver integrator_driver;
-
-#define CM_ID __io_address(INTEGRATOR_HDR_ID)
-#define CM_OSC __io_address(INTEGRATOR_HDR_OSC)
-#define CM_STAT __io_address(INTEGRATOR_HDR_STAT)
-#define CM_LOCK __io_address(INTEGRATOR_HDR_LOCK)
-
-static const struct icst_params lclk_params = {
- .ref = 24000000,
- .vco_max = ICST525_VCO_MAX_5V,
- .vco_min = ICST525_VCO_MIN,
- .vd_min = 8,
- .vd_max = 132,
- .rd_min = 24,
- .rd_max = 24,
- .s2div = icst525_s2div,
- .idx2s = icst525_idx2s,
-};
-
-static const struct icst_params cclk_params = {
- .ref = 24000000,
- .vco_max = ICST525_VCO_MAX_5V,
- .vco_min = ICST525_VCO_MIN,
- .vd_min = 12,
- .vd_max = 160,
- .rd_min = 24,
- .rd_max = 24,
- .s2div = icst525_s2div,
- .idx2s = icst525_idx2s,
-};
-
-/*
- * Validate the speed policy.
- */
-static int integrator_verify_policy(struct cpufreq_policy *policy)
-{
- struct icst_vco vco;
-
- cpufreq_verify_within_limits(policy,
- policy->cpuinfo.min_freq,
- policy->cpuinfo.max_freq);
-
- vco = icst_hz_to_vco(&cclk_params, policy->max * 1000);
- policy->max = icst_hz(&cclk_params, vco) / 1000;
-
- vco = icst_hz_to_vco(&cclk_params, policy->min * 1000);
- policy->min = icst_hz(&cclk_params, vco) / 1000;
-
- cpufreq_verify_within_limits(policy,
- policy->cpuinfo.min_freq,
- policy->cpuinfo.max_freq);
-
- return 0;
-}
-
-
-static int integrator_set_target(struct cpufreq_policy *policy,
- unsigned int target_freq,
- unsigned int relation)
-{
- cpumask_t cpus_allowed;
- int cpu = policy->cpu;
- struct icst_vco vco;
- struct cpufreq_freqs freqs;
- u_int cm_osc;
-
- /*
- * Save this threads cpus_allowed mask.
- */
- cpus_allowed = current->cpus_allowed;
-
- /*
- * Bind to the specified CPU. When this call returns,
- * we should be running on the right CPU.
- */
- set_cpus_allowed(current, cpumask_of_cpu(cpu));
- BUG_ON(cpu != smp_processor_id());
-
- /* get current setting */
- cm_osc = __raw_readl(CM_OSC);
-
- if (machine_is_integrator()) {
- vco.s = (cm_osc >> 8) & 7;
- } else if (machine_is_cintegrator()) {
- vco.s = 1;
- }
- vco.v = cm_osc & 255;
- vco.r = 22;
- freqs.old = icst_hz(&cclk_params, vco) / 1000;
-
- /* icst_hz_to_vco rounds down -- so we need the next
- * larger freq in case of CPUFREQ_RELATION_L.
- */
- if (relation == CPUFREQ_RELATION_L)
- target_freq += 999;
- if (target_freq > policy->max)
- target_freq = policy->max;
- vco = icst_hz_to_vco(&cclk_params, target_freq * 1000);
- freqs.new = icst_hz(&cclk_params, vco) / 1000;
-
- freqs.cpu = policy->cpu;
-
- if (freqs.old == freqs.new) {
- set_cpus_allowed(current, cpus_allowed);
- return 0;
- }
-
- cpufreq_notify_transition(&freqs, CPUFREQ_PRECHANGE);
-
- cm_osc = __raw_readl(CM_OSC);
-
- if (machine_is_integrator()) {
- cm_osc &= 0xfffff800;
- cm_osc |= vco.s << 8;
- } else if (machine_is_cintegrator()) {
- cm_osc &= 0xffffff00;
- }
- cm_osc |= vco.v;
-
- __raw_writel(0xa05f, CM_LOCK);
- __raw_writel(cm_osc, CM_OSC);
- __raw_writel(0, CM_LOCK);
-
- /*
- * Restore the CPUs allowed mask.
- */
- set_cpus_allowed(current, cpus_allowed);
-
- cpufreq_notify_transition(&freqs, CPUFREQ_POSTCHANGE);
-
- return 0;
-}
-
-static unsigned int integrator_get(unsigned int cpu)
-{
- cpumask_t cpus_allowed;
- unsigned int current_freq;
- u_int cm_osc;
- struct icst_vco vco;
-
- cpus_allowed = current->cpus_allowed;
-
- set_cpus_allowed(current, cpumask_of_cpu(cpu));
- BUG_ON(cpu != smp_processor_id());
-
- /* detect memory etc. */
- cm_osc = __raw_readl(CM_OSC);
-
- if (machine_is_integrator()) {
- vco.s = (cm_osc >> 8) & 7;
- } else {
- vco.s = 1;
- }
- vco.v = cm_osc & 255;
- vco.r = 22;
-
- current_freq = icst_hz(&cclk_params, vco) / 1000; /* current freq */
-
- set_cpus_allowed(current, cpus_allowed);
-
- return current_freq;
-}
-
-static int integrator_cpufreq_init(struct cpufreq_policy *policy)
-{
-
- /* set default policy and cpuinfo */
- policy->cpuinfo.max_freq = 160000;
- policy->cpuinfo.min_freq = 12000;
- policy->cpuinfo.transition_latency = 1000000; /* 1 ms, assumed */
- policy->cur = policy->min = policy->max = integrator_get(policy->cpu);
-
- return 0;
-}
-
-static struct cpufreq_driver integrator_driver = {
- .verify = integrator_verify_policy,
- .target = integrator_set_target,
- .get = integrator_get,
- .init = integrator_cpufreq_init,
- .name = "integrator",
-};
-
-static int __init integrator_cpu_init(void)
-{
- return cpufreq_register_driver(&integrator_driver);
-}
-
-static void __exit integrator_cpu_exit(void)
-{
- cpufreq_unregister_driver(&integrator_driver);
-}
-
-MODULE_AUTHOR ("Russell M. King");
-MODULE_DESCRIPTION ("cpufreq driver for ARM Integrator CPUs");
-MODULE_LICENSE ("GPL");
-
-module_init(integrator_cpu_init);
-module_exit(integrator_cpu_exit);
diff --git a/arch/arm/mach-omap2/pm.c b/arch/arm/mach-omap2/pm.c
index 673a4c1..8d15f9a 100644
--- a/arch/arm/mach-omap2/pm.c
+++ b/arch/arm/mach-omap2/pm.c
@@ -265,6 +265,12 @@ static void __init omap4_init_voltages(void)
omap2_set_init_voltage("iva", "dpll_iva_m5x2_ck", "iva");
}
+static inline void omap_init_cpufreq(void)
+{
+ struct platform_device_info devinfo = { .name = "omap-cpufreq", };
+ platform_device_register_full(&devinfo);
+}
+
static int __init omap2_common_pm_init(void)
{
if (!of_have_populated_dt())
@@ -294,6 +300,9 @@ int __init omap2_common_pm_late_init(void)
/* Smartreflex device init */
omap_devinit_smartreflex();
+
+ /* cpufreq dummy device instantiation */
+ omap_init_cpufreq();
}
#ifdef CONFIG_SUSPEND
diff --git a/arch/arm/mach-pxa/Makefile b/arch/arm/mach-pxa/Makefile
index 12c5005..648867a 100644
--- a/arch/arm/mach-pxa/Makefile
+++ b/arch/arm/mach-pxa/Makefile
@@ -7,12 +7,6 @@ obj-y += clock.o devices.o generic.o irq.o \
time.o reset.o
obj-$(CONFIG_PM) += pm.o sleep.o standby.o
-ifeq ($(CONFIG_CPU_FREQ),y)
-obj-$(CONFIG_PXA25x) += cpufreq-pxa2xx.o
-obj-$(CONFIG_PXA27x) += cpufreq-pxa2xx.o
-obj-$(CONFIG_PXA3xx) += cpufreq-pxa3xx.o
-endif
-
# Generic drivers that other drivers may depend upon
# SoC-specific code
diff --git a/arch/arm/mach-pxa/cpufreq-pxa2xx.c b/arch/arm/mach-pxa/cpufreq-pxa2xx.c
deleted file mode 100644
index 6a7aeab..0000000
--- a/arch/arm/mach-pxa/cpufreq-pxa2xx.c
+++ /dev/null
@@ -1,494 +0,0 @@
-/*
- * linux/arch/arm/mach-pxa/cpufreq-pxa2xx.c
- *
- * Copyright (C) 2002,2003 Intrinsyc Software
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
- *
- * History:
- * 31-Jul-2002 : Initial version [FB]
- * 29-Jan-2003 : added PXA255 support [FB]
- * 20-Apr-2003 : ported to v2.5 (Dustin McIntire, Sensoria Corp.)
- *
- * Note:
- * This driver may change the memory bus clock rate, but will not do any
- * platform specific access timing changes... for example if you have flash
- * memory connected to CS0, you will need to register a platform specific
- * notifier which will adjust the memory access strobes to maintain a
- * minimum strobe width.
- *
- */
-
-#include <linux/kernel.h>
-#include <linux/module.h>
-#include <linux/sched.h>
-#include <linux/init.h>
-#include <linux/cpufreq.h>
-#include <linux/err.h>
-#include <linux/regulator/consumer.h>
-#include <linux/io.h>
-
-#include <mach/pxa2xx-regs.h>
-#include <mach/smemc.h>
-
-#ifdef DEBUG
-static unsigned int freq_debug;
-module_param(freq_debug, uint, 0);
-MODULE_PARM_DESC(freq_debug, "Set the debug messages to on=1/off=0");
-#else
-#define freq_debug 0
-#endif
-
-static struct regulator *vcc_core;
-
-static unsigned int pxa27x_maxfreq;
-module_param(pxa27x_maxfreq, uint, 0);
-MODULE_PARM_DESC(pxa27x_maxfreq, "Set the pxa27x maxfreq in MHz"
- "(typically 624=>pxa270, 416=>pxa271, 520=>pxa272)");
-
-typedef struct {
- unsigned int khz;
- unsigned int membus;
- unsigned int cccr;
- unsigned int div2;
- unsigned int cclkcfg;
- int vmin;
- int vmax;
-} pxa_freqs_t;
-
-/* Define the refresh period in mSec for the SDRAM and the number of rows */
-#define SDRAM_TREF 64 /* standard 64ms SDRAM */
-static unsigned int sdram_rows;
-
-#define CCLKCFG_TURBO 0x1
-#define CCLKCFG_FCS 0x2
-#define CCLKCFG_HALFTURBO 0x4
-#define CCLKCFG_FASTBUS 0x8
-#define MDREFR_DB2_MASK (MDREFR_K2DB2 | MDREFR_K1DB2)
-#define MDREFR_DRI_MASK 0xFFF
-
-#define MDCNFG_DRAC2(mdcnfg) (((mdcnfg) >> 21) & 0x3)
-#define MDCNFG_DRAC0(mdcnfg) (((mdcnfg) >> 5) & 0x3)
-
-/*
- * PXA255 definitions
- */
-/* Use the run mode frequencies for the CPUFREQ_POLICY_PERFORMANCE policy */
-#define CCLKCFG CCLKCFG_TURBO | CCLKCFG_FCS
-
-static pxa_freqs_t pxa255_run_freqs[] =
-{
- /* CPU MEMBUS CCCR DIV2 CCLKCFG run turbo PXbus SDRAM */
- { 99500, 99500, 0x121, 1, CCLKCFG, -1, -1}, /* 99, 99, 50, 50 */
- {132700, 132700, 0x123, 1, CCLKCFG, -1, -1}, /* 133, 133, 66, 66 */
- {199100, 99500, 0x141, 0, CCLKCFG, -1, -1}, /* 199, 199, 99, 99 */
- {265400, 132700, 0x143, 1, CCLKCFG, -1, -1}, /* 265, 265, 133, 66 */
- {331800, 165900, 0x145, 1, CCLKCFG, -1, -1}, /* 331, 331, 166, 83 */
- {398100, 99500, 0x161, 0, CCLKCFG, -1, -1}, /* 398, 398, 196, 99 */
-};
-
-/* Use the turbo mode frequencies for the CPUFREQ_POLICY_POWERSAVE policy */
-static pxa_freqs_t pxa255_turbo_freqs[] =
-{
- /* CPU MEMBUS CCCR DIV2 CCLKCFG run turbo PXbus SDRAM */
- { 99500, 99500, 0x121, 1, CCLKCFG, -1, -1}, /* 99, 99, 50, 50 */
- {199100, 99500, 0x221, 0, CCLKCFG, -1, -1}, /* 99, 199, 50, 99 */
- {298500, 99500, 0x321, 0, CCLKCFG, -1, -1}, /* 99, 287, 50, 99 */
- {298600, 99500, 0x1c1, 0, CCLKCFG, -1, -1}, /* 199, 287, 99, 99 */
- {398100, 99500, 0x241, 0, CCLKCFG, -1, -1}, /* 199, 398, 99, 99 */
-};
-
-#define NUM_PXA25x_RUN_FREQS ARRAY_SIZE(pxa255_run_freqs)
-#define NUM_PXA25x_TURBO_FREQS ARRAY_SIZE(pxa255_turbo_freqs)
-
-static struct cpufreq_frequency_table
- pxa255_run_freq_table[NUM_PXA25x_RUN_FREQS+1];
-static struct cpufreq_frequency_table
- pxa255_turbo_freq_table[NUM_PXA25x_TURBO_FREQS+1];
-
-static unsigned int pxa255_turbo_table;
-module_param(pxa255_turbo_table, uint, 0);
-MODULE_PARM_DESC(pxa255_turbo_table, "Selects the frequency table (0 = run table, !0 = turbo table)");
-
-/*
- * PXA270 definitions
- *
- * For the PXA27x:
- * Control variables are A, L, 2N for CCCR; B, HT, T for CLKCFG.
- *
- * A = 0 => memory controller clock from table 3-7,
- * A = 1 => memory controller clock = system bus clock
- * Run mode frequency = 13 MHz * L
- * Turbo mode frequency = 13 MHz * L * N
- * System bus frequency = 13 MHz * L / (B + 1)
- *
- * In CCCR:
- * A = 1
- * L = 16 oscillator to run mode ratio
- * 2N = 6 2 * (turbo mode to run mode ratio)
- *
- * In CCLKCFG:
- * B = 1 Fast bus mode
- * HT = 0 Half-Turbo mode
- * T = 1 Turbo mode
- *
- * For now, just support some of the combinations in table 3-7 of
- * PXA27x Processor Family Developer's Manual to simplify frequency
- * change sequences.
- */
-#define PXA27x_CCCR(A, L, N2) (A << 25 | N2 << 7 | L)
-#define CCLKCFG2(B, HT, T) \
- (CCLKCFG_FCS | \
- ((B) ? CCLKCFG_FASTBUS : 0) | \
- ((HT) ? CCLKCFG_HALFTURBO : 0) | \
- ((T) ? CCLKCFG_TURBO : 0))
-
-static pxa_freqs_t pxa27x_freqs[] = {
- {104000, 104000, PXA27x_CCCR(1, 8, 2), 0, CCLKCFG2(1, 0, 1), 900000, 1705000 },
- {156000, 104000, PXA27x_CCCR(1, 8, 3), 0, CCLKCFG2(1, 0, 1), 1000000, 1705000 },
- {208000, 208000, PXA27x_CCCR(0, 16, 2), 1, CCLKCFG2(0, 0, 1), 1180000, 1705000 },
- {312000, 208000, PXA27x_CCCR(1, 16, 3), 1, CCLKCFG2(1, 0, 1), 1250000, 1705000 },
- {416000, 208000, PXA27x_CCCR(1, 16, 4), 1, CCLKCFG2(1, 0, 1), 1350000, 1705000 },
- {520000, 208000, PXA27x_CCCR(1, 16, 5), 1, CCLKCFG2(1, 0, 1), 1450000, 1705000 },
- {624000, 208000, PXA27x_CCCR(1, 16, 6), 1, CCLKCFG2(1, 0, 1), 1550000, 1705000 }
-};
-
-#define NUM_PXA27x_FREQS ARRAY_SIZE(pxa27x_freqs)
-static struct cpufreq_frequency_table
- pxa27x_freq_table[NUM_PXA27x_FREQS+1];
-
-extern unsigned get_clk_frequency_khz(int info);
-
-#ifdef CONFIG_REGULATOR
-
-static int pxa_cpufreq_change_voltage(pxa_freqs_t *pxa_freq)
-{
- int ret = 0;
- int vmin, vmax;
-
- if (!cpu_is_pxa27x())
- return 0;
-
- vmin = pxa_freq->vmin;
- vmax = pxa_freq->vmax;
- if ((vmin == -1) || (vmax == -1))
- return 0;
-
- ret = regulator_set_voltage(vcc_core, vmin, vmax);
- if (ret)
- pr_err("cpufreq: Failed to set vcc_core in [%dmV..%dmV]\n",
- vmin, vmax);
- return ret;
-}
-
-static __init void pxa_cpufreq_init_voltages(void)
-{
- vcc_core = regulator_get(NULL, "vcc_core");
- if (IS_ERR(vcc_core)) {
- pr_info("cpufreq: Didn't find vcc_core regulator\n");
- vcc_core = NULL;
- } else {
- pr_info("cpufreq: Found vcc_core regulator\n");
- }
-}
-#else
-static int pxa_cpufreq_change_voltage(pxa_freqs_t *pxa_freq)
-{
- return 0;
-}
-
-static __init void pxa_cpufreq_init_voltages(void) { }
-#endif
-
-static void find_freq_tables(struct cpufreq_frequency_table **freq_table,
- pxa_freqs_t **pxa_freqs)
-{
- if (cpu_is_pxa25x()) {
- if (!pxa255_turbo_table) {
- *pxa_freqs = pxa255_run_freqs;
- *freq_table = pxa255_run_freq_table;
- } else {
- *pxa_freqs = pxa255_turbo_freqs;
- *freq_table = pxa255_turbo_freq_table;
- }
- }
- if (cpu_is_pxa27x()) {
- *pxa_freqs = pxa27x_freqs;
- *freq_table = pxa27x_freq_table;
- }
-}
-
-static void pxa27x_guess_max_freq(void)
-{
- if (!pxa27x_maxfreq) {
- pxa27x_maxfreq = 416000;
- printk(KERN_INFO "PXA CPU 27x max frequency not defined "
- "(pxa27x_maxfreq), assuming pxa271 with %dkHz maxfreq\n",
- pxa27x_maxfreq);
- } else {
- pxa27x_maxfreq *= 1000;
- }
-}
-
-static void init_sdram_rows(void)
-{
- uint32_t mdcnfg = __raw_readl(MDCNFG);
- unsigned int drac2 = 0, drac0 = 0;
-
- if (mdcnfg & (MDCNFG_DE2 | MDCNFG_DE3))
- drac2 = MDCNFG_DRAC2(mdcnfg);
-
- if (mdcnfg & (MDCNFG_DE0 | MDCNFG_DE1))
- drac0 = MDCNFG_DRAC0(mdcnfg);
-
- sdram_rows = 1 << (11 + max(drac0, drac2));
-}
-
-static u32 mdrefr_dri(unsigned int freq)
-{
- u32 interval = freq * SDRAM_TREF / sdram_rows;
-
- return (interval - (cpu_is_pxa27x() ? 31 : 0)) / 32;
-}
-
-/* find a valid frequency point */
-static int pxa_verify_policy(struct cpufreq_policy *policy)
-{
- struct cpufreq_frequency_table *pxa_freqs_table;
- pxa_freqs_t *pxa_freqs;
- int ret;
-
- find_freq_tables(&pxa_freqs_table, &pxa_freqs);
- ret = cpufreq_frequency_table_verify(policy, pxa_freqs_table);
-
- if (freq_debug)
- pr_debug("Verified CPU policy: %dKhz min to %dKhz max\n",
- policy->min, policy->max);
-
- return ret;
-}
-
-static unsigned int pxa_cpufreq_get(unsigned int cpu)
-{
- return get_clk_frequency_khz(0);
-}
-
-static int pxa_set_target(struct cpufreq_policy *policy,
- unsigned int target_freq,
- unsigned int relation)
-{
- struct cpufreq_frequency_table *pxa_freqs_table;
- pxa_freqs_t *pxa_freq_settings;
- struct cpufreq_freqs freqs;
- unsigned int idx;
- unsigned long flags;
- unsigned int new_freq_cpu, new_freq_mem;
- unsigned int unused, preset_mdrefr, postset_mdrefr, cclkcfg;
- int ret = 0;
-
- /* Get the current policy */
- find_freq_tables(&pxa_freqs_table, &pxa_freq_settings);
-
- /* Lookup the next frequency */
- if (cpufreq_frequency_table_target(policy, pxa_freqs_table,
- target_freq, relation, &idx)) {
- return -EINVAL;
- }
-
- new_freq_cpu = pxa_freq_settings[idx].khz;
- new_freq_mem = pxa_freq_settings[idx].membus;
- freqs.old = policy->cur;
- freqs.new = new_freq_cpu;
- freqs.cpu = policy->cpu;
-
- if (freq_debug)
- pr_debug("Changing CPU frequency to %d Mhz, (SDRAM %d Mhz)\n",
- freqs.new / 1000, (pxa_freq_settings[idx].div2) ?
- (new_freq_mem / 2000) : (new_freq_mem / 1000));
-
- if (vcc_core && freqs.new > freqs.old)
- ret = pxa_cpufreq_change_voltage(&pxa_freq_settings[idx]);
- if (ret)
- return ret;
- /*
- * Tell everyone what we're about to do...
- * you should add a notify client with any platform specific
- * Vcc changing capability
- */
- cpufreq_notify_transition(&freqs, CPUFREQ_PRECHANGE);
-
- /* Calculate the next MDREFR. If we're slowing down the SDRAM clock
- * we need to preset the smaller DRI before the change. If we're
- * speeding up we need to set the larger DRI value after the change.
- */
- preset_mdrefr = postset_mdrefr = __raw_readl(MDREFR);
- if ((preset_mdrefr & MDREFR_DRI_MASK) > mdrefr_dri(new_freq_mem)) {
- preset_mdrefr = (preset_mdrefr & ~MDREFR_DRI_MASK);
- preset_mdrefr |= mdrefr_dri(new_freq_mem);
- }
- postset_mdrefr =
- (postset_mdrefr & ~MDREFR_DRI_MASK) | mdrefr_dri(new_freq_mem);
-
- /* If we're dividing the memory clock by two for the SDRAM clock, this
- * must be set prior to the change. Clearing the divide must be done
- * after the change.
- */
- if (pxa_freq_settings[idx].div2) {
- preset_mdrefr |= MDREFR_DB2_MASK;
- postset_mdrefr |= MDREFR_DB2_MASK;
- } else {
- postset_mdrefr &= ~MDREFR_DB2_MASK;
- }
-
- local_irq_save(flags);
-
- /* Set new the CCCR and prepare CCLKCFG */
- CCCR = pxa_freq_settings[idx].cccr;
- cclkcfg = pxa_freq_settings[idx].cclkcfg;
-
- asm volatile(" \n\
- ldr r4, [%1] /* load MDREFR */ \n\
- b 2f \n\
- .align 5 \n\
-1: \n\
- str %3, [%1] /* preset the MDREFR */ \n\
- mcr p14, 0, %2, c6, c0, 0 /* set CCLKCFG[FCS] */ \n\
- str %4, [%1] /* postset the MDREFR */ \n\
- \n\
- b 3f \n\
-2: b 1b \n\
-3: nop \n\
- "
- : "=&r" (unused)
- : "r" (MDREFR), "r" (cclkcfg),
- "r" (preset_mdrefr), "r" (postset_mdrefr)
- : "r4", "r5");
- local_irq_restore(flags);
-
- /*
- * Tell everyone what we've just done...
- * you should add a notify client with any platform specific
- * SDRAM refresh timer adjustments
- */
- cpufreq_notify_transition(&freqs, CPUFREQ_POSTCHANGE);
-
- /*
- * Even if voltage setting fails, we don't report it, as the frequency
- * change succeeded. The voltage reduction is not a critical failure,
- * only power savings will suffer from this.
- *
- * Note: if the voltage change fails, and a return value is returned, a
- * bug is triggered (seems a deadlock). Should anybody find out where,
- * the "return 0" should become a "return ret".
- */
- if (vcc_core && freqs.new < freqs.old)
- ret = pxa_cpufreq_change_voltage(&pxa_freq_settings[idx]);
-
- return 0;
-}
-
-static int pxa_cpufreq_init(struct cpufreq_policy *policy)
-{
- int i;
- unsigned int freq;
- struct cpufreq_frequency_table *pxa255_freq_table;
- pxa_freqs_t *pxa255_freqs;
-
- /* try to guess pxa27x cpu */
- if (cpu_is_pxa27x())
- pxa27x_guess_max_freq();
-
- pxa_cpufreq_init_voltages();
-
- init_sdram_rows();
-
- /* set default policy and cpuinfo */
- policy->cpuinfo.transition_latency = 1000; /* FIXME: 1 ms, assumed */
- policy->cur = get_clk_frequency_khz(0); /* current freq */
- policy->min = policy->max = policy->cur;
-
- /* Generate pxa25x the run cpufreq_frequency_table struct */
- for (i = 0; i < NUM_PXA25x_RUN_FREQS; i++) {
- pxa255_run_freq_table[i].frequency = pxa255_run_freqs[i].khz;
- pxa255_run_freq_table[i].index = i;
- }
- pxa255_run_freq_table[i].frequency = CPUFREQ_TABLE_END;
-
- /* Generate pxa25x the turbo cpufreq_frequency_table struct */
- for (i = 0; i < NUM_PXA25x_TURBO_FREQS; i++) {
- pxa255_turbo_freq_table[i].frequency =
- pxa255_turbo_freqs[i].khz;
- pxa255_turbo_freq_table[i].index = i;
- }
- pxa255_turbo_freq_table[i].frequency = CPUFREQ_TABLE_END;
-
- pxa255_turbo_table = !!pxa255_turbo_table;
-
- /* Generate the pxa27x cpufreq_frequency_table struct */
- for (i = 0; i < NUM_PXA27x_FREQS; i++) {
- freq = pxa27x_freqs[i].khz;
- if (freq > pxa27x_maxfreq)
- break;
- pxa27x_freq_table[i].frequency = freq;
- pxa27x_freq_table[i].index = i;
- }
- pxa27x_freq_table[i].index = i;
- pxa27x_freq_table[i].frequency = CPUFREQ_TABLE_END;
-
- /*
- * Set the policy's minimum and maximum frequencies from the tables
- * just constructed. This sets cpuinfo.mxx_freq, min and max.
- */
- if (cpu_is_pxa25x()) {
- find_freq_tables(&pxa255_freq_table, &pxa255_freqs);
- pr_info("PXA255 cpufreq using %s frequency table\n",
- pxa255_turbo_table ? "turbo" : "run");
- cpufreq_frequency_table_cpuinfo(policy, pxa255_freq_table);
- }
- else if (cpu_is_pxa27x())
- cpufreq_frequency_table_cpuinfo(policy, pxa27x_freq_table);
-
- printk(KERN_INFO "PXA CPU frequency change support initialized\n");
-
- return 0;
-}
-
-static struct cpufreq_driver pxa_cpufreq_driver = {
- .verify = pxa_verify_policy,
- .target = pxa_set_target,
- .init = pxa_cpufreq_init,
- .get = pxa_cpufreq_get,
- .name = "PXA2xx",
-};
-
-static int __init pxa_cpu_init(void)
-{
- int ret = -ENODEV;
- if (cpu_is_pxa25x() || cpu_is_pxa27x())
- ret = cpufreq_register_driver(&pxa_cpufreq_driver);
- return ret;
-}
-
-static void __exit pxa_cpu_exit(void)
-{
- cpufreq_unregister_driver(&pxa_cpufreq_driver);
-}
-
-
-MODULE_AUTHOR("Intrinsyc Software Inc.");
-MODULE_DESCRIPTION("CPU frequency changing driver for the PXA architecture");
-MODULE_LICENSE("GPL");
-module_init(pxa_cpu_init);
-module_exit(pxa_cpu_exit);
diff --git a/arch/arm/mach-pxa/cpufreq-pxa3xx.c b/arch/arm/mach-pxa/cpufreq-pxa3xx.c
deleted file mode 100644
index b85b4ab..0000000
--- a/arch/arm/mach-pxa/cpufreq-pxa3xx.c
+++ /dev/null
@@ -1,258 +0,0 @@
-/*
- * linux/arch/arm/mach-pxa/cpufreq-pxa3xx.c
- *
- * Copyright (C) 2008 Marvell International Ltd.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- */
-
-#include <linux/kernel.h>
-#include <linux/module.h>
-#include <linux/sched.h>
-#include <linux/init.h>
-#include <linux/cpufreq.h>
-#include <linux/slab.h>
-#include <linux/io.h>
-
-#include <mach/pxa3xx-regs.h>
-
-#include "generic.h"
-
-#define HSS_104M (0)
-#define HSS_156M (1)
-#define HSS_208M (2)
-#define HSS_312M (3)
-
-#define SMCFS_78M (0)
-#define SMCFS_104M (2)
-#define SMCFS_208M (5)
-
-#define SFLFS_104M (0)
-#define SFLFS_156M (1)
-#define SFLFS_208M (2)
-#define SFLFS_312M (3)
-
-#define XSPCLK_156M (0)
-#define XSPCLK_NONE (3)
-
-#define DMCFS_26M (0)
-#define DMCFS_260M (3)
-
-struct pxa3xx_freq_info {
- unsigned int cpufreq_mhz;
- unsigned int core_xl : 5;
- unsigned int core_xn : 3;
- unsigned int hss : 2;
- unsigned int dmcfs : 2;
- unsigned int smcfs : 3;
- unsigned int sflfs : 2;
- unsigned int df_clkdiv : 3;
-
- int vcc_core; /* in mV */
- int vcc_sram; /* in mV */
-};
-
-#define OP(cpufreq, _xl, _xn, _hss, _dmc, _smc, _sfl, _dfi, vcore, vsram) \
-{ \
- .cpufreq_mhz = cpufreq, \
- .core_xl = _xl, \
- .core_xn = _xn, \
- .hss = HSS_##_hss##M, \
- .dmcfs = DMCFS_##_dmc##M, \
- .smcfs = SMCFS_##_smc##M, \
- .sflfs = SFLFS_##_sfl##M, \
- .df_clkdiv = _dfi, \
- .vcc_core = vcore, \
- .vcc_sram = vsram, \
-}
-
-static struct pxa3xx_freq_info pxa300_freqs[] = {
- /* CPU XL XN HSS DMEM SMEM SRAM DFI VCC_CORE VCC_SRAM */
- OP(104, 8, 1, 104, 260, 78, 104, 3, 1000, 1100), /* 104MHz */
- OP(208, 16, 1, 104, 260, 104, 156, 2, 1000, 1100), /* 208MHz */
- OP(416, 16, 2, 156, 260, 104, 208, 2, 1100, 1200), /* 416MHz */
- OP(624, 24, 2, 208, 260, 208, 312, 3, 1375, 1400), /* 624MHz */
-};
-
-static struct pxa3xx_freq_info pxa320_freqs[] = {
- /* CPU XL XN HSS DMEM SMEM SRAM DFI VCC_CORE VCC_SRAM */
- OP(104, 8, 1, 104, 260, 78, 104, 3, 1000, 1100), /* 104MHz */
- OP(208, 16, 1, 104, 260, 104, 156, 2, 1000, 1100), /* 208MHz */
- OP(416, 16, 2, 156, 260, 104, 208, 2, 1100, 1200), /* 416MHz */
- OP(624, 24, 2, 208, 260, 208, 312, 3, 1375, 1400), /* 624MHz */
- OP(806, 31, 2, 208, 260, 208, 312, 3, 1400, 1400), /* 806MHz */
-};
-
-static unsigned int pxa3xx_freqs_num;
-static struct pxa3xx_freq_info *pxa3xx_freqs;
-static struct cpufreq_frequency_table *pxa3xx_freqs_table;
-
-static int setup_freqs_table(struct cpufreq_policy *policy,
- struct pxa3xx_freq_info *freqs, int num)
-{
- struct cpufreq_frequency_table *table;
- int i;
-
- table = kzalloc((num + 1) * sizeof(*table), GFP_KERNEL);
- if (table == NULL)
- return -ENOMEM;
-
- for (i = 0; i < num; i++) {
- table[i].index = i;
- table[i].frequency = freqs[i].cpufreq_mhz * 1000;
- }
- table[num].index = i;
- table[num].frequency = CPUFREQ_TABLE_END;
-
- pxa3xx_freqs = freqs;
- pxa3xx_freqs_num = num;
- pxa3xx_freqs_table = table;
-
- return cpufreq_frequency_table_cpuinfo(policy, table);
-}
-
-static void __update_core_freq(struct pxa3xx_freq_info *info)
-{
- uint32_t mask = ACCR_XN_MASK | ACCR_XL_MASK;
- uint32_t accr = ACCR;
- uint32_t xclkcfg;
-
- accr &= ~(ACCR_XN_MASK | ACCR_XL_MASK | ACCR_XSPCLK_MASK);
- accr |= ACCR_XN(info->core_xn) | ACCR_XL(info->core_xl);
-
- /* No clock until core PLL is re-locked */
- accr |= ACCR_XSPCLK(XSPCLK_NONE);
-
- xclkcfg = (info->core_xn == 2) ? 0x3 : 0x2; /* turbo bit */
-
- ACCR = accr;
- __asm__("mcr p14, 0, %0, c6, c0, 0\n" : : "r"(xclkcfg));
-
- while ((ACSR & mask) != (accr & mask))
- cpu_relax();
-}
-
-static void __update_bus_freq(struct pxa3xx_freq_info *info)
-{
- uint32_t mask;
- uint32_t accr = ACCR;
-
- mask = ACCR_SMCFS_MASK | ACCR_SFLFS_MASK | ACCR_HSS_MASK |
- ACCR_DMCFS_MASK;
-
- accr &= ~mask;
- accr |= ACCR_SMCFS(info->smcfs) | ACCR_SFLFS(info->sflfs) |
- ACCR_HSS(info->hss) | ACCR_DMCFS(info->dmcfs);
-
- ACCR = accr;
-
- while ((ACSR & mask) != (accr & mask))
- cpu_relax();
-}
-
-static int pxa3xx_cpufreq_verify(struct cpufreq_policy *policy)
-{
- return cpufreq_frequency_table_verify(policy, pxa3xx_freqs_table);
-}
-
-static unsigned int pxa3xx_cpufreq_get(unsigned int cpu)
-{
- return pxa3xx_get_clk_frequency_khz(0);
-}
-
-static int pxa3xx_cpufreq_set(struct cpufreq_policy *policy,
- unsigned int target_freq,
- unsigned int relation)
-{
- struct pxa3xx_freq_info *next;
- struct cpufreq_freqs freqs;
- unsigned long flags;
- int idx;
-
- if (policy->cpu != 0)
- return -EINVAL;
-
- /* Lookup the next frequency */
- if (cpufreq_frequency_table_target(policy, pxa3xx_freqs_table,
- target_freq, relation, &idx))
- return -EINVAL;
-
- next = &pxa3xx_freqs[idx];
-
- freqs.old = policy->cur;
- freqs.new = next->cpufreq_mhz * 1000;
- freqs.cpu = policy->cpu;
-
- pr_debug("CPU frequency from %d MHz to %d MHz%s\n",
- freqs.old / 1000, freqs.new / 1000,
- (freqs.old == freqs.new) ? " (skipped)" : "");
-
- if (freqs.old == target_freq)
- return 0;
-
- cpufreq_notify_transition(&freqs, CPUFREQ_PRECHANGE);
-
- local_irq_save(flags);
- __update_core_freq(next);
- __update_bus_freq(next);
- local_irq_restore(flags);
-
- cpufreq_notify_transition(&freqs, CPUFREQ_POSTCHANGE);
-
- return 0;
-}
-
-static int pxa3xx_cpufreq_init(struct cpufreq_policy *policy)
-{
- int ret = -EINVAL;
-
- /* set default policy and cpuinfo */
- policy->cpuinfo.min_freq = 104000;
- policy->cpuinfo.max_freq = (cpu_is_pxa320()) ? 806000 : 624000;
- policy->cpuinfo.transition_latency = 1000; /* FIXME: 1 ms, assumed */
- policy->max = pxa3xx_get_clk_frequency_khz(0);
- policy->cur = policy->min = policy->max;
-
- if (cpu_is_pxa300() || cpu_is_pxa310())
- ret = setup_freqs_table(policy, ARRAY_AND_SIZE(pxa300_freqs));
-
- if (cpu_is_pxa320())
- ret = setup_freqs_table(policy, ARRAY_AND_SIZE(pxa320_freqs));
-
- if (ret) {
- pr_err("failed to setup frequency table\n");
- return ret;
- }
-
- pr_info("CPUFREQ support for PXA3xx initialized\n");
- return 0;
-}
-
-static struct cpufreq_driver pxa3xx_cpufreq_driver = {
- .verify = pxa3xx_cpufreq_verify,
- .target = pxa3xx_cpufreq_set,
- .init = pxa3xx_cpufreq_init,
- .get = pxa3xx_cpufreq_get,
- .name = "pxa3xx-cpufreq",
-};
-
-static int __init cpufreq_init(void)
-{
- if (cpu_is_pxa3xx())
- return cpufreq_register_driver(&pxa3xx_cpufreq_driver);
-
- return 0;
-}
-module_init(cpufreq_init);
-
-static void __exit cpufreq_exit(void)
-{
- cpufreq_unregister_driver(&pxa3xx_cpufreq_driver);
-}
-module_exit(cpufreq_exit);
-
-MODULE_DESCRIPTION("CPU frequency scaling driver for PXA3xx");
-MODULE_LICENSE("GPL");
diff --git a/arch/arm/mach-pxa/include/mach/generic.h b/arch/arm/mach-pxa/include/mach/generic.h
new file mode 100644
index 0000000..665542e
--- /dev/null
+++ b/arch/arm/mach-pxa/include/mach/generic.h
@@ -0,0 +1 @@
+#include "../../generic.h"
diff --git a/arch/arm/mach-s3c24xx/cpufreq.c b/arch/arm/mach-s3c24xx/cpufreq.c
index 5f181e7..3c0e78e 100644
--- a/arch/arm/mach-s3c24xx/cpufreq.c
+++ b/arch/arm/mach-s3c24xx/cpufreq.c
@@ -204,7 +204,6 @@ static int s3c_cpufreq_settarget(struct cpufreq_policy *policy,
freqs.old = cpu_cur.freq;
freqs.new = cpu_new.freq;
- freqs.freqs.cpu = 0;
freqs.freqs.old = cpu_cur.freq.armclk / 1000;
freqs.freqs.new = cpu_new.freq.armclk / 1000;
@@ -218,9 +217,7 @@ static int s3c_cpufreq_settarget(struct cpufreq_policy *policy,
s3c_cpufreq_updateclk(clk_pclk, cpu_new.freq.pclk);
/* start the frequency change */
-
- if (policy)
- cpufreq_notify_transition(&freqs.freqs, CPUFREQ_PRECHANGE);
+ cpufreq_notify_transition(policy, &freqs.freqs, CPUFREQ_PRECHANGE);
/* If hclk is staying the same, then we do not need to
* re-write the IO or the refresh timings whilst we are changing
@@ -264,8 +261,7 @@ static int s3c_cpufreq_settarget(struct cpufreq_policy *policy,
local_irq_restore(flags);
/* notify everyone we've done this */
- if (policy)
- cpufreq_notify_transition(&freqs.freqs, CPUFREQ_POSTCHANGE);
+ cpufreq_notify_transition(policy, &freqs.freqs, CPUFREQ_POSTCHANGE);
s3c_freq_dbg("%s: finished\n", __func__);
return 0;
diff --git a/arch/arm/mach-sa1100/Kconfig b/arch/arm/mach-sa1100/Kconfig
index ca14dbd..04f9784 100644
--- a/arch/arm/mach-sa1100/Kconfig
+++ b/arch/arm/mach-sa1100/Kconfig
@@ -4,7 +4,7 @@ menu "SA11x0 Implementations"
config SA1100_ASSABET
bool "Assabet"
- select CPU_FREQ_SA1110
+ select ARM_SA1110_CPUFREQ
help
Say Y here if you are using the Intel(R) StrongARM(R) SA-1110
Microprocessor Development Board (also known as the Assabet).
@@ -20,7 +20,7 @@ config ASSABET_NEPONSET
config SA1100_CERF
bool "CerfBoard"
- select CPU_FREQ_SA1110
+ select ARM_SA1110_CPUFREQ
help
The Intrinsyc CerfBoard is based on the StrongARM 1110 (Discontinued).
More information is available at:
@@ -47,7 +47,7 @@ endchoice
config SA1100_COLLIE
bool "Sharp Zaurus SL5500"
- # FIXME: select CPU_FREQ_SA11x0
+ # FIXME: select ARM_SA11x0_CPUFREQ
select SHARP_LOCOMO
select SHARP_PARAM
select SHARP_SCOOP
@@ -56,7 +56,7 @@ config SA1100_COLLIE
config SA1100_H3100
bool "Compaq iPAQ H3100"
- select CPU_FREQ_SA1110
+ select ARM_SA1110_CPUFREQ
select HTC_EGPIO
help
Say Y here if you intend to run this kernel on the Compaq iPAQ
@@ -67,7 +67,7 @@ config SA1100_H3100
config SA1100_H3600
bool "Compaq iPAQ H3600/H3700"
- select CPU_FREQ_SA1110
+ select ARM_SA1110_CPUFREQ
select HTC_EGPIO
help
Say Y here if you intend to run this kernel on the Compaq iPAQ
@@ -78,7 +78,7 @@ config SA1100_H3600
config SA1100_BADGE4
bool "HP Labs BadgePAD 4"
- select CPU_FREQ_SA1100
+ select ARM_SA1100_CPUFREQ
select SA1111
help
Say Y here if you want to build a kernel for the HP Laboratories
@@ -86,7 +86,7 @@ config SA1100_BADGE4
config SA1100_JORNADA720
bool "HP Jornada 720"
- # FIXME: select CPU_FREQ_SA11x0
+ # FIXME: select ARM_SA11x0_CPUFREQ
select SA1111
help
Say Y here if you want to build a kernel for the HP Jornada 720
@@ -105,14 +105,14 @@ config SA1100_JORNADA720_SSP
config SA1100_HACKKIT
bool "HackKit Core CPU Board"
- select CPU_FREQ_SA1100
+ select ARM_SA1100_CPUFREQ
help
Say Y here to support the HackKit Core CPU Board
<http://hackkit.eletztrick.de>;
config SA1100_LART
bool "LART"
- select CPU_FREQ_SA1100
+ select ARM_SA1100_CPUFREQ
help
Say Y here if you are using the Linux Advanced Radio Terminal
(also known as the LART). See <http://www.lartmaker.nl/> for
@@ -120,7 +120,7 @@ config SA1100_LART
config SA1100_NANOENGINE
bool "nanoEngine"
- select CPU_FREQ_SA1110
+ select ARM_SA1110_CPUFREQ
select PCI
select PCI_NANOENGINE
help
@@ -130,7 +130,7 @@ config SA1100_NANOENGINE
config SA1100_PLEB
bool "PLEB"
- select CPU_FREQ_SA1100
+ select ARM_SA1100_CPUFREQ
help
Say Y here if you are using version 1 of the Portable Linux
Embedded Board (also known as PLEB).
@@ -139,7 +139,7 @@ config SA1100_PLEB
config SA1100_SHANNON
bool "Shannon"
- select CPU_FREQ_SA1100
+ select ARM_SA1100_CPUFREQ
help
The Shannon (also known as a Tuxscreen, and also as a IS2630) was a
limited edition webphone produced by Philips. The Shannon is a SA1100
@@ -148,7 +148,7 @@ config SA1100_SHANNON
config SA1100_SIMPAD
bool "Simpad"
- select CPU_FREQ_SA1110
+ select ARM_SA1110_CPUFREQ
help
The SIEMENS webpad SIMpad is based on the StrongARM 1110. There
are two different versions CL4 and SL4. CL4 has 32MB RAM and 16MB
diff --git a/arch/arm/mach-sa1100/Makefile b/arch/arm/mach-sa1100/Makefile
index 1aed9e7..2732eef 100644
--- a/arch/arm/mach-sa1100/Makefile
+++ b/arch/arm/mach-sa1100/Makefile
@@ -8,9 +8,6 @@ obj-m :=
obj-n :=
obj- :=
-obj-$(CONFIG_CPU_FREQ_SA1100) += cpu-sa1100.o
-obj-$(CONFIG_CPU_FREQ_SA1110) += cpu-sa1110.o
-
# Specific board support
obj-$(CONFIG_SA1100_ASSABET) += assabet.o
obj-$(CONFIG_ASSABET_NEPONSET) += neponset.o
diff --git a/arch/arm/mach-sa1100/cpu-sa1100.c b/arch/arm/mach-sa1100/cpu-sa1100.c
deleted file mode 100644
index e8f4d1e..0000000
--- a/arch/arm/mach-sa1100/cpu-sa1100.c
+++ /dev/null
@@ -1,249 +0,0 @@
-/*
- * cpu-sa1100.c: clock scaling for the SA1100
- *
- * Copyright (C) 2000 2001, The Delft University of Technology
- *
- * Authors:
- * - Johan Pouwelse (J.A.Pouwelse@its.tudelft.nl): initial version
- * - Erik Mouw (J.A.K.Mouw@its.tudelft.nl):
- * - major rewrite for linux-2.3.99
- * - rewritten for the more generic power management scheme in
- * linux-2.4.5-rmk1
- *
- * This software has been developed while working on the LART
- * computing board (http://www.lartmaker.nl/), which is
- * sponsored by the Mobile Multi-media Communications
- * (http://www.mobimedia.org/) and Ubiquitous Communications
- * (http://www.ubicom.tudelft.nl/) projects.
- *
- * The authors can be reached at:
- *
- * Erik Mouw
- * Information and Communication Theory Group
- * Faculty of Information Technology and Systems
- * Delft University of Technology
- * P.O. Box 5031
- * 2600 GA Delft
- * The Netherlands
- *
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
- *
- *
- * Theory of operations
- * ====================
- *
- * Clock scaling can be used to lower the power consumption of the CPU
- * core. This will give you a somewhat longer running time.
- *
- * The SA-1100 has a single register to change the core clock speed:
- *
- * PPCR 0x90020014 PLL config
- *
- * However, the DRAM timings are closely related to the core clock
- * speed, so we need to change these, too. The used registers are:
- *
- * MDCNFG 0xA0000000 DRAM config
- * MDCAS0 0xA0000004 Access waveform
- * MDCAS1 0xA0000008 Access waveform
- * MDCAS2 0xA000000C Access waveform
- *
- * Care must be taken to change the DRAM parameters the correct way,
- * because otherwise the DRAM becomes unusable and the kernel will
- * crash.
- *
- * The simple solution to avoid a kernel crash is to put the actual
- * clock change in ROM and jump to that code from the kernel. The main
- * disadvantage is that the ROM has to be modified, which is not
- * possible on all SA-1100 platforms. Another disadvantage is that
- * jumping to ROM makes clock switching unnecessary complicated.
- *
- * The idea behind this driver is that the memory configuration can be
- * changed while running from DRAM (even with interrupts turned on!)
- * as long as all re-configuration steps yield a valid DRAM
- * configuration. The advantages are clear: it will run on all SA-1100
- * platforms, and the code is very simple.
- *
- * If you really want to understand what is going on in
- * sa1100_update_dram_timings(), you'll have to read sections 8.2,
- * 9.5.7.3, and 10.2 from the "Intel StrongARM SA-1100 Microprocessor
- * Developers Manual" (available for free from Intel).
- *
- */
-
-#include <linux/kernel.h>
-#include <linux/types.h>
-#include <linux/init.h>
-#include <linux/cpufreq.h>
-#include <linux/io.h>
-
-#include <asm/cputype.h>
-
-#include <mach/hardware.h>
-
-#include "generic.h"
-
-struct sa1100_dram_regs {
- int speed;
- u32 mdcnfg;
- u32 mdcas0;
- u32 mdcas1;
- u32 mdcas2;
-};
-
-
-static struct cpufreq_driver sa1100_driver;
-
-static struct sa1100_dram_regs sa1100_dram_settings[] = {
- /*speed, mdcnfg, mdcas0, mdcas1, mdcas2, clock freq */
- { 59000, 0x00dc88a3, 0xcccccccf, 0xfffffffc, 0xffffffff},/* 59.0 MHz */
- { 73700, 0x011490a3, 0xcccccccf, 0xfffffffc, 0xffffffff},/* 73.7 MHz */
- { 88500, 0x014e90a3, 0xcccccccf, 0xfffffffc, 0xffffffff},/* 88.5 MHz */
- {103200, 0x01889923, 0xcccccccf, 0xfffffffc, 0xffffffff},/* 103.2 MHz */
- {118000, 0x01c29923, 0x9999998f, 0xfffffff9, 0xffffffff},/* 118.0 MHz */
- {132700, 0x01fb2123, 0x9999998f, 0xfffffff9, 0xffffffff},/* 132.7 MHz */
- {147500, 0x02352123, 0x3333330f, 0xfffffff3, 0xffffffff},/* 147.5 MHz */
- {162200, 0x026b29a3, 0x38e38e1f, 0xfff8e38e, 0xffffffff},/* 162.2 MHz */
- {176900, 0x02a329a3, 0x71c71c1f, 0xfff1c71c, 0xffffffff},/* 176.9 MHz */
- {191700, 0x02dd31a3, 0xe38e383f, 0xffe38e38, 0xffffffff},/* 191.7 MHz */
- {206400, 0x03153223, 0xc71c703f, 0xffc71c71, 0xffffffff},/* 206.4 MHz */
- {221200, 0x034fba23, 0xc71c703f, 0xffc71c71, 0xffffffff},/* 221.2 MHz */
- {235900, 0x03853a23, 0xe1e1e07f, 0xe1e1e1e1, 0xffffffe1},/* 235.9 MHz */
- {250700, 0x03bf3aa3, 0xc3c3c07f, 0xc3c3c3c3, 0xffffffc3},/* 250.7 MHz */
- {265400, 0x03f7c2a3, 0xc3c3c07f, 0xc3c3c3c3, 0xffffffc3},/* 265.4 MHz */
- {280200, 0x0431c2a3, 0x878780ff, 0x87878787, 0xffffff87},/* 280.2 MHz */
- { 0, 0, 0, 0, 0 } /* last entry */
-};
-
-static void sa1100_update_dram_timings(int current_speed, int new_speed)
-{
- struct sa1100_dram_regs *settings = sa1100_dram_settings;
-
- /* find speed */
- while (settings->speed != 0) {
- if (new_speed == settings->speed)
- break;
-
- settings++;
- }
-
- if (settings->speed == 0) {
- panic("%s: couldn't find dram setting for speed %d\n",
- __func__, new_speed);
- }
-
- /* No risk, no fun: run with interrupts on! */
- if (new_speed > current_speed) {
- /* We're going FASTER, so first relax the memory
- * timings before changing the core frequency
- */
-
- /* Half the memory access clock */
- MDCNFG |= MDCNFG_CDB2;
-
- /* The order of these statements IS important, keep 8
- * pulses!!
- */
- MDCAS2 = settings->mdcas2;
- MDCAS1 = settings->mdcas1;
- MDCAS0 = settings->mdcas0;
- MDCNFG = settings->mdcnfg;
- } else {
- /* We're going SLOWER: first decrease the core
- * frequency and then tighten the memory settings.
- */
-
- /* Half the memory access clock */
- MDCNFG |= MDCNFG_CDB2;
-
- /* The order of these statements IS important, keep 8
- * pulses!!
- */
- MDCAS0 = settings->mdcas0;
- MDCAS1 = settings->mdcas1;
- MDCAS2 = settings->mdcas2;
- MDCNFG = settings->mdcnfg;
- }
-}
-
-static int sa1100_target(struct cpufreq_policy *policy,
- unsigned int target_freq,
- unsigned int relation)
-{
- unsigned int cur = sa11x0_getspeed(0);
- unsigned int new_ppcr;
- struct cpufreq_freqs freqs;
-
- new_ppcr = sa11x0_freq_to_ppcr(target_freq);
- switch (relation) {
- case CPUFREQ_RELATION_L:
- if (sa11x0_ppcr_to_freq(new_ppcr) > policy->max)
- new_ppcr--;
- break;
- case CPUFREQ_RELATION_H:
- if ((sa11x0_ppcr_to_freq(new_ppcr) > target_freq) &&
- (sa11x0_ppcr_to_freq(new_ppcr - 1) >= policy->min))
- new_ppcr--;
- break;
- }
-
- freqs.old = cur;
- freqs.new = sa11x0_ppcr_to_freq(new_ppcr);
- freqs.cpu = 0;
-
- cpufreq_notify_transition(&freqs, CPUFREQ_PRECHANGE);
-
- if (freqs.new > cur)
- sa1100_update_dram_timings(cur, freqs.new);
-
- PPCR = new_ppcr;
-
- if (freqs.new < cur)
- sa1100_update_dram_timings(cur, freqs.new);
-
- cpufreq_notify_transition(&freqs, CPUFREQ_POSTCHANGE);
-
- return 0;
-}
-
-static int __init sa1100_cpu_init(struct cpufreq_policy *policy)
-{
- if (policy->cpu != 0)
- return -EINVAL;
- policy->cur = policy->min = policy->max = sa11x0_getspeed(0);
- policy->cpuinfo.min_freq = 59000;
- policy->cpuinfo.max_freq = 287000;
- policy->cpuinfo.transition_latency = CPUFREQ_ETERNAL;
- return 0;
-}
-
-static struct cpufreq_driver sa1100_driver __refdata = {
- .flags = CPUFREQ_STICKY,
- .verify = sa11x0_verify_speed,
- .target = sa1100_target,
- .get = sa11x0_getspeed,
- .init = sa1100_cpu_init,
- .name = "sa1100",
-};
-
-static int __init sa1100_dram_init(void)
-{
- if (cpu_is_sa1100())
- return cpufreq_register_driver(&sa1100_driver);
- else
- return -ENODEV;
-}
-
-arch_initcall(sa1100_dram_init);
diff --git a/arch/arm/mach-sa1100/cpu-sa1110.c b/arch/arm/mach-sa1100/cpu-sa1110.c
deleted file mode 100644
index 48c45b0..0000000
--- a/arch/arm/mach-sa1100/cpu-sa1110.c
+++ /dev/null
@@ -1,408 +0,0 @@
-/*
- * linux/arch/arm/mach-sa1100/cpu-sa1110.c
- *
- * Copyright (C) 2001 Russell King
- *
- * 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.
- *
- * Note: there are two erratas that apply to the SA1110 here:
- * 7 - SDRAM auto-power-up failure (rev A0)
- * 13 - Corruption of internal register reads/writes following
- * SDRAM reads (rev A0, B0, B1)
- *
- * We ignore rev. A0 and B0 devices; I don't think they're worth supporting.
- *
- * The SDRAM type can be passed on the command line as cpu_sa1110.sdram=type
- */
-#include <linux/cpufreq.h>
-#include <linux/delay.h>
-#include <linux/init.h>
-#include <linux/io.h>
-#include <linux/kernel.h>
-#include <linux/moduleparam.h>
-#include <linux/types.h>
-
-#include <asm/cputype.h>
-#include <asm/mach-types.h>
-
-#include <mach/hardware.h>
-
-#include "generic.h"
-
-#undef DEBUG
-
-struct sdram_params {
- const char name[20];
- u_char rows; /* bits */
- u_char cas_latency; /* cycles */
- u_char tck; /* clock cycle time (ns) */
- u_char trcd; /* activate to r/w (ns) */
- u_char trp; /* precharge to activate (ns) */
- u_char twr; /* write recovery time (ns) */
- u_short refresh; /* refresh time for array (us) */
-};
-
-struct sdram_info {
- u_int mdcnfg;
- u_int mdrefr;
- u_int mdcas[3];
-};
-
-static struct sdram_params sdram_tbl[] __initdata = {
- { /* Toshiba TC59SM716 CL2 */
- .name = "TC59SM716-CL2",
- .rows = 12,
- .tck = 10,
- .trcd = 20,
- .trp = 20,
- .twr = 10,
- .refresh = 64000,
- .cas_latency = 2,
- }, { /* Toshiba TC59SM716 CL3 */
- .name = "TC59SM716-CL3",
- .rows = 12,
- .tck = 8,
- .trcd = 20,
- .trp = 20,
- .twr = 8,
- .refresh = 64000,
- .cas_latency = 3,
- }, { /* Samsung K4S641632D TC75 */
- .name = "K4S641632D",
- .rows = 14,
- .tck = 9,
- .trcd = 27,
- .trp = 20,
- .twr = 9,
- .refresh = 64000,
- .cas_latency = 3,
- }, { /* Samsung K4S281632B-1H */
- .name = "K4S281632B-1H",
- .rows = 12,
- .tck = 10,
- .trp = 20,
- .twr = 10,
- .refresh = 64000,
- .cas_latency = 3,
- }, { /* Samsung KM416S4030CT */
- .name = "KM416S4030CT",
- .rows = 13,
- .tck = 8,
- .trcd = 24, /* 3 CLKs */
- .trp = 24, /* 3 CLKs */
- .twr = 16, /* Trdl: 2 CLKs */
- .refresh = 64000,
- .cas_latency = 3,
- }, { /* Winbond W982516AH75L CL3 */
- .name = "W982516AH75L",
- .rows = 16,
- .tck = 8,
- .trcd = 20,
- .trp = 20,
- .twr = 8,
- .refresh = 64000,
- .cas_latency = 3,
- }, { /* Micron MT48LC8M16A2TG-75 */
- .name = "MT48LC8M16A2TG-75",
- .rows = 12,
- .tck = 8,
- .trcd = 20,
- .trp = 20,
- .twr = 8,
- .refresh = 64000,
- .cas_latency = 3,
- },
-};
-
-static struct sdram_params sdram_params;
-
-/*
- * Given a period in ns and frequency in khz, calculate the number of
- * cycles of frequency in period. Note that we round up to the next
- * cycle, even if we are only slightly over.
- */
-static inline u_int ns_to_cycles(u_int ns, u_int khz)
-{
- return (ns * khz + 999999) / 1000000;
-}
-
-/*
- * Create the MDCAS register bit pattern.
- */
-static inline void set_mdcas(u_int *mdcas, int delayed, u_int rcd)
-{
- u_int shift;
-
- rcd = 2 * rcd - 1;
- shift = delayed + 1 + rcd;
-
- mdcas[0] = (1 << rcd) - 1;
- mdcas[0] |= 0x55555555 << shift;
- mdcas[1] = mdcas[2] = 0x55555555 << (shift & 1);
-}
-
-static void
-sdram_calculate_timing(struct sdram_info *sd, u_int cpu_khz,
- struct sdram_params *sdram)
-{
- u_int mem_khz, sd_khz, trp, twr;
-
- mem_khz = cpu_khz / 2;
- sd_khz = mem_khz;
-
- /*
- * If SDCLK would invalidate the SDRAM timings,
- * run SDCLK at half speed.
- *
- * CPU steppings prior to B2 must either run the memory at
- * half speed or use delayed read latching (errata 13).
- */
- if ((ns_to_cycles(sdram->tck, sd_khz) > 1) ||
- (CPU_REVISION < CPU_SA1110_B2 && sd_khz < 62000))
- sd_khz /= 2;
-
- sd->mdcnfg = MDCNFG & 0x007f007f;
-
- twr = ns_to_cycles(sdram->twr, mem_khz);
-
- /* trp should always be >1 */
- trp = ns_to_cycles(sdram->trp, mem_khz) - 1;
- if (trp < 1)
- trp = 1;
-
- sd->mdcnfg |= trp << 8;
- sd->mdcnfg |= trp << 24;
- sd->mdcnfg |= sdram->cas_latency << 12;
- sd->mdcnfg |= sdram->cas_latency << 28;
- sd->mdcnfg |= twr << 14;
- sd->mdcnfg |= twr << 30;
-
- sd->mdrefr = MDREFR & 0xffbffff0;
- sd->mdrefr |= 7;
-
- if (sd_khz != mem_khz)
- sd->mdrefr |= MDREFR_K1DB2;
-
- /* initial number of '1's in MDCAS + 1 */
- set_mdcas(sd->mdcas, sd_khz >= 62000,
- ns_to_cycles(sdram->trcd, mem_khz));
-
-#ifdef DEBUG
- printk(KERN_DEBUG "MDCNFG: %08x MDREFR: %08x MDCAS0: %08x MDCAS1: %08x MDCAS2: %08x\n",
- sd->mdcnfg, sd->mdrefr, sd->mdcas[0], sd->mdcas[1],
- sd->mdcas[2]);
-#endif
-}
-
-/*
- * Set the SDRAM refresh rate.
- */
-static inline void sdram_set_refresh(u_int dri)
-{
- MDREFR = (MDREFR & 0xffff000f) | (dri << 4);
- (void) MDREFR;
-}
-
-/*
- * Update the refresh period. We do this such that we always refresh
- * the SDRAMs within their permissible period. The refresh period is
- * always a multiple of the memory clock (fixed at cpu_clock / 2).
- *
- * FIXME: we don't currently take account of burst accesses here,
- * but neither do Intels DM nor Angel.
- */
-static void
-sdram_update_refresh(u_int cpu_khz, struct sdram_params *sdram)
-{
- u_int ns_row = (sdram->refresh * 1000) >> sdram->rows;
- u_int dri = ns_to_cycles(ns_row, cpu_khz / 2) / 32;
-
-#ifdef DEBUG
- mdelay(250);
- printk(KERN_DEBUG "new dri value = %d\n", dri);
-#endif
-
- sdram_set_refresh(dri);
-}
-
-/*
- * Ok, set the CPU frequency.
- */
-static int sa1110_target(struct cpufreq_policy *policy,
- unsigned int target_freq,
- unsigned int relation)
-{
- struct sdram_params *sdram = &sdram_params;
- struct cpufreq_freqs freqs;
- struct sdram_info sd;
- unsigned long flags;
- unsigned int ppcr, unused;
-
- switch (relation) {
- case CPUFREQ_RELATION_L:
- ppcr = sa11x0_freq_to_ppcr(target_freq);
- if (sa11x0_ppcr_to_freq(ppcr) > policy->max)
- ppcr--;
- break;
- case CPUFREQ_RELATION_H:
- ppcr = sa11x0_freq_to_ppcr(target_freq);
- if (ppcr && (sa11x0_ppcr_to_freq(ppcr) > target_freq) &&
- (sa11x0_ppcr_to_freq(ppcr-1) >= policy->min))
- ppcr--;
- break;
- default:
- return -EINVAL;
- }
-
- freqs.old = sa11x0_getspeed(0);
- freqs.new = sa11x0_ppcr_to_freq(ppcr);
- freqs.cpu = 0;
-
- sdram_calculate_timing(&sd, freqs.new, sdram);
-
-#if 0
- /*
- * These values are wrong according to the SA1110 documentation
- * and errata, but they seem to work. Need to get a storage
- * scope on to the SDRAM signals to work out why.
- */
- if (policy->max < 147500) {
- sd.mdrefr |= MDREFR_K1DB2;
- sd.mdcas[0] = 0xaaaaaa7f;
- } else {
- sd.mdrefr &= ~MDREFR_K1DB2;
- sd.mdcas[0] = 0xaaaaaa9f;
- }
- sd.mdcas[1] = 0xaaaaaaaa;
- sd.mdcas[2] = 0xaaaaaaaa;
-#endif
-
- cpufreq_notify_transition(&freqs, CPUFREQ_PRECHANGE);
-
- /*
- * The clock could be going away for some time. Set the SDRAMs
- * to refresh rapidly (every 64 memory clock cycles). To get
- * through the whole array, we need to wait 262144 mclk cycles.
- * We wait 20ms to be safe.
- */
- sdram_set_refresh(2);
- if (!irqs_disabled())
- msleep(20);
- else
- mdelay(20);
-
- /*
- * Reprogram the DRAM timings with interrupts disabled, and
- * ensure that we are doing this within a complete cache line.
- * This means that we won't access SDRAM for the duration of
- * the programming.
- */
- local_irq_save(flags);
- asm("mcr p15, 0, %0, c7, c10, 4" : : "r" (0));
- udelay(10);
- __asm__ __volatile__("\n\
- b 2f \n\
- .align 5 \n\
-1: str %3, [%1, #0] @ MDCNFG \n\
- str %4, [%1, #28] @ MDREFR \n\
- str %5, [%1, #4] @ MDCAS0 \n\
- str %6, [%1, #8] @ MDCAS1 \n\
- str %7, [%1, #12] @ MDCAS2 \n\
- str %8, [%2, #0] @ PPCR \n\
- ldr %0, [%1, #0] \n\
- b 3f \n\
-2: b 1b \n\
-3: nop \n\
- nop"
- : "=&r" (unused)
- : "r" (&MDCNFG), "r" (&PPCR), "0" (sd.mdcnfg),
- "r" (sd.mdrefr), "r" (sd.mdcas[0]),
- "r" (sd.mdcas[1]), "r" (sd.mdcas[2]), "r" (ppcr));
- local_irq_restore(flags);
-
- /*
- * Now, return the SDRAM refresh back to normal.
- */
- sdram_update_refresh(freqs.new, sdram);
-
- cpufreq_notify_transition(&freqs, CPUFREQ_POSTCHANGE);
-
- return 0;
-}
-
-static int __init sa1110_cpu_init(struct cpufreq_policy *policy)
-{
- if (policy->cpu != 0)
- return -EINVAL;
- policy->cur = policy->min = policy->max = sa11x0_getspeed(0);
- policy->cpuinfo.min_freq = 59000;
- policy->cpuinfo.max_freq = 287000;
- policy->cpuinfo.transition_latency = CPUFREQ_ETERNAL;
- return 0;
-}
-
-/* sa1110_driver needs __refdata because it must remain after init registers
- * it with cpufreq_register_driver() */
-static struct cpufreq_driver sa1110_driver __refdata = {
- .flags = CPUFREQ_STICKY,
- .verify = sa11x0_verify_speed,
- .target = sa1110_target,
- .get = sa11x0_getspeed,
- .init = sa1110_cpu_init,
- .name = "sa1110",
-};
-
-static struct sdram_params *sa1110_find_sdram(const char *name)
-{
- struct sdram_params *sdram;
-
- for (sdram = sdram_tbl; sdram < sdram_tbl + ARRAY_SIZE(sdram_tbl);
- sdram++)
- if (strcmp(name, sdram->name) == 0)
- return sdram;
-
- return NULL;
-}
-
-static char sdram_name[16];
-
-static int __init sa1110_clk_init(void)
-{
- struct sdram_params *sdram;
- const char *name = sdram_name;
-
- if (!cpu_is_sa1110())
- return -ENODEV;
-
- if (!name[0]) {
- if (machine_is_assabet())
- name = "TC59SM716-CL3";
- if (machine_is_pt_system3())
- name = "K4S641632D";
- if (machine_is_h3100())
- name = "KM416S4030CT";
- if (machine_is_jornada720())
- name = "K4S281632B-1H";
- if (machine_is_nanoengine())
- name = "MT48LC8M16A2TG-75";
- }
-
- sdram = sa1110_find_sdram(name);
- if (sdram) {
- printk(KERN_DEBUG "SDRAM: tck: %d trcd: %d trp: %d"
- " twr: %d refresh: %d cas_latency: %d\n",
- sdram->tck, sdram->trcd, sdram->trp,
- sdram->twr, sdram->refresh, sdram->cas_latency);
-
- memcpy(&sdram_params, sdram, sizeof(sdram_params));
-
- return cpufreq_register_driver(&sa1110_driver);
- }
-
- return 0;
-}
-
-module_param_string(sdram, sdram_name, sizeof(sdram_name), 0);
-arch_initcall(sa1110_clk_init);
diff --git a/arch/arm/mach-sa1100/include/mach/generic.h b/arch/arm/mach-sa1100/include/mach/generic.h
new file mode 100644
index 0000000..665542e
--- /dev/null
+++ b/arch/arm/mach-sa1100/include/mach/generic.h
@@ -0,0 +1 @@
+#include "../../generic.h"
diff --git a/arch/arm/mach-tegra/Makefile b/arch/arm/mach-tegra/Makefile
index f6b46ae..09b578f 100644
--- a/arch/arm/mach-tegra/Makefile
+++ b/arch/arm/mach-tegra/Makefile
@@ -24,7 +24,6 @@ obj-$(CONFIG_ARCH_TEGRA_3x_SOC) += cpuidle-tegra30.o
endif
obj-$(CONFIG_SMP) += platsmp.o headsmp.o
obj-$(CONFIG_HOTPLUG_CPU) += hotplug.o
-obj-$(CONFIG_CPU_FREQ) += cpu-tegra.o
obj-$(CONFIG_TEGRA_PCI) += pcie.o
obj-$(CONFIG_ARCH_TEGRA_2x_SOC) += board-dt-tegra20.o
diff --git a/arch/arm/mach-tegra/cpu-tegra.c b/arch/arm/mach-tegra/cpu-tegra.c
deleted file mode 100644
index e3d6e15..0000000
--- a/arch/arm/mach-tegra/cpu-tegra.c
+++ /dev/null
@@ -1,293 +0,0 @@
-/*
- * arch/arm/mach-tegra/cpu-tegra.c
- *
- * Copyright (C) 2010 Google, Inc.
- *
- * Author:
- * Colin Cross <ccross@google.com>
- * Based on arch/arm/plat-omap/cpu-omap.c, (C) 2005 Nokia Corporation
- *
- * This software is licensed under the terms of the GNU General Public
- * License version 2, as published by the Free Software Foundation, and
- * may be copied, distributed, and modified under those terms.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- */
-
-#include <linux/kernel.h>
-#include <linux/module.h>
-#include <linux/types.h>
-#include <linux/sched.h>
-#include <linux/cpufreq.h>
-#include <linux/delay.h>
-#include <linux/init.h>
-#include <linux/err.h>
-#include <linux/clk.h>
-#include <linux/io.h>
-#include <linux/suspend.h>
-
-/* Frequency table index must be sequential starting at 0 */
-static struct cpufreq_frequency_table freq_table[] = {
- { 0, 216000 },
- { 1, 312000 },
- { 2, 456000 },
- { 3, 608000 },
- { 4, 760000 },
- { 5, 816000 },
- { 6, 912000 },
- { 7, 1000000 },
- { 8, CPUFREQ_TABLE_END },
-};
-
-#define NUM_CPUS 2
-
-static struct clk *cpu_clk;
-static struct clk *pll_x_clk;
-static struct clk *pll_p_clk;
-static struct clk *emc_clk;
-
-static unsigned long target_cpu_speed[NUM_CPUS];
-static DEFINE_MUTEX(tegra_cpu_lock);
-static bool is_suspended;
-
-static int tegra_verify_speed(struct cpufreq_policy *policy)
-{
- return cpufreq_frequency_table_verify(policy, freq_table);
-}
-
-static unsigned int tegra_getspeed(unsigned int cpu)
-{
- unsigned long rate;
-
- if (cpu >= NUM_CPUS)
- return 0;
-
- rate = clk_get_rate(cpu_clk) / 1000;
- return rate;
-}
-
-static int tegra_cpu_clk_set_rate(unsigned long rate)
-{
- int ret;
-
- /*
- * Take an extra reference to the main pll so it doesn't turn
- * off when we move the cpu off of it
- */
- clk_prepare_enable(pll_x_clk);
-
- ret = clk_set_parent(cpu_clk, pll_p_clk);
- if (ret) {
- pr_err("Failed to switch cpu to clock pll_p\n");
- goto out;
- }
-
- if (rate == clk_get_rate(pll_p_clk))
- goto out;
-
- ret = clk_set_rate(pll_x_clk, rate);
- if (ret) {
- pr_err("Failed to change pll_x to %lu\n", rate);
- goto out;
- }
-
- ret = clk_set_parent(cpu_clk, pll_x_clk);
- if (ret) {
- pr_err("Failed to switch cpu to clock pll_x\n");
- goto out;
- }
-
-out:
- clk_disable_unprepare(pll_x_clk);
- return ret;
-}
-
-static int tegra_update_cpu_speed(unsigned long rate)
-{
- int ret = 0;
- struct cpufreq_freqs freqs;
-
- freqs.old = tegra_getspeed(0);
- freqs.new = rate;
-
- if (freqs.old == freqs.new)
- return ret;
-
- /*
- * Vote on memory bus frequency based on cpu frequency
- * This sets the minimum frequency, display or avp may request higher
- */
- if (rate >= 816000)
- clk_set_rate(emc_clk, 600000000); /* cpu 816 MHz, emc max */
- else if (rate >= 456000)
- clk_set_rate(emc_clk, 300000000); /* cpu 456 MHz, emc 150Mhz */
- else
- clk_set_rate(emc_clk, 100000000); /* emc 50Mhz */
-
- for_each_online_cpu(freqs.cpu)
- cpufreq_notify_transition(&freqs, CPUFREQ_PRECHANGE);
-
-#ifdef CONFIG_CPU_FREQ_DEBUG
- printk(KERN_DEBUG "cpufreq-tegra: transition: %u --> %u\n",
- freqs.old, freqs.new);
-#endif
-
- ret = tegra_cpu_clk_set_rate(freqs.new * 1000);
- if (ret) {
- pr_err("cpu-tegra: Failed to set cpu frequency to %d kHz\n",
- freqs.new);
- return ret;
- }
-
- for_each_online_cpu(freqs.cpu)
- cpufreq_notify_transition(&freqs, CPUFREQ_POSTCHANGE);
-
- return 0;
-}
-
-static unsigned long tegra_cpu_highest_speed(void)
-{
- unsigned long rate = 0;
- int i;
-
- for_each_online_cpu(i)
- rate = max(rate, target_cpu_speed[i]);
- return rate;
-}
-
-static int tegra_target(struct cpufreq_policy *policy,
- unsigned int target_freq,
- unsigned int relation)
-{
- unsigned int idx;
- unsigned int freq;
- int ret = 0;
-
- mutex_lock(&tegra_cpu_lock);
-
- if (is_suspended) {
- ret = -EBUSY;
- goto out;
- }
-
- cpufreq_frequency_table_target(policy, freq_table, target_freq,
- relation, &idx);
-
- freq = freq_table[idx].frequency;
-
- target_cpu_speed[policy->cpu] = freq;
-
- ret = tegra_update_cpu_speed(tegra_cpu_highest_speed());
-
-out:
- mutex_unlock(&tegra_cpu_lock);
- return ret;
-}
-
-static int tegra_pm_notify(struct notifier_block *nb, unsigned long event,
- void *dummy)
-{
- mutex_lock(&tegra_cpu_lock);
- if (event == PM_SUSPEND_PREPARE) {
- is_suspended = true;
- pr_info("Tegra cpufreq suspend: setting frequency to %d kHz\n",
- freq_table[0].frequency);
- tegra_update_cpu_speed(freq_table[0].frequency);
- } else if (event == PM_POST_SUSPEND) {
- is_suspended = false;
- }
- mutex_unlock(&tegra_cpu_lock);
-
- return NOTIFY_OK;
-}
-
-static struct notifier_block tegra_cpu_pm_notifier = {
- .notifier_call = tegra_pm_notify,
-};
-
-static int tegra_cpu_init(struct cpufreq_policy *policy)
-{
- if (policy->cpu >= NUM_CPUS)
- return -EINVAL;
-
- clk_prepare_enable(emc_clk);
- clk_prepare_enable(cpu_clk);
-
- cpufreq_frequency_table_cpuinfo(policy, freq_table);
- cpufreq_frequency_table_get_attr(freq_table, policy->cpu);
- policy->cur = tegra_getspeed(policy->cpu);
- target_cpu_speed[policy->cpu] = policy->cur;
-
- /* FIXME: what's the actual transition time? */
- policy->cpuinfo.transition_latency = 300 * 1000;
-
- cpumask_copy(policy->cpus, cpu_possible_mask);
-
- if (policy->cpu == 0)
- register_pm_notifier(&tegra_cpu_pm_notifier);
-
- return 0;
-}
-
-static int tegra_cpu_exit(struct cpufreq_policy *policy)
-{
- cpufreq_frequency_table_cpuinfo(policy, freq_table);
- clk_disable_unprepare(emc_clk);
- return 0;
-}
-
-static struct freq_attr *tegra_cpufreq_attr[] = {
- &cpufreq_freq_attr_scaling_available_freqs,
- NULL,
-};
-
-static struct cpufreq_driver tegra_cpufreq_driver = {
- .verify = tegra_verify_speed,
- .target = tegra_target,
- .get = tegra_getspeed,
- .init = tegra_cpu_init,
- .exit = tegra_cpu_exit,
- .name = "tegra",
- .attr = tegra_cpufreq_attr,
-};
-
-static int __init tegra_cpufreq_init(void)
-{
- cpu_clk = clk_get_sys(NULL, "cpu");
- if (IS_ERR(cpu_clk))
- return PTR_ERR(cpu_clk);
-
- pll_x_clk = clk_get_sys(NULL, "pll_x");
- if (IS_ERR(pll_x_clk))
- return PTR_ERR(pll_x_clk);
-
- pll_p_clk = clk_get_sys(NULL, "pll_p_cclk");
- if (IS_ERR(pll_p_clk))
- return PTR_ERR(pll_p_clk);
-
- emc_clk = clk_get_sys("cpu", "emc");
- if (IS_ERR(emc_clk)) {
- clk_put(cpu_clk);
- return PTR_ERR(emc_clk);
- }
-
- return cpufreq_register_driver(&tegra_cpufreq_driver);
-}
-
-static void __exit tegra_cpufreq_exit(void)
-{
- cpufreq_unregister_driver(&tegra_cpufreq_driver);
- clk_put(emc_clk);
- clk_put(cpu_clk);
-}
-
-
-MODULE_AUTHOR("Colin Cross <ccross@android.com>");
-MODULE_DESCRIPTION("cpufreq driver for Nvidia Tegra2");
-MODULE_LICENSE("GPL");
-module_init(tegra_cpufreq_init);
-module_exit(tegra_cpufreq_exit);