* [PATCH 05/10] cpufreq: OMAP: move clk name decision to init
From: Kevin Hilman @ 2011-09-22 21:07 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <1316725648-26710-1-git-send-email-khilman@ti.com>
From: Nishanth Menon <nm@ti.com>
Clk name does'nt need to dynamically detected during clk init.
move them off to driver initialization, if we dont have a clk name,
there is no point in registering the driver anyways. The actual clk
get and put is left at cpu_init and exit functions.
Signed-off-by: Nishanth Menon <nm@ti.com>
Signed-off-by: Kevin Hilman <khilman@ti.com>
---
drivers/cpufreq/omap-cpufreq.c | 20 +++++++++++++-------
1 files changed, 13 insertions(+), 7 deletions(-)
diff --git a/drivers/cpufreq/omap-cpufreq.c b/drivers/cpufreq/omap-cpufreq.c
index 724d36c..07e835d 100644
--- a/drivers/cpufreq/omap-cpufreq.c
+++ b/drivers/cpufreq/omap-cpufreq.c
@@ -48,6 +48,7 @@ static struct lpj_info global_lpj_ref;
static struct cpufreq_frequency_table *freq_table;
static struct clk *mpu_clk;
+static char *mpu_clk_name;
static int omap_verify_speed(struct cpufreq_policy *policy)
{
@@ -152,13 +153,7 @@ static int __cpuinit omap_cpu_init(struct cpufreq_policy *policy)
int result = 0;
struct device *mpu_dev;
- if (cpu_is_omap24xx())
- mpu_clk = clk_get(NULL, "virt_prcm_set");
- else if (cpu_is_omap34xx())
- mpu_clk = clk_get(NULL, "dpll1_ck");
- else if (cpu_is_omap44xx())
- mpu_clk = clk_get(NULL, "dpll_mpu_ck");
-
+ mpu_clk = clk_get(NULL, mpu_clk_name);
if (IS_ERR(mpu_clk))
return PTR_ERR(mpu_clk);
@@ -232,6 +227,17 @@ static struct cpufreq_driver omap_driver = {
static int __init omap_cpufreq_init(void)
{
+ if (cpu_is_omap24xx())
+ mpu_clk_name = "virt_prcm_set";
+ else if (cpu_is_omap34xx())
+ mpu_clk_name = "dpll1_ck";
+ else if (cpu_is_omap44xx())
+ mpu_clk_name = "dpll_mpu_ck";
+
+ if (!mpu_clk_name) {
+ pr_err("%s: unsupported Silicon?\n", __func__);
+ return -EINVAL;
+ }
return cpufreq_register_driver(&omap_driver);
}
--
1.7.6
^ permalink raw reply related
* [PATCH 04/10] cpufreq: OMAP: notify even with bad boot frequency
From: Kevin Hilman @ 2011-09-22 21:07 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <1316725648-26710-1-git-send-email-khilman@ti.com>
From: Colin Cross <ccross@google.com>
Sometimes, bootloaders starts up with a frequency which is not
in the OPP table. At cpu_init, policy->cur contains the frequency
we pick at boot. It is possible that system might have fixed
it's boot frequency later on as part of power initialization.
After this condition, the first call to omap_target results in the
following:
omap_getspeed(actual device frequency) != policy->cur(frequency that
cpufreq thinks that the system is at), and it is possible that
freqs.old == freqs.new (because the governor requested a scale down).
We exit without triggering the notifiers in the current code, which
does'nt let code which depends on cpufreq_notify_transition to have
accurate information as to what the system frequency is.
Instead, we do a normal transition if policy->cur is wrong, then,
freqs.old will be the actual cpu frequency, freqs.new will be the
actual new cpu frequency and all required notifiers have the accurate
information.
Acked-by: Nishanth Menon <nm@ti.com>
Signed-off-by: Colin Cross <ccross@google.com>
Signed-off-by: Kevin Hilman <khilman@ti.com>
---
drivers/cpufreq/omap-cpufreq.c | 2 +-
1 files changed, 1 insertions(+), 1 deletions(-)
diff --git a/drivers/cpufreq/omap-cpufreq.c b/drivers/cpufreq/omap-cpufreq.c
index 5e2f05a..724d36c 100644
--- a/drivers/cpufreq/omap-cpufreq.c
+++ b/drivers/cpufreq/omap-cpufreq.c
@@ -96,7 +96,7 @@ static int omap_target(struct cpufreq_policy *policy,
freqs.new = clk_round_rate(mpu_clk, target_freq * 1000) / 1000;
freqs.cpu = policy->cpu;
- if (freqs.old == freqs.new)
+ if (freqs.old == freqs.new && policy->cur == freqs.new)
return ret;
/* notifiers */
--
1.7.6
^ permalink raw reply related
* [PATCH 03/10] cpufreq: OMAP: Enable all CPUs in shared policy mask
From: Kevin Hilman @ 2011-09-22 21:07 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <1316725648-26710-1-git-send-email-khilman@ti.com>
From: Todd Poynor <toddpoynor@google.com>
Enable all CPUs in the shared policy in the CPU init callback.
Otherwise, the governor CPUFREQ_GOV_START event is invoked with
a policy that only includes the first CPU, leaving other CPUs
uninitialized by the governor.
Signed-off-by: Todd Poynor <toddpoynor@google.com>
Acked-by: Santosh Shilimkar <santosh.shilimkar@ti.com>
Signed-off-by: Kevin Hilman <khilman@ti.com>
---
drivers/cpufreq/omap-cpufreq.c | 4 +---
1 files changed, 1 insertions(+), 3 deletions(-)
diff --git a/drivers/cpufreq/omap-cpufreq.c b/drivers/cpufreq/omap-cpufreq.c
index f9b4c4d..5e2f05a 100644
--- a/drivers/cpufreq/omap-cpufreq.c
+++ b/drivers/cpufreq/omap-cpufreq.c
@@ -151,7 +151,6 @@ static int __cpuinit omap_cpu_init(struct cpufreq_policy *policy)
{
int result = 0;
struct device *mpu_dev;
- static cpumask_var_t cpumask;
if (cpu_is_omap24xx())
mpu_clk = clk_get(NULL, "virt_prcm_set");
@@ -199,8 +198,7 @@ static int __cpuinit omap_cpu_init(struct cpufreq_policy *policy)
*/
if (is_smp()) {
policy->shared_type = CPUFREQ_SHARED_TYPE_ANY;
- cpumask_or(cpumask, cpumask_of(policy->cpu), cpumask);
- cpumask_copy(policy->cpus, cpumask);
+ cpumask_setall(policy->cpus);
}
/* FIXME: what's the actual transition time? */
--
1.7.6
^ permalink raw reply related
* [PATCH 02/10] cpufreq: OMAP: Add SMP support for OMAP4+
From: Kevin Hilman @ 2011-09-22 21:07 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <1316725648-26710-1-git-send-email-khilman@ti.com>
From: Russell King <rmk+kernel@arm.linux.org.uk>
On OMAP SMP configuartion, both processors share the voltage
and clock. So both CPUs needs to be scaled together and hence
needs software co-ordination.
Also, update lpj with reference value to avoid progressive error.
Adjust _both_ the per-cpu loops_per_jiffy and global lpj. Calibrate
them with with reference to the initial values to avoid a
progressively bigger and bigger error in the value over time.
While at this, re-use the notifiers for UP/SMP since on UP machine or
UP_ON_SMP policy->cpus mask would contain only the boot CPU.
Based on initial SMP support by Santosh Shilimkar.
Signed-off-by: Russell King <rmk+kernel@arm.linux.org.uk>
Signed-off-by: Santosh Shilimkar <santosh.shilimkar@ti.com>
[khilman at ti.com: due to overlap/rework, combined original Santosh patch
and Russell's rework]
Signed-off-by: Kevin Hilman <khilman@ti.com>
---
drivers/cpufreq/omap-cpufreq.c | 80 +++++++++++++++++++++++++++++++++++-----
1 files changed, 70 insertions(+), 10 deletions(-)
diff --git a/drivers/cpufreq/omap-cpufreq.c b/drivers/cpufreq/omap-cpufreq.c
index a6b2be7..f9b4c4d 100644
--- a/drivers/cpufreq/omap-cpufreq.c
+++ b/drivers/cpufreq/omap-cpufreq.c
@@ -23,6 +23,7 @@
#include <linux/clk.h>
#include <linux/io.h>
#include <linux/opp.h>
+#include <linux/cpu.h>
#include <asm/system.h>
#include <asm/smp_plat.h>
@@ -35,6 +36,16 @@
#define VERY_HI_RATE 900000000
+#ifdef CONFIG_SMP
+struct lpj_info {
+ unsigned long ref;
+ unsigned int freq;
+};
+
+static DEFINE_PER_CPU(struct lpj_info, lpj_ref);
+static struct lpj_info global_lpj_ref;
+#endif
+
static struct cpufreq_frequency_table *freq_table;
static struct clk *mpu_clk;
@@ -60,7 +71,7 @@ static unsigned int omap_getspeed(unsigned int cpu)
{
unsigned long rate;
- if (cpu)
+ if (cpu >= NR_CPUS)
return 0;
rate = clk_get_rate(mpu_clk) / 1000;
@@ -71,7 +82,7 @@ static int omap_target(struct cpufreq_policy *policy,
unsigned int target_freq,
unsigned int relation)
{
- int ret = 0;
+ int i, ret = 0;
struct cpufreq_freqs freqs;
/* Ensure desired rate is within allowed range. Some govenors
@@ -81,22 +92,57 @@ static int omap_target(struct cpufreq_policy *policy,
if (target_freq > policy->max)
target_freq = policy->max;
- freqs.old = omap_getspeed(0);
+ freqs.old = omap_getspeed(policy->cpu);
freqs.new = clk_round_rate(mpu_clk, target_freq * 1000) / 1000;
- freqs.cpu = 0;
+ freqs.cpu = policy->cpu;
if (freqs.old == freqs.new)
return ret;
- cpufreq_notify_transition(&freqs, CPUFREQ_PRECHANGE);
+ /* notifiers */
+ for_each_cpu(i, policy->cpus) {
+ freqs.cpu = i;
+ cpufreq_notify_transition(&freqs, CPUFREQ_PRECHANGE);
+ }
#ifdef CONFIG_CPU_FREQ_DEBUG
pr_info("cpufreq-omap: transition: %u --> %u\n", freqs.old, freqs.new);
#endif
ret = clk_set_rate(mpu_clk, freqs.new * 1000);
+ freqs.new = omap_getspeed(policy->cpu);
+
+#ifdef CONFIG_SMP
+ /*
+ * Note that loops_per_jiffy is not updated on SMP systems in
+ * cpufreq driver. So, update the per-CPU loops_per_jiffy value
+ * on frequency transition. We need to update all dependent CPUs.
+ */
+ for_each_cpu(i, policy->cpus) {
+ struct lpj_info *lpj = &per_cpu(lpj_ref, i);
+ if (!lpj->freq) {
+ lpj->ref = per_cpu(cpu_data, i).loops_per_jiffy;
+ lpj->freq = freqs.old;
+ }
+
+ per_cpu(cpu_data, i).loops_per_jiffy =
+ cpufreq_scale(lpj->ref, lpj->freq, freqs.new);
+ }
- cpufreq_notify_transition(&freqs, CPUFREQ_POSTCHANGE);
+ /* And don't forget to adjust the global one */
+ if (!global_lpj_ref.freq) {
+ global_lpj_ref.ref = loops_per_jiffy;
+ global_lpj_ref.freq = freqs.old;
+ }
+ loops_per_jiffy = cpufreq_scale(global_lpj_ref.ref, global_lpj_ref.freq,
+ freqs.new);
+#endif
+
+ /* notifiers */
+ for_each_cpu(i, policy->cpus) {
+ freqs.cpu = i;
+ cpufreq_notify_transition(&freqs, CPUFREQ_POSTCHANGE);
+ }
return ret;
}
@@ -105,6 +151,7 @@ static int __cpuinit omap_cpu_init(struct cpufreq_policy *policy)
{
int result = 0;
struct device *mpu_dev;
+ static cpumask_var_t cpumask;
if (cpu_is_omap24xx())
mpu_clk = clk_get(NULL, "virt_prcm_set");
@@ -116,12 +163,12 @@ static int __cpuinit omap_cpu_init(struct cpufreq_policy *policy)
if (IS_ERR(mpu_clk))
return PTR_ERR(mpu_clk);
- if (policy->cpu != 0)
+ if (policy->cpu >= NR_CPUS)
return -EINVAL;
- policy->cur = policy->min = policy->max = omap_getspeed(0);
-
+ policy->cur = policy->min = policy->max = omap_getspeed(policy->cpu);
mpu_dev = omap2_get_mpuss_device();
+
if (!mpu_dev) {
pr_warning("%s: unable to get the mpu device\n", __func__);
return -EINVAL;
@@ -141,7 +188,20 @@ static int __cpuinit omap_cpu_init(struct cpufreq_policy *policy)
policy->min = policy->cpuinfo.min_freq;
policy->max = policy->cpuinfo.max_freq;
- policy->cur = omap_getspeed(0);
+ policy->cur = omap_getspeed(policy->cpu);
+
+ /*
+ * On OMAP SMP configuartion, both processors share the voltage
+ * and clock. So both CPUs needs to be scaled together and hence
+ * needs software co-ordination. Use cpufreq affected_cpus
+ * interface to handle this scenario. Additional is_smp() check
+ * is to keep SMP_ON_UP build working.
+ */
+ if (is_smp()) {
+ policy->shared_type = CPUFREQ_SHARED_TYPE_ANY;
+ cpumask_or(cpumask, cpumask_of(policy->cpu), cpumask);
+ cpumask_copy(policy->cpus, cpumask);
+ }
/* FIXME: what's the actual transition time? */
policy->cpuinfo.transition_latency = 300 * 1000;
--
1.7.6
^ permalink raw reply related
* [PATCH 01/10] cpufreq: OMAP: cleanup for multi-SoC support, move into drivers/cpufreq
From: Kevin Hilman @ 2011-09-22 21:07 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <1316725648-26710-1-git-send-email-khilman@ti.com>
From: Santosh Shilimkar <santosh.shilimkar@ti.com>
Move OMAP cpufreq driver from arch/arm/mach-omap2 into
drivers/cpufreq, along with a few cleanups:
- generalize support for better handling of different SoCs in the OMAP
- use OPP layer instead of OMAP clock internals for frequency table init
Signed-off-by: Santosh Shilimkar <santosh.shilimkar@ti.com>
[khilman at ti.com: move to drivers]
Signed-off-by: Kevin Hilman <khilman@ti.com>
---
arch/arm/plat-omap/Makefile | 1 -
arch/arm/plat-omap/cpu-omap.c | 171 ------------------------------------
drivers/cpufreq/Makefile | 1 +
drivers/cpufreq/omap-cpufreq.c | 188 ++++++++++++++++++++++++++++++++++++++++
4 files changed, 189 insertions(+), 172 deletions(-)
delete mode 100644 arch/arm/plat-omap/cpu-omap.c
create mode 100644 drivers/cpufreq/omap-cpufreq.c
diff --git a/arch/arm/plat-omap/Makefile b/arch/arm/plat-omap/Makefile
index f0233e6..4ef7493 100644
--- a/arch/arm/plat-omap/Makefile
+++ b/arch/arm/plat-omap/Makefile
@@ -21,7 +21,6 @@ obj-$(CONFIG_OMAP_MCBSP) += mcbsp.o
obj-$(CONFIG_OMAP_IOMMU) += iommu.o iovmm.o
obj-$(CONFIG_OMAP_IOMMU_DEBUG) += iommu-debug.o
-obj-$(CONFIG_CPU_FREQ) += cpu-omap.o
obj-$(CONFIG_OMAP_DM_TIMER) += dmtimer.o
obj-$(CONFIG_OMAP_DEBUG_DEVICES) += debug-devices.o
obj-$(CONFIG_OMAP_DEBUG_LEDS) += debug-leds.o
diff --git a/arch/arm/plat-omap/cpu-omap.c b/arch/arm/plat-omap/cpu-omap.c
deleted file mode 100644
index da4f68d..0000000
--- a/arch/arm/plat-omap/cpu-omap.c
+++ /dev/null
@@ -1,171 +0,0 @@
-/*
- * linux/arch/arm/plat-omap/cpu-omap.c
- *
- * CPU frequency scaling for OMAP
- *
- * Copyright (C) 2005 Nokia Corporation
- * Written by Tony Lindgren <tony@atomide.com>
- *
- * Based on 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.
- */
-#include <linux/types.h>
-#include <linux/kernel.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 <mach/hardware.h>
-#include <plat/clock.h>
-#include <asm/system.h>
-
-#define VERY_HI_RATE 900000000
-
-static struct cpufreq_frequency_table *freq_table;
-
-#ifdef CONFIG_ARCH_OMAP1
-#define MPU_CLK "mpu"
-#else
-#define MPU_CLK "virt_prcm_set"
-#endif
-
-static struct clk *mpu_clk;
-
-/* TODO: Add support for SDRAM timing changes */
-
-static int omap_verify_speed(struct cpufreq_policy *policy)
-{
- 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(mpu_clk, policy->min * 1000) / 1000;
- policy->max = clk_round_rate(mpu_clk, policy->max * 1000) / 1000;
- cpufreq_verify_within_limits(policy, policy->cpuinfo.min_freq,
- policy->cpuinfo.max_freq);
- return 0;
-}
-
-static unsigned int omap_getspeed(unsigned int cpu)
-{
- unsigned long rate;
-
- if (cpu)
- return 0;
-
- rate = clk_get_rate(mpu_clk) / 1000;
- return rate;
-}
-
-static int omap_target(struct cpufreq_policy *policy,
- unsigned int target_freq,
- unsigned int relation)
-{
- struct cpufreq_freqs freqs;
- int ret = 0;
-
- /* Ensure desired rate is within allowed range. Some govenors
- * (ondemand) will just pass target_freq=0 to get the minimum. */
- if (target_freq < policy->min)
- target_freq = policy->min;
- if (target_freq > policy->max)
- target_freq = policy->max;
-
- freqs.old = omap_getspeed(0);
- freqs.new = clk_round_rate(mpu_clk, target_freq * 1000) / 1000;
- freqs.cpu = 0;
-
- if (freqs.old == freqs.new)
- return ret;
-
- cpufreq_notify_transition(&freqs, CPUFREQ_PRECHANGE);
-#ifdef CONFIG_CPU_FREQ_DEBUG
- printk(KERN_DEBUG "cpufreq-omap: transition: %u --> %u\n",
- freqs.old, freqs.new);
-#endif
- ret = clk_set_rate(mpu_clk, freqs.new * 1000);
- cpufreq_notify_transition(&freqs, CPUFREQ_POSTCHANGE);
-
- return ret;
-}
-
-static int __cpuinit omap_cpu_init(struct cpufreq_policy *policy)
-{
- int result = 0;
-
- mpu_clk = clk_get(NULL, MPU_CLK);
- if (IS_ERR(mpu_clk))
- return PTR_ERR(mpu_clk);
-
- if (policy->cpu != 0)
- return -EINVAL;
-
- policy->cur = policy->min = policy->max = omap_getspeed(0);
-
- clk_init_cpufreq_table(&freq_table);
- 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 = clk_round_rate(mpu_clk, 0) / 1000;
- policy->cpuinfo.max_freq = clk_round_rate(mpu_clk,
- VERY_HI_RATE) / 1000;
- }
-
- /* FIXME: what's the actual transition time? */
- policy->cpuinfo.transition_latency = 300 * 1000;
-
- return 0;
-}
-
-static int omap_cpu_exit(struct cpufreq_policy *policy)
-{
- clk_exit_cpufreq_table(&freq_table);
- clk_put(mpu_clk);
- return 0;
-}
-
-static struct freq_attr *omap_cpufreq_attr[] = {
- &cpufreq_freq_attr_scaling_available_freqs,
- NULL,
-};
-
-static struct cpufreq_driver omap_driver = {
- .flags = CPUFREQ_STICKY,
- .verify = omap_verify_speed,
- .target = omap_target,
- .get = omap_getspeed,
- .init = omap_cpu_init,
- .exit = omap_cpu_exit,
- .name = "omap",
- .attr = omap_cpufreq_attr,
-};
-
-static int __init omap_cpufreq_init(void)
-{
- return cpufreq_register_driver(&omap_driver);
-}
-
-arch_initcall(omap_cpufreq_init);
-
-/*
- * if ever we want to remove this, upon cleanup call:
- *
- * cpufreq_unregister_driver()
- * cpufreq_frequency_table_put_attr()
- */
-
diff --git a/drivers/cpufreq/Makefile b/drivers/cpufreq/Makefile
index a48bc02..ce75fcb 100644
--- a/drivers/cpufreq/Makefile
+++ b/drivers/cpufreq/Makefile
@@ -43,6 +43,7 @@ obj-$(CONFIG_UX500_SOC_DB8500) += db8500-cpufreq.o
obj-$(CONFIG_ARM_S3C64XX_CPUFREQ) += s3c64xx-cpufreq.o
obj-$(CONFIG_ARM_S5PV210_CPUFREQ) += s5pv210-cpufreq.o
obj-$(CONFIG_ARM_EXYNOS4210_CPUFREQ) += exynos4210-cpufreq.o
+obj-$(CONFIG_ARCH_OMAP2PLUS) += omap-cpufreq.o
##################################################################################
# PowerPC platform drivers
diff --git a/drivers/cpufreq/omap-cpufreq.c b/drivers/cpufreq/omap-cpufreq.c
new file mode 100644
index 0000000..a6b2be7
--- /dev/null
+++ b/drivers/cpufreq/omap-cpufreq.c
@@ -0,0 +1,188 @@
+/*
+ * CPU frequency scaling for OMAP
+ *
+ * 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-2011 Texas Instruments, Inc.
+ * - OMAP3/4 support by Rajendra Nayak, Santosh Shilimkar
+ *
+ * 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/kernel.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/opp.h>
+
+#include <asm/system.h>
+#include <asm/smp_plat.h>
+
+#include <plat/clock.h>
+#include <plat/omap-pm.h>
+#include <plat/common.h>
+
+#include <mach/hardware.h>
+
+#define VERY_HI_RATE 900000000
+
+static struct cpufreq_frequency_table *freq_table;
+static struct clk *mpu_clk;
+
+static int omap_verify_speed(struct cpufreq_policy *policy)
+{
+ 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(mpu_clk, policy->min * 1000) / 1000;
+ policy->max = clk_round_rate(mpu_clk, policy->max * 1000) / 1000;
+ cpufreq_verify_within_limits(policy, policy->cpuinfo.min_freq,
+ policy->cpuinfo.max_freq);
+ return 0;
+}
+
+static unsigned int omap_getspeed(unsigned int cpu)
+{
+ unsigned long rate;
+
+ if (cpu)
+ return 0;
+
+ rate = clk_get_rate(mpu_clk) / 1000;
+ return rate;
+}
+
+static int omap_target(struct cpufreq_policy *policy,
+ unsigned int target_freq,
+ unsigned int relation)
+{
+ int ret = 0;
+ struct cpufreq_freqs freqs;
+
+ /* Ensure desired rate is within allowed range. Some govenors
+ * (ondemand) will just pass target_freq=0 to get the minimum. */
+ if (target_freq < policy->min)
+ target_freq = policy->min;
+ if (target_freq > policy->max)
+ target_freq = policy->max;
+
+ freqs.old = omap_getspeed(0);
+ freqs.new = clk_round_rate(mpu_clk, target_freq * 1000) / 1000;
+ freqs.cpu = 0;
+
+ if (freqs.old == freqs.new)
+ return ret;
+
+ cpufreq_notify_transition(&freqs, CPUFREQ_PRECHANGE);
+
+#ifdef CONFIG_CPU_FREQ_DEBUG
+ pr_info("cpufreq-omap: transition: %u --> %u\n", freqs.old, freqs.new);
+#endif
+
+ ret = clk_set_rate(mpu_clk, freqs.new * 1000);
+
+ cpufreq_notify_transition(&freqs, CPUFREQ_POSTCHANGE);
+
+ return ret;
+}
+
+static int __cpuinit omap_cpu_init(struct cpufreq_policy *policy)
+{
+ int result = 0;
+ struct device *mpu_dev;
+
+ if (cpu_is_omap24xx())
+ mpu_clk = clk_get(NULL, "virt_prcm_set");
+ else if (cpu_is_omap34xx())
+ mpu_clk = clk_get(NULL, "dpll1_ck");
+ else if (cpu_is_omap44xx())
+ mpu_clk = clk_get(NULL, "dpll_mpu_ck");
+
+ if (IS_ERR(mpu_clk))
+ return PTR_ERR(mpu_clk);
+
+ if (policy->cpu != 0)
+ return -EINVAL;
+
+ policy->cur = policy->min = policy->max = omap_getspeed(0);
+
+ mpu_dev = omap2_get_mpuss_device();
+ if (!mpu_dev) {
+ pr_warning("%s: unable to get the mpu device\n", __func__);
+ return -EINVAL;
+ }
+ opp_init_cpufreq_table(mpu_dev, &freq_table);
+
+ 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 = clk_round_rate(mpu_clk, 0) / 1000;
+ policy->cpuinfo.max_freq = clk_round_rate(mpu_clk,
+ VERY_HI_RATE) / 1000;
+ }
+
+ policy->min = policy->cpuinfo.min_freq;
+ policy->max = policy->cpuinfo.max_freq;
+ policy->cur = omap_getspeed(0);
+
+ /* FIXME: what's the actual transition time? */
+ policy->cpuinfo.transition_latency = 300 * 1000;
+
+ return 0;
+}
+
+static int omap_cpu_exit(struct cpufreq_policy *policy)
+{
+ clk_exit_cpufreq_table(&freq_table);
+ clk_put(mpu_clk);
+ return 0;
+}
+
+static struct freq_attr *omap_cpufreq_attr[] = {
+ &cpufreq_freq_attr_scaling_available_freqs,
+ NULL,
+};
+
+static struct cpufreq_driver omap_driver = {
+ .flags = CPUFREQ_STICKY,
+ .verify = omap_verify_speed,
+ .target = omap_target,
+ .get = omap_getspeed,
+ .init = omap_cpu_init,
+ .exit = omap_cpu_exit,
+ .name = "omap",
+ .attr = omap_cpufreq_attr,
+};
+
+static int __init omap_cpufreq_init(void)
+{
+ return cpufreq_register_driver(&omap_driver);
+}
+
+static void __exit omap_cpufreq_exit(void)
+{
+ cpufreq_unregister_driver(&omap_driver);
+}
+
+MODULE_DESCRIPTION("cpufreq driver for OMAP SoCs");
+MODULE_LICENSE("GPL");
+module_init(omap_cpufreq_init);
+module_exit(omap_cpufreq_exit);
--
1.7.6
^ permalink raw reply related
* [PATCH 00/10] cpufreq: OMAP: move into drivers, cleanups/fixes for v3.2
From: Kevin Hilman @ 2011-09-22 21:07 UTC (permalink / raw)
To: linux-arm-kernel
This series moves the OMAP CPUfreq driver into drivers/cpufreq, add
support for SMP devices (OMAP4+) and includes several cleanups and
fixes from Nishanth Menon.
This series applies to v3.1-rc6, and is available here:
git://github.com/khilman/linux-omap-pm.git for_3.2/omap-cpufreq
Kevin
Colin Cross (1):
cpufreq: OMAP: notify even with bad boot frequency
Nishanth Menon (6):
cpufreq: OMAP: move clk name decision to init
cpufreq: OMAP: deny initialization if no mpudev
cpufreq: OMAP: dont support !freq_table
cpufreq: OMAP: only supports OPP library
cpufreq: OMAP: put clk if cpu_init failed
cpufreq: OMAP: fix freq_table leak
Russell King (1):
cpufreq: OMAP: Add SMP support for OMAP4+
Santosh Shilimkar (1):
cpufreq: OMAP: cleanup for multi-SoC support, move into
drivers/cpufreq
Todd Poynor (1):
cpufreq: OMAP: Enable all CPUs in shared policy mask
arch/arm/plat-omap/Makefile | 1 -
arch/arm/plat-omap/cpu-omap.c | 171 -------------------------
drivers/cpufreq/Makefile | 1 +
drivers/cpufreq/omap-cpufreq.c | 271 ++++++++++++++++++++++++++++++++++++++++
4 files changed, 272 insertions(+), 172 deletions(-)
delete mode 100644 arch/arm/plat-omap/cpu-omap.c
create mode 100644 drivers/cpufreq/omap-cpufreq.c
--
1.7.6
^ permalink raw reply
* [PATCH 4/4] arm/tegra: Convert pinmux driver to a platform device
From: Stephen Warren @ 2011-09-22 21:06 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <1316725567-17881-1-git-send-email-swarren@nvidia.com>
Signed-off-by: Stephen Warren <swarren@nvidia.com>
---
See patch 0000 for details on dependencies.
arch/arm/mach-tegra/pinmux.c | 26 ++++++++++++++++++++++++++
1 files changed, 26 insertions(+), 0 deletions(-)
diff --git a/arch/arm/mach-tegra/pinmux.c b/arch/arm/mach-tegra/pinmux.c
index f80d507..46b9d87 100644
--- a/arch/arm/mach-tegra/pinmux.c
+++ b/arch/arm/mach-tegra/pinmux.c
@@ -20,6 +20,7 @@
#include <linux/errno.h>
#include <linux/spinlock.h>
#include <linux/io.h>
+#include <linux/platform_device.h>
#include <mach/iomap.h>
#include <mach/pinmux.h>
@@ -665,6 +666,31 @@ void tegra_pinmux_config_pullupdown_table(const struct tegra_pingroup_config *co
}
}
+static int __init tegra_pinmux_probe(struct platform_device *pdev)
+{
+ return 0;
+}
+
+static struct of_device_id tegra_pinmux_of_match[] __devinitdata = {
+ { .compatible = "nvidia,tegra20-pinmux", },
+ { },
+};
+
+static struct platform_driver tegra_pinmux_driver = {
+ .driver = {
+ .name = "tegra-pinmux",
+ .owner = THIS_MODULE,
+ .of_match_table = tegra_pinmux_of_match,
+ },
+ .probe = tegra_pinmux_probe,
+};
+
+static int __init tegra_pinmux_init(void)
+{
+ return platform_driver_register(&tegra_pinmux_driver);
+}
+postcore_initcall(tegra_pinmux_init);
+
#ifdef CONFIG_DEBUG_FS
#include <linux/debugfs.h>
--
1.7.0.4
^ permalink raw reply related
* [PATCH 3/4] gpio/tegra: Convert to a platform device
From: Stephen Warren @ 2011-09-22 21:06 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <1316725567-17881-1-git-send-email-swarren@nvidia.com>
Signed-off-by: Stephen Warren <swarren@nvidia.com>
---
See patch 0000 for details on dependencies.
drivers/gpio/gpio-tegra.c | 31 ++++++++++++++++++++-----------
1 files changed, 20 insertions(+), 11 deletions(-)
diff --git a/drivers/gpio/gpio-tegra.c b/drivers/gpio/gpio-tegra.c
index 6b65207..849da25 100644
--- a/drivers/gpio/gpio-tegra.c
+++ b/drivers/gpio/gpio-tegra.c
@@ -20,10 +20,10 @@
#include <linux/init.h>
#include <linux/irq.h>
#include <linux/interrupt.h>
-
#include <linux/io.h>
#include <linux/gpio.h>
#include <linux/of.h>
+#include <linux/platform_device.h>
#include <asm/mach/irq.h>
@@ -333,7 +333,7 @@ static struct irq_chip tegra_gpio_irq_chip = {
*/
static struct lock_class_key gpio_lock_class;
-static int __init tegra_gpio_init(void)
+static int __init tegra_gpio_probe(struct platform_device *pdev)
{
struct tegra_gpio_bank *bank;
int gpio;
@@ -347,15 +347,6 @@ static int __init tegra_gpio_init(void)
}
}
-#ifdef CONFIG_OF_GPIO
- /*
- * This isn't ideal, but it gets things hooked up until this
- * driver is converted into a platform_device
- */
- tegra_gpio_chip.of_node = of_find_compatible_node(NULL, NULL,
- "nvidia,tegra20-gpio");
-#endif /* CONFIG_OF_GPIO */
-
gpiochip_add(&tegra_gpio_chip);
for (gpio = 0; gpio < TEGRA_NR_GPIOS; gpio++) {
@@ -384,6 +375,24 @@ static int __init tegra_gpio_init(void)
return 0;
}
+static struct of_device_id tegra_gpio_of_match[] __devinitdata = {
+ { .compatible = "nvidia,tegra20-gpio", },
+ { },
+};
+
+static struct platform_driver tegra_gpio_driver = {
+ .driver = {
+ .name = "tegra-gpio",
+ .owner = THIS_MODULE,
+ .of_match_table = tegra_gpio_of_match,
+ },
+ .probe = tegra_gpio_probe,
+};
+
+static int __init tegra_gpio_init(void)
+{
+ return platform_driver_register(&tegra_gpio_driver);
+}
postcore_initcall(tegra_gpio_init);
void __init tegra_gpio_config(struct tegra_gpio_table *table, int num)
--
1.7.0.4
^ permalink raw reply related
* [PATCH 2/4] arm/dt: Tegra: Add pinmux node to tegra20.dtsi
From: Stephen Warren @ 2011-09-22 21:06 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <1316725567-17881-1-git-send-email-swarren@nvidia.com>
Add a pinmux node to tegra20.dtsi in order to instantiate the future
pinmux device.
Signed-off-by: Stephen Warren <swarren@nvidia.com>
---
See patch 0000 for details on dependencies.
.../devicetree/bindings/pinmux/pinmux_nvidia.txt | 5 +++++
arch/arm/boot/dts/tegra20.dtsi | 5 +++++
2 files changed, 10 insertions(+), 0 deletions(-)
create mode 100644 Documentation/devicetree/bindings/pinmux/pinmux_nvidia.txt
diff --git a/Documentation/devicetree/bindings/pinmux/pinmux_nvidia.txt b/Documentation/devicetree/bindings/pinmux/pinmux_nvidia.txt
new file mode 100644
index 0000000..36f82db
--- /dev/null
+++ b/Documentation/devicetree/bindings/pinmux/pinmux_nvidia.txt
@@ -0,0 +1,5 @@
+NVIDIA Tegra 2 pinmux controller
+
+Required properties:
+- compatible : "nvidia,tegra20-pinmux"
+
diff --git a/arch/arm/boot/dts/tegra20.dtsi b/arch/arm/boot/dts/tegra20.dtsi
index 5727595..5921c1d 100644
--- a/arch/arm/boot/dts/tegra20.dtsi
+++ b/arch/arm/boot/dts/tegra20.dtsi
@@ -77,6 +77,11 @@
gpio-controller;
};
+ pinmux: pinmux at 70000000 {
+ compatible = "nvidia,tegra20-pinmux";
+ reg = < 0x70000000 0xc00 >;
+ };
+
serial at 70006000 {
compatible = "nvidia,tegra20-uart";
reg = <0x70006000 0x40>;
--
1.7.0.4
^ permalink raw reply related
* [PATCH 1/4] arm/tegra: Prep boards for gpio/pinmux conversion to pdevs
From: Stephen Warren @ 2011-09-22 21:06 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <1316725567-17881-1-git-send-email-swarren@nvidia.com>
The Tegra GPIO driver will be converted from static registration via
postcore_initcall() to be a platform device later in this patch series.
A new Tegra pinmux platform device will also be added.
Prepare for this by modifying all boards to register the appropriate
platform devices before-hand, so that when the drivers are converted,
those devices will be probed, and git bisectability will be maintained.
Signed-off-by: Stephen Warren <swarren@nvidia.com>
---
See patch 0000 for details on dependencies.
arch/arm/mach-tegra/board-harmony-pinmux.c | 8 ++++++++
arch/arm/mach-tegra/board-paz00-pinmux.c | 8 ++++++++
arch/arm/mach-tegra/board-seaboard-pinmux.c | 9 +++++++--
arch/arm/mach-tegra/board-trimslice-pinmux.c | 7 +++++++
arch/arm/mach-tegra/devices.c | 10 ++++++++++
arch/arm/mach-tegra/devices.h | 2 ++
6 files changed, 42 insertions(+), 2 deletions(-)
diff --git a/arch/arm/mach-tegra/board-harmony-pinmux.c b/arch/arm/mach-tegra/board-harmony-pinmux.c
index 4d63e2e..e99b456 100644
--- a/arch/arm/mach-tegra/board-harmony-pinmux.c
+++ b/arch/arm/mach-tegra/board-harmony-pinmux.c
@@ -20,6 +20,7 @@
#include "gpio-names.h"
#include "board-harmony.h"
+#include "devices.h"
static struct tegra_pingroup_config harmony_pinmux[] = {
{TEGRA_PINGROUP_ATA, TEGRA_MUX_IDE, TEGRA_PUPD_NORMAL, TEGRA_TRI_NORMAL},
@@ -140,6 +141,11 @@ static struct tegra_pingroup_config harmony_pinmux[] = {
{TEGRA_PINGROUP_XM2D, TEGRA_MUX_NONE, TEGRA_PUPD_NORMAL, TEGRA_TRI_NORMAL},
};
+static struct platform_device *pinmux_devices[] = {
+ &tegra_gpio_device,
+ &tegra_pinmux_device,
+};
+
static struct tegra_gpio_table gpio_table[] = {
{ .gpio = TEGRA_GPIO_SD2_CD, .enable = true },
{ .gpio = TEGRA_GPIO_SD2_WP, .enable = true },
@@ -155,6 +161,8 @@ static struct tegra_gpio_table gpio_table[] = {
void harmony_pinmux_init(void)
{
+ platform_add_devices(pinmux_devices, ARRAY_SIZE(pinmux_devices));
+
tegra_pinmux_config_table(harmony_pinmux, ARRAY_SIZE(harmony_pinmux));
tegra_gpio_config(gpio_table, ARRAY_SIZE(gpio_table));
diff --git a/arch/arm/mach-tegra/board-paz00-pinmux.c b/arch/arm/mach-tegra/board-paz00-pinmux.c
index 2225769..fb20894 100644
--- a/arch/arm/mach-tegra/board-paz00-pinmux.c
+++ b/arch/arm/mach-tegra/board-paz00-pinmux.c
@@ -20,6 +20,7 @@
#include "gpio-names.h"
#include "board-paz00.h"
+#include "devices.h"
static struct tegra_pingroup_config paz00_pinmux[] = {
{TEGRA_PINGROUP_ATA, TEGRA_MUX_GMI, TEGRA_PUPD_NORMAL, TEGRA_TRI_NORMAL},
@@ -140,6 +141,11 @@ static struct tegra_pingroup_config paz00_pinmux[] = {
{TEGRA_PINGROUP_XM2D, TEGRA_MUX_NONE, TEGRA_PUPD_NORMAL, TEGRA_TRI_NORMAL},
};
+static struct platform_device *pinmux_devices[] = {
+ &tegra_gpio_device,
+ &tegra_pinmux_device,
+};
+
static struct tegra_gpio_table gpio_table[] = {
{ .gpio = TEGRA_GPIO_SD1_CD, .enable = true },
{ .gpio = TEGRA_GPIO_SD1_WP, .enable = true },
@@ -152,6 +158,8 @@ static struct tegra_gpio_table gpio_table[] = {
void paz00_pinmux_init(void)
{
+ platform_add_devices(pinmux_devices, ARRAY_SIZE(pinmux_devices));
+
tegra_pinmux_config_table(paz00_pinmux, ARRAY_SIZE(paz00_pinmux));
tegra_gpio_config(gpio_table, ARRAY_SIZE(gpio_table));
diff --git a/arch/arm/mach-tegra/board-seaboard-pinmux.c b/arch/arm/mach-tegra/board-seaboard-pinmux.c
index 74f78b7..f092298 100644
--- a/arch/arm/mach-tegra/board-seaboard-pinmux.c
+++ b/arch/arm/mach-tegra/board-seaboard-pinmux.c
@@ -21,6 +21,7 @@
#include "gpio-names.h"
#include "board-seaboard.h"
+#include "devices.h"
#define DEFAULT_DRIVE(_name) \
{ \
@@ -157,8 +158,10 @@ static __initdata struct tegra_pingroup_config seaboard_pinmux[] = {
{TEGRA_PINGROUP_XM2D, TEGRA_MUX_NONE, TEGRA_PUPD_NORMAL, TEGRA_TRI_NORMAL},
};
-
-
+static struct platform_device *pinmux_devices[] = {
+ &tegra_gpio_device,
+ &tegra_pinmux_device,
+};
static struct tegra_gpio_table gpio_table[] = {
{ .gpio = TEGRA_GPIO_SD2_CD, .enable = true },
@@ -173,6 +176,8 @@ static struct tegra_gpio_table gpio_table[] = {
void __init seaboard_pinmux_init(void)
{
+ platform_add_devices(pinmux_devices, ARRAY_SIZE(pinmux_devices));
+
tegra_pinmux_config_table(seaboard_pinmux, ARRAY_SIZE(seaboard_pinmux));
tegra_drive_pinmux_config_table(seaboard_drive_pinmux,
diff --git a/arch/arm/mach-tegra/board-trimslice-pinmux.c b/arch/arm/mach-tegra/board-trimslice-pinmux.c
index bcb1916..4969dd2 100644
--- a/arch/arm/mach-tegra/board-trimslice-pinmux.c
+++ b/arch/arm/mach-tegra/board-trimslice-pinmux.c
@@ -21,6 +21,7 @@
#include "gpio-names.h"
#include "board-trimslice.h"
+#include "devices.h"
static __initdata struct tegra_pingroup_config trimslice_pinmux[] = {
{TEGRA_PINGROUP_ATA, TEGRA_MUX_IDE, TEGRA_PUPD_NORMAL, TEGRA_TRI_TRISTATE},
@@ -141,6 +142,11 @@ static __initdata struct tegra_pingroup_config trimslice_pinmux[] = {
{TEGRA_PINGROUP_XM2D, TEGRA_MUX_NONE, TEGRA_PUPD_NORMAL, TEGRA_TRI_NORMAL},
};
+static struct platform_device *pinmux_devices[] = {
+ &tegra_gpio_device,
+ &tegra_pinmux_device,
+};
+
static struct tegra_gpio_table gpio_table[] = {
{ .gpio = TRIMSLICE_GPIO_SD4_CD, .enable = true }, /* mmc4 cd */
{ .gpio = TRIMSLICE_GPIO_SD4_WP, .enable = true }, /* mmc4 wp */
@@ -151,6 +157,7 @@ static struct tegra_gpio_table gpio_table[] = {
void __init trimslice_pinmux_init(void)
{
+ platform_add_devices(pinmux_devices, ARRAY_SIZE(pinmux_devices));
tegra_pinmux_config_table(trimslice_pinmux, ARRAY_SIZE(trimslice_pinmux));
tegra_gpio_config(gpio_table, ARRAY_SIZE(gpio_table));
}
diff --git a/arch/arm/mach-tegra/devices.c b/arch/arm/mach-tegra/devices.c
index 57e35d2..48262bf 100644
--- a/arch/arm/mach-tegra/devices.c
+++ b/arch/arm/mach-tegra/devices.c
@@ -31,6 +31,16 @@
#include <mach/usb_phy.h>
#include "gpio-names.h"
+struct platform_device tegra_gpio_device = {
+ .name = "tegra-gpio",
+ .id = -1,
+};
+
+struct platform_device tegra_pinmux_device = {
+ .name = "tegra-pinmux",
+ .id = -1,
+};
+
static struct resource i2c_resource1[] = {
[0] = {
.start = INT_I2C,
diff --git a/arch/arm/mach-tegra/devices.h b/arch/arm/mach-tegra/devices.h
index 4a7dc0a..873ecb2 100644
--- a/arch/arm/mach-tegra/devices.h
+++ b/arch/arm/mach-tegra/devices.h
@@ -21,6 +21,8 @@
#include <linux/platform_device.h>
+extern struct platform_device tegra_gpio_device;
+extern struct platform_device tegra_pinmux_device;
extern struct platform_device tegra_sdhci_device1;
extern struct platform_device tegra_sdhci_device2;
extern struct platform_device tegra_sdhci_device3;
--
1.7.0.4
^ permalink raw reply related
* [PATCH 0/4] arm/tegra: Convert gpio & pinmux to platform devices
From: Stephen Warren @ 2011-09-22 21:06 UTC (permalink / raw)
To: linux-arm-kernel
This series converts the Tegra GPIO and pinmux drivers to be regular
platform devices.
The series is extracted from an earlier series I posted that augmented
these drivers to initialize HW state from the device-tree. I'm holding
off on that aspect of the changes, since it's not entirely clear to me
whether the new pinmux API should drive the initial pinmux state setup
via "system hog" definitions, or whether pinmux drivers should indeed
do their own thing.
Dependencies:
* The patches need to be merged in one branch in order for bisectability.
* At least patch 3 depends on changes in Russell's gpio branch, since it
edits a file renamed there. I imagine the series will be merged into
that branch.
* The whole series is based off next-20110922 plus a couple patches in the
ARM patch system (7094, 7095).
* This series affects both the GPIO and pinmux drivers. Potentially, the
changes to the two driver could be split into separate series, but this
would be complicated by the fact patch 1 edits all the board files to
make the same change for both GPIO and pinmux; if split up, merging that
all back together would cause conflicts.
* Patch 1's changes to board-seaboard-pinmux.c will have some merge
conflicts with the patches Peter De Schrijver recently posted to enhance
that file to support Ventana; each of our patches will change the context
changes in the others' diffs. I'm not sure how best to manage this.
Stephen Warren (4):
arm/tegra: Prep boards for gpio/pinmux conversion to pdevs
arm/dt: Tegra: Add pinmux node to tegra20.dtsi
gpio/tegra: Convert to a platform device
arm/tegra: Convert pinmux driver to a platform device
.../devicetree/bindings/pinmux/pinmux_nvidia.txt | 5 +++
arch/arm/boot/dts/tegra20.dtsi | 5 +++
arch/arm/mach-tegra/board-harmony-pinmux.c | 8 +++++
arch/arm/mach-tegra/board-paz00-pinmux.c | 8 +++++
arch/arm/mach-tegra/board-seaboard-pinmux.c | 9 ++++-
arch/arm/mach-tegra/board-trimslice-pinmux.c | 7 ++++
arch/arm/mach-tegra/devices.c | 10 ++++++
arch/arm/mach-tegra/devices.h | 2 +
arch/arm/mach-tegra/pinmux.c | 26 ++++++++++++++++
drivers/gpio/gpio-tegra.c | 31 +++++++++++++-------
10 files changed, 98 insertions(+), 13 deletions(-)
create mode 100644 Documentation/devicetree/bindings/pinmux/pinmux_nvidia.txt
^ permalink raw reply
* [PATCH][RESEND] ARM: cache: detect PIPT I-cache using CTR
From: Russell King - ARM Linux @ 2011-09-22 21:05 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <1316723111-10473-1-git-send-email-will.deacon@arm.com>
On Thu, Sep 22, 2011 at 09:25:11PM +0100, Will Deacon wrote:
> The Cache Type Register L1Ip field identifies I-caches with a PIPT
> policy using the encoding 11b.
>
> This patch extends the cache policy parsing to identify PIPT I-caches
> correctly and prevent them from being treated as VIPT aliasing in cases
> where they are sufficiently large.
>
> Signed-off-by: Will Deacon <will.deacon@arm.com>
> KernelVersion: 3.1-rc3
> ---
>
> Russell - this has been sitting in the patch system as 7062/1 for a
> while now. Please can you add it to your for-next branch for 3.2?
Well... I don't apply any patch to the for-next branch itself - that'd
be madness as the branch is re-built from the topic branches and it's
just a convenience for SFR so I don't have to keep on listing out all
the individual branches for him to pull.
Last time I tried to apply it to my misc branch (which was 3.1-rc1 based)
it wouldn't apply. I've since rebased that branch (for various reasons)
and it now appears to apply cleanly, so I can _only_ _now_ apply it.
^ permalink raw reply
* [PATCH v3 2/2] OMAP: omap_device: Add a method to build an omap_device from a DT node
From: Benoit Cousson @ 2011-09-22 20:52 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <1316724745-24896-1-git-send-email-b-cousson@ti.com>
Add a notifier called during device_add phase. If an of_node is present,
retrieve the hwmod entry in order to populate properly the omap_device
structure.
For the moment the resource from the device-tree are overloaded.
DT does not support named resource yet, and thus, most driver
will not work without that information.
Add two helpers function to parse a property that contains multiple
strings. Please note that these helpers will be replaced by a more generic
iterator currently proposed on devicetree mailing list as soon as it
will be merged.
Add a documentation to capture the specifics OMAP bindings
needed for device-tree support.
Signed-off-by: Benoit Cousson <b-cousson@ti.com>
Cc: Kevin Hilman <khilman@ti.com>
---
.../devicetree/bindings/arm/omap/omap.txt | 42 ++++++
arch/arm/plat-omap/omap_device.c | 145 ++++++++++++++++++++
2 files changed, 187 insertions(+), 0 deletions(-)
create mode 100644 Documentation/devicetree/bindings/arm/omap/omap.txt
diff --git a/Documentation/devicetree/bindings/arm/omap/omap.txt b/Documentation/devicetree/bindings/arm/omap/omap.txt
new file mode 100644
index 0000000..6513d05
--- /dev/null
+++ b/Documentation/devicetree/bindings/arm/omap/omap.txt
@@ -0,0 +1,42 @@
+* Texas Instruments OMAP
+
+OMAP is currently using a static file per SoC family to describe the
+IPs present in the SoC.
+On top of that an omap_device is created to extend the platform_device
+capabilities and to allow binding with one or several hwmods.
+The hwmods will contain all the information to build the device:
+adresse range, irq lines, dma lines, interconnect, PRCM register,
+clock domain, input clocks.
+For the moment just point to the existing hwmod, the next step will be
+to move data from hwmod to device-tree representation.
+
+
+Required properties:
+- compatible: Every devices present in OMAP SoC should be in the
+ form: "ti,XXX"
+- ti,hwmods: list of hwmods attached to a device. Must contain at least
+ one hwmod.
+
+Optional properties:
+- ti,no_idle_on_suspend: When present, it prevents the PM to idle the module
+ during suspend.
+
+
+Example:
+
+spinlock at 1 {
+ compatible = "ti,omap-spinlock";
+ ti,hwmods = "spinlock";
+};
+
+
+Boards:
+
+- OMAP3 BeagleBoard : Low cost community board
+ compatible = "ti,omap3-beagle", "ti,omap3"
+
+- OMAP4 SDP : Software Developement Board
+ compatible = "ti,omap4-sdp", "ti,omap4430"
+
+- OMAP4 PandaBoard : Low cost community board
+ compatible = "ti,omap4-panda", "ti,omap4430"
diff --git a/arch/arm/plat-omap/omap_device.c b/arch/arm/plat-omap/omap_device.c
index cac7b9a..5b63989 100644
--- a/arch/arm/plat-omap/omap_device.c
+++ b/arch/arm/plat-omap/omap_device.c
@@ -85,6 +85,8 @@
#include <linux/clk.h>
#include <linux/clkdev.h>
#include <linux/pm_runtime.h>
+#include <linux/of.h>
+#include <linux/notifier.h>
#include <plat/omap_device.h>
#include <plat/omap_hwmod.h>
@@ -94,12 +96,15 @@
#define USE_WAKEUP_LAT 0
#define IGNORE_WAKEUP_LAT 1
+#define MAX_HWMOD_NAME_SIZE 32
+
static int omap_device_register(struct platform_device *pdev);
static int omap_early_device_register(struct platform_device *pdev);
static struct omap_device *omap_device_alloc(struct platform_device *pdev,
struct omap_hwmod **ohs, int oh_cnt,
struct omap_device_pm_latency *pm_lats,
int pm_lats_cnt);
+static void omap_device_delete(struct omap_device *od);
static struct omap_device_pm_latency omap_default_latency[] = {
@@ -315,6 +320,138 @@ static void _add_hwmod_clocks_clkdev(struct omap_device *od,
_add_clkdev(od, oh->opt_clks[i].role, oh->opt_clks[i].clk);
}
+/*
+ * XXX: DT helper functions that should be replaced by more generic
+ * API introduced by Stephen Warren once they'll be in mainline.
+ */
+static int _dt_count_property_string(const char *prop, int len)
+{
+ int i = 0;
+ size_t l = 0, total = 0;
+
+ if (!prop || !len)
+ return -EINVAL;
+
+ for (i = 0; len >= total; total += l, prop += l) {
+ l = strlen(prop) + 1;
+ if (*prop != 0)
+ i++;
+ }
+ return i;
+}
+
+static int _dt_get_property(const char *prop, int len, int index, char *output,
+ int size)
+{
+ int i = 0;
+ size_t l = 0, total = 0;
+
+ if (!prop || !len)
+ return -EINVAL;
+
+ for (i = 0; len >= total; total += l, prop += l) {
+ l = strlcpy(output, prop, size) + 1;
+ if (*prop != 0) {
+ if (i++ == index)
+ return 0;
+ }
+ }
+ return -ENODEV;
+}
+
+static struct dev_pm_domain omap_device_pm_domain;
+
+/**
+ * omap_device_build_from_dt - build an omap_device with multiple hwmods
+ * @pdev_name: name of the platform_device driver to use
+ * @pdev_id: this platform_device's connection ID
+ * @oh: ptr to the single omap_hwmod that backs this omap_device
+ * @pdata: platform_data ptr to associate with the platform_device
+ * @pdata_len: amount of memory pointed to by @pdata
+ * @pm_lats: pointer to a omap_device_pm_latency array for this device
+ * @pm_lats_cnt: ARRAY_SIZE() of @pm_lats
+ * @is_early_device: should the device be registered as an early device or not
+ *
+ * Function for building an omap_device already registered from device-tree
+ *
+ * Returns 0 or PTR_ERR() on error.
+ */
+static int omap_device_build_from_dt(struct platform_device *pdev)
+{
+ struct omap_hwmod **hwmods;
+ struct omap_device *od;
+ struct omap_hwmod *oh;
+ char oh_name[MAX_HWMOD_NAME_SIZE];
+ const char *prop;
+ int oh_cnt, i, prop_len;
+ int ret = 0;
+
+ prop = of_get_property(pdev->dev.of_node, "ti,hwmods", &prop_len);
+ oh_cnt = _dt_count_property_string(prop, prop_len);
+ if (!oh_cnt || IS_ERR_VALUE(oh_cnt)) {
+ dev_warn(&pdev->dev, "No 'hwmods' to build omap_device\n");
+ return -ENODEV;
+ }
+
+ hwmods = kzalloc(sizeof(struct omap_hwmod *) * oh_cnt, GFP_KERNEL);
+ if (!hwmods) {
+ ret = -ENOMEM;
+ goto odbfd_exit;
+ }
+
+ for (i = 0; i < oh_cnt; i++) {
+ _dt_get_property(prop, prop_len, i, oh_name,
+ MAX_HWMOD_NAME_SIZE);
+
+ oh = omap_hwmod_lookup(oh_name);
+ if (!oh) {
+ dev_err(&pdev->dev, "Cannot lookup hwmod '%s'\n",
+ oh_name);
+ ret = -EINVAL;
+ goto odbfd_exit1;
+ }
+ hwmods[i] = oh;
+ }
+
+ od = omap_device_alloc(pdev, hwmods, oh_cnt, NULL, 0);
+ if (!od) {
+ dev_err(&pdev->dev, "Cannot allocate omap_device for :%s\n",
+ oh_name);
+ ret = PTR_ERR(od);
+ goto odbfd_exit1;
+ }
+
+ if (of_get_property(pdev->dev.of_node, "ti,no_idle_on_suspend", NULL))
+ omap_device_disable_idle_on_suspend(pdev);
+
+ pdev->dev.pm_domain = &omap_device_pm_domain;
+
+odbfd_exit1:
+ kfree(hwmods);
+odbfd_exit:
+ return ret;
+}
+
+static int _omap_device_notifier_call(struct notifier_block *nb,
+ unsigned long event, void *dev)
+{
+ struct platform_device *pdev = to_platform_device(dev);
+
+ switch (event) {
+ case BUS_NOTIFY_ADD_DEVICE:
+ if (pdev->dev.of_node)
+ omap_device_build_from_dt(pdev);
+ break;
+
+ case BUS_NOTIFY_DEL_DEVICE:
+ if (pdev->archdata.od)
+ omap_device_delete(pdev->archdata.od);
+ break;
+ }
+
+ return NOTIFY_DONE;
+}
+
/* Public functions for use by core code */
@@ -499,6 +636,9 @@ oda_exit1:
static void omap_device_delete(struct omap_device *od)
{
+ if (!od)
+ return;
+
od->pdev->archdata.od = NULL;
kfree(od->pm_lats);
kfree(od->hwmods);
@@ -1034,8 +1174,13 @@ struct device omap_device_parent = {
.parent = &platform_bus,
};
+static struct notifier_block platform_nb = {
+ .notifier_call = _omap_device_notifier_call,
+};
+
static int __init omap_device_init(void)
{
+ bus_register_notifier(&platform_bus_type, &platform_nb);
return device_register(&omap_device_parent);
}
core_initcall(omap_device_init);
--
1.7.0.4
^ permalink raw reply related
* [PATCH v3 1/2] OMAP: omap_device: Add omap_device_[alloc|delete] for DT integration
From: Benoit Cousson @ 2011-09-22 20:52 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <1316724745-24896-1-git-send-email-b-cousson@ti.com>
Split the omap_device_build_ss into two smaller functions
that will allow to populate a platform_device already allocated by
device-tree.
The functionality of the omap_device_build_ss is still the same, but
the omap_device_alloc will be usable with devices already built by
device-tree.
Signed-off-by: Benoit Cousson <b-cousson@ti.com>
Cc: Kevin Hilman <khilman@ti.com>
---
arch/arm/plat-omap/omap_device.c | 177 +++++++++++++++++++++++++------------
1 files changed, 119 insertions(+), 58 deletions(-)
diff --git a/arch/arm/plat-omap/omap_device.c b/arch/arm/plat-omap/omap_device.c
index 54bbe7b..cac7b9a 100644
--- a/arch/arm/plat-omap/omap_device.c
+++ b/arch/arm/plat-omap/omap_device.c
@@ -96,6 +96,11 @@
static int omap_device_register(struct platform_device *pdev);
static int omap_early_device_register(struct platform_device *pdev);
+static struct omap_device *omap_device_alloc(struct platform_device *pdev,
+ struct omap_hwmod **ohs, int oh_cnt,
+ struct omap_device_pm_latency *pm_lats,
+ int pm_lats_cnt);
+
static struct omap_device_pm_latency omap_default_latency[] = {
{
@@ -397,6 +402,110 @@ static int omap_device_fill_resources(struct omap_device *od,
}
/**
+ * omap_device_alloc - allocate an omap_device
+ * @pdev: platform_device that will be included in this omap_device
+ * @oh: ptr to the single omap_hwmod that backs this omap_device
+ * @pdata: platform_data ptr to associate with the platform_device
+ * @pdata_len: amount of memory pointed to by @pdata
+ * @pm_lats: pointer to a omap_device_pm_latency array for this device
+ * @pm_lats_cnt: ARRAY_SIZE() of @pm_lats
+ *
+ * Convenience function for allocating an omap_device structure and filling
+ * hwmods, resources and pm_latency attributes.
+ *
+ * Returns an struct omap_device pointer or ERR_PTR() on error;
+ */
+static struct omap_device *omap_device_alloc(struct platform_device *pdev,
+ struct omap_hwmod **ohs, int oh_cnt,
+ struct omap_device_pm_latency *pm_lats,
+ int pm_lats_cnt)
+{
+ int ret = -ENOMEM;
+ struct omap_device *od;
+ struct resource *res = NULL;
+ int i, res_count;
+ struct omap_hwmod **hwmods;
+
+ od = kzalloc(sizeof(struct omap_device), GFP_KERNEL);
+ if (!od) {
+ ret = -ENOMEM;
+ goto oda_exit1;
+ }
+ od->hwmods_cnt = oh_cnt;
+
+ hwmods = kmemdup(ohs, sizeof(struct omap_hwmod *) * oh_cnt, GFP_KERNEL);
+ if (!hwmods)
+ goto oda_exit2;
+
+ od->hwmods = hwmods;
+ od->pdev = pdev;
+
+ /*
+ * HACK: Ideally the resources from DT should match, and hwmod
+ * should just add the missing ones. Since the name is not
+ * properly populated by DT, stick to hwmod resources only.
+ */
+ if (pdev->num_resources && pdev->resource)
+ dev_warn(&pdev->dev, "%s(): resources already allocated %d\n",
+ __func__, pdev->num_resources);
+
+ res_count = omap_device_count_resources(od);
+ if (res_count > 0) {
+ dev_dbg(&pdev->dev, "%s(): resources allocated from hwmod %d\n",
+ __func__, res_count);
+ res = kzalloc(sizeof(struct resource) * res_count, GFP_KERNEL);
+ if (!res)
+ goto oda_exit3;
+
+ omap_device_fill_resources(od, res);
+
+ ret = platform_device_add_resources(pdev, res, res_count);
+ kfree(res);
+
+ if (ret)
+ goto oda_exit3;
+ }
+
+ if (!pm_lats) {
+ pm_lats = omap_default_latency;
+ pm_lats_cnt = ARRAY_SIZE(omap_default_latency);
+ }
+
+ od->pm_lats_cnt = pm_lats_cnt;
+ od->pm_lats = kmemdup(pm_lats,
+ sizeof(struct omap_device_pm_latency) * pm_lats_cnt,
+ GFP_KERNEL);
+ if (!od->pm_lats)
+ goto oda_exit3;
+
+ pdev->archdata.od = od;
+
+ for (i = 0; i < oh_cnt; i++) {
+ hwmods[i]->od = od;
+ _add_hwmod_clocks_clkdev(od, hwmods[i]);
+ }
+
+ return od;
+
+oda_exit3:
+ kfree(hwmods);
+oda_exit2:
+ kfree(od);
+oda_exit1:
+ dev_err(&pdev->dev, "omap_device: build failed (%d)\n", ret);
+
+ return ERR_PTR(ret);
+}
+
+static void omap_device_delete(struct omap_device *od)
+{
+ od->pdev->archdata.od = NULL;
+ kfree(od->pm_lats);
+ kfree(od->hwmods);
+ kfree(od);
+}
+
+/**
* omap_device_build - build and register an omap_device with one omap_hwmod
* @pdev_name: name of the platform_device driver to use
* @pdev_id: this platform_device's connection ID
@@ -455,9 +564,6 @@ struct platform_device *omap_device_build_ss(const char *pdev_name, int pdev_id,
int ret = -ENOMEM;
struct platform_device *pdev;
struct omap_device *od;
- struct resource *res = NULL;
- int i, res_count;
- struct omap_hwmod **hwmods;
if (!ohs || oh_cnt == 0 || !pdev_name)
return ERR_PTR(-EINVAL);
@@ -471,76 +577,31 @@ struct platform_device *omap_device_build_ss(const char *pdev_name, int pdev_id,
goto odbs_exit;
}
- pr_debug("omap_device: %s: building with %d hwmods\n", pdev_name,
- oh_cnt);
+ /* Set the dev_name early to allow dev_xxx in omap_device_alloc */
+ if (pdev->id != -1)
+ dev_set_name(&pdev->dev, "%s.%d", pdev->name, pdev->id);
+ else
+ dev_set_name(&pdev->dev, "%s", pdev->name);
- od = kzalloc(sizeof(struct omap_device), GFP_KERNEL);
- if (!od) {
- ret = -ENOMEM;
+ od = omap_device_alloc(pdev, ohs, oh_cnt, pm_lats, pm_lats_cnt);
+ if (!od)
goto odbs_exit1;
- }
- od->hwmods_cnt = oh_cnt;
-
- hwmods = kzalloc(sizeof(struct omap_hwmod *) * oh_cnt,
- GFP_KERNEL);
- if (!hwmods)
- goto odbs_exit2;
-
- memcpy(hwmods, ohs, sizeof(struct omap_hwmod *) * oh_cnt);
- od->hwmods = hwmods;
- od->pdev = pdev;
-
- res_count = omap_device_count_resources(od);
- if (res_count > 0) {
- res = kzalloc(sizeof(struct resource) * res_count, GFP_KERNEL);
- if (!res)
- goto odbs_exit3;
-
- omap_device_fill_resources(od, res);
-
- ret = platform_device_add_resources(pdev, res, res_count);
- kfree(res);
-
- if (ret)
- goto odbs_exit3;
- }
ret = platform_device_add_data(pdev, pdata, pdata_len);
if (ret)
- goto odbs_exit3;
-
- pdev->archdata.od = od;
+ goto odbs_exit2;
if (is_early_device)
ret = omap_early_device_register(pdev);
else
ret = omap_device_register(pdev);
if (ret)
- goto odbs_exit3;
-
- if (!pm_lats) {
- pm_lats = omap_default_latency;
- pm_lats_cnt = ARRAY_SIZE(omap_default_latency);
- }
-
- od->pm_lats_cnt = pm_lats_cnt;
- od->pm_lats = kmemdup(pm_lats,
- sizeof(struct omap_device_pm_latency) * pm_lats_cnt,
- GFP_KERNEL);
- if (!od->pm_lats)
- goto odbs_exit3;
-
- for (i = 0; i < oh_cnt; i++) {
- hwmods[i]->od = od;
- _add_hwmod_clocks_clkdev(od, hwmods[i]);
- }
+ goto odbs_exit2;
return pdev;
-odbs_exit3:
- kfree(hwmods);
odbs_exit2:
- kfree(od);
+ omap_device_delete(od);
odbs_exit1:
platform_device_put(pdev);
odbs_exit:
--
1.7.0.4
^ permalink raw reply related
* [PATCH v3 0/2] OMAP: omap_device: Add a method to build an omap_device from a DT node
From: Benoit Cousson @ 2011-09-22 20:52 UTC (permalink / raw)
To: linux-arm-kernel
Hi Kevin,
This is the updated version of the initial series that introduced a
notifier in order to create an omap_device from a platform_device bound
to DT node as suggested by Grant.
For the moment, the informations are all extracted from the hwmod data.
The idea is to focus first on the devices / board static init removal.
The other issue is that some bindings, like dma, are still not present
in the DT core code. The reg and irq bindings are there, but cannot
be used by some drivers due to the lack of named resources in DT for
the moment.
We agreed with Grant about the strategy to introduce the name without
breaking the compatibility and the default assumption about the order.
I'll update that in another series after 3.2 and then these informations
will be moved from hwmod to DT.
Patches are based on my for_3.2/1_omap_device_cleanup branch and are
available here:
git://gitorious.org/omap-pm/linux.git for_3.2/2_omap_device_dt
It is tested on OMAP4 SDP, Panda and Beagle-xM with and without CONFIG_OF.
Regards,
Benoit
Changes since v1: http://www.spinics.net/lists/linux-omap/msg55814.html
- delete omap_device structure during BUS_NOTIFY_DEL_DEVICE callback
as suggested by Kevin
- merge previous patches 2&3 as suggested by Kevin
- delete pm_lats in omap_device_delete since this is now kmalloc-ed
- use kmemdup instead of kzalloc + memcopy for hmwods creation
- Fix the wrong usage of of_*.h includes to build properly without
CONFIG_OF.
Changes since v2: http://www.mail-archive.com/linux-omap at vger.kernel.org/msg55892.html
- Add binding documentation for the OMAP attributes
- Add "ti," prefix to hwmods and no_idle_on_suspend attributes
- Change the static init of the notifier_block structure as suggested by Grant
- Add a comment to remove the helpers once the generic one from swarren will
be merged
Benoit Cousson (2):
OMAP: omap_device: Add omap_device_[alloc|delete] for DT integration
OMAP: omap_device: Add a method to build an omap_device from a DT node
.../devicetree/bindings/arm/omap/omap.txt | 42 +++
arch/arm/plat-omap/omap_device.c | 322 ++++++++++++++++----
2 files changed, 306 insertions(+), 58 deletions(-)
create mode 100644 Documentation/devicetree/bindings/arm/omap/omap.txt
^ permalink raw reply
* [PATCH v7 00/26] gpio/omap: driver cleanup and fixes
From: Kevin Hilman @ 2011-09-22 20:36 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <CAC83ZvKa7R_rUe-Fa15m0_5P-GE4WC2thazQ+iqF-HAqn8cE1w@mail.gmail.com>
Hi Tarun,
"DebBarma, Tarun Kanti" <tarun.kanti@ti.com> writes:
> On Tue, Sep 13, 2011 at 6:32 PM, Tarun Kanti DebBarma
> <tarun.kanti@ti.com> wrote:
>> This series is continuation of cleanup of OMAP GPIO driver and fixes.
>> The cleanup include getting rid of cpu_is_* checks wherever possible,
>> use of gpio_bank list instead of static array, use of unique platform
>> specific value associated data member to OMAP platforms to avoid
>> cpu_is_* checks. The series also include PM runtime support.*
>>
>> Baseline: git://gitorious.org/khilman/linux-omap-pm.git
>> Branch: for_3.2/gpio-cleanup
>> Commit: 8323374
> Thanks Tony for ack'ing the patches.
> Kevin,
> Since Tony's has acked the patches, can you please pull them?
Before merging, I still need to review and test this version, and I
*might* still get to it this week.
Based on the dbclk aliases you added, I assume this has now been tested
on platforms using some GPIOs with debounce enabled?
Kevin
^ permalink raw reply
* [RFC PATCH v3] drivercore: Add driver probe deferral mechanism
From: Alan Cox @ 2011-09-22 20:29 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <20110922184614.25419.84606.stgit@ponder>
Definitely what is needed for some of the x86 SoC stuff and would let us
rip out some of the special case magic for the SCU discovery.
First thing that strikes me is driver_bound kicks the processing queue
again. That seems odd - surely this isn't needed because any driver that
does initialise this time and may allow something else to get going will
queue the kick itself. Thus this seems to just add overhead.
It all looks a bit O(N?) if we don't expect the drivers that might
trigger something else binding to just say 'hey I'm one of the
troublemakers'
^ permalink raw reply
* [PATCH][RESEND] ARM: cache: detect PIPT I-cache using CTR
From: Will Deacon @ 2011-09-22 20:25 UTC (permalink / raw)
To: linux-arm-kernel
The Cache Type Register L1Ip field identifies I-caches with a PIPT
policy using the encoding 11b.
This patch extends the cache policy parsing to identify PIPT I-caches
correctly and prevent them from being treated as VIPT aliasing in cases
where they are sufficiently large.
Signed-off-by: Will Deacon <will.deacon@arm.com>
KernelVersion: 3.1-rc3
---
Russell - this has been sitting in the patch system as 7062/1 for a
while now. Please can you add it to your for-next branch for 3.2?
Thanks,
Will
arch/arm/include/asm/cachetype.h | 5 ++++-
arch/arm/kernel/setup.c | 15 +++++++++++++--
2 files changed, 17 insertions(+), 3 deletions(-)
diff --git a/arch/arm/include/asm/cachetype.h b/arch/arm/include/asm/cachetype.h
index c023db0..7ea7814 100644
--- a/arch/arm/include/asm/cachetype.h
+++ b/arch/arm/include/asm/cachetype.h
@@ -7,6 +7,7 @@
#define CACHEID_VIPT (CACHEID_VIPT_ALIASING|CACHEID_VIPT_NONALIASING)
#define CACHEID_ASID_TAGGED (1 << 3)
#define CACHEID_VIPT_I_ALIASING (1 << 4)
+#define CACHEID_PIPT (1 << 5)
extern unsigned int cacheid;
@@ -16,6 +17,7 @@ extern unsigned int cacheid;
#define cache_is_vipt_aliasing() cacheid_is(CACHEID_VIPT_ALIASING)
#define icache_is_vivt_asid_tagged() cacheid_is(CACHEID_ASID_TAGGED)
#define icache_is_vipt_aliasing() cacheid_is(CACHEID_VIPT_I_ALIASING)
+#define icache_is_pipt() cacheid_is(CACHEID_PIPT)
/*
* __LINUX_ARM_ARCH__ is the minimum supported CPU architecture
@@ -26,7 +28,8 @@ extern unsigned int cacheid;
#if __LINUX_ARM_ARCH__ >= 7
#define __CACHEID_ARCH_MIN (CACHEID_VIPT_NONALIASING |\
CACHEID_ASID_TAGGED |\
- CACHEID_VIPT_I_ALIASING)
+ CACHEID_VIPT_I_ALIASING |\
+ CACHEID_PIPT)
#elif __LINUX_ARM_ARCH__ >= 6
#define __CACHEID_ARCH_MIN (~CACHEID_VIVT)
#else
diff --git a/arch/arm/kernel/setup.c b/arch/arm/kernel/setup.c
index 2cdba13..6311da7 100644
--- a/arch/arm/kernel/setup.c
+++ b/arch/arm/kernel/setup.c
@@ -248,6 +248,10 @@ static int cpu_has_aliasing_icache(unsigned int arch)
int aliasing_icache;
unsigned int id_reg, num_sets, line_size;
+ /* PIPT caches never alias. */
+ if (icache_is_pipt())
+ return 0;
+
/* arch specifies the register format */
switch (arch) {
case CPU_ARCH_ARMv7:
@@ -282,8 +286,14 @@ static void __init cacheid_init(void)
/* ARMv7 register format */
arch = CPU_ARCH_ARMv7;
cacheid = CACHEID_VIPT_NONALIASING;
- if ((cachetype & (3 << 14)) == 1 << 14)
+ switch (cachetype & (3 << 14)) {
+ case (1 << 14):
cacheid |= CACHEID_ASID_TAGGED;
+ break;
+ case (3 << 14):
+ cacheid |= CACHEID_PIPT;
+ break;
+ }
} else {
arch = CPU_ARCH_ARMv6;
if (cachetype & (1 << 23))
@@ -300,10 +310,11 @@ static void __init cacheid_init(void)
printk("CPU: %s data cache, %s instruction cache\n",
cache_is_vivt() ? "VIVT" :
cache_is_vipt_aliasing() ? "VIPT aliasing" :
- cache_is_vipt_nonaliasing() ? "VIPT nonaliasing" : "unknown",
+ cache_is_vipt_nonaliasing() ? "PIPT / VIPT nonaliasing" : "unknown",
cache_is_vivt() ? "VIVT" :
icache_is_vivt_asid_tagged() ? "VIVT ASID tagged" :
icache_is_vipt_aliasing() ? "VIPT aliasing" :
+ icache_is_pipt() ? "PIPT" :
cache_is_vipt_nonaliasing() ? "VIPT nonaliasing" : "unknown");
}
--
1.7.0.4
^ permalink raw reply related
* [PATCH] ARM: futex: preserve oldval in SMP __futex_atomic_op
From: Will Deacon @ 2011-09-22 20:14 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <alpine.LFD.2.00.1109221449470.12663@xanadu.home>
On Thu, Sep 22, 2011 at 08:09:41PM +0100, Nicolas Pitre wrote:
> On Thu, 22 Sep 2011, Will Deacon wrote:
>
> > The SMP implementation of __futex_atomic_op clobbers oldval with the
> > status flag from the exclusive store. This causes it to always read as
> > zero when performing the FUTEX_OP_CMP_* operation.
> >
> > This patch updates the ARM __futex_atomic_op implementations to take a
> > tmp argument, allowing us to store the strex status flag without
> > overwriting the register containing oldval.
> >
> > Cc: stable at kernel.org
> > Reported-by: Minho Ben <mhban@samsung.com>
> > Signed-off-by: Will Deacon <will.deacon@arm.com>
>
> Reviewed-by: Nicolas Pitre <nicolas.pitre@linaro.org>
Thanks Nicolas, I'll put this into the patch system tomorrow.
> > ---
> >
> > Following up on:
> >
> > http://lists.infradead.org/pipermail/linux-arm-kernel/2011-September/066348.html
> >
> > it turns out that we don't need to use named arguments after all,
> > although it might be nice to add that as a later patch. For now, I'm
> > trying to keep this as small as possible for -stable.
>
> Agreed that named arguments would make this code more obvious,
> especially with the insn argument of __futex_atomic_op() which uses
> numbered registers away from the actual inline asm statement where it is
> used.
Yup, I'll post this as a separate patch in the future.
> I'm a bit worried that the LTP tests still passed though. In theory it
> shouldn't have worked at all except if you were lucky with test values.
Urgh, I just looked at the implementation of the tests I ran; all they do is
check that the {set,get}_robust_list system calls return -1 when passed
invalid argument combinations. No wonder they passed...
Will
^ permalink raw reply
* [PATCH] ARM: Don't include mach-nuc93x/Kconfig
From: Nicolas Pitre @ 2011-09-22 20:10 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <1316721802-10852-1-git-send-email-swarren@nvidia.com>
On Thu, 22 Sep 2011, Stephen Warren wrote:
> Commit 6adc1e7ff19d9befdbb7781b26fff42bb0bc21e2 "ARM: mach-nuc93x: delete"
> removed support for this sub-architecture, thus deleting that file. So,
> don't include it. grep indicates no more references to this machine.
>
> Signed-off-by: Stephen Warren <swarren@nvidia.com>
This is fixed in the latest arm-soc.git.
> ---
> arch/arm/Kconfig | 2 --
> 1 files changed, 0 insertions(+), 2 deletions(-)
>
> diff --git a/arch/arm/Kconfig b/arch/arm/Kconfig
> index 89bd520..472a7f8 100644
> --- a/arch/arm/Kconfig
> +++ b/arch/arm/Kconfig
> @@ -969,8 +969,6 @@ source "arch/arm/mach-netx/Kconfig"
> source "arch/arm/mach-nomadik/Kconfig"
> source "arch/arm/plat-nomadik/Kconfig"
>
> -source "arch/arm/mach-nuc93x/Kconfig"
> -
> source "arch/arm/plat-omap/Kconfig"
>
> source "arch/arm/mach-omap1/Kconfig"
> --
> 1.7.0.4
>
^ permalink raw reply
* [PATCH] ARM: Don't include mach-nuc93x/Kconfig
From: Stephen Warren @ 2011-09-22 20:03 UTC (permalink / raw)
To: linux-arm-kernel
Commit 6adc1e7ff19d9befdbb7781b26fff42bb0bc21e2 "ARM: mach-nuc93x: delete"
removed support for this sub-architecture, thus deleting that file. So,
don't include it. grep indicates no more references to this machine.
Signed-off-by: Stephen Warren <swarren@nvidia.com>
---
arch/arm/Kconfig | 2 --
1 files changed, 0 insertions(+), 2 deletions(-)
diff --git a/arch/arm/Kconfig b/arch/arm/Kconfig
index 89bd520..472a7f8 100644
--- a/arch/arm/Kconfig
+++ b/arch/arm/Kconfig
@@ -969,8 +969,6 @@ source "arch/arm/mach-netx/Kconfig"
source "arch/arm/mach-nomadik/Kconfig"
source "arch/arm/plat-nomadik/Kconfig"
-source "arch/arm/mach-nuc93x/Kconfig"
-
source "arch/arm/plat-omap/Kconfig"
source "arch/arm/mach-omap1/Kconfig"
--
1.7.0.4
^ permalink raw reply related
* [RFC PATCH V6 0/4] cpuidle: Global registration of idle states with per-cpu statistics
From: Kevin Hilman @ 2011-09-22 19:45 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <20110922082840.10520.85895.stgit@localhost6.localdomain6>
Deepthi Dharwar <deepthi@linux.vnet.ibm.com> writes:
> The following patch series implements global registration of cpuidle
> states, and also has the necessary data structure changes to
> accommodate the per-cpu writable members of the cpuidle_states
> structure.
I reviewed earlier versions of the series, and this version still looks
good to me. Any reason it is still RFC?
Reviewed-by: Kevin Hilman <khilman@ti.com>
and for the OMAP-specific parts,
Acked-by: Kevin Hilman <khilman@ti.com>
Kevin
^ permalink raw reply
* [RFC PATCH V6 0/4] cpuidle: Global registration of idle states with per-cpu statistics
From: Jean Pihet @ 2011-09-22 19:37 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <20110922082840.10520.85895.stgit@localhost6.localdomain6>
Hi,
On Thu, Sep 22, 2011 at 10:28 AM, Deepthi Dharwar
<deepthi@linux.vnet.ibm.com> wrote:
> The following patch series implements global registration of cpuidle
> states, and also has the necessary data structure changes to
> accommodate the per-cpu writable members of the cpuidle_states
> structure.
>
> This patch series had been in discussion earlier and
> following are the links to the previous discussions.
>
> v1 --> https://lkml.org/lkml/2011/3/22/161
> v2 --> https://lkml.org/lkml/2011/1/13/98
> v3 --> https://lkml.org/lkml/2011/2/8/73
> v4 --> https://lkml.org/lkml/2011/4/28/312
> v5 --> https://lkml.org/lkml/2011/6/6/259
>
> Changes from previous version (V5):
>
> ? ?Rebased the series to 3.1-rc7
>
> Tests done:
>
> ? ?1. Compile tested for ARM using the following configs: da8xx_omapl_defconfig,
> ? ?exynos4_defconfig, kirkwood_defconfig, omap2plus_defconfig,
> ? ?at91rm9200_defconfig
Tested OK on OMAP3:
Signed-off-by: Jean Pihet <j-pihet@ti.com>
>
> ? ?2. Boot tested on x86 nehalem with multiple C-states for both intel_idle
> ? ?and acpi_idle drivers.
>
> ? ?3. Boot tested on T60p thinkpad that has T2600 cpu with multiple C-states.
> ? ?Also tested the case when there is dynamic changes in C-states
> ? ?AC <-> Battery Power switch.
>
> Brief description of the patches:
>
> Core change in this series is to split the cpuidle_device structure
> into two parts, i.e ?global and per-cpu basis.
>
> The per-cpu pieces are mostly generic statistics that can be independent
> of current running driver. As a result of these changes, there is single
> copy of cpuidle_states structure and single registration done by one
> cpu. The low level driver is free to set per-cpu driver data on
> each cpu if needed using the cpuidle_set_statedata() as the case
> today. Only in very rare cases asymmetric C-states exist which can be
> handled within the cpuidle driver. Most architectures do not have
> asymmetric C-states.
>
> First two patches in the series facilitate splitting of cpuidle_states
> and cpuidle_device structure and next two patches do the actual split,
> change the API's and make existing code follow the changed API.
>
> [1/4] - Move the idle residency accounting part from cpuidle.c to
> the respective low level drivers, so that the accounting can
> be accurately maintained if the driver decides to demote the
> chosen (suggested) by the governor.
This is a nice improvement since OMAP heavily uses the state demotion
in the cpuidle driver, and will use it even more with the per-device
PM QoS support added.
Thanks & regards,
Jean
>
> [2/4] - removes the cpuidle_device()->prepare API since is is not
> widely used and the only use case was to allow software
> demotion using CPUIDLE_FLAG_IGNORE flag. ?Both these
> functions can be absorbed within the cpuidle back-end
> driver ad hence deprecating the prepare routine and the
> CPUIDLE_FLAG_IGNORE flag.
>
> ? ?- Ref: https://lkml.org/lkml/2011/3/25/52
>
> [3/4] - Splits the usage statistics (read/write) part out of
> cpuidle_state structure, so that the states can become read
> only and hence made global.
>
> [4/4] - Most APIs will now need to pass pointer to both global
> cpuidle_driver and per-cpu cpuidle_device structure.
>
> ?arch/arm/mach-at91/cpuidle.c ? ? ? ? ?| ? 41 +++--
> ?arch/arm/mach-davinci/cpuidle.c ? ? ? | ? 51 ++++---
> ?arch/arm/mach-exynos4/cpuidle.c ? ? ? | ? 30 ++--
> ?arch/arm/mach-kirkwood/cpuidle.c ? ? ?| ? 42 +++---
> ?arch/arm/mach-omap2/cpuidle34xx.c ? ? | ?133 +++++++++++------
> ?arch/sh/kernel/cpu/shmobile/cpuidle.c | ? 28 ++--
> ?drivers/acpi/processor_driver.c ? ? ? | ? 20 ---
> ?drivers/acpi/processor_idle.c ? ? ? ? | ?251 +++++++++++++++++++++++++++------
> ?drivers/cpuidle/cpuidle.c ? ? ? ? ? ? | ? 86 ++++-------
> ?drivers/cpuidle/driver.c ? ? ? ? ? ? ?| ? 25 +++
> ?drivers/cpuidle/governors/ladder.c ? ?| ? 41 ++++-
> ?drivers/cpuidle/governors/menu.c ? ? ?| ? 29 ++--
> ?drivers/cpuidle/sysfs.c ? ? ? ? ? ? ? | ? 22 ++-
> ?drivers/idle/intel_idle.c ? ? ? ? ? ? | ?130 +++++++++++++----
> ?include/acpi/processor.h ? ? ? ? ? ? ?| ? ?1
> ?include/linux/cpuidle.h ? ? ? ? ? ? ? | ? 52 ++++---
> ?16 files changed, 650 insertions(+), 332 deletions(-)
>
>
> --
>
> Thanks
> ?-Deepthi
>
> _______________________________________________
> linux-arm-kernel mailing list
> linux-arm-kernel at lists.infradead.org
> http://lists.infradead.org/mailman/listinfo/linux-arm-kernel
>
^ permalink raw reply
* [PATCH v4 1/3] AM35x: Using OMAP3 generic hwmods
From: Paul Walmsley @ 2011-09-22 19:10 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <1316697993-696-2-git-send-email-abhilash.kv@ti.com>
+ Chase
Hi
On Thu, 22 Sep 2011, Abhilash K V wrote:
> This patch enables AM35x SoCs to use generic OMAP3 hwmods
> (i,e. omap3xxx_hwmods) by allowing am35xx_init_early() to
> disable the modules which are not present in AM3517.
>
> Reviewed-by: Sanjeev Premi <premi@ti.com>
> Signed-off-by: Abhilash K V <abhilash.kv@ti.com>
We now use a different approach for registering hwmods that are
device-specific. Could you please take a look at the approach that's in
Tony's master branch and use it instead to handle AM3517 hwmod
registration?
- Paul
^ permalink raw reply
* [PATCH] ARM: futex: preserve oldval in SMP __futex_atomic_op
From: Nicolas Pitre @ 2011-09-22 19:09 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <1316716500-25376-1-git-send-email-will.deacon@arm.com>
On Thu, 22 Sep 2011, Will Deacon wrote:
> The SMP implementation of __futex_atomic_op clobbers oldval with the
> status flag from the exclusive store. This causes it to always read as
> zero when performing the FUTEX_OP_CMP_* operation.
>
> This patch updates the ARM __futex_atomic_op implementations to take a
> tmp argument, allowing us to store the strex status flag without
> overwriting the register containing oldval.
>
> Cc: stable at kernel.org
> Reported-by: Minho Ben <mhban@samsung.com>
> Signed-off-by: Will Deacon <will.deacon@arm.com>
Reviewed-by: Nicolas Pitre <nicolas.pitre@linaro.org>
> ---
>
> Following up on:
>
> http://lists.infradead.org/pipermail/linux-arm-kernel/2011-September/066348.html
>
> it turns out that we don't need to use named arguments after all,
> although it might be nice to add that as a later patch. For now, I'm
> trying to keep this as small as possible for -stable.
Agreed that named arguments would make this code more obvious,
especially with the insn argument of __futex_atomic_op() which uses
numbered registers away from the actual inline asm statement where it is
used.
I'm a bit worried that the LTP tests still passed though. In theory it
shouldn't have worked at all except if you were lucky with test values.
>
> arch/arm/include/asm/futex.h | 34 +++++++++++++++++-----------------
> 1 files changed, 17 insertions(+), 17 deletions(-)
>
> diff --git a/arch/arm/include/asm/futex.h b/arch/arm/include/asm/futex.h
> index 8c73900..253cc86 100644
> --- a/arch/arm/include/asm/futex.h
> +++ b/arch/arm/include/asm/futex.h
> @@ -25,17 +25,17 @@
>
> #ifdef CONFIG_SMP
>
> -#define __futex_atomic_op(insn, ret, oldval, uaddr, oparg) \
> +#define __futex_atomic_op(insn, ret, oldval, tmp, uaddr, oparg) \
> smp_mb(); \
> __asm__ __volatile__( \
> - "1: ldrex %1, [%2]\n" \
> + "1: ldrex %1, [%3]\n" \
> " " insn "\n" \
> - "2: strex %1, %0, [%2]\n" \
> - " teq %1, #0\n" \
> + "2: strex %2, %0, [%3]\n" \
> + " teq %2, #0\n" \
> " bne 1b\n" \
> " mov %0, #0\n" \
> - __futex_atomic_ex_table("%4") \
> - : "=&r" (ret), "=&r" (oldval) \
> + __futex_atomic_ex_table("%5") \
> + : "=&r" (ret), "=&r" (oldval), "=&r" (tmp) \
> : "r" (uaddr), "r" (oparg), "Ir" (-EFAULT) \
> : "cc", "memory")
>
> @@ -73,14 +73,14 @@ futex_atomic_cmpxchg_inatomic(u32 *uval, u32 __user *uaddr,
> #include <linux/preempt.h>
> #include <asm/domain.h>
>
> -#define __futex_atomic_op(insn, ret, oldval, uaddr, oparg) \
> +#define __futex_atomic_op(insn, ret, oldval, tmp, uaddr, oparg) \
> __asm__ __volatile__( \
> - "1: " T(ldr) " %1, [%2]\n" \
> + "1: " T(ldr) " %1, [%3]\n" \
> " " insn "\n" \
> - "2: " T(str) " %0, [%2]\n" \
> + "2: " T(str) " %0, [%3]\n" \
> " mov %0, #0\n" \
> - __futex_atomic_ex_table("%4") \
> - : "=&r" (ret), "=&r" (oldval) \
> + __futex_atomic_ex_table("%5") \
> + : "=&r" (ret), "=&r" (oldval), "=&r" (tmp) \
> : "r" (uaddr), "r" (oparg), "Ir" (-EFAULT) \
> : "cc", "memory")
>
> @@ -117,7 +117,7 @@ futex_atomic_op_inuser (int encoded_op, u32 __user *uaddr)
> int cmp = (encoded_op >> 24) & 15;
> int oparg = (encoded_op << 8) >> 20;
> int cmparg = (encoded_op << 20) >> 20;
> - int oldval = 0, ret;
> + int oldval = 0, ret, tmp;
>
> if (encoded_op & (FUTEX_OP_OPARG_SHIFT << 28))
> oparg = 1 << oparg;
> @@ -129,19 +129,19 @@ futex_atomic_op_inuser (int encoded_op, u32 __user *uaddr)
>
> switch (op) {
> case FUTEX_OP_SET:
> - __futex_atomic_op("mov %0, %3", ret, oldval, uaddr, oparg);
> + __futex_atomic_op("mov %0, %4", ret, oldval, tmp, uaddr, oparg);
> break;
> case FUTEX_OP_ADD:
> - __futex_atomic_op("add %0, %1, %3", ret, oldval, uaddr, oparg);
> + __futex_atomic_op("add %0, %1, %4", ret, oldval, tmp, uaddr, oparg);
> break;
> case FUTEX_OP_OR:
> - __futex_atomic_op("orr %0, %1, %3", ret, oldval, uaddr, oparg);
> + __futex_atomic_op("orr %0, %1, %4", ret, oldval, tmp, uaddr, oparg);
> break;
> case FUTEX_OP_ANDN:
> - __futex_atomic_op("and %0, %1, %3", ret, oldval, uaddr, ~oparg);
> + __futex_atomic_op("and %0, %1, %4", ret, oldval, tmp, uaddr, ~oparg);
> break;
> case FUTEX_OP_XOR:
> - __futex_atomic_op("eor %0, %1, %3", ret, oldval, uaddr, oparg);
> + __futex_atomic_op("eor %0, %1, %4", ret, oldval, tmp, uaddr, oparg);
> break;
> default:
> ret = -ENOSYS;
> --
> 1.7.0.4
>
>
> _______________________________________________
> linux-arm-kernel mailing list
> linux-arm-kernel at lists.infradead.org
> http://lists.infradead.org/mailman/listinfo/linux-arm-kernel
>
^ permalink raw reply
page: next (older) | prev (newer) | latest
- recent:[subjects (threaded)|topics (new)|topics (active)]
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox