* [v8 PATCH 4/8]: POWER: enable cpuidle for POWER.
From: Arun R Bharadwaj @ 2009-10-08 9:52 UTC (permalink / raw)
To: Peter Zijlstra, Benjamin Herrenschmidt, Ingo Molnar,
Vaidyanathan Srinivasan, Dipankar Sarma, Balbir Singh,
Arjan van de Ven, Arun Bharadwaj
Cc: linux-arch, linux-acpi, linuxppc-dev, linux-kernel
In-Reply-To: <20091008094828.GA20595@linux.vnet.ibm.com>
* Arun R Bharadwaj <arun@linux.vnet.ibm.com> [2009-10-08 15:18:28]:
This patch enables the cpuidle option in Kconfig for pSeries.
Currently cpuidle infrastructure is enabled only for x86 and ARM.
This code is almost completely borrowed from x86 to enable
cpuidle for pSeries.
Signed-off-by: Arun R Bharadwaj <arun@linux.vnet.ibm.com>
---
arch/powerpc/Kconfig | 17 +++++++++++++++++
arch/powerpc/include/asm/system.h | 2 ++
arch/powerpc/kernel/idle.c | 19 +++++++++++++++++++
3 files changed, 38 insertions(+)
Index: linux.trees.git/arch/powerpc/Kconfig
===================================================================
--- linux.trees.git.orig/arch/powerpc/Kconfig
+++ linux.trees.git/arch/powerpc/Kconfig
@@ -91,6 +91,9 @@ config ARCH_HAS_ILOG2_U64
bool
default y if 64BIT
+config ARCH_HAS_CPU_IDLE_WAIT
+ def_bool y
+
config GENERIC_HWEIGHT
bool
default y
@@ -247,6 +250,20 @@ source "kernel/Kconfig.freezer"
source "arch/powerpc/sysdev/Kconfig"
source "arch/powerpc/platforms/Kconfig"
+menu "Power management options"
+
+source "drivers/cpuidle/Kconfig"
+
+config PSERIES_PROCESSOR_IDLE
+ bool "Idle Power Management Support for pSeries"
+ depends on PPC_PSERIES && CPU_IDLE
+ default y
+ help
+ Idle Power Management Support for pSeries. This hooks onto cpuidle
+ infrastructure to help in idle cpu power management.
+
+endmenu
+
menu "Kernel options"
config HIGHMEM
Index: linux.trees.git/arch/powerpc/include/asm/system.h
===================================================================
--- linux.trees.git.orig/arch/powerpc/include/asm/system.h
+++ linux.trees.git/arch/powerpc/include/asm/system.h
@@ -546,5 +546,7 @@ extern void account_system_vtime(struct
extern struct dentry *powerpc_debugfs_root;
+void cpu_idle_wait(void);
+
#endif /* __KERNEL__ */
#endif /* _ASM_POWERPC_SYSTEM_H */
Index: linux.trees.git/arch/powerpc/kernel/idle.c
===================================================================
--- linux.trees.git.orig/arch/powerpc/kernel/idle.c
+++ linux.trees.git/arch/powerpc/kernel/idle.c
@@ -102,6 +102,25 @@ void cpu_idle(void)
}
}
+static void do_nothing(void *unused)
+{
+}
+
+/*
+ * cpu_idle_wait - Used to ensure that all the CPUs come out of the old
+ * idle loop and start using the new idle loop.
+ * Required while changing idle handler on SMP systems.
+ * Caller must have changed idle handler to the new value before the call.
+ */
+void cpu_idle_wait(void)
+{
+ /* Ensure that new value of idle is set */
+ smp_mb();
+ /* kick all the CPUs so that they exit out of old idle routine */
+ smp_call_function(do_nothing, NULL, 1);
+}
+EXPORT_SYMBOL_GPL(cpu_idle_wait);
+
int powersave_nap;
#ifdef CONFIG_SYSCTL
^ permalink raw reply
* [v8 PATCH 3/8]: x86: refactor x86 idle power management code and remove all instances of pm_idle.
From: Arun R Bharadwaj @ 2009-10-08 9:51 UTC (permalink / raw)
To: Peter Zijlstra, Benjamin Herrenschmidt, Ingo Molnar,
Vaidyanathan Srinivasan, Dipankar Sarma, Balbir Singh,
Arjan van de Ven, Arun Bharadwaj
Cc: linux-arch, linux-acpi, linuxppc-dev, linux-kernel
In-Reply-To: <20091008094828.GA20595@linux.vnet.ibm.com>
* Arun R Bharadwaj <arun@linux.vnet.ibm.com> [2009-10-08 15:18:28]:
This patch cleans up x86 of all instances of pm_idle.
pm_idle which was earlier called from cpu_idle() idle loop
is replaced by cpuidle_idle_call.
x86 also registers to cpuidle when the idle routine is selected,
by populating the cpuidle_device data structure for each cpu.
This is replicated for apm module and for xen, which also used pm_idle.
Signed-off-by: Arun R Bharadwaj <arun@linux.vnet.ibm.com>
---
arch/x86/kernel/apm_32.c | 55 +++++++++++++++++++++++-
arch/x86/kernel/process.c | 93 ++++++++++++++++++++++++++----------------
arch/x86/kernel/process_32.c | 3 -
arch/x86/kernel/process_64.c | 3 -
arch/x86/xen/setup.c | 40 +++++++++++++++++-
drivers/acpi/processor_core.c | 9 ++--
drivers/cpuidle/cpuidle.c | 16 ++++---
include/linux/cpuidle.h | 1
8 files changed, 172 insertions(+), 48 deletions(-)
Index: linux.trees.git/arch/x86/kernel/process.c
===================================================================
--- linux.trees.git.orig/arch/x86/kernel/process.c
+++ linux.trees.git/arch/x86/kernel/process.c
@@ -9,6 +9,7 @@
#include <linux/pm.h>
#include <linux/clockchips.h>
#include <linux/random.h>
+#include <linux/cpuidle.h>
#include <trace/events/power.h>
#include <asm/system.h>
#include <asm/apic.h>
@@ -244,12 +245,6 @@ int sys_vfork(struct pt_regs *regs)
unsigned long boot_option_idle_override = 0;
EXPORT_SYMBOL(boot_option_idle_override);
-/*
- * Powermanagement idle function, if any..
- */
-void (*pm_idle)(void);
-EXPORT_SYMBOL(pm_idle);
-
#ifdef CONFIG_X86_32
/*
* This halt magic was a workaround for ancient floppy DMA
@@ -329,17 +324,15 @@ static void do_nothing(void *unused)
}
/*
- * cpu_idle_wait - Used to ensure that all the CPUs discard old value of
- * pm_idle and update to new pm_idle value. Required while changing pm_idle
- * handler on SMP systems.
+ * cpu_idle_wait - Required while changing idle routine handler on SMP systems.
*
- * Caller must have changed pm_idle to the new value before the call. Old
- * pm_idle value will not be used by any CPU after the return of this function.
+ * Caller must have changed idle routine to the new value before the call. Old
+ * value will not be used by any CPU after the return of this function.
*/
void cpu_idle_wait(void)
{
smp_mb();
- /* kick all the CPUs so that they exit out of pm_idle */
+ /* kick all the CPUs so that they exit out of idle loop */
smp_call_function(do_nothing, NULL, 1);
}
EXPORT_SYMBOL_GPL(cpu_idle_wait);
@@ -387,20 +380,6 @@ static void mwait_idle(void)
}
/*
- * On SMP it's slightly faster (but much more power-consuming!)
- * to poll the ->work.need_resched flag instead of waiting for the
- * cross-CPU IPI to arrive. Use this option with caution.
- */
-static void poll_idle(void)
-{
- trace_power_start(POWER_CSTATE, 0);
- local_irq_enable();
- while (!need_resched())
- cpu_relax();
- trace_power_end(0);
-}
-
-/*
* mwait selection logic:
*
* It depends on the CPU. For AMD CPUs that support MWAIT this is
@@ -518,15 +497,59 @@ static void c1e_idle(void)
default_idle();
}
+static void (*local_idle)(void);
+DEFINE_PER_CPU(struct cpuidle_device, idle_devices);
+
+struct cpuidle_driver cpuidle_default_driver = {
+ .name = "cpuidle_default",
+};
+
+static int local_idle_loop(struct cpuidle_device *dev, struct cpuidle_state *st)
+{
+ ktime_t t1, t2;
+ s64 diff;
+ int ret;
+
+ t1 = ktime_get();
+ local_idle();
+ t2 = ktime_get();
+
+ diff = ktime_to_us(ktime_sub(t2, t1));
+ if (diff > INT_MAX)
+ diff = INT_MAX;
+ ret = (int) diff;
+
+ return ret;
+}
+
+static int setup_cpuidle_simple(void)
+{
+ struct cpuidle_device *dev;
+ int cpu;
+
+ if (!cpuidle_curr_driver)
+ cpuidle_register_driver(&cpuidle_default_driver);
+
+ for_each_online_cpu(cpu) {
+ dev = &per_cpu(idle_devices, cpu);
+ dev->cpu = cpu;
+ dev->states[0].enter = local_idle_loop;
+ dev->state_count = 1;
+ cpuidle_register_device(dev);
+ }
+ return 0;
+}
+device_initcall(setup_cpuidle_simple);
+
void __cpuinit select_idle_routine(const struct cpuinfo_x86 *c)
{
#ifdef CONFIG_SMP
- if (pm_idle == poll_idle && smp_num_siblings > 1) {
+ if (local_idle == poll_idle && smp_num_siblings > 1) {
printk(KERN_WARNING "WARNING: polling idle and HT enabled,"
" performance may degrade.\n");
}
#endif
- if (pm_idle)
+ if (local_idle)
return;
if (cpu_has(c, X86_FEATURE_MWAIT) && mwait_usable(c)) {
@@ -534,18 +557,20 @@ void __cpuinit select_idle_routine(const
* One CPU supports mwait => All CPUs supports mwait
*/
printk(KERN_INFO "using mwait in idle threads.\n");
- pm_idle = mwait_idle;
+ local_idle = mwait_idle;
} else if (check_c1e_idle(c)) {
printk(KERN_INFO "using C1E aware idle routine\n");
- pm_idle = c1e_idle;
+ local_idle = c1e_idle;
} else
- pm_idle = default_idle;
+ local_idle = default_idle;
+
+ return;
}
void __init init_c1e_mask(void)
{
/* If we're using c1e_idle, we need to allocate c1e_mask. */
- if (pm_idle == c1e_idle)
+ if (local_idle == c1e_idle)
zalloc_cpumask_var(&c1e_mask, GFP_KERNEL);
}
@@ -556,7 +581,7 @@ static int __init idle_setup(char *str)
if (!strcmp(str, "poll")) {
printk("using polling idle threads.\n");
- pm_idle = poll_idle;
+ local_idle = poll_idle;
} else if (!strcmp(str, "mwait"))
force_mwait = 1;
else if (!strcmp(str, "halt")) {
@@ -567,7 +592,7 @@ static int __init idle_setup(char *str)
* To continue to load the CPU idle driver, don't touch
* the boot_option_idle_override.
*/
- pm_idle = default_idle;
+ local_idle = default_idle;
idle_halt = 1;
return 0;
} else if (!strcmp(str, "nomwait")) {
Index: linux.trees.git/arch/x86/kernel/process_32.c
===================================================================
--- linux.trees.git.orig/arch/x86/kernel/process_32.c
+++ linux.trees.git/arch/x86/kernel/process_32.c
@@ -40,6 +40,7 @@
#include <linux/uaccess.h>
#include <linux/io.h>
#include <linux/kdebug.h>
+#include <linux/cpuidle.h>
#include <asm/pgtable.h>
#include <asm/system.h>
@@ -113,7 +114,7 @@ void cpu_idle(void)
local_irq_disable();
/* Don't trace irqs off for idle */
stop_critical_timings();
- pm_idle();
+ cpuidle_idle_call();
start_critical_timings();
}
tick_nohz_restart_sched_tick();
Index: linux.trees.git/arch/x86/kernel/process_64.c
===================================================================
--- linux.trees.git.orig/arch/x86/kernel/process_64.c
+++ linux.trees.git/arch/x86/kernel/process_64.c
@@ -39,6 +39,7 @@
#include <linux/io.h>
#include <linux/ftrace.h>
#include <linux/dmi.h>
+#include <linux/cpuidle.h>
#include <asm/pgtable.h>
#include <asm/system.h>
@@ -142,7 +143,7 @@ void cpu_idle(void)
enter_idle();
/* Don't trace irqs off for idle */
stop_critical_timings();
- pm_idle();
+ cpuidle_idle_call();
start_critical_timings();
/* In many cases the interrupt that ended idle
has already called exit_idle. But some idle
Index: linux.trees.git/arch/x86/kernel/apm_32.c
===================================================================
--- linux.trees.git.orig/arch/x86/kernel/apm_32.c
+++ linux.trees.git/arch/x86/kernel/apm_32.c
@@ -2257,6 +2257,56 @@ static struct dmi_system_id __initdata a
{ }
};
+DEFINE_PER_CPU(struct cpuidle_device, apm_idle_devices);
+
+struct cpuidle_driver cpuidle_apm_driver = {
+ .name = "cpuidle_apm",
+};
+
+static int apm_idle_loop(struct cpuidle_device *dev, struct cpuidle_state *st)
+{
+ ktime_t t1, t2;
+ s64 diff;
+ int ret;
+
+ t1 = ktime_get();
+ apm_cpu_idle();
+ t2 = ktime_get();
+
+ diff = ktime_to_us(ktime_sub(t2, t1));
+ if (diff > INT_MAX)
+ diff = INT_MAX;
+ ret = (int) diff;
+
+ return ret;
+}
+
+void __cpuinit setup_cpuidle_apm(void)
+{
+ struct cpuidle_device *dev;
+
+ if (!cpuidle_curr_driver)
+ cpuidle_register_driver(&cpuidle_apm_driver);
+
+ dev = &per_cpu(apm_idle_devices, smp_processor_id());
+ dev->cpu = smp_processor_id();
+ dev->states[0].enter = apm_idle_loop;
+ dev->state_count = 1;
+ cpuidle_register_device(dev);
+}
+
+void exit_cpuidle_apm(void)
+{
+ struct cpuidle_device *dev;
+ int cpu;
+
+ for_each_online_cpu(cpu) {
+ dev = &per_cpu(apm_idle_devices, cpu);
+ cpuidle_unregister_device(dev);
+ }
+}
+
+
/*
* Just start the APM thread. We do NOT want to do APM BIOS
* calls from anything but the APM thread, if for no other reason
@@ -2394,8 +2444,7 @@ static int __init apm_init(void)
if (HZ != 100)
idle_period = (idle_period * HZ) / 100;
if (idle_threshold < 100) {
- original_pm_idle = pm_idle;
- pm_idle = apm_cpu_idle;
+ setup_cpuidle_apm();
set_pm_idle = 1;
}
@@ -2407,7 +2456,7 @@ static void __exit apm_exit(void)
int error;
if (set_pm_idle) {
- pm_idle = original_pm_idle;
+ exit_cpuidle_apm();
/*
* We are about to unload the current idle thread pm callback
* (pm_idle), Wait for all processors to update cached/local
Index: linux.trees.git/arch/x86/xen/setup.c
===================================================================
--- linux.trees.git.orig/arch/x86/xen/setup.c
+++ linux.trees.git/arch/x86/xen/setup.c
@@ -8,6 +8,7 @@
#include <linux/sched.h>
#include <linux/mm.h>
#include <linux/pm.h>
+#include <linux/cpuidle.h>
#include <asm/elf.h>
#include <asm/vdso.h>
@@ -151,6 +152,43 @@ void __cpuinit xen_enable_syscall(void)
#endif /* CONFIG_X86_64 */
}
+DEFINE_PER_CPU(struct cpuidle_device, xen_idle_devices);
+struct cpuidle_driver cpuidle_xen_driver = {
+ .name = "cpuidle_xen",
+};
+
+static int xen_idle_loop(struct cpuidle_device *dev, struct cpuidle_state *st)
+{
+ ktime_t t1, t2;
+ s64 diff;
+ int ret;
+
+ t1 = ktime_get();
+ xen_idle();
+ t2 = ktime_get();
+
+ diff = ktime_to_us(ktime_sub(t2, t1));
+ if (diff > INT_MAX)
+ diff = INT_MAX;
+ ret = (int) diff;
+
+ return ret;
+}
+
+void __cpuinit setup_cpuidle_xen(void)
+{
+ struct cpuidle_device *dev;
+
+ if (!cpuidle_curr_driver)
+ cpuidle_register_driver(&cpuidle_xen_driver);
+
+ dev = &per_cpu(xen_idle_devices, smp_processor_id());
+ dev->cpu = smp_processor_id();
+ dev->states[0].enter = xen_idle_loop;
+ dev->state_count = 1;
+ cpuidle_register_device(dev);
+}
+
void __init xen_arch_setup(void)
{
struct physdev_set_iopl set_iopl;
@@ -186,7 +224,7 @@ void __init xen_arch_setup(void)
MAX_GUEST_CMDLINE > COMMAND_LINE_SIZE ?
COMMAND_LINE_SIZE : MAX_GUEST_CMDLINE);
- pm_idle = xen_idle;
+ setup_cpuidle_xen();
paravirt_disable_iospace();
Index: linux.trees.git/drivers/acpi/processor_core.c
===================================================================
--- linux.trees.git.orig/drivers/acpi/processor_core.c
+++ linux.trees.git/drivers/acpi/processor_core.c
@@ -1150,9 +1150,12 @@ static int __init acpi_processor_init(vo
* should not use mwait for CPU-states.
*/
dmi_check_system(processor_idle_dmi_table);
- result = cpuidle_register_driver(&acpi_idle_driver);
- if (result < 0)
- goto out_proc;
+
+ if (!boot_option_idle_override) {
+ result = cpuidle_register_driver(&acpi_idle_driver);
+ if (result < 0)
+ goto out_proc;
+ }
result = acpi_bus_register_driver(&acpi_processor_driver);
if (result < 0)
Index: linux.trees.git/drivers/cpuidle/cpuidle.c
===================================================================
--- linux.trees.git.orig/drivers/cpuidle/cpuidle.c
+++ linux.trees.git/drivers/cpuidle/cpuidle.c
@@ -224,16 +224,22 @@ void cpuidle_disable_device(struct cpuid
EXPORT_SYMBOL_GPL(cpuidle_disable_device);
#ifdef CONFIG_ARCH_HAS_CPU_RELAX
-static int poll_idle(struct cpuidle_device *dev, struct cpuidle_state *st)
+void poll_idle(void)
+{
+ local_irq_enable();
+ while (!need_resched())
+ cpu_relax();
+}
+
+static int poll_idle_loop(struct cpuidle_device *dev, struct cpuidle_state *st)
{
ktime_t t1, t2;
s64 diff;
int ret;
t1 = ktime_get();
- local_irq_enable();
- while (!need_resched())
- cpu_relax();
+
+ poll_idle();
t2 = ktime_get();
diff = ktime_to_us(ktime_sub(t2, t1));
@@ -256,7 +262,7 @@ static void poll_idle_init(struct cpuidl
state->target_residency = 0;
state->power_usage = -1;
state->flags = CPUIDLE_FLAG_POLL;
- state->enter = poll_idle;
+ state->enter = poll_idle_loop;
}
#else
static void poll_idle_init(struct cpuidle_device *dev) {}
Index: linux.trees.git/include/linux/cpuidle.h
===================================================================
--- linux.trees.git.orig/include/linux/cpuidle.h
+++ linux.trees.git/include/linux/cpuidle.h
@@ -187,6 +187,7 @@ static inline void cpuidle_unregister_go
#ifdef CONFIG_ARCH_HAS_CPU_RELAX
#define CPUIDLE_DRIVER_STATE_START 1
+extern void poll_idle(void);
#else
#define CPUIDLE_DRIVER_STATE_START 0
#endif
^ permalink raw reply
* [v8 PATCH 2/8]: cpuidle: implement a list based approach to register a set of idle routines.
From: Arun R Bharadwaj @ 2009-10-08 9:50 UTC (permalink / raw)
To: Peter Zijlstra, Benjamin Herrenschmidt, Ingo Molnar,
Vaidyanathan Srinivasan, Dipankar Sarma, Balbir Singh,
Arjan van de Ven, Arun Bharadwaj
Cc: linux-arch, linux-acpi, linuxppc-dev, linux-kernel
In-Reply-To: <20091008094828.GA20595@linux.vnet.ibm.com>
* Arun R Bharadwaj <arun@linux.vnet.ibm.com> [2009-10-08 15:18:28]:
Implement a list based registering mechanism for architectures which
have multiple sets of idle routines which are to be registered.
Currently, in x86 it is done by merely setting pm_idle = idle_routine
and managing this pm_idle pointer is messy.
To give an example of how this mechanism works:
In x86, initially, idle routine is selected from the set of poll/mwait/
c1e/default idle loops. So the selected idle loop is registered in cpuidle
as one idle state cpuidle devices. Once ACPI comes up, it registers
another set of idle states on top of this state. Again, suppose a module
registers another set of idle loops, it is added to this list.
This provides a clean way of registering and unregistering idle state
routines.
In the current implementation, pm_idle is set as the current idle routine
being used and the old idle routine has to be maintained and when a module
registers/unregisters an idle routine, confusion arises.
Signed-off-by: Arun R Bharadwaj <arun@linux.vnet.ibm.com>
---
drivers/cpuidle/cpuidle.c | 54 ++++++++++++++++++++++++++++++++++++++++------
include/linux/cpuidle.h | 1
2 files changed, 48 insertions(+), 7 deletions(-)
Index: linux.trees.git/drivers/cpuidle/cpuidle.c
===================================================================
--- linux.trees.git.orig/drivers/cpuidle/cpuidle.c
+++ linux.trees.git/drivers/cpuidle/cpuidle.c
@@ -22,6 +22,7 @@
#include "cpuidle.h"
DEFINE_PER_CPU(struct cpuidle_device *, cpuidle_devices);
+DEFINE_PER_CPU(struct list_head, cpuidle_devices_list);
DEFINE_MUTEX(cpuidle_lock);
@@ -112,6 +113,45 @@ void cpuidle_resume_and_unlock(void)
EXPORT_SYMBOL_GPL(cpuidle_resume_and_unlock);
+int cpuidle_add_to_list(struct cpuidle_device *dev)
+{
+ int ret, cpu = dev->cpu;
+ struct cpuidle_device *old_dev;
+
+ if (!list_empty(&per_cpu(cpuidle_devices_list, cpu))) {
+ old_dev = list_first_entry(&per_cpu(cpuidle_devices_list, cpu),
+ struct cpuidle_device, idle_list);
+ cpuidle_remove_state_sysfs(old_dev);
+ }
+
+ list_add(&dev->idle_list, &per_cpu(cpuidle_devices_list, cpu));
+ ret = cpuidle_add_state_sysfs(dev);
+ return ret;
+}
+
+void cpuidle_remove_from_list(struct cpuidle_device *dev)
+{
+ struct cpuidle_device *temp_dev;
+ struct list_head *pos;
+ int ret, cpu = dev->cpu;
+
+ list_for_each(pos, &per_cpu(cpuidle_devices_list, cpu)) {
+ temp_dev = container_of(pos, struct cpuidle_device, idle_list);
+ if (dev == temp_dev) {
+ list_del(&temp_dev->idle_list);
+ cpuidle_remove_state_sysfs(temp_dev);
+ break;
+ }
+ }
+
+ if (!list_empty(&per_cpu(cpuidle_devices_list, cpu))) {
+ temp_dev = list_first_entry(&per_cpu(cpuidle_devices_list, cpu),
+ struct cpuidle_device, idle_list);
+ ret = cpuidle_add_state_sysfs(temp_dev);
+ }
+ cpuidle_kick_cpus();
+}
+
/**
* cpuidle_enable_device - enables idle PM for a CPU
* @dev: the CPU
@@ -136,9 +176,6 @@ int cpuidle_enable_device(struct cpuidle
return ret;
}
- if ((ret = cpuidle_add_state_sysfs(dev)))
- return ret;
-
if (cpuidle_curr_governor->enable &&
(ret = cpuidle_curr_governor->enable(dev)))
goto fail_sysfs;
@@ -157,7 +194,7 @@ int cpuidle_enable_device(struct cpuidle
return 0;
fail_sysfs:
- cpuidle_remove_state_sysfs(dev);
+ cpuidle_remove_from_list(dev);
return ret;
}
@@ -182,8 +219,6 @@ void cpuidle_disable_device(struct cpuid
if (cpuidle_curr_governor->disable)
cpuidle_curr_governor->disable(dev);
-
- cpuidle_remove_state_sysfs(dev);
}
EXPORT_SYMBOL_GPL(cpuidle_disable_device);
@@ -267,6 +302,7 @@ int cpuidle_register_device(struct cpuid
}
cpuidle_enable_device(dev);
+ cpuidle_add_to_list(dev);
mutex_unlock(&cpuidle_lock);
@@ -288,6 +324,7 @@ void cpuidle_unregister_device(struct cp
cpuidle_pause_and_lock();
cpuidle_disable_device(dev);
+ cpuidle_remove_from_list(dev);
per_cpu(cpuidle_devices, dev->cpu) = NULL;
@@ -338,12 +375,15 @@ static inline void latency_notifier_init
*/
static int __init cpuidle_init(void)
{
- int ret;
+ int ret, cpu;
ret = cpuidle_add_class_sysfs(&cpu_sysdev_class);
if (ret)
return ret;
+ for_each_possible_cpu(cpu)
+ INIT_LIST_HEAD(&per_cpu(cpuidle_devices_list, cpu));
+
latency_notifier_init(&cpuidle_latency_notifier);
return 0;
Index: linux.trees.git/include/linux/cpuidle.h
===================================================================
--- linux.trees.git.orig/include/linux/cpuidle.h
+++ linux.trees.git/include/linux/cpuidle.h
@@ -92,6 +92,7 @@ struct cpuidle_device {
struct cpuidle_state_kobj *kobjs[CPUIDLE_STATE_MAX];
struct cpuidle_state *last_state;
+ struct list_head idle_list;
struct kobject kobj;
struct completion kobj_unregister;
void *governor_data;
^ permalink raw reply
* [v8 PATCH 1/8]: cpuidle: cleanup drivers/cpuidle/cpuidle.c
From: Arun R Bharadwaj @ 2009-10-08 9:49 UTC (permalink / raw)
To: Peter Zijlstra, Benjamin Herrenschmidt, Ingo Molnar,
Vaidyanathan Srinivasan, Dipankar Sarma, Balbir Singh,
Arjan van de Ven, Arun Bharadwaj
Cc: linux-arch, linux-acpi, linuxppc-dev, linux-kernel
In-Reply-To: <20091008094828.GA20595@linux.vnet.ibm.com>
* Arun R Bharadwaj <arun@linux.vnet.ibm.com> [2009-10-08 15:18:28]:
This patch cleans up drivers/cpuidle/cpuidle.c
Earlier cpuidle assumed pm_idle as the default idle loop. Break that
assumption and make it more generic. cpuidle_idle_call() which is the
main idle loop of cpuidle is to be called by architectures which have
registered to cpuidle.
Remove routines cpuidle_install/uninstall_idle_handler() which are not
needed anymore.
Signed-off-by: Arun R Bharadwaj <arun@linux.vnet.ibm.com>
---
drivers/cpuidle/cpuidle.c | 62 +++++----------------------------------------
drivers/cpuidle/cpuidle.h | 6 +---
drivers/cpuidle/driver.c | 4 --
drivers/cpuidle/governor.c | 13 +++------
drivers/cpuidle/sysfs.c | 34 +++++++++++++-----------
include/linux/cpuidle.h | 4 ++
6 files changed, 37 insertions(+), 86 deletions(-)
Index: linux.trees.git/drivers/cpuidle/cpuidle.c
===================================================================
--- linux.trees.git.orig/drivers/cpuidle/cpuidle.c
+++ linux.trees.git/drivers/cpuidle/cpuidle.c
@@ -24,10 +24,6 @@
DEFINE_PER_CPU(struct cpuidle_device *, cpuidle_devices);
DEFINE_MUTEX(cpuidle_lock);
-LIST_HEAD(cpuidle_detected_devices);
-static void (*pm_idle_old)(void);
-
-static int enabled_devices;
#if defined(CONFIG_ARCH_HAS_CPU_IDLE_WAIT)
static void cpuidle_kick_cpus(void)
@@ -47,7 +43,7 @@ static int __cpuidle_register_device(str
*
* NOTE: no locks or semaphores should be used here
*/
-static void cpuidle_idle_call(void)
+void cpuidle_idle_call(void)
{
struct cpuidle_device *dev = __get_cpu_var(cpuidle_devices);
struct cpuidle_state *target_state;
@@ -55,13 +51,10 @@ static void cpuidle_idle_call(void)
/* check if the device is ready */
if (!dev || !dev->enabled) {
- if (pm_idle_old)
- pm_idle_old();
- else
#if defined(CONFIG_ARCH_HAS_DEFAULT_IDLE)
- default_idle();
+ default_idle();
#else
- local_irq_enable();
+ local_irq_enable();
#endif
return;
}
@@ -75,7 +68,11 @@ static void cpuidle_idle_call(void)
hrtimer_peek_ahead_timers();
#endif
/* ask the governor for the next state */
- next_state = cpuidle_curr_governor->select(dev);
+ if (dev->state_count > 1)
+ next_state = cpuidle_curr_governor->select(dev);
+ else
+ next_state = 0;
+
if (need_resched())
return;
target_state = &dev->states[next_state];
@@ -96,35 +93,11 @@ static void cpuidle_idle_call(void)
}
/**
- * cpuidle_install_idle_handler - installs the cpuidle idle loop handler
- */
-void cpuidle_install_idle_handler(void)
-{
- if (enabled_devices && (pm_idle != cpuidle_idle_call)) {
- /* Make sure all changes finished before we switch to new idle */
- smp_wmb();
- pm_idle = cpuidle_idle_call;
- }
-}
-
-/**
- * cpuidle_uninstall_idle_handler - uninstalls the cpuidle idle loop handler
- */
-void cpuidle_uninstall_idle_handler(void)
-{
- if (enabled_devices && pm_idle_old && (pm_idle != pm_idle_old)) {
- pm_idle = pm_idle_old;
- cpuidle_kick_cpus();
- }
-}
-
-/**
* cpuidle_pause_and_lock - temporarily disables CPUIDLE
*/
void cpuidle_pause_and_lock(void)
{
mutex_lock(&cpuidle_lock);
- cpuidle_uninstall_idle_handler();
}
EXPORT_SYMBOL_GPL(cpuidle_pause_and_lock);
@@ -134,7 +107,6 @@ EXPORT_SYMBOL_GPL(cpuidle_pause_and_lock
*/
void cpuidle_resume_and_unlock(void)
{
- cpuidle_install_idle_handler();
mutex_unlock(&cpuidle_lock);
}
@@ -182,7 +154,6 @@ int cpuidle_enable_device(struct cpuidle
dev->enabled = 1;
- enabled_devices++;
return 0;
fail_sysfs:
@@ -213,7 +184,6 @@ void cpuidle_disable_device(struct cpuid
cpuidle_curr_governor->disable(dev);
cpuidle_remove_state_sysfs(dev);
- enabled_devices--;
}
EXPORT_SYMBOL_GPL(cpuidle_disable_device);
@@ -266,7 +236,6 @@ static void poll_idle_init(struct cpuidl
*/
static int __cpuidle_register_device(struct cpuidle_device *dev)
{
- int ret;
struct sys_device *sys_dev = get_cpu_sysdev((unsigned long)dev->cpu);
if (!sys_dev)
@@ -274,16 +243,9 @@ static int __cpuidle_register_device(str
if (!try_module_get(cpuidle_curr_driver->owner))
return -EINVAL;
- init_completion(&dev->kobj_unregister);
-
poll_idle_init(dev);
per_cpu(cpuidle_devices, dev->cpu) = dev;
- list_add(&dev->device_list, &cpuidle_detected_devices);
- if ((ret = cpuidle_add_sysfs(sys_dev))) {
- module_put(cpuidle_curr_driver->owner);
- return ret;
- }
dev->registered = 1;
return 0;
@@ -305,7 +267,6 @@ int cpuidle_register_device(struct cpuid
}
cpuidle_enable_device(dev);
- cpuidle_install_idle_handler();
mutex_unlock(&cpuidle_lock);
@@ -321,8 +282,6 @@ EXPORT_SYMBOL_GPL(cpuidle_register_devic
*/
void cpuidle_unregister_device(struct cpuidle_device *dev)
{
- struct sys_device *sys_dev = get_cpu_sysdev((unsigned long)dev->cpu);
-
if (dev->registered == 0)
return;
@@ -330,9 +289,6 @@ void cpuidle_unregister_device(struct cp
cpuidle_disable_device(dev);
- cpuidle_remove_sysfs(sys_dev);
- list_del(&dev->device_list);
- wait_for_completion(&dev->kobj_unregister);
per_cpu(cpuidle_devices, dev->cpu) = NULL;
cpuidle_resume_and_unlock();
@@ -384,8 +340,6 @@ static int __init cpuidle_init(void)
{
int ret;
- pm_idle_old = pm_idle;
-
ret = cpuidle_add_class_sysfs(&cpu_sysdev_class);
if (ret)
return ret;
Index: linux.trees.git/drivers/cpuidle/governor.c
===================================================================
--- linux.trees.git.orig/drivers/cpuidle/governor.c
+++ linux.trees.git/drivers/cpuidle/governor.c
@@ -43,16 +43,14 @@ static struct cpuidle_governor * __cpuid
*/
int cpuidle_switch_governor(struct cpuidle_governor *gov)
{
- struct cpuidle_device *dev;
+ int cpu;
if (gov == cpuidle_curr_governor)
return 0;
- cpuidle_uninstall_idle_handler();
-
if (cpuidle_curr_governor) {
- list_for_each_entry(dev, &cpuidle_detected_devices, device_list)
- cpuidle_disable_device(dev);
+ for_each_online_cpu(cpu)
+ cpuidle_disable_device(per_cpu(cpuidle_devices, cpu));
module_put(cpuidle_curr_governor->owner);
}
@@ -61,9 +59,8 @@ int cpuidle_switch_governor(struct cpuid
if (gov) {
if (!try_module_get(cpuidle_curr_governor->owner))
return -EINVAL;
- list_for_each_entry(dev, &cpuidle_detected_devices, device_list)
- cpuidle_enable_device(dev);
- cpuidle_install_idle_handler();
+ for_each_online_cpu(cpu)
+ cpuidle_enable_device(per_cpu(cpuidle_devices, cpu));
printk(KERN_INFO "cpuidle: using governor %s\n", gov->name);
}
Index: linux.trees.git/include/linux/cpuidle.h
===================================================================
--- linux.trees.git.orig/include/linux/cpuidle.h
+++ linux.trees.git/include/linux/cpuidle.h
@@ -92,7 +92,6 @@ struct cpuidle_device {
struct cpuidle_state_kobj *kobjs[CPUIDLE_STATE_MAX];
struct cpuidle_state *last_state;
- struct list_head device_list;
struct kobject kobj;
struct completion kobj_unregister;
void *governor_data;
@@ -112,6 +111,9 @@ static inline int cpuidle_get_last_resid
return dev->last_residency;
}
+extern void cpuidle_idle_call(void);
+extern struct cpuidle_driver *cpuidle_curr_driver;
+
/****************************
* CPUIDLE DRIVER INTERFACE *
Index: linux.trees.git/drivers/cpuidle/cpuidle.h
===================================================================
--- linux.trees.git.orig/drivers/cpuidle/cpuidle.h
+++ linux.trees.git/drivers/cpuidle/cpuidle.h
@@ -9,9 +9,7 @@
/* For internal use only */
extern struct cpuidle_governor *cpuidle_curr_governor;
-extern struct cpuidle_driver *cpuidle_curr_driver;
extern struct list_head cpuidle_governors;
-extern struct list_head cpuidle_detected_devices;
extern struct mutex cpuidle_lock;
extern spinlock_t cpuidle_driver_lock;
@@ -27,7 +25,7 @@ extern int cpuidle_add_class_sysfs(struc
extern void cpuidle_remove_class_sysfs(struct sysdev_class *cls);
extern int cpuidle_add_state_sysfs(struct cpuidle_device *device);
extern void cpuidle_remove_state_sysfs(struct cpuidle_device *device);
-extern int cpuidle_add_sysfs(struct sys_device *sysdev);
-extern void cpuidle_remove_sysfs(struct sys_device *sysdev);
+extern int cpuidle_add_sysfs(struct cpuidle_device *device);
+extern void cpuidle_remove_sysfs(struct cpuidle_device *device);
#endif /* __DRIVER_CPUIDLE_H */
Index: linux.trees.git/drivers/cpuidle/sysfs.c
===================================================================
--- linux.trees.git.orig/drivers/cpuidle/sysfs.c
+++ linux.trees.git/drivers/cpuidle/sysfs.c
@@ -311,6 +311,13 @@ int cpuidle_add_state_sysfs(struct cpuid
int i, ret = -ENOMEM;
struct cpuidle_state_kobj *kobj;
+ init_completion(&device->kobj_unregister);
+
+ ret = cpuidle_add_sysfs(device);
+ if (ret) {
+ module_put(cpuidle_curr_driver->owner);
+ return ret;
+ }
/* state statistics */
for (i = 0; i < device->state_count; i++) {
kobj = kzalloc(sizeof(struct cpuidle_state_kobj), GFP_KERNEL);
@@ -347,35 +354,32 @@ void cpuidle_remove_state_sysfs(struct c
for (i = 0; i < device->state_count; i++)
cpuidle_free_state_kobj(device, i);
+
+ cpuidle_remove_sysfs(device);
}
/**
* cpuidle_add_sysfs - creates a sysfs instance for the target device
- * @sysdev: the target device
+ * @device: the target device
*/
-int cpuidle_add_sysfs(struct sys_device *sysdev)
+int cpuidle_add_sysfs(struct cpuidle_device *device)
{
- int cpu = sysdev->id;
- struct cpuidle_device *dev;
int error;
+ struct sys_device *sysdev = get_cpu_sysdev((unsigned long)device->cpu);
- dev = per_cpu(cpuidle_devices, cpu);
- error = kobject_init_and_add(&dev->kobj, &ktype_cpuidle, &sysdev->kobj,
- "cpuidle");
+ error = kobject_init_and_add(&device->kobj, &ktype_cpuidle,
+ &sysdev->kobj, "cpuidle");
if (!error)
- kobject_uevent(&dev->kobj, KOBJ_ADD);
+ kobject_uevent(&device->kobj, KOBJ_ADD);
return error;
}
/**
* cpuidle_remove_sysfs - deletes a sysfs instance on the target device
- * @sysdev: the target device
+ * @device: the target device
*/
-void cpuidle_remove_sysfs(struct sys_device *sysdev)
+void cpuidle_remove_sysfs(struct cpuidle_device *device)
{
- int cpu = sysdev->id;
- struct cpuidle_device *dev;
-
- dev = per_cpu(cpuidle_devices, cpu);
- kobject_put(&dev->kobj);
+ kobject_put(&device->kobj);
+ wait_for_completion(&device->kobj_unregister);
}
Index: linux.trees.git/drivers/cpuidle/driver.c
===================================================================
--- linux.trees.git.orig/drivers/cpuidle/driver.c
+++ linux.trees.git/drivers/cpuidle/driver.c
@@ -27,10 +27,6 @@ int cpuidle_register_driver(struct cpuid
return -EINVAL;
spin_lock(&cpuidle_driver_lock);
- if (cpuidle_curr_driver) {
- spin_unlock(&cpuidle_driver_lock);
- return -EBUSY;
- }
cpuidle_curr_driver = drv;
spin_unlock(&cpuidle_driver_lock);
^ permalink raw reply
* [v8 PATCH 0/8]: cpuidle: Cleanup cpuidle/ Introduce cpuidle to POWER.
From: Arun R Bharadwaj @ 2009-10-08 9:48 UTC (permalink / raw)
To: Peter Zijlstra, Benjamin Herrenschmidt, Ingo Molnar,
Vaidyanathan Srinivasan, Dipankar Sarma, Balbir Singh,
Arjan van de Ven, Arun Bharadwaj
Cc: linux-arch, linux-acpi, linuxppc-dev, linux-kernel
Hi
Please consider this for inclusion into the testing tree.
This patchset introduces cpuidle infrastructure to POWER, prototyping
for pSeries, and also does a major refactoring of current x86 idle
power management and a cleanup of cpuidle infrastructure.
Earlier discussions on the same can be found at:
v7 --> http://lkml.org/lkml/2009/10/6/278
v6 --> http://lkml.org/lkml/2009/9/22/180
v5 --> http://lkml.org/lkml/2009/9/22/26
v4 --> http://lkml.org/lkml/2009/9/1/133
v3 --> http://lkml.org/lkml/2009/8/27/124
v2 --> http://lkml.org/lkml/2009/8/26/233
v1 --> http://lkml.org/lkml/2009/8/19/150
Changes in this version:
--------------------------------------
* Remove redundant poll_idle definition in arch/x86/kernel/process.c
* Prevent acpi_driver from registering when boot_option_idle_override
is set and let cpuidle_default driver to take over in this case.
* Enable default_idle when power_save=off in POWER.
thanks,
arun
^ permalink raw reply
* Re: [PATCH] Remove nested function
From: David Miller @ 2009-10-08 9:10 UTC (permalink / raw)
To: jezz; +Cc: netdev, linuxppc-dev, afleming
In-Reply-To: <1254990863-15271-1-git-send-email-jezz@sysmic.org>
From: J=E9r=F4me Pouiller <jezz@sysmic.org>
Date: Thu, 8 Oct 2009 10:34:23 +0200
> Some toolchains dislike nested function definition, so we define func=
tion match
> outside of of_phy_find_device.
> =
> Signed-off-by: J=E9r=F4me Pouiller <jezz@sysmic.org>
Acked-by: David S. Miller <davem@davemloft.net>
^ permalink raw reply
* Re: Nested function in drivers/of/of_mdio.c
From: Jérôme Pouiller @ 2009-10-08 8:45 UTC (permalink / raw)
To: linuxppc-dev, Grant Likely; +Cc: netdev, Andy Fleming, David S. Miller
In-Reply-To: <f608b67d0910070923h54c30c2doae08550b0791ed1b@mail.gmail.com>
I did some grep on codebase. I have not found any other instances of=20
nested functions, but my regexps are not enough to be 100% sure.
On Wednesday 07 October 2009 18:23:04 vb@vsbe.com wrote:
> Guys, are there other instances of nested C functions in the codebase
> or was this the first attempt?
>=20
> On Wed, Oct 7, 2009 at 9:11 AM, Grant Likely=20
<grant.likely@secretlab.ca> wrote:
> > On Wed, Oct 7, 2009 at 9:15 AM, J=E9r=F4me Pouiller <jezz@sysmic.org>=20
wrote:
> >> Dear,
> >>
> >> I have a problem with commit
> >> 8bc487d150b939e69830c39322df4ee486efe381 in file
> >> drivers/of/of_mdio.c in function of_phy_find_device.
> >>
> >> As you see, this function define match() as a nested function. My
> >> compiler (powerpc-e500-linux-gnu-gcc-3.4.1) raise an error during
> >> link due to this nested definition:
> >> drivers/built-in.o(.text+0x5e2a4): In function
> >> `of_phy_find_device':
> >> /home/jezz/linux-next/drivers/of/of_mdio.c:107: undefined
> >> reference to `__trampoline_setup'
> >>
> >> I am sure I could solve problem by rebuilding my toolchain.
> >> Nevertheless, I think nested function definition is not perfectly
> >> supported by all compilers. Also, I suggest to place function
> >> match() outside of scope of of_phy_find_device as in following
> >> patch.
> >
> > I'm okay with that, but if you're moving code out of the file
> > scope, then please rename the function to of_phy_match() to avoid
> > global namespace conflicts.
> >
> > g.
> >
> >> diff --git a/drivers/of/of_mdio.c b/drivers/of/of_mdio.c
> >> index bacaa53..c7b2e26 100644
> >> --- a/drivers/of/of_mdio.c
> >> +++ b/drivers/of/of_mdio.c
> >> @@ -97,6 +97,10 @@ int of_mdiobus_register(struct mii_bus *mdio,
> >> struct device_node *np) }
> >> EXPORT_SYMBOL(of_mdiobus_register);
> >>
> >> +static int match(struct device *dev, void *phy_np)
> >> +{
> >> + return dev_archdata_get_node(&dev->archdata) =3D=3D phy_np;
> >> +}
> >> /**
> >> * of_phy_find_device - Give a PHY node, find the phy_device
> >> * @phy_np: Pointer to the phy's device tree node
> >> @@ -106,11 +110,6 @@ EXPORT_SYMBOL(of_mdiobus_register);
> >> struct phy_device *of_phy_find_device(struct device_node *phy_np)
> >> {
> >> struct device *d;
> >> - int match(struct device *dev, void *phy_np)
> >> - {
> >> - return dev_archdata_get_node(&dev->archdata) =3D=3D
> >> phy_np; - }
> >> -
> >> if (!phy_np)
> >> return NULL;
> >>
> >>
> >> What do you think about it?
> >>
> >> Best regards,
> >>
> >> --
> >> J=E9r=F4me Pouiller (jezz AT sysmic DOT org)
> >
> > --
> > Grant Likely, B.Sc., P.Eng.
> > Secret Lab Technologies Ltd.
> > _______________________________________________
> > Linuxppc-dev mailing list
> > Linuxppc-dev@lists.ozlabs.org
> > https://lists.ozlabs.org/listinfo/linuxppc-dev
>=20
> _______________________________________________
> Linuxppc-dev mailing list
> Linuxppc-dev@lists.ozlabs.org
> https://lists.ozlabs.org/listinfo/linuxppc-dev
>=20
=2D-=20
J=E9r=F4me Pouiller (jerome AT sysmic DOT org)
Expert Linux Embarqu=E9
^ permalink raw reply
* [PATCH] Remove nested function
From: Jérôme Pouiller @ 2009-10-08 8:34 UTC (permalink / raw)
To: Grant Likely
Cc: netdev, linuxppc, Andy Fleming, Jérôme Pouiller,
David S. Miller
In-Reply-To: <fa686aa40910070911x769d7d41u908fbcf6b0980962@mail.gmail.com>
Some toolchains dislike nested function definition, so we define function match
outside of of_phy_find_device.
Signed-off-by: Jérôme Pouiller <jezz@sysmic.org>
---
drivers/of/of_mdio.c | 13 +++++++------
1 files changed, 7 insertions(+), 6 deletions(-)
diff --git a/drivers/of/of_mdio.c b/drivers/of/of_mdio.c
index bacaa53..4b22ba5 100644
--- a/drivers/of/of_mdio.c
+++ b/drivers/of/of_mdio.c
@@ -97,6 +97,12 @@ int of_mdiobus_register(struct mii_bus *mdio, struct device_node *np)
}
EXPORT_SYMBOL(of_mdiobus_register);
+/* Helper function for of_phy_find_device */
+static int of_phy_match(struct device *dev, void *phy_np)
+{
+ return dev_archdata_get_node(&dev->archdata) == phy_np;
+}
+
/**
* of_phy_find_device - Give a PHY node, find the phy_device
* @phy_np: Pointer to the phy's device tree node
@@ -106,15 +112,10 @@ EXPORT_SYMBOL(of_mdiobus_register);
struct phy_device *of_phy_find_device(struct device_node *phy_np)
{
struct device *d;
- int match(struct device *dev, void *phy_np)
- {
- return dev_archdata_get_node(&dev->archdata) == phy_np;
- }
-
if (!phy_np)
return NULL;
- d = bus_find_device(&mdio_bus_type, NULL, phy_np, match);
+ d = bus_find_device(&mdio_bus_type, NULL, phy_np, of_phy_match);
return d ? to_phy_device(d) : NULL;
}
EXPORT_SYMBOL(of_phy_find_device);
--
1.6.0.4
^ permalink raw reply related
* Re: [PATCH 2/6] 8xx: get rid of _PAGE_HWWRITE dependency in MMU.
From: Joakim Tjernlund @ 2009-10-08 6:45 UTC (permalink / raw)
To: Benjamin Herrenschmidt; +Cc: Scott Wood, linuxppc-dev@ozlabs.org, Rex Feany
In-Reply-To: <1254961699.2417.1.camel@pasglop>
Benjamin Herrenschmidt <benh@kernel.crashing.org> wrote on 08/10/2009 02:28:19:
>
> On Thu, 2009-10-08 at 02:19 +0200, Joakim Tjernlund wrote:
> > Benjamin Herrenschmidt <benh@kernel.crashing.org> wrote on 08/10/2009 02:04:56:
> > >
> > >
> > > > Yes it does. If one adds HWEXEC it will fail, right?
> > >
> > > Why ? We can just filter out DSISR, we don't really care why it failed
> > > as long as we know whether it was a store or not.
> > >
> > > > Also this count as a read and you could easily end up
> > > > in the protection case(in 2.4 you do)
> > >
> > > I'm not sure what you mean by "the protection case" Again, the C code
> > > shouldn't care.
> >
> > it does, and it should. How else should you know if you try
> > to read a NA space?
>
> Generic code should sort it out in handle_mm_fault() (or earlier if it
> can't find a VMA at all).
How can it? You need to know more that just read and write.
>
> The DSISR munging is really not necessary I believe.
Well, it is today and I don't see how you can remove it.
>
> > 2.4 and 2.6 have the same handling in asm.
>
> Yeah but the C code, especially the generic part, is different.
yes, but it seem to work the same.
>
> > hmm, maybe I should just call C, but 8xx isn't a speed monster so every
> > cycle counts :)
>
> But that's a slow path anyways.
How so? You take a TLB Error for the first write to
every page.
Jocke
^ permalink raw reply
* [PATCH v4] mpc5200: support for the MAN mpc5200 based board mucmc52
From: Heiko Schocher @ 2009-10-08 5:54 UTC (permalink / raw)
To: Grant Likely; +Cc: linuxppc-dev
In-Reply-To: <fa686aa40910070657o2b68156dq25cb44d6d6509abc@mail.gmail.com>
- serial Console on PSC1
- 64MB SDRAM
- MTD CFI Flash
- Ethernet FEC
- IDE support
Signed-off-by: Heiko Schocher <hs@denx.de>
Reviewed-by: Wolfram Sang <w.sang@pengutronix.de>
---
- based on:
git://git.kernel.org/pub/scm/linux/kernel/git/benh/powerpc.git next
- checked with:
$ ./scripts/checkpatch.pl 0002-mpc5200-support-for-the-MAN-mpc5200-based-board-muc.patch
total: 0 errors, 0 warnings, 360 lines checked
0002-mpc5200-support-for-the-MAN-mpc5200-based-board-muc.patch has no obvious style problems and is ready for submission.
$
changes since v1:
- add comments from Grant Likely <grant.likely@secretlab.ca>
use mpc5200_defconfig as default configuration, therefore added
SIMPLE_GPIO support in it, because this is not selectable as a
module.
- add comments from Wolfram Sang <w.sang@pengutronix.de>
- rebase against current next
changes since v2:
- add comment from Wolfram Sang
remove unofficial binding
changes since v3:
- add comment from Wolfram Sang
use "fsl,mpc5200b-immr" only
added Reviewed-by: Wolfram Sang <w.sang@pengutronix.de>
arch/powerpc/boot/dts/mucmc52.dts | 345 ++++++++++++++++++++++++++
arch/powerpc/configs/mpc5200_defconfig | 2 +-
arch/powerpc/platforms/52xx/mpc5200_simple.c | 1 +
3 files changed, 347 insertions(+), 1 deletions(-)
create mode 100644 arch/powerpc/boot/dts/mucmc52.dts
diff --git a/arch/powerpc/boot/dts/mucmc52.dts b/arch/powerpc/boot/dts/mucmc52.dts
new file mode 100644
index 0000000..7b29d76
--- /dev/null
+++ b/arch/powerpc/boot/dts/mucmc52.dts
@@ -0,0 +1,345 @@
+/*
+ * mucmc52 board Device Tree Source
+ *
+ * Copyright (C) 2009 DENX Software Engineering GmbH
+ * Heiko Schocher <hs@denx.de>
+ *
+ * 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.
+ */
+
+/dts-v1/;
+
+/ {
+ model = "manroland,mucmc52";
+ compatible = "manroland,mucmc52";
+ #address-cells = <1>;
+ #size-cells = <1>;
+ interrupt-parent = <&mpc5200_pic>;
+
+ cpus {
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ PowerPC,5200@0 {
+ device_type = "cpu";
+ reg = <0>;
+ d-cache-line-size = <32>;
+ i-cache-line-size = <32>;
+ d-cache-size = <0x4000>; // L1, 16K
+ i-cache-size = <0x4000>; // L1, 16K
+ timebase-frequency = <0>; // from bootloader
+ bus-frequency = <0>; // from bootloader
+ clock-frequency = <0>; // from bootloader
+ };
+ };
+
+ memory {
+ device_type = "memory";
+ reg = <0x00000000 0x04000000>; // 64MB
+ };
+
+ soc5200@f0000000 {
+ #address-cells = <1>;
+ #size-cells = <1>;
+ compatible = "fsl,mpc5200b-immr";
+ ranges = <0 0xf0000000 0x0000c000>;
+ reg = <0xf0000000 0x00000100>;
+ bus-frequency = <0>; // from bootloader
+ system-frequency = <0>; // from bootloader
+
+ cdm@200 {
+ compatible = "fsl,mpc5200b-cdm","fsl,mpc5200-cdm";
+ reg = <0x200 0x38>;
+ };
+
+ mpc5200_pic: interrupt-controller@500 {
+ // 5200 interrupts are encoded into two levels;
+ interrupt-controller;
+ #interrupt-cells = <3>;
+ compatible = "fsl,mpc5200b-pic","fsl,mpc5200-pic";
+ reg = <0x500 0x80>;
+ interrupts = <0 0 3>;
+ };
+
+ gpt0: timer@600 { // GPT 0 in GPIO mode
+ compatible = "fsl,mpc5200b-gpt-gpio",
+ "fsl,mpc5200-gpt-gpio";
+ #gpio-cells = <2>;
+ reg = <0x600 0x10>;
+ interrupts = <1 9 0>;
+ gpio-controller;
+ };
+
+ gpt1: timer@610 { // GPT 1 in GPIO mode
+ compatible = "fsl,mpc5200b-gpt-gpio",
+ "fsl,mpc5200-gpt-gpio";
+ #gpio-cells = <2>;
+ reg = <0x610 0x10>;
+ interrupts = <1 10 0>;
+ gpio-controller;
+ };
+
+ gpt2: timer@620 { // GPT 2 in GPIO mode
+ compatible = "fsl,mpc5200b-gpt-gpio",
+ "fsl,mpc5200-gpt-gpio";
+ #gpio-cells = <2>;
+ reg = <0x620 0x10>;
+ interrupts = <1 11 0>;
+ gpio-controller;
+ };
+
+ gpt3: timer@630 { // GPT 3 in GPIO mode
+ compatible = "fsl,mpc5200b-gpt-gpio",
+ "fsl,mpc5200-gpt-gpio";
+ #gpio-cells = <2>;
+ reg = <0x630 0x10>;
+ interrupts = <1 12 0>;
+ gpio-controller;
+ };
+
+ gpio_simple: gpio@b00 {
+ compatible = "fsl,mpc5200b-gpio","fsl,mpc5200-gpio";
+ #gpio-cells = <2>;
+ reg = <0xb00 0x40>;
+ interrupts = <1 7 0>;
+ gpio-controller;
+ };
+
+ gpio_wkup: gpio@c00 {
+ compatible = "fsl,mpc5200b-gpio-wkup",
+ "fsl,mpc5200-gpio-wkup";
+ #gpio-cells = <2>;
+ reg = <0xc00 0x40>;
+ interrupts = <1 8 0 0 3 0>;
+ gpio-controller;
+ };
+
+ dma-controller@1200 {
+ device_type = "dma-controller";
+ compatible = "fsl,mpc5200b-bestcomm",
+ "fsl,mpc5200-bestcomm";
+ reg = <0x1200 0x80>;
+ interrupts = <3 0 0 3 1 0 3 2 0 3 3 0
+ 3 4 0 3 5 0 3 6 0 3 7 0
+ 3 8 0 3 9 0 3 10 0 3 11 0
+ 3 12 0 3 13 0 3 14 0 3 15 0>;
+ };
+
+ xlb@1f00 {
+ compatible = "fsl,mpc5200b-xlb","fsl,mpc5200-xlb";
+ reg = <0x1f00 0x100>;
+ };
+
+ serial@2000 { // PSC1
+ compatible = "fsl,mpc5200b-psc-uart",
+ "fsl,mpc5200-psc-uart";
+ reg = <0x2000 0x100>;
+ interrupts = <2 1 0>;
+ };
+
+ serial@2200 { // PSC2
+ compatible = "fsl,mpc5200b-psc-uart",
+ "fsl,mpc5200-psc-uart";
+ reg = <0x2200 0x100>;
+ interrupts = <2 2 0>;
+ };
+
+ serial@2c00 { // PSC6
+ compatible = "fsl,mpc5200b-psc-uart",
+ "fsl,mpc5200-psc-uart";
+ reg = <0x2c00 0x100>;
+ interrupts = <2 6 0>;
+ };
+
+ ethernet@3000 {
+ compatible = "fsl,mpc5200b-fec","fsl,mpc5200-fec";
+ reg = <0x3000 0x400>;
+ local-mac-address = [ 00 00 00 00 00 00 ];
+ interrupts = <2 5 0>;
+ phy-handle = <&phy0>;
+ };
+
+ mdio@3000 {
+ #address-cells = <1>;
+ #size-cells = <0>;
+ compatible = "fsl,mpc5200b-mdio","fsl,mpc5200-mdio";
+ reg = <0x3000 0x400>; // fec range, since we need to
+ // setup fec interrupts
+ interrupts = <2 5 0>; // these are for "mii command
+ // finished", not link changes
+ // & co.
+
+ phy0: ethernet-phy@0 {
+ compatible = "intel,lxt971";
+ reg = <0>;
+ };
+ };
+
+ ata@3a00 {
+ compatible = "fsl,mpc5200b-ata","fsl,mpc5200-ata";
+ reg = <0x3a00 0x100>;
+ interrupts = <2 7 0>;
+ };
+
+ i2c@3d40 {
+ #address-cells = <1>;
+ #size-cells = <0>;
+ compatible = "fsl,mpc5200b-i2c","fsl,mpc5200-i2c",
+ "fsl-i2c";
+ reg = <0x3d40 0x40>;
+ interrupts = <2 16 0>;
+
+ hwmon@2c {
+ compatible = "ad,adm9240";
+ reg = <0x2c>;
+ };
+ rtc@51 {
+ compatible = "nxp,pcf8563";
+ reg = <0x51>;
+ };
+ };
+
+ sram@8000 {
+ compatible = "fsl,mpc5200b-sram","fsl,mpc5200-sram";
+ reg = <0x8000 0x4000>;
+ };
+ };
+
+ localbus {
+ compatible = "fsl,mpc5200b-lpb","simple-bus";
+ #address-cells = <2>;
+ #size-cells = <1>;
+ ranges = <0 0 0xff800000 0x00800000
+ 1 0 0x80000000 0x00800000
+ 3 0 0x80000000 0x00800000>;
+
+ flash@0,0 {
+ compatible = "cfi-flash";
+ reg = <0 0 0x00800000>;
+ bank-width = <4>;
+ device-width = <2>;
+ #size-cells = <1>;
+ #address-cells = <1>;
+ partition@0 {
+ label = "DTS";
+ reg = <0x0 0x00100000>;
+ };
+ partition@100000 {
+ label = "Kernel";
+ reg = <0x100000 0x00200000>;
+ };
+ partition@300000 {
+ label = "RootFS";
+ reg = <0x00300000 0x00200000>;
+ };
+ partition@500000 {
+ label = "user";
+ reg = <0x00500000 0x00200000>;
+ };
+ partition@700000 {
+ label = "U-Boot";
+ reg = <0x00700000 0x00040000>;
+ };
+ partition@740000 {
+ label = "Env";
+ reg = <0x00740000 0x00020000>;
+ };
+ partition@760000 {
+ label = "red. Env";
+ reg = <0x00760000 0x00020000>;
+ };
+ partition@780000 {
+ label = "reserve";
+ reg = <0x00780000 0x00080000>;
+ };
+ };
+
+ simple100: gpio-controller-100@3,600100 {
+ #gpio-cells = <2>;
+ compatible = "manroland,mucmc52-aux-gpio";
+ reg = <3 0x00600100 0x1>;
+ gpio-controller;
+ };
+ simple104: gpio-controller-104@3,600104 {
+ #gpio-cells = <2>;
+ compatible = "manroland,mucmc52-aux-gpio";
+ reg = <3 0x00600104 0x1>;
+ gpio-controller;
+ };
+ simple200: gpio-controller-200@3,600200 {
+ #gpio-cells = <2>;
+ compatible = "manroland,mucmc52-aux-gpio";
+ reg = <3 0x00600200 0x1>;
+ gpio-controller;
+ };
+ simple201: gpio-controller-201@3,600201 {
+ #gpio-cells = <2>;
+ compatible = "manroland,mucmc52-aux-gpio";
+ reg = <3 0x00600201 0x1>;
+ gpio-controller;
+ };
+ simple202: gpio-controller-202@3,600202 {
+ #gpio-cells = <2>;
+ compatible = "manroland,mucmc52-aux-gpio";
+ reg = <3 0x00600202 0x1>;
+ gpio-controller;
+ };
+ simple203: gpio-controller-203@3,600203 {
+ #gpio-cells = <2>;
+ compatible = "manroland,mucmc52-aux-gpio";
+ reg = <3 0x00600203 0x1>;
+ gpio-controller;
+ };
+ simple204: gpio-controller-204@3,600204 {
+ #gpio-cells = <2>;
+ compatible = "manroland,mucmc52-aux-gpio";
+ reg = <3 0x00600204 0x1>;
+ gpio-controller;
+ };
+ simple206: gpio-controller-206@3,600206 {
+ #gpio-cells = <2>;
+ compatible = "manroland,mucmc52-aux-gpio";
+ reg = <3 0x00600206 0x1>;
+ gpio-controller;
+ };
+ simple207: gpio-controller-207@3,600207 {
+ #gpio-cells = <2>;
+ compatible = "manroland,mucmc52-aux-gpio";
+ reg = <3 0x00600207 0x1>;
+ gpio-controller;
+ };
+ simple20f: gpio-controller-20f@3,60020f {
+ #gpio-cells = <2>;
+ compatible = "manroland,mucmc52-aux-gpio";
+ reg = <3 0x0060020f 0x1>;
+ gpio-controller;
+ };
+
+ };
+
+ pci@f0000d00 {
+ #interrupt-cells = <1>;
+ #size-cells = <2>;
+ #address-cells = <3>;
+ device_type = "pci";
+ compatible = "fsl,mpc5200-pci";
+ reg = <0xf0000d00 0x100>;
+ interrupt-map-mask = <0xf800 0 0 7>;
+ interrupt-map = <
+ /* IDSEL 0x10 */
+ 0x8000 0 0 1 &mpc5200_pic 0 3 3
+ 0x8000 0 0 2 &mpc5200_pic 0 3 3
+ 0x8000 0 0 3 &mpc5200_pic 0 2 3
+ 0x8000 0 0 4 &mpc5200_pic 0 1 3
+ >;
+ clock-frequency = <0>; // From boot loader
+ interrupts = <2 8 0 2 9 0 2 10 0>;
+ bus-range = <0 0>;
+ ranges = <0x42000000 0 0x60000000 0x60000000 0 0x10000000
+ 0x02000000 0 0x90000000 0x90000000 0 0x10000000
+ 0x01000000 0 0x00000000 0xa0000000 0 0x01000000>;
+ };
+};
diff --git a/arch/powerpc/configs/mpc5200_defconfig b/arch/powerpc/configs/mpc5200_defconfig
index aaa4416..d035421 100644
--- a/arch/powerpc/configs/mpc5200_defconfig
+++ b/arch/powerpc/configs/mpc5200_defconfig
@@ -205,7 +205,7 @@ CONFIG_RTAS_PROC=y
CONFIG_PPC_BESTCOMM=y
CONFIG_PPC_BESTCOMM_ATA=y
CONFIG_PPC_BESTCOMM_FEC=y
-# CONFIG_SIMPLE_GPIO is not set
+CONFIG_SIMPLE_GPIO=y
#
# Kernel options
diff --git a/arch/powerpc/platforms/52xx/mpc5200_simple.c b/arch/powerpc/platforms/52xx/mpc5200_simple.c
index caf6d92..d45be5b 100644
--- a/arch/powerpc/platforms/52xx/mpc5200_simple.c
+++ b/arch/powerpc/platforms/52xx/mpc5200_simple.c
@@ -51,6 +51,7 @@ static void __init mpc5200_simple_setup_arch(void)
/* list of the supported boards */
static char *board[] __initdata = {
"intercontrol,digsy-mtc",
+ "manroland,mucmc52",
"manroland,uc101",
"phytec,pcm030",
"phytec,pcm032",
--
1.6.0.6
--
DENX Software Engineering GmbH, MD: Wolfgang Denk & Detlev Zundel
HRB 165235 Munich, Office: Kirchenstr.5, D-82194 Groebenzell, Germany
^ permalink raw reply related
* [PATCH v4] mpc5200: support for the MAN mpc5200 based board uc101
From: Heiko Schocher @ 2009-10-08 5:54 UTC (permalink / raw)
To: Grant Likely; +Cc: linuxppc-dev
In-Reply-To: <fa686aa40910070657o2b68156dq25cb44d6d6509abc@mail.gmail.com>
- serial Console on PSC1
- 64MB SDRAM
- MTD CFI Flash
- Ethernet FEC
- I2C with PCF8563 and Temp. Sensor ADM9240
- IDE support
Signed-off-by: Heiko Schocher <hs@denx.de>
Reviewed-by: Wolfram Sang <w.sang@pengutronix.de>
---
- based on:
git://git.kernel.org/pub/scm/linux/kernel/git/benh/powerpc.git next
- checked with:
$ ./scripts/checkpatch.pl 0001-mpc5200-support-for-the-MAN-mpc5200-based-board-uc1.patch
total: 0 errors, 0 warnings, 316 lines checked
0001-mpc5200-support-for-the-MAN-mpc5200-based-board-uc1.patch has no obvious style problems and is ready for submission.
$
changes since v1:
- add comments from Grant Likely <grant.likely@secretlab.ca>
use mpc5200_defconfig as default configuration
- add comments from Wolfram Sang <w.sang@pengutronix.de>
- rebase against current next
changes since v2:
- add comment from Wolfram Sang
remove unofficial binding
changes since v3:
- add comment from Wolfram Sang
use "fsl,mpc5200b-immr" only
added Reviewed-by: Wolfram Sang <w.sang@pengutronix.de>
arch/powerpc/boot/dts/uc101.dts | 309 ++++++++++++++++++++++++++
arch/powerpc/platforms/52xx/mpc5200_simple.c | 1 +
2 files changed, 310 insertions(+), 0 deletions(-)
create mode 100644 arch/powerpc/boot/dts/uc101.dts
diff --git a/arch/powerpc/boot/dts/uc101.dts b/arch/powerpc/boot/dts/uc101.dts
new file mode 100644
index 0000000..e928d22
--- /dev/null
+++ b/arch/powerpc/boot/dts/uc101.dts
@@ -0,0 +1,309 @@
+/*
+ * uc101 board Device Tree Source
+ *
+ * Copyright (C) 2009 DENX Software Engineering GmbH
+ * Heiko Schocher <hs@denx.de>
+ *
+ * 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.
+ */
+
+/dts-v1/;
+
+/ {
+ model = "manroland,uc101";
+ compatible = "manroland,uc101";
+ #address-cells = <1>;
+ #size-cells = <1>;
+ interrupt-parent = <&mpc5200_pic>;
+
+ cpus {
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ PowerPC,5200@0 {
+ device_type = "cpu";
+ reg = <0>;
+ d-cache-line-size = <32>;
+ i-cache-line-size = <32>;
+ d-cache-size = <0x4000>; // L1, 16K
+ i-cache-size = <0x4000>; // L1, 16K
+ timebase-frequency = <0>; // from bootloader
+ bus-frequency = <0>; // from bootloader
+ clock-frequency = <0>; // from bootloader
+ };
+ };
+
+ memory {
+ device_type = "memory";
+ reg = <0x00000000 0x04000000>; // 64MB
+ };
+
+ soc5200@f0000000 {
+ #address-cells = <1>;
+ #size-cells = <1>;
+ compatible = "fsl,mpc5200b-immr";
+ ranges = <0 0xf0000000 0x0000c000>;
+ reg = <0xf0000000 0x00000100>;
+ bus-frequency = <0>; // from bootloader
+ system-frequency = <0>; // from bootloader
+
+ cdm@200 {
+ compatible = "fsl,mpc5200b-cdm","fsl,mpc5200-cdm";
+ reg = <0x200 0x38>;
+ };
+
+ mpc5200_pic: interrupt-controller@500 {
+ // 5200 interrupts are encoded into two levels;
+ interrupt-controller;
+ #interrupt-cells = <3>;
+ compatible = "fsl,mpc5200b-pic","fsl,mpc5200-pic";
+ reg = <0x500 0x80>;
+ interrupts = <0 0 3>;
+ };
+
+ gpt0: timer@600 { // GPT 0 in GPIO mode
+ compatible = "fsl,mpc5200b-gpt-gpio",
+ "fsl,mpc5200-gpt-gpio";
+ #gpio-cells = <2>;
+ reg = <0x600 0x10>;
+ interrupts = <1 9 0>;
+ gpio-controller;
+ };
+
+ gpt1: timer@610 { // GPT 1 in GPIO mode
+ compatible = "fsl,mpc5200b-gpt-gpio",
+ "fsl,mpc5200-gpt-gpio";
+ #gpio-cells = <2>;
+ reg = <0x610 0x10>;
+ interrupts = <1 10 0>;
+ gpio-controller;
+ };
+
+ gpt2: timer@620 { // GPT 2 in GPIO mode
+ compatible = "fsl,mpc5200b-gpt-gpio",
+ "fsl,mpc5200-gpt-gpio";
+ #gpio-cells = <2>;
+ reg = <0x620 0x10>;
+ interrupts = <1 11 0>;
+ gpio-controller;
+ };
+
+ gpt3: timer@630 { // GPT 3 in GPIO mode
+ compatible = "fsl,mpc5200b-gpt-gpio",
+ "fsl,mpc5200-gpt-gpio";
+ #gpio-cells = <2>;
+ reg = <0x630 0x10>;
+ interrupts = <1 12 0>;
+ gpio-controller;
+ };
+
+ gpt4: timer@640 { // GPT 4 in GPIO mode
+ compatible = "fsl,mpc5200b-gpt-gpio",
+ "fsl,mpc5200-gpt-gpio";
+ #gpio-cells = <2>;
+ reg = <0x640 0x10>;
+ interrupts = <1 13 0>;
+ gpio-controller;
+ };
+
+ gpt5: timer@650 { // GPT 5 in GPIO mode
+ compatible = "fsl,mpc5200b-gpt-gpio",
+ "fsl,mpc5200-gpt-gpio";
+ #gpio-cells = <2>;
+ reg = <0x650 0x10>;
+ interrupts = <1 14 0>;
+ gpio-controller;
+ };
+
+ gpt6: timer@660 { // GPT 6 in GPIO mode
+ compatible = "fsl,mpc5200b-gpt-gpio",
+ "fsl,mpc5200-gpt-gpio";
+ #gpio-cells = <2>;
+ reg = <0x660 0x10>;
+ interrupts = <1 15 0>;
+ gpio-controller;
+ };
+
+ gpt7: timer@670 { // GPT 7 in GPIO mode
+ compatible = "fsl,mpc5200b-gpt-gpio",
+ "fsl,mpc5200-gpt-gpio";
+ #gpio-cells = <2>;
+ reg = <0x670 0x10>;
+ interrupts = <1 16 0>;
+ gpio-controller;
+ };
+
+ gpio_simple: gpio@b00 {
+ compatible = "fsl,mpc5200b-gpio","fsl,mpc5200-gpio";
+ reg = <0xb00 0x40>;
+ interrupts = <1 7 0>;
+ gpio-controller;
+ #gpio-cells = <2>;
+ };
+
+ gpio_wkup: gpio@c00 {
+ compatible = "fsl,mpc5200b-gpio-wkup",
+ "fsl,mpc5200-gpio-wkup";
+ reg = <0xc00 0x40>;
+ interrupts = <1 8 0 0 3 0>;
+ gpio-controller;
+ #gpio-cells = <2>;
+ };
+
+ gpio_sint: gpio_sint@b00 {
+ compatible = "fsl,mpc5200b-gpio-sint",
+ "fsl,mpc5200-gpio-sint";
+ reg = <0xb00 0x40>;
+ interrupts = <1 8 0 0 3 0>;
+ gpio-controller;
+ #gpio-cells = <2>;
+ };
+
+ dma-controller@1200 {
+ device_type = "dma-controller";
+ compatible = "fsl,mpc5200b-bestcomm",
+ "fsl,mpc5200-bestcomm";
+ reg = <0x1200 0x80>;
+ interrupts = <3 0 0 3 1 0 3 2 0 3 3 0
+ 3 4 0 3 5 0 3 6 0 3 7 0
+ 3 8 0 3 9 0 3 10 0 3 11 0
+ 3 12 0 3 13 0 3 14 0 3 15 0>;
+ };
+
+ xlb@1f00 {
+ compatible = "fsl,mpc5200b-xlb","fsl,mpc5200-xlb";
+ reg = <0x1f00 0x100>;
+ };
+
+ serial@2000 { // PSC1
+ compatible = "fsl,mpc5200b-psc-uart",
+ "fsl,mpc5200-psc-uart";
+ reg = <0x2000 0x100>;
+ interrupts = <2 1 0>;
+ };
+
+ serial@2200 { // PSC2
+ compatible = "fsl,mpc5200b-psc-uart",
+ "fsl,mpc5200-psc-uart";
+ reg = <0x2200 0x100>;
+ interrupts = <2 2 0>;
+ };
+
+ serial@2c00 { // PSC6
+ compatible = "fsl,mpc5200b-psc-uart",
+ "fsl,mpc5200-psc-uart";
+ reg = <0x2c00 0x100>;
+ interrupts = <2 6 0>;
+ };
+
+ ethernet@3000 {
+ compatible = "fsl,mpc5200b-fec","fsl,mpc5200-fec";
+ reg = <0x3000 0x400>;
+ local-mac-address = [ 00 00 00 00 00 00 ];
+ interrupts = <2 5 0>;
+ phy-handle = <&phy0>;
+ };
+
+ mdio@3000 {
+ #address-cells = <1>;
+ #size-cells = <0>;
+ compatible = "fsl,mpc5200b-mdio","fsl,mpc5200-mdio";
+ reg = <0x3000 0x400>; // fec range, since we need to
+ // setup fec interrupts
+ interrupts = <2 5 0>; // these are for "mii command
+ // finished", not link
+ // changes & co.
+
+ phy0: ethernet-phy@0 {
+ compatible = "intel,lxt971";
+ reg = <0>;
+ };
+ };
+
+ ata@3a00 {
+ compatible = "fsl,mpc5200b-ata","fsl,mpc5200-ata";
+ reg = <0x3a00 0x100>;
+ interrupts = <2 7 0>;
+ };
+
+ i2c@3d40 {
+ #address-cells = <1>;
+ #size-cells = <0>;
+ compatible = "fsl,mpc5200b-i2c","fsl,mpc5200-i2c",
+ "fsl-i2c";
+ reg = <0x3d40 0x40>;
+ interrupts = <2 16 0>;
+ fsl,preserve-clocking;
+ clock-frequency = <400000>;
+
+ hwmon@2c {
+ compatible = "ad,adm9240";
+ reg = <0x2c>;
+ };
+ rtc@51 {
+ compatible = "nxp,pcf8563";
+ reg = <0x51>;
+ };
+ };
+
+ sram@8000 {
+ compatible = "fsl,mpc5200b-sram","fsl,mpc5200-sram";
+ reg = <0x8000 0x4000>;
+ };
+ };
+
+ localbus {
+ compatible = "fsl,mpc5200b-lpb","simple-bus";
+ #address-cells = <2>;
+ #size-cells = <1>;
+ ranges = <0 0 0xff800000 0x00800000
+ 1 0 0x80000000 0x00800000
+ 3 0 0x80000000 0x00800000>;
+
+ flash@0,0 {
+ compatible = "cfi-flash";
+ reg = <0 0 0x00800000>;
+ bank-width = <2>;
+ device-width = <2>;
+ #size-cells = <1>;
+ #address-cells = <1>;
+ partition@0 {
+ label = "DTS";
+ reg = <0x0 0x00100000>;
+ };
+ partition@100000 {
+ label = "Kernel";
+ reg = <0x100000 0x00200000>;
+ };
+ partition@300000 {
+ label = "RootFS";
+ reg = <0x00300000 0x00200000>;
+ };
+
+ partition@500000 {
+ label = "user";
+ reg = <0x00500000 0x00200000>;
+ };
+ partition@700000 {
+ label = "U-Boot";
+ reg = <0x00700000 0x00040000>;
+ };
+ partition@740000 {
+ label = "Env";
+ reg = <0x00740000 0x00010000>;
+ };
+ partition@750000 {
+ label = "red. Env";
+ reg = <0x00750000 0x00010000>;
+ };
+ partition@760000 {
+ label = "reserve";
+ reg = <0x00760000 0x000a0000>;
+ };
+ };
+
+ };
+};
diff --git a/arch/powerpc/platforms/52xx/mpc5200_simple.c b/arch/powerpc/platforms/52xx/mpc5200_simple.c
index c31e5b5..caf6d92 100644
--- a/arch/powerpc/platforms/52xx/mpc5200_simple.c
+++ b/arch/powerpc/platforms/52xx/mpc5200_simple.c
@@ -51,6 +51,7 @@ static void __init mpc5200_simple_setup_arch(void)
/* list of the supported boards */
static char *board[] __initdata = {
"intercontrol,digsy-mtc",
+ "manroland,uc101",
"phytec,pcm030",
"phytec,pcm032",
"promess,motionpro",
--
1.6.0.6
--
DENX Software Engineering GmbH, MD: Wolfgang Denk & Detlev Zundel
HRB 165235 Munich, Office: Kirchenstr.5, D-82194 Groebenzell, Germany
^ permalink raw reply related
* Re: [PATCH v3] mpc5200: support for the MAN mpc5200 based board mucmc52
From: Heiko Schocher @ 2009-10-08 5:49 UTC (permalink / raw)
To: Wolfram Sang; +Cc: linuxppc-dev
In-Reply-To: <20091007094936.GE3177@pengutronix.de>
Hello Wolfram,
Wolfram Sang wrote:
> On Wed, Oct 07, 2009 at 08:40:37AM +0200, Heiko Schocher wrote:
>> - serial Console on PSC1
>> - 64MB SDRAM
>> - MTD CFI Flash
>> - Ethernet FEC
>> - IDE support
>>
>> Signed-off-by: Heiko Schocher <hs@denx.de>
>
> Sorry for finding things incrementally, but I think there is still one issue
> left. Once this is sorted out, you could add my:
No problem, thanks for finding it!
> Reviewed-by: Wolfram Sang <w.sang@pengutronix.de>
OK, added, send patches soon.
thanks
bye
Heiko
--
DENX Software Engineering GmbH, MD: Wolfgang Denk & Detlev Zundel
HRB 165235 Munich, Office: Kirchenstr.5, D-82194 Groebenzell, Germany
^ permalink raw reply
* Re: [v7 PATCH 3/7]: x86: refactor x86 idle power management code and remove all instances of pm_idle.
From: Arun R Bharadwaj @ 2009-10-08 5:54 UTC (permalink / raw)
To: Peter Zijlstra
Cc: linux-arch, Gautham R Shenoy, Venkatesh Pallipadi, linux-kernel,
Paul Mackerras, Arun Bharadwaj, Ingo Molnar, linuxppc-dev
In-Reply-To: <1254926750.26976.253.camel@twins>
* Peter Zijlstra <a.p.zijlstra@chello.nl> [2009-10-07 16:45:50]:
> On Tue, 2009-10-06 at 21:01 +0530, Arun R Bharadwaj wrote:
> > +++ linux.trees.git/arch/x86/kernel/process.c
> > @@ -9,6 +9,7 @@
> > #include <linux/pm.h>
> > #include <linux/clockchips.h>
> > #include <linux/random.h>
> > +#include <linux/cpuidle.h>
> > #include <trace/events/power.h>
> > #include <asm/system.h>
> > #include <asm/apic.h>
> > @@ -244,12 +245,6 @@ int sys_vfork(struct pt_regs *regs)
> > unsigned long boot_option_idle_override = 0;
> > EXPORT_SYMBOL(boot_option_idle_override);
> >
> > -/*
> > - * Powermanagement idle function, if any..
> > - */
> > -void (*pm_idle)(void);
> > -EXPORT_SYMBOL(pm_idle);
> > -
> > #ifdef CONFIG_X86_32
> > /*
> > * This halt magic was a workaround for ancient floppy DMA
> > @@ -329,17 +324,15 @@ static void do_nothing(void *unused)
> > }
> >
> > /*
> > - * cpu_idle_wait - Used to ensure that all the CPUs discard old value of
> > - * pm_idle and update to new pm_idle value. Required while changing pm_idle
> > - * handler on SMP systems.
> > + * cpu_idle_wait - Required while changing idle routine handler on SMP systems.
> > *
> > - * Caller must have changed pm_idle to the new value before the call. Old
> > - * pm_idle value will not be used by any CPU after the return of this function.
> > + * Caller must have changed idle routine to the new value before the call. Old
> > + * value will not be used by any CPU after the return of this function.
> > */
> > void cpu_idle_wait(void)
> > {
> > smp_mb();
> > - /* kick all the CPUs so that they exit out of pm_idle */
> > + /* kick all the CPUs so that they exit out of idle loop */
> > smp_call_function(do_nothing, NULL, 1);
> > }
> > EXPORT_SYMBOL_GPL(cpu_idle_wait);
> > @@ -518,15 +511,59 @@ static void c1e_idle(void)
> > default_idle();
> > }
> >
> > +static void (*local_idle)(void);
> > +DEFINE_PER_CPU(struct cpuidle_device, idle_devices);
> > +
> > +struct cpuidle_driver cpuidle_default_driver = {
> > + .name = "cpuidle_default",
> > +};
> > +
> > +static int local_idle_loop(struct cpuidle_device *dev, struct cpuidle_state *st)
> > +{
> > + ktime_t t1, t2;
> > + s64 diff;
> > + int ret;
> > +
> > + t1 = ktime_get();
> > + local_idle();
> > + t2 = ktime_get();
> > +
> > + diff = ktime_to_us(ktime_sub(t2, t1));
> > + if (diff > INT_MAX)
> > + diff = INT_MAX;
> > + ret = (int) diff;
> > +
> > + return ret;
> > +}
> > +
> > +static int setup_cpuidle_simple(void)
> > +{
> > + struct cpuidle_device *dev;
> > + int cpu;
> > +
> > + if (!cpuidle_curr_driver)
> > + cpuidle_register_driver(&cpuidle_default_driver);
> > +
> > + for_each_online_cpu(cpu) {
> > + dev = &per_cpu(idle_devices, cpu);
> > + dev->cpu = cpu;
> > + dev->states[0].enter = local_idle_loop;
> > + dev->state_count = 1;
> > + cpuidle_register_device(dev);
> > + }
> > + return 0;
> > +}
> > +device_initcall(setup_cpuidle_simple);
> > +
> > void __cpuinit select_idle_routine(const struct cpuinfo_x86 *c)
> > {
> > #ifdef CONFIG_SMP
> > - if (pm_idle == poll_idle && smp_num_siblings > 1) {
> > + if (local_idle == poll_idle && smp_num_siblings > 1) {
> > printk(KERN_WARNING "WARNING: polling idle and HT enabled,"
> > " performance may degrade.\n");
> > }
> > #endif
> > - if (pm_idle)
> > + if (local_idle)
> > return;
> >
> > if (cpu_has(c, X86_FEATURE_MWAIT) && mwait_usable(c)) {
> > @@ -534,18 +571,20 @@ void __cpuinit select_idle_routine(const
> > * One CPU supports mwait => All CPUs supports mwait
> > */
> > printk(KERN_INFO "using mwait in idle threads.\n");
> > - pm_idle = mwait_idle;
> > + local_idle = mwait_idle;
> > } else if (check_c1e_idle(c)) {
> > printk(KERN_INFO "using C1E aware idle routine\n");
> > - pm_idle = c1e_idle;
> > + local_idle = c1e_idle;
> > } else
> > - pm_idle = default_idle;
> > + local_idle = default_idle;
> > +
> > + return;
> > }
> >
> > void __init init_c1e_mask(void)
> > {
> > /* If we're using c1e_idle, we need to allocate c1e_mask. */
> > - if (pm_idle == c1e_idle)
> > + if (local_idle == c1e_idle)
> > zalloc_cpumask_var(&c1e_mask, GFP_KERNEL);
> > }
> >
> > @@ -556,7 +595,7 @@ static int __init idle_setup(char *str)
> >
> > if (!strcmp(str, "poll")) {
> > printk("using polling idle threads.\n");
> > - pm_idle = poll_idle;
> > + local_idle = poll_idle;
> > } else if (!strcmp(str, "mwait"))
> > force_mwait = 1;
> > else if (!strcmp(str, "halt")) {
> > @@ -567,7 +606,7 @@ static int __init idle_setup(char *str)
> > * To continue to load the CPU idle driver, don't touch
> > * the boot_option_idle_override.
> > */
> > - pm_idle = default_idle;
> > + local_idle = default_idle;
> > idle_halt = 1;
> > return 0;
> > } else if (!strcmp(str, "nomwait")) {
>
>
> What guarantees that the cpuidle bits actually select this
> cpuidle_default driver when you do idle=poll?
>
> Also, cpuidle already has a poll loop in it, why duplicate that?
>
Yes, now i see it.. I'll get rid of the redundant poll_idle definition
^ permalink raw reply
* Re: [RFC PATCH 00/12] Merge common OpenFirmware device tree code
From: David Miller @ 2009-10-08 4:39 UTC (permalink / raw)
To: crn
Cc: sammy, sfr, microblaze-uclinux, devicetree-discuss, sparclinux,
julian.calaby, wmb, linuxppc-dev
In-Reply-To: <Pine.LNX.4.60.0910080155210.12519@mailgate.netunix.com>
From: Chris Newport <crn@netunix.com>
Date: Thu, 8 Oct 2009 02:29:25 +0100 (BST)
> Sun4d has never had SMP support and
Wrong.
> this is apparantly problematic due to Cray interlectual property
> causing a lack of bus documentation.
XBUS documentation is not available, but we fully know how to
program the SBUS interrupt controller and whatnot. It's all
there in the sun4d interrupt and SMP support and it did work
just fine at one point.
Amusingly the SBUS interrupt stuff on sun4d is a very close
sibling to the IMAP/ICLR scheme used on sun4u.
^ permalink raw reply
* Re: [RFC PATCH 00/12] Merge common OpenFirmware device tree code
From: Chris Newport @ 2009-10-08 1:29 UTC (permalink / raw)
To: David Miller
Cc: sammy, sfr, microblaze-uclinux, devicetree-discuss, sparclinux,
julian.calaby, wmb, linuxppc-dev
In-Reply-To: <20091007.140938.255120957.davem@davemloft.net>
On Wed, 7 Oct 2009, David Miller wrote:
>> Sun4c has also been broken for a long time and sun4d has never worked
>> properly. Is it time to also prune these ?.
>> That would leave only Sun4m in the 32bit kernel, which still works and
>> has plenty of ongoing user interest.
>
> Chris don't over-exaggerate the state.
>
> The truth is that the whole sparc32 port is in a state of mild
> disrepair, and many of the issues apply to all the port rather than
> just one family of systems. I think someone suitably motivated
> could get most of the bugs sorted out.
>
> There is no reason to drop support for SS1 machines, we already fully
> build the software device tree and use all of the generic OF
> infrastructure in the Linux kernel on those systems. It is not a road
> block at all for the OF genericization work, if that's what you read
> into wmb's email.
Your call, as you say there is little to be gained other than tidyness.
FWIW my opinions (and ICBW) are based on :-
Sun4c machines have a max of 48 or 64Mb and very few are still working
Sun4d has never had SMP support and this is apparantly problematic
due to Cray interlectual property causing a lack of bus documentation.
Running these heavy and power hungry lumps UP is a bit silly.
^ permalink raw reply
* Re: [PATCH 2/6] 8xx: get rid of _PAGE_HWWRITE dependency in MMU.
From: Benjamin Herrenschmidt @ 2009-10-08 0:28 UTC (permalink / raw)
To: Joakim Tjernlund; +Cc: Scott Wood, linuxppc-dev@ozlabs.org, Rex Feany
In-Reply-To: <OFE2E96EF3.F21AB563-ONC1257649.0000A4AC-C1257649.0001C04D@transmode.se>
On Thu, 2009-10-08 at 02:19 +0200, Joakim Tjernlund wrote:
> Benjamin Herrenschmidt <benh@kernel.crashing.org> wrote on 08/10/2009 02:04:56:
> >
> >
> > > Yes it does. If one adds HWEXEC it will fail, right?
> >
> > Why ? We can just filter out DSISR, we don't really care why it failed
> > as long as we know whether it was a store or not.
> >
> > > Also this count as a read and you could easily end up
> > > in the protection case(in 2.4 you do)
> >
> > I'm not sure what you mean by "the protection case" Again, the C code
> > shouldn't care.
>
> it does, and it should. How else should you know if you try
> to read a NA space?
Generic code should sort it out in handle_mm_fault() (or earlier if it
can't find a VMA at all).
The DSISR munging is really not necessary I believe.
> 2.4 and 2.6 have the same handling in asm.
Yeah but the C code, especially the generic part, is different.
> hmm, maybe I should just call C, but 8xx isn't a speed monster so every
> cycle counts :)
But that's a slow path anyways.
> It works if I trap to C for DIRTY too.
> Before thinking on porting my old board, I want 2.4 to enjoy
> the new TLB code too :)
Hehehe.
Cheers,
Ben.
^ permalink raw reply
* Re: [PATCH 2/6] 8xx: get rid of _PAGE_HWWRITE dependency in MMU.
From: Joakim Tjernlund @ 2009-10-08 0:19 UTC (permalink / raw)
To: Benjamin Herrenschmidt; +Cc: Scott Wood, linuxppc-dev@ozlabs.org, Rex Feany
In-Reply-To: <1254960296.2733.3.camel@pasglop>
Benjamin Herrenschmidt <benh@kernel.crashing.org> wrote on 08/10/2009 02:04:56:
>
>
> > Yes it does. If one adds HWEXEC it will fail, right?
>
> Why ? We can just filter out DSISR, we don't really care why it failed
> as long as we know whether it was a store or not.
>
> > Also this count as a read and you could easily end up
> > in the protection case(in 2.4 you do)
>
> I'm not sure what you mean by "the protection case" Again, the C code
> shouldn't care.
it does, and it should. How else should you know if you try
to read a NA space?
See:
/* Protection fault on exec go straight to failure on
* Hash based MMUs as they either don't support per-page
* execute permission, or if they do, it's handled already
* at the hash level. This test would probably have to
* be removed if we change the way this works to make hash
* processors use the same I/D cache coherency mechanism
* as embedded.
*/
if (error_code & DSISR_PROTFAULT)
goto bad_area;
...
/* a read */
} else {
/* protection fault */
if (error_code & 0x08000000)
goto bad_area;
>
> > hey, I think you have to show how then :) I am not
> > good at ppc shift, mask, rotate insn.
>
> They are so fun ! :-0
Great that someone thinks so :)
>
> > >
> > > > Because if you go to C with a protection fault, you are in trouble.
> > >
> > > Why ?
> >
> > In 2.4 you end up in read protection fault an get a SEGV back :)
>
> We probably should ignore the DSISR bits then. So it just goes to
> generic C code which then fixes up ACCESSED etc... and returns.
Not really I think.
>
> > Now I only handle DIRTY and the rest in C. Figured it is
> > much faster and really simplie now, stay tuned.
>
> You should not even have to handle DIRTY at all in asm. At least in 2.6.
> I can't vouch for what 2.4 generic code does... You should really port
> your board over :-)
2.4 and 2.6 have the same handling in asm.
hmm, maybe I should just call C, but 8xx isn't a speed monster so every
cycle counts :)
It works if I trap to C for DIRTY too.
Before thinking on porting my old board, I want 2.4 to enjoy
the new TLB code too :)
Jocke
^ permalink raw reply
* Re: [PATCH 2/6] 8xx: get rid of _PAGE_HWWRITE dependency in MMU.
From: Benjamin Herrenschmidt @ 2009-10-08 0:04 UTC (permalink / raw)
To: Joakim Tjernlund; +Cc: Scott Wood, linuxppc-dev@ozlabs.org, Rex Feany
In-Reply-To: <OFCA7943E6.AFEF924A-ONC1257648.007E27B0-C1257648.007F62E9@transmode.se>
> Yes it does. If one adds HWEXEC it will fail, right?
Why ? We can just filter out DSISR, we don't really care why it failed
as long as we know whether it was a store or not.
> Also this count as a read and you could easily end up
> in the protection case(in 2.4 you do)
I'm not sure what you mean by "the protection case" Again, the C code
shouldn't care.
> hey, I think you have to show how then :) I am not
> good at ppc shift, mask, rotate insn.
They are so fun ! :-0
> >
> > > Because if you go to C with a protection fault, you are in trouble.
> >
> > Why ?
>
> In 2.4 you end up in read protection fault an get a SEGV back :)
We probably should ignore the DSISR bits then. So it just goes to
generic C code which then fixes up ACCESSED etc... and returns.
> Now I only handle DIRTY and the rest in C. Figured it is
> much faster and really simplie now, stay tuned.
You should not even have to handle DIRTY at all in asm. At least in 2.6.
I can't vouch for what 2.4 generic code does... You should really port
your board over :-)
Cheers,
Ben.
^ permalink raw reply
* Re: [PATCH 2/6] 8xx: get rid of _PAGE_HWWRITE dependency in MMU.
From: Joakim Tjernlund @ 2009-10-07 23:34 UTC (permalink / raw)
Cc: Scott Wood, Rex Feany, linuxppc-dev@ozlabs.org
In-Reply-To: <OFCA7943E6.AFEF924A-ONC1257648.007E27B0-C1257648.007F62E9@LocalDomain>
Joakim Tjernlund/Transmode wrote on 08/10/2009 01:11:23:
>
> Benjamin Herrenschmidt <benh@kernel.crashing.org> wrote on 08/10/2009 00:20:17:
> >
> > On Thu, 2009-10-08 at 00:08 +0200, Joakim Tjernlund wrote:
> > >
> > > Benjamin Herrenschmidt <benh@kernel.crashing.org> wrote on 07/10/2009 23:14:52:
> > > >
> > > > On Wed, 2009-10-07 at 22:46 +0200, Joakim Tjernlund wrote:
> > > >
> > > > > + andi. r11, r10, _PAGE_USER | _PAGE_ACCESSED
> > > > > + cmpwi cr0, r11, _PAGE_USER | _PAGE_ACCESSED
> > > > > + bne- cr0, 2f
> > > >
> > > > Did you mean _PAGE_PRESENT | _PAGE_ACCESSED ?
>
> YES! cut and paste error, will send a new much improved patch
> with my new idea.
So here it is(on top for now), what do you think?
diff --git a/arch/powerpc/kernel/head_8xx.S b/arch/powerpc/kernel/head_8xx.S
index 8c4c416..fea9f5b 100644
--- a/arch/powerpc/kernel/head_8xx.S
+++ b/arch/powerpc/kernel/head_8xx.S
@@ -339,8 +339,8 @@ InstructionTLBMiss:
mfspr r11, SPRN_MD_TWC /* ....and get the pte address */
lwz r10, 0(r11) /* Get the pte */
- andi. r11, r10, _PAGE_USER | _PAGE_ACCESSED
- cmpwi cr0, r11, _PAGE_USER | _PAGE_ACCESSED
+ andi. r21, r20, _PAGE_ACCESSED | _PAGE_PRESENT
+ cmpwi cr0, r21, _PAGE_ACCESSED | _PAGE_PRESENT
bne- cr0, 2f
/* Dont' bother with PP lsb, bit 21 for now */
@@ -365,7 +365,10 @@ InstructionTLBMiss:
rfi
2:
mfspr r11, SRR1
- rlwinm r11, r11, 0, 5, 3 /* clear guarded */
+ /* clear all error bits as TLB Miss
+ * sets a few unconditionally
+ */
+ rlwinm r21, r21, 0, 0xffff
mtspr SRR1, r11
mfspr r10, SPRN_M_TW /* Restore registers */
@@ -422,8 +425,8 @@ DataStoreTLBMiss:
andi. r11, r10, _PAGE_ACCESSED
bne+ cr0, 5f /* branch if access allowed */
- rlwinm r10, r10, 0, 21, 19 /* Clear _PAGE_USER */
- ori r10, r10, _PAGE_RW /* Set RW bit for xor below to clear it */
+ /* Need to know if load/store -> force a TLB Error */
+ rlwinm r20, r20, 0, 0, 30 /* Clear _PAGE_PRESENT */
5: xori r10, r10, _PAGE_RW /* invert RW bit */
/* The Linux PTE won't go exactly into the MMU TLB.
@@ -482,8 +485,11 @@ DARFix: /* Return from dcbx instruction bug workaround, r10 holds value of DAR *
/* First, make sure this was a store operation.
*/
mfspr r11, SPRN_DSISR
- andis. r11, r11, 0x4000 /* no translation */
- bne 2f /* branch if set */
+ andis. r21, r21, 0x4800 /* !translation or protection */
+ bne 2f /* branch if either is set */
+ /* Only Change bit left now, do it here as it is faster
+ * than trapping to the C fault handler.
+ */
/* The EA of a data TLB miss is automatically stored in the MD_EPN
* register. The EA of a data TLB error is automatically stored in
@@ -533,16 +539,8 @@ DARFix: /* Return from dcbx instruction bug workaround, r10 holds value of DAR *
mfspr r11, SPRN_MD_TWC /* ....and get the pte address */
lwz r10, 0(r11) /* Get the pte */
- mfspr r11, DSISR
- andis. r11, r11, 0x0200 /* store */
- beq 5f
- andi. r11, r10, _PAGE_RW /* writeable? */
- beq 2f /* nope */
- ori r10, r10, _PAGE_DIRTY|_PAGE_HWWRITE
-5: ori r10, r10, _PAGE_ACCESSED
- mfspr r11, MD_TWC /* Get pte address again */
+ ori r10, r10, _PAGE_DIRTY | _PAGE_ACCESSED | _PAGE_HWWRITE
stw r10, 0(r11) /* and update pte in table */
-
xori r10, r10, _PAGE_RW /* RW bit is inverted */
/* The Linux PTE won't go exactly into the MMU TLB.
^ permalink raw reply related
* Re: [PATCH 2/6] 8xx: get rid of _PAGE_HWWRITE dependency in MMU.
From: Joakim Tjernlund @ 2009-10-07 23:11 UTC (permalink / raw)
To: Benjamin Herrenschmidt; +Cc: Scott Wood, linuxppc-dev@ozlabs.org, Rex Feany
In-Reply-To: <1254954017.2409.14.camel@pasglop>
Benjamin Herrenschmidt <benh@kernel.crashing.org> wrote on 08/10/2009 00:20:17:
>
> On Thu, 2009-10-08 at 00:08 +0200, Joakim Tjernlund wrote:
> >
> > Benjamin Herrenschmidt <benh@kernel.crashing.org> wrote on 07/10/2009 23:14:52:
> > >
> > > On Wed, 2009-10-07 at 22:46 +0200, Joakim Tjernlund wrote:
> > >
> > > > + andi. r11, r10, _PAGE_USER | _PAGE_ACCESSED
> > > > + cmpwi cr0, r11, _PAGE_USER | _PAGE_ACCESSED
> > > > + bne- cr0, 2f
> > >
> > > Did you mean _PAGE_PRESENT | _PAGE_ACCESSED ?
YES! cut and paste error, will send a new much improved patch
with my new idea.
> > >
> > > > +2:
> > > > + mfspr r11, SRR1
> > > > + rlwinm r11, r11, 0, 5, 3 /* clear guarded */
> > > > + mtspr SRR1, r11
> > >
> > > What is the above for ?
> >
> > TLB Miss will set that bit unconditionally and that is
> > the same bit as protection error in TLB error.
>
> And ? Big deal :-) IE. Once you get to InstructionAccess, it doesn't
> matter if that bit is set, does it ?
Yes it does. If one adds HWEXEC it will fail, right?
Also this count as a read and you could easily end up
in the protection case(in 2.4 you do)
>
> > Lets start simple, shall we? :)
> > Anyhow, I looked some more at that and I don't the best thing is
> > to use shifts. All bits are correct if you invert RW and add an exception
> > for extended coding.
>
> Right, as long as you avoid doing a conditional branch :-)
hey, I think you have to show how then :) I am not
good at ppc shift, mask, rotate insn.
>
> > Because if you go to C with a protection fault, you are in trouble.
>
> Why ?
In 2.4 you end up in read protection fault an get a SEGV back :)
>
> > So deal with it here. Now, I got another idea too that will make this go away
> > if it work out
>
> I don't understand your point about protection faults.
>
> You should be able to go straight to C with -anything-, that's what I do
> for all other platforms.
Well, you don't force a tlb error like I do, however my new version
handles this better.
Now I only handle DIRTY and the rest in C. Figured it is
much faster and really simplie now, stay tuned.
^ permalink raw reply
* Re: [PATCH 4/6] 8xx: Tag DAR with 0x00f0 to catch buggy instructions.
From: Joakim Tjernlund @ 2009-10-07 23:12 UTC (permalink / raw)
To: Benjamin Herrenschmidt; +Cc: Scott Wood, linuxppc-dev@ozlabs.org, Rex Feany
In-Reply-To: <1254954084.2409.16.camel@pasglop>
Benjamin Herrenschmidt <benh@kernel.crashing.org> wrote on 08/10/2009 00:21:24:
>
> On Thu, 2009-10-08 at 00:13 +0200, Joakim Tjernlund wrote:
> > Benjamin Herrenschmidt <benh@kernel.crashing.org> wrote on 07/10/2009 23:18:21:
> > >
> > > On Wed, 2009-10-07 at 22:46 +0200, Joakim Tjernlund wrote:
> > > > dcbz, dcbf, dcbi, dcbst and icbi do not set DAR when they
> > > > cause a DTLB Error. Dectect this by tagging DAR with 0x00f0
> > > > at every exception exit that modifies DAR.
> > > > Test for DAR=0x00f0 in DataTLBError and bail
> > > > to handle_page_fault().
> > >
> > > Why not -1 ? :-)
> >
> > Because 0x00f0 is already in use in the TLB fast path, saves one insn.
>
> But will cause weird things if the user really uses 0xf0 (though granted
> that's unlikely :-)
Yeah, you will most likely end up with a segv anyway.
^ permalink raw reply
* Re: [RFC PATCH 00/12] Merge common OpenFirmware device tree code
From: Brad Boyer @ 2009-10-07 22:57 UTC (permalink / raw)
To: Sam Creasey
Cc: Stephen Rothwell, Julian Calaby, devicetree-discuss,
microblaze-uclinux, sparclinux, linuxppc-dev, davem
In-Reply-To: <20091007135243.GC21646@anhedonia>
On Wed, Oct 07, 2009 at 09:52:43AM -0400, Sam Creasey wrote:
> On Wed, Oct 07, 2009 at 03:18:04PM +1000, Julian Calaby wrote:
> > On the subject of merging code, I know that the SUN3 code in m68k uses
> > a similar prom interface to the sparc32 code. (and I've also
> > considered unifying that and ... well ... see above) Does anyone know
> > if it has an OpenFirmware interface for it's devices? Is OF on SUN3
> > even remotely useful? Does Linux on SUN3 even work with modern
> > kernels?
>
> Sun3 doesn't have OF, though I've got some dormant patches to add an
> OF emulation layer to make it easier to reuse Sparc drivers on
> Sun3... Never finished enough to submit, so it probably shouldn't
> affect anything you're doing here.
I was also looking at using the OF code on m68k, but for a different
reason. My goal was to get macio_bus working so we can merge a few
of the m68k Mac drivers into the ppc Mac drivers. The simplest way
to do that seemed to be supporting OF since macio_dev is a wrapper
for of_device. It was also a nice way to build up a table of all the
onboard devices in memory. Hopefully it would enable better user-space
device detection as well.
I got the framework built against an older kernel, but it wasn't enough
to be useful at that point. This set of patches could help quite a bit.
Brad Boyer
flar@allandria.com
^ permalink raw reply
* Re: [PATCH 4/6] 8xx: Tag DAR with 0x00f0 to catch buggy instructions.
From: Benjamin Herrenschmidt @ 2009-10-07 22:21 UTC (permalink / raw)
To: Joakim Tjernlund; +Cc: Scott Wood, linuxppc-dev@ozlabs.org, Rex Feany
In-Reply-To: <OF36596A29.5EDD5659-ONC1257648.0079FC5B-C1257648.007A1D0B@transmode.se>
On Thu, 2009-10-08 at 00:13 +0200, Joakim Tjernlund wrote:
> Benjamin Herrenschmidt <benh@kernel.crashing.org> wrote on 07/10/2009 23:18:21:
> >
> > On Wed, 2009-10-07 at 22:46 +0200, Joakim Tjernlund wrote:
> > > dcbz, dcbf, dcbi, dcbst and icbi do not set DAR when they
> > > cause a DTLB Error. Dectect this by tagging DAR with 0x00f0
> > > at every exception exit that modifies DAR.
> > > Test for DAR=0x00f0 in DataTLBError and bail
> > > to handle_page_fault().
> >
> > Why not -1 ? :-)
>
> Because 0x00f0 is already in use in the TLB fast path, saves one insn.
But will cause weird things if the user really uses 0xf0 (though granted
that's unlikely :-)
Cheers,
Ben.
^ permalink raw reply
* Re: [PATCH 3/6] 8xx: invalidate non present TLBs
From: Benjamin Herrenschmidt @ 2009-10-07 22:20 UTC (permalink / raw)
To: Joakim Tjernlund; +Cc: Scott Wood, linuxppc-dev@ozlabs.org, Rex Feany
In-Reply-To: <OFB2B65282.B3B9914E-ONC1257648.0079A053-C1257648.0079F903@transmode.se>
On Thu, 2009-10-08 at 00:12 +0200, Joakim Tjernlund wrote:
> > not sure about the dsisr test here, what is the point ?
>
> To remove the need to do the same in generic pte code. Then
> we only need to do it when it counts. Lets see how it works out.
But I'm not sure I trust that DSISR test. Just do it unconditionally...
How much does it cost anyway ?
Ben.
^ permalink raw reply
* Re: [PATCH 2/6] 8xx: get rid of _PAGE_HWWRITE dependency in MMU.
From: Benjamin Herrenschmidt @ 2009-10-07 22:20 UTC (permalink / raw)
To: Joakim Tjernlund; +Cc: Scott Wood, linuxppc-dev@ozlabs.org, Rex Feany
In-Reply-To: <OF8D2D6F89.B0DB8BCB-ONC1257648.00787F6E-C1257648.00799B83@transmode.se>
On Thu, 2009-10-08 at 00:08 +0200, Joakim Tjernlund wrote:
>
> Benjamin Herrenschmidt <benh@kernel.crashing.org> wrote on 07/10/2009 23:14:52:
> >
> > On Wed, 2009-10-07 at 22:46 +0200, Joakim Tjernlund wrote:
> >
> > > + andi. r11, r10, _PAGE_USER | _PAGE_ACCESSED
> > > + cmpwi cr0, r11, _PAGE_USER | _PAGE_ACCESSED
> > > + bne- cr0, 2f
> >
> > Did you mean _PAGE_PRESENT | _PAGE_ACCESSED ?
> >
> > > +2:
> > > + mfspr r11, SRR1
> > > + rlwinm r11, r11, 0, 5, 3 /* clear guarded */
> > > + mtspr SRR1, r11
> >
> > What is the above for ?
>
> TLB Miss will set that bit unconditionally and that is
> the same bit as protection error in TLB error.
And ? Big deal :-) IE. Once you get to InstructionAccess, it doesn't
matter if that bit is set, does it ?
> Lets start simple, shall we? :)
> Anyhow, I looked some more at that and I don't the best thing is
> to use shifts. All bits are correct if you invert RW and add an exception
> for extended coding.
Right, as long as you avoid doing a conditional branch :-)
> Because if you go to C with a protection fault, you are in trouble.
Why ?
> So deal with it here. Now, I got another idea too that will make this go away
> if it work out
I don't understand your point about protection faults.
You should be able to go straight to C with -anything-, that's what I do
for all other platforms.
Ben.
^ 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