* [PATCH v2] [POWERPC] Add IRQSTACKS support on ppc32
From: Kumar Gala @ 2008-04-28 6:21 UTC (permalink / raw)
To: Paul Mackerras; +Cc: linuxppc-dev
* Added allocation and initialization of the irq stacks. We limit the
stacks to be in lowmem for ppc32.
* Implemented ppc32 versions of call_do_softirq() and call_handle_irq()
to switch the stack pointers
* Reworked how we do stack overflow detection. We now keep around the
limit of the stack in the thread_struct and compare against the limit
to see if we've overflowed. We can now use this on ppc64 if desired.
Signed-off-by: Kumar Gala <galak@kernel.crashing.org>
---
Removed ifdef from init_IRQ since we have a dummy version of irq_ctx_init
in irq.h
arch/powerpc/Kconfig.debug | 1 -
arch/powerpc/kernel/asm-offsets.c | 1 +
arch/powerpc/kernel/entry_32.S | 4 ++--
arch/powerpc/kernel/irq.c | 10 ++++++++--
arch/powerpc/kernel/misc_32.S | 25 +++++++++++++++++++++++++
arch/powerpc/kernel/process.c | 2 ++
arch/powerpc/kernel/setup_32.c | 21 +++++++++++++++++++++
include/asm-powerpc/processor.h | 6 ++++++
8 files changed, 65 insertions(+), 5 deletions(-)
diff --git a/arch/powerpc/Kconfig.debug b/arch/powerpc/Kconfig.debug
index a86d8d8..2cf72d2 100644
--- a/arch/powerpc/Kconfig.debug
+++ b/arch/powerpc/Kconfig.debug
@@ -118,7 +118,6 @@ config XMON_DISASSEMBLY
config IRQSTACKS
bool "Use separate kernel stacks when processing interrupts"
- depends on PPC64
help
If you say Y here the kernel will use separate kernel stacks
for handling hard and soft interrupts. This can help avoid
diff --git a/arch/powerpc/kernel/asm-offsets.c b/arch/powerpc/kernel/asm-offsets.c
index adf1d09..0ef4d41 100644
--- a/arch/powerpc/kernel/asm-offsets.c
+++ b/arch/powerpc/kernel/asm-offsets.c
@@ -64,6 +64,7 @@ int main(void)
#endif /* CONFIG_PPC64 */
DEFINE(KSP, offsetof(struct thread_struct, ksp));
+ DEFINE(KSP_LIMIT, offsetof(struct thread_struct, ksp_limit));
DEFINE(PT_REGS, offsetof(struct thread_struct, regs));
DEFINE(THREAD_FPEXC_MODE, offsetof(struct thread_struct, fpexc_mode));
DEFINE(THREAD_FPR0, offsetof(struct thread_struct, fpr[0]));
diff --git a/arch/powerpc/kernel/entry_32.S b/arch/powerpc/kernel/entry_32.S
index 84c8686..f33c1fe 100644
--- a/arch/powerpc/kernel/entry_32.S
+++ b/arch/powerpc/kernel/entry_32.S
@@ -137,8 +137,8 @@ transfer_to_handler:
2: /* if from kernel, check interrupted DOZE/NAP mode and
* check for stack overflow
*/
- lwz r9,THREAD_INFO-THREAD(r12)
- cmplw r1,r9 /* if r1 <= current->thread_info */
+ lwz r9,KSP_LIMIT(r12)
+ cmplw r1,r9 /* if r1 <= ksp_limit */
ble- stack_ovf /* then the kernel stack overflowed */
5:
#ifdef CONFIG_6xx
diff --git a/arch/powerpc/kernel/irq.c b/arch/powerpc/kernel/irq.c
index 425616f..2f73f70 100644
--- a/arch/powerpc/kernel/irq.c
+++ b/arch/powerpc/kernel/irq.c
@@ -307,6 +307,7 @@ void do_IRQ(struct pt_regs *regs)
if (curtp != irqtp) {
struct irq_desc *desc = irq_desc + irq;
void *handler = desc->handle_irq;
+ unsigned long saved_sp_limit = current->thread.ksp_limit;
if (handler == NULL)
handler = &__do_IRQ;
irqtp->task = curtp->task;
@@ -319,7 +320,10 @@ void do_IRQ(struct pt_regs *regs)
(irqtp->preempt_count & ~SOFTIRQ_MASK) |
(curtp->preempt_count & SOFTIRQ_MASK);
+ current->thread.ksp_limit = (unsigned long)irqtp +
+ _ALIGN_UP(sizeof(struct thread_info), 16);
call_handle_irq(irq, desc, irqtp, handler);
+ current->thread.ksp_limit = saved_sp_limit;
irqtp->task = NULL;
@@ -352,9 +356,7 @@ void __init init_IRQ(void)
{
if (ppc_md.init_IRQ)
ppc_md.init_IRQ();
-#ifdef CONFIG_PPC64
irq_ctx_init();
-#endif
}
@@ -383,11 +385,15 @@ void irq_ctx_init(void)
static inline void do_softirq_onstack(void)
{
struct thread_info *curtp, *irqtp;
+ unsigned long saved_sp_limit = current->thread.ksp_limit;
curtp = current_thread_info();
irqtp = softirq_ctx[smp_processor_id()];
irqtp->task = curtp->task;
+ current->thread.ksp_limit = (unsigned long)irqtp +
+ _ALIGN_UP(sizeof(struct thread_info), 16);
call_do_softirq(irqtp);
+ current->thread.ksp_limit = saved_sp_limit;
irqtp->task = NULL;
}
diff --git a/arch/powerpc/kernel/misc_32.S b/arch/powerpc/kernel/misc_32.S
index 92ccc6f..89aaaa6 100644
--- a/arch/powerpc/kernel/misc_32.S
+++ b/arch/powerpc/kernel/misc_32.S
@@ -32,6 +32,31 @@
.text
+#ifdef CONFIG_IRQSTACKS
+_GLOBAL(call_do_softirq)
+ mflr r0
+ stw r0,4(r1)
+ stwu r1,THREAD_SIZE-STACK_FRAME_OVERHEAD(r3)
+ mr r1,r3
+ bl __do_softirq
+ lwz r1,0(r1)
+ lwz r0,4(r1)
+ mtlr r0
+ blr
+
+_GLOBAL(call_handle_irq)
+ mflr r0
+ stw r0,4(r1)
+ mtctr r6
+ stwu r1,THREAD_SIZE-STACK_FRAME_OVERHEAD(r5)
+ mr r1,r5
+ bctrl
+ lwz r1,0(r1)
+ lwz r0,4(r1)
+ mtlr r0
+ blr
+#endif /* CONFIG_IRQSTACKS */
+
/*
* This returns the high 64 bits of the product of two 64-bit numbers.
*/
diff --git a/arch/powerpc/kernel/process.c b/arch/powerpc/kernel/process.c
index 6caad17..7de41c3 100644
--- a/arch/powerpc/kernel/process.c
+++ b/arch/powerpc/kernel/process.c
@@ -589,6 +589,8 @@ int copy_thread(int nr, unsigned long clone_flags, unsigned long usp,
kregs = (struct pt_regs *) sp;
sp -= STACK_FRAME_OVERHEAD;
p->thread.ksp = sp;
+ p->thread.ksp_limit = (unsigned long)task_stack_page(p) +
+ _ALIGN_UP(sizeof(struct thread_info), 16);
#ifdef CONFIG_PPC64
if (cpu_has_feature(CPU_FTR_SLB)) {
diff --git a/arch/powerpc/kernel/setup_32.c b/arch/powerpc/kernel/setup_32.c
index 36f6779..5112a4a 100644
--- a/arch/powerpc/kernel/setup_32.c
+++ b/arch/powerpc/kernel/setup_32.c
@@ -16,6 +16,7 @@
#include <linux/root_dev.h>
#include <linux/cpu.h>
#include <linux/console.h>
+#include <linux/lmb.h>
#include <asm/io.h>
#include <asm/prom.h>
@@ -229,6 +230,24 @@ int __init ppc_init(void)
arch_initcall(ppc_init);
+#ifdef CONFIG_IRQSTACKS
+static void __init irqstack_early_init(void)
+{
+ unsigned int i;
+
+ /* interrupt stacks must be in lowmem, we get that for free on ppc32
+ * as the lmb is limited to lowmem by LMB_REAL_LIMIT */
+ for_each_possible_cpu(i) {
+ softirq_ctx[i] = (struct thread_info *)
+ __va(lmb_alloc(THREAD_SIZE, THREAD_SIZE));
+ hardirq_ctx[i] = (struct thread_info *)
+ __va(lmb_alloc(THREAD_SIZE, THREAD_SIZE));
+ }
+}
+#else
+#define irqstack_early_init()
+#endif
+
/* Warning, IO base is not yet inited */
void __init setup_arch(char **cmdline_p)
{
@@ -286,6 +305,8 @@ void __init setup_arch(char **cmdline_p)
init_mm.end_data = (unsigned long) _edata;
init_mm.brk = klimit;
+ irqstack_early_init();
+
/* set up the bootmem stuff with available memory */
do_init_bootmem();
if ( ppc_md.progress ) ppc_md.progress("setup_arch: bootmem", 0x3eab);
diff --git a/include/asm-powerpc/processor.h b/include/asm-powerpc/processor.h
index fd98ca9..cf83f2d 100644
--- a/include/asm-powerpc/processor.h
+++ b/include/asm-powerpc/processor.h
@@ -138,6 +138,8 @@ typedef struct {
struct thread_struct {
unsigned long ksp; /* Kernel stack pointer */
+ unsigned long ksp_limit; /* if ksp <= ksp_limit stack overflow */
+
#ifdef CONFIG_PPC64
unsigned long ksp_vsid;
#endif
@@ -182,11 +184,14 @@ struct thread_struct {
#define ARCH_MIN_TASKALIGN 16
#define INIT_SP (sizeof(init_stack) + (unsigned long) &init_stack)
+#define INIT_SP_LIMIT \
+ (_ALIGN_UP(sizeof(init_thread_info), 16) + (unsigned long) &init_stack)
#ifdef CONFIG_PPC32
#define INIT_THREAD { \
.ksp = INIT_SP, \
+ .ksp_limit = INIT_SP_LIMIT, \
.fs = KERNEL_DS, \
.pgdir = swapper_pg_dir, \
.fpexc_mode = MSR_FE0 | MSR_FE1, \
@@ -194,6 +199,7 @@ struct thread_struct {
#else
#define INIT_THREAD { \
.ksp = INIT_SP, \
+ .ksp_limit = INIT_SP_LIMIT, \
.regs = (struct pt_regs *)INIT_SP - 1, /* XXX bogus, I think */ \
.fs = KERNEL_DS, \
.fpr = {0}, \
--
1.5.4.1
^ permalink raw reply related
* Re: [PATHC V3] Watchdog on MPC85xx SMP system
From: Kumar Gala @ 2008-04-28 6:28 UTC (permalink / raw)
To: Chen Gong
Cc: linuxppc-dev@ozlabs.org list, Wim Van Sebroeck, lkml Mailing List
In-Reply-To: <1209363637-22739-1-git-send-email-g.chen@freescale.com>
On Apr 28, 2008, at 1:20 AM, Chen Gong wrote:
> On Book-E SMP systems each core has its own private watchdog.
> If only one watchdog is enabled, when the core that doesn't
> enable the watchdog is hung, system can't reset because no
> watchdog is running on it. That's bad. It means we must enable
> watchdogs on both cores.
>
> We can use smp_call_function() to send appropriate messages to all
> the other
> cores to enable and update the watchdog.
>
> Signed-off-by: Chen Gong <g.chen@freescale.com>
In the future Wim should be copied as maintainer of WATCHDOG drivers
in the kernel.
- k
>
> ---
> Tested on MPC8572DS platform.
>
> drivers/char/watchdog/booke_wdt.c | 34 ++++++++++++++++++++++++++
> +-------
> 1 files changed, 27 insertions(+), 7 deletions(-)
>
> diff --git a/drivers/char/watchdog/booke_wdt.c b/drivers/char/
> watchdog/booke_wdt.c
> index d362f5b..b3a37d0 100644
> --- a/drivers/char/watchdog/booke_wdt.c
> +++ b/drivers/char/watchdog/booke_wdt.c
> @@ -6,7 +6,12 @@
> * Author: Matthew McClintock
> * Maintainer: Kumar Gala <galak@kernel.crashing.org>
> *
> - * Copyright 2005 Freescale Semiconductor Inc.
> + * Copyright 2005, 2008 Freescale Semiconductor Inc.
> + *
> + * Changelog:
> + * 2008-04-28 Chen Gong <g.chen@freescale.com>
> + * Add SMP support for MPC85xx system. Tested on
> + * MPC8572DS platform
> *
> * 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
> @@ -16,6 +21,7 @@
>
> #include <linux/module.h>
> #include <linux/fs.h>
> +#include <linux/smp.h>
> #include <linux/miscdevice.h>
> #include <linux/notifier.h>
> #include <linux/watchdog.h>
> @@ -47,23 +53,31 @@ u32 booke_wdt_period = WDT_PERIOD_DEFAULT;
> #define WDTP(x) (TCR_WP(x))
> #endif
>
> +static DEFINE_SPINLOCK(booke_wdt_lock);
> +
> +static void __booke_wdt_ping(void *data)
> +{
> + mtspr(SPRN_TSR, TSR_ENW|TSR_WIS);
> +}
> +
> /*
> * booke_wdt_ping:
> */
> static __inline__ void booke_wdt_ping(void)
> {
> - mtspr(SPRN_TSR, TSR_ENW|TSR_WIS);
> + smp_call_function(__booke_wdt_ping, NULL, 0, 0);
> + __booke_wdt_ping(NULL);
> }
>
> /*
> - * booke_wdt_enable:
> + * __booke_wdt_enable:
> */
> -static __inline__ void booke_wdt_enable(void)
> +static __inline__ void __booke_wdt_enable(void *data)
> {
> u32 val;
>
> /* clear status before enabling watchdog */
> - booke_wdt_ping();
> + __booke_wdt_ping(NULL);
> val = mfspr(SPRN_TCR);
> val |= (TCR_WIE|TCR_WRC(WRC_CHIP)|WDTP(booke_wdt_period));
>
> @@ -137,12 +151,15 @@ static int booke_wdt_ioctl (struct inode
> *inode, struct file *file,
> */
> static int booke_wdt_open (struct inode *inode, struct file *file)
> {
> + spin_lock(&booke_wdt_lock);
> if (booke_wdt_enabled == 0) {
> booke_wdt_enabled = 1;
> - booke_wdt_enable();
> + __booke_wdt_enable(NULL);
> + smp_call_function(__booke_wdt_enable, NULL, 0, 0);
> printk (KERN_INFO "PowerPC Book-E Watchdog Timer Enabled
> (wdt_period=%d)\n",
> booke_wdt_period);
> }
> + spin_unlock(&booke_wdt_lock);
>
> return nonseekable_open(inode, file);
> }
> @@ -183,11 +200,14 @@ static int __init booke_wdt_init(void)
> return ret;
> }
>
> + spin_lock(&booke_wdt_lock);
> if (booke_wdt_enabled == 1) {
> printk (KERN_INFO "PowerPC Book-E Watchdog Timer Enabled
> (wdt_period=%d)\n",
> booke_wdt_period);
> - booke_wdt_enable();
> + __booke_wdt_enable(NULL);
> + smp_call_function(__booke_wdt_enable, NULL, 0, 0);
> }
> + spin_unlock(&booke_wdt_lock);
>
> return ret;
> }
> --
> 1.5.4
^ permalink raw reply
* Re: [PATCH] powerpc TLF_RESTORE_SIGMASK
From: Roland McGrath @ 2008-04-28 7:30 UTC (permalink / raw)
To: Paul Mackerras; +Cc: linuxppc-dev, akpm, linux-kernel
In-Reply-To: <18448.10563.385481.904182@cargo.ozlabs.ibm.com>
> Thanks. That can't go in until some generic changes have gone in
> first, right? So are you going to push the lot in one go via Andrew,
> or should I wait until the generic part is upstream and then push the
> powerpc bit?
>From what I can see, the related patches are in -mm now, but the powerpc
patch is not. Linus already said he approved of the patches, so I hope
they can be merged in real soon. That will simplify the juggling for arch
patches. That said, there is really no hurry for this change for powerpc;
it's a small optimization.
> Oh, and could you please also fix the occurrence of
> TIF_RESTORE_SIGMASK in arch/ppc/kernel/entry.S when this stuff goes
> in?
Oh, I didn't realize that file was in use (or existed).
Third time's the charm (or is this the fifth time?).
Thanks,
Roland
---
[PATCH] powerpc TLF_RESTORE_SIGMASK
Replace TIF_RESTORE_SIGMASK with TLF_RESTORE_SIGMASK and define
our own set_restore_sigmask() function. This saves the costly
SMP-safe set_bit operation, which we do not need for the sigmask
flag since TIF_SIGPENDING always has to be set too.
Signed-off-by: Roland McGrath <roland@redhat.com>
---
arch/powerpc/kernel/entry_32.S | 4 ++--
arch/powerpc/kernel/signal.c | 12 ++++++------
arch/powerpc/kernel/signal_32.c | 2 +-
arch/ppc/kernel/entry.S | 4 ++--
include/asm-powerpc/thread_info.h | 17 +++++++++++++----
5 files changed, 24 insertions(+), 15 deletions(-)
diff --git a/arch/powerpc/kernel/entry_32.S b/arch/powerpc/kernel/entry_32.S
index 84c8686..7e2ecf0 100644
--- a/arch/powerpc/kernel/entry_32.S
+++ b/arch/powerpc/kernel/entry_32.S
@@ -667,7 +667,7 @@ user_exc_return: /* r10 contains MSR_KERNEL here */
/* Check current_thread_info()->flags */
rlwinm r9,r1,0,0,(31-THREAD_SHIFT)
lwz r9,TI_FLAGS(r9)
- andi. r0,r9,(_TIF_SIGPENDING|_TIF_RESTORE_SIGMASK|_TIF_NEED_RESCHED)
+ andi. r0,r9,_TIF_USER_WORK_MASK
bne do_work
restore_user:
@@ -924,7 +924,7 @@ recheck:
lwz r9,TI_FLAGS(r9)
andi. r0,r9,_TIF_NEED_RESCHED
bne- do_resched
- andi. r0,r9,_TIF_SIGPENDING|_TIF_RESTORE_SIGMASK
+ andi. r0,r9,_TIF_USER_WORK_MASK
beq restore_user
do_user_signal: /* r10 contains MSR_KERNEL here */
ori r10,r10,MSR_EE
diff --git a/arch/powerpc/kernel/signal.c b/arch/powerpc/kernel/signal.c
index a65a44f..ad55488 100644
--- a/arch/powerpc/kernel/signal.c
+++ b/arch/powerpc/kernel/signal.c
@@ -120,7 +120,7 @@ int do_signal(sigset_t *oldset, struct pt_regs *regs)
int ret;
int is32 = is_32bit_task();
- if (test_thread_flag(TIF_RESTORE_SIGMASK))
+ if (current_thread_info()->local_flags & _TLF_RESTORE_SIGMASK)
oldset = ¤t->saved_sigmask;
else if (!oldset)
oldset = ¤t->blocked;
@@ -131,9 +131,10 @@ int do_signal(sigset_t *oldset, struct pt_regs *regs)
check_syscall_restart(regs, &ka, signr > 0);
if (signr <= 0) {
+ struct thread_info *ti = current_thread_info();
/* No signal to deliver -- put the saved sigmask back */
- if (test_thread_flag(TIF_RESTORE_SIGMASK)) {
- clear_thread_flag(TIF_RESTORE_SIGMASK);
+ if (ti->local_flags & _TLF_RESTORE_SIGMASK) {
+ ti->local_flags &= ~_TLF_RESTORE_SIGMASK;
sigprocmask(SIG_SETMASK, ¤t->saved_sigmask, NULL);
}
return 0; /* no signals delivered */
@@ -169,10 +170,9 @@ int do_signal(sigset_t *oldset, struct pt_regs *regs)
/*
* A signal was successfully delivered; the saved sigmask is in
- * its frame, and we can clear the TIF_RESTORE_SIGMASK flag.
+ * its frame, and we can clear the TLF_RESTORE_SIGMASK flag.
*/
- if (test_thread_flag(TIF_RESTORE_SIGMASK))
- clear_thread_flag(TIF_RESTORE_SIGMASK);
+ current_thread_info()->local_flags &= ~_TLF_RESTORE_SIGMASK;
}
return ret;
diff --git a/arch/powerpc/kernel/signal_32.c b/arch/powerpc/kernel/signal_32.c
index ad69434..4ae16d1 100644
--- a/arch/powerpc/kernel/signal_32.c
+++ b/arch/powerpc/kernel/signal_32.c
@@ -243,7 +243,7 @@ long sys_sigsuspend(old_sigset_t mask)
current->state = TASK_INTERRUPTIBLE;
schedule();
- set_thread_flag(TIF_RESTORE_SIGMASK);
+ set_restore_sigmask();
return -ERESTARTNOHAND;
}
diff --git a/arch/ppc/kernel/entry.S b/arch/ppc/kernel/entry.S
index 5f3a5d0..fcd830a 100644
--- a/arch/ppc/kernel/entry.S
+++ b/arch/ppc/kernel/entry.S
@@ -647,7 +647,7 @@ user_exc_return: /* r10 contains MSR_KERNEL here */
/* Check current_thread_info()->flags */
rlwinm r9,r1,0,0,18
lwz r9,TI_FLAGS(r9)
- andi. r0,r9,(_TIF_SIGPENDING|_TIF_RESTORE_SIGMASK|_TIF_NEED_RESCHED)
+ andi. r0,r9,_TIF_USER_WORK_MASK
bne do_work
restore_user:
@@ -898,7 +898,7 @@ recheck:
lwz r9,TI_FLAGS(r9)
andi. r0,r9,_TIF_NEED_RESCHED
bne- do_resched
- andi. r0,r9,_TIF_SIGPENDING
+ andi. r0,r9,_TIF_USER_WORK_MASK
beq restore_user
do_user_signal: /* r10 contains MSR_KERNEL here */
ori r10,r10,MSR_EE
diff --git a/include/asm-powerpc/thread_info.h b/include/asm-powerpc/thread_info.h
index d030f5c..e079e81 100644
--- a/include/asm-powerpc/thread_info.h
+++ b/include/asm-powerpc/thread_info.h
@@ -116,7 +116,6 @@ static inline struct thread_info *current_thread_info(void)
#define TIF_SECCOMP 10 /* secure computing */
#define TIF_RESTOREALL 11 /* Restore all regs (implies NOERROR) */
#define TIF_NOERROR 12 /* Force successful syscall return */
-#define TIF_RESTORE_SIGMASK 13 /* Restore signal mask in do_signal */
#define TIF_FREEZE 14 /* Freezing for suspend */
#define TIF_RUNLATCH 15 /* Is the runlatch enabled? */
#define TIF_ABI_PENDING 16 /* 32/64 bit switch needed */
@@ -134,21 +133,31 @@ static inline struct thread_info *current_thread_info(void)
#define _TIF_SECCOMP (1<<TIF_SECCOMP)
#define _TIF_RESTOREALL (1<<TIF_RESTOREALL)
#define _TIF_NOERROR (1<<TIF_NOERROR)
-#define _TIF_RESTORE_SIGMASK (1<<TIF_RESTORE_SIGMASK)
#define _TIF_FREEZE (1<<TIF_FREEZE)
#define _TIF_RUNLATCH (1<<TIF_RUNLATCH)
#define _TIF_ABI_PENDING (1<<TIF_ABI_PENDING)
#define _TIF_SYSCALL_T_OR_A (_TIF_SYSCALL_TRACE|_TIF_SYSCALL_AUDIT|_TIF_SECCOMP)
-#define _TIF_USER_WORK_MASK ( _TIF_SIGPENDING | \
- _TIF_NEED_RESCHED | _TIF_RESTORE_SIGMASK)
+#define _TIF_USER_WORK_MASK (_TIF_SIGPENDING | _TIF_NEED_RESCHED)
#define _TIF_PERSYSCALL_MASK (_TIF_RESTOREALL|_TIF_NOERROR)
/* Bits in local_flags */
/* Don't move TLF_NAPPING without adjusting the code in entry_32.S */
#define TLF_NAPPING 0 /* idle thread enabled NAP mode */
+#define TLF_RESTORE_SIGMASK 1 /* Restore signal mask in do_signal */
#define _TLF_NAPPING (1 << TLF_NAPPING)
+#define _TLF_RESTORE_SIGMASK (1 << TLF_RESTORE_SIGMASK)
+
+#ifndef __ASSEMBLY__
+#define HAVE_SET_RESTORE_SIGMASK 1
+static inline void set_restore_sigmask(void)
+{
+ struct thread_info *ti = current_thread_info();
+ ti->local_flags |= _TLF_RESTORE_SIGMASK;
+ set_bit(TIF_SIGPENDING, &ti->flags);
+}
+#endif /* !__ASSEMBLY__ */
#endif /* __KERNEL__ */
^ permalink raw reply related
* Linux support MPC7448 L2 ECC errors
From: Assaf Hoffman @ 2008-04-28 7:40 UTC (permalink / raw)
To: linuxppc-embedded
Hi all,
Can you please tell if MPC7448 L2 ECC error handling is implemented in
any of Linux kernels?
Many thanks.
^ permalink raw reply
* Re: cpu_clock confusion
From: Gabriel Paubert @ 2008-04-28 8:46 UTC (permalink / raw)
To: Johannes Berg
Cc: linux-kernel, benh, linuxppc-dev, tglx, arndb, mingo,
David Miller
In-Reply-To: <1209029257.3357.55.camel@johannes.berg>
On Thu, Apr 24, 2008 at 11:27:37AM +0200, Johannes Berg wrote:
> On Thu, 2008-04-24 at 02:24 -0700, David Miller wrote:
> > From: Johannes Berg <johannes@sipsolutions.net>
> > Date: Thu, 24 Apr 2008 11:21:52 +0200
> >
> > > Hmm. Why is that whole cpu_clock stuff in place anyway? powerpc has
> > > perfectly synchronised time across processors with dirt cheap access to
> > > it as well, so why build all this code that only messes it up on top of
> > > it?
> >
> > Same on sparc64. These changes add more bugs than they fix.
>
> I tend to think all this clock business should be done local to those
> arches that aren't capable of providing cheap, useful synchronised and
> accurate clocks themselves. Or be a lib that they can link in if needed.
> As it stands, it seems to me that it all just penalises those
> architectures that have decent clocks.
100% agreed.
Gabriel
^ permalink raw reply
* [PATCH 0/2] i2c: Add support for device alias names
From: Jean Delvare @ 2008-04-28 9:30 UTC (permalink / raw)
To: Linux I2C
Cc: Laurent, Sievers, linuxppc-dev list, Paul Mundt, Scott Wood, Kay
Hi all,
This is an updated, minimal patchset to add support for device alias
names to the i2c subsystem. It is based on earlier work by Jon Smirl,
Jochen Friedrich and myself.
For 2.6.26-rc1 I'll only attempt to push the first two patches: the one
adding the support for alias names and the one converting the drivers
to make use of it. I've even excluded most of the video drivers from
this patch, as they are a bit more difficult to deal with and I don't
want to break them for rc1. This will come later, together with the
patch removing the old device/driver matching scheme.
I've fixed a number of bugs since the previous iteration, and added a
few missing chunks as well. I hope I caught all the pieces this time
but that's hard to tell given that much of the changes are in arch code
I can't even build. So I would like everyone interested in these two
patches getting in 2.6.26-rc1 to give them good testing on as many
systems as possible, and report to me, ideally by the end of the day.
Sorry for the short notice, but I did my best with the little spare
time I had.
Note that there are RTC patches pending for upstream merge, which will
conflict with my patches. Andrew Morton should push them to Linus
today, so that I can rebase my patches before I send them to Linus
(tomorrow). The current versions of the patches apply on top of
2.6.26-git11.
Thanks,
--
Jean Delvare
^ permalink raw reply
* MPC852T Linux Support
From: Ankur Maheshwari @ 2008-04-28 9:22 UTC (permalink / raw)
To: Linux PPC
Hi all,
I am planning to use MPC-852T on my next card. I want to know whether
any Linux support is available for MPC-852T.
I have worked with MPC860-Kernel-2.4.4 (MPC8xx) earlier. Can I use the
same kernel for MPC-852T or do I need to change something.
If MPC852T Evaluation card / linux support is already available, kindly
send me the pointers.
thanks,
Ankur Maheshwari
^ permalink raw reply
* [PATCH 1/2] i2c: Add support for device alias names
From: Jean Delvare @ 2008-04-28 9:39 UTC (permalink / raw)
To: Linux I2C
Cc: Laurent, Sievers, linuxppc-dev list, Paul Mundt, Scott Wood, Kay
In-Reply-To: <20080428113052.6d024bda@hyperion.delvare>
Based on earlier work by Jon Smirl and Jochen Friedrich.
This patch allows new-style i2c chip drivers to have alias names using
the official kernel aliasing system and MODULE_DEVICE_TABLE(). At this
point, the old i2c driver binding scheme (driver_name/type) is still
supported.
Signed-off-by: Jean Delvare <khali@linux-fr.org>
Cc: Jochen Friedrich <jochen@scram.de>
Cc: Jon Smirl <jonsmirl@gmail.com>
Cc: Kay Sievers <kay.sievers@vrfy.org>
---
One thing I am still not happy with is that the aliases created have a
trailing "*":
$ /sbin/modinfo lm90
filename: /lib/modules/2.6.25-git11/kernel/drivers/hwmon/lm90.ko
author: Jean Delvare <khali@linux-fr.org>
description: LM90/ADM1032 driver
license: GPL
vermagic: 2.6.25-git11 mod_unload
depends: hwmon
alias: i2c:lm90*
alias: i2c:adm1032*
alias: i2c:lm99*
alias: i2c:lm86*
alias: i2c:max6657*
alias: i2c:adt7461*
alias: i2c:max6680*
$
This would cause trouble if one I2C chip name matches the beginning of
another I2C chip name and both chips are supported by different
drivers. This has yet to be seen, but still, I'd like to see this
problem fixed quickly.
Documentation/i2c/writing-clients | 3 +
drivers/gpio/pca953x.c | 3 +
drivers/gpio/pcf857x.c | 3 +
drivers/hwmon/f75375s.c | 8 ++--
drivers/i2c/chips/ds1682.c | 3 +
drivers/i2c/chips/menelaus.c | 3 +
drivers/i2c/chips/tps65010.c | 3 +
drivers/i2c/chips/tsl2550.c | 3 +
drivers/i2c/i2c-core.c | 51 +++++++++++++++++++++++-----
drivers/media/video/cs5345.c | 3 +
drivers/media/video/cs53l32a.c | 3 +
drivers/media/video/cx25840/cx25840-core.c | 3 +
drivers/media/video/m52790.c | 3 +
drivers/media/video/msp3400-driver.c | 2 -
drivers/media/video/mt9m001.c | 3 +
drivers/media/video/mt9v022.c | 3 +
drivers/media/video/saa7115.c | 3 +
drivers/media/video/saa7127.c | 3 +
drivers/media/video/saa717x.c | 3 +
drivers/media/video/tcm825x.c | 3 +
drivers/media/video/tlv320aic23b.c | 3 +
drivers/media/video/tuner-core.c | 3 +
drivers/media/video/tvaudio.c | 2 -
drivers/media/video/upd64031a.c | 3 +
drivers/media/video/upd64083.c | 3 +
drivers/media/video/v4l2-common.c | 5 +-
drivers/media/video/vp27smpx.c | 3 +
drivers/media/video/wm8739.c | 3 +
drivers/media/video/wm8775.c | 3 +
drivers/rtc/rtc-ds1307.c | 3 +
drivers/rtc/rtc-ds1374.c | 3 +
drivers/rtc/rtc-m41t80.c | 3 +
drivers/rtc/rtc-rs5c372.c | 3 +
drivers/rtc/rtc-s35390a.c | 3 +
include/linux/i2c.h | 5 +-
include/linux/mod_devicetable.h | 11 ++++++
include/media/v4l2-common.h | 4 +-
include/media/v4l2-i2c-drv-legacy.h | 2 -
include/media/v4l2-i2c-drv.h | 2 -
scripts/mod/file2alias.c | 13 +++++++
40 files changed, 141 insertions(+), 51 deletions(-)
--- linux-2.6.26-rc0.orig/Documentation/i2c/writing-clients 2008-04-27 22:05:00.000000000 +0200
+++ linux-2.6.26-rc0/Documentation/i2c/writing-clients 2008-04-27 22:09:29.000000000 +0200
@@ -164,7 +164,8 @@ I2C device drivers using this binding mo
kind of driver in Linux: they provide a probe() method to bind to
those devices, and a remove() method to unbind.
- static int foo_probe(struct i2c_client *client);
+ static int foo_probe(struct i2c_client *client,
+ const struct i2c_device_id *id);
static int foo_remove(struct i2c_client *client);
Remember that the i2c_driver does not create those client handles. The
--- linux-2.6.26-rc0.orig/drivers/gpio/pca953x.c 2008-04-27 22:05:00.000000000 +0200
+++ linux-2.6.26-rc0/drivers/gpio/pca953x.c 2008-04-27 22:09:29.000000000 +0200
@@ -191,7 +191,8 @@ static void pca953x_setup_gpio(struct pc
gc->label = chip->client->name;
}
-static int __devinit pca953x_probe(struct i2c_client *client)
+static int __devinit pca953x_probe(struct i2c_client *client,
+ const struct i2c_device_id *did)
{
struct pca953x_platform_data *pdata;
struct pca953x_chip *chip;
--- linux-2.6.26-rc0.orig/drivers/gpio/pcf857x.c 2008-04-27 22:05:00.000000000 +0200
+++ linux-2.6.26-rc0/drivers/gpio/pcf857x.c 2008-04-27 22:09:29.000000000 +0200
@@ -142,7 +142,8 @@ static void pcf857x_set16(struct gpio_ch
/*-------------------------------------------------------------------------*/
-static int pcf857x_probe(struct i2c_client *client)
+static int pcf857x_probe(struct i2c_client *client,
+ const struct i2c_device_id *id)
{
struct pcf857x_platform_data *pdata;
struct pcf857x *gpio;
--- linux-2.6.26-rc0.orig/drivers/hwmon/f75375s.c 2008-04-27 22:05:00.000000000 +0200
+++ linux-2.6.26-rc0/drivers/hwmon/f75375s.c 2008-04-27 22:09:29.000000000 +0200
@@ -117,7 +117,8 @@ struct f75375_data {
static int f75375_attach_adapter(struct i2c_adapter *adapter);
static int f75375_detect(struct i2c_adapter *adapter, int address, int kind);
static int f75375_detach_client(struct i2c_client *client);
-static int f75375_probe(struct i2c_client *client);
+static int f75375_probe(struct i2c_client *client,
+ const struct i2c_device_id *id);
static int f75375_remove(struct i2c_client *client);
static struct i2c_driver f75375_legacy_driver = {
@@ -628,7 +629,8 @@ static void f75375_init(struct i2c_clien
}
-static int f75375_probe(struct i2c_client *client)
+static int f75375_probe(struct i2c_client *client,
+ const struct i2c_device_id *id)
{
struct f75375_data *data = i2c_get_clientdata(client);
struct f75375s_platform_data *f75375s_pdata = client->dev.platform_data;
@@ -748,7 +750,7 @@ static int f75375_detect(struct i2c_adap
if ((err = i2c_attach_client(client)))
goto exit_free;
- if ((err = f75375_probe(client)) < 0)
+ if ((err = f75375_probe(client, NULL)) < 0)
goto exit_detach;
return 0;
--- linux-2.6.26-rc0.orig/drivers/i2c/chips/ds1682.c 2008-04-27 22:05:00.000000000 +0200
+++ linux-2.6.26-rc0/drivers/i2c/chips/ds1682.c 2008-04-27 22:09:29.000000000 +0200
@@ -200,7 +200,8 @@ static struct bin_attribute ds1682_eepro
/*
* Called when a ds1682 device is matched with this driver
*/
-static int ds1682_probe(struct i2c_client *client)
+static int ds1682_probe(struct i2c_client *client,
+ const struct i2c_device_id *id)
{
int rc;
--- linux-2.6.26-rc0.orig/drivers/i2c/chips/menelaus.c 2008-04-27 22:05:00.000000000 +0200
+++ linux-2.6.26-rc0/drivers/i2c/chips/menelaus.c 2008-04-27 22:09:29.000000000 +0200
@@ -1149,7 +1149,8 @@ static inline void menelaus_rtc_init(str
static struct i2c_driver menelaus_i2c_driver;
-static int menelaus_probe(struct i2c_client *client)
+static int menelaus_probe(struct i2c_client *client,
+ const struct i2c_device_id *id)
{
struct menelaus_chip *menelaus;
int rev = 0, val;
--- linux-2.6.26-rc0.orig/drivers/i2c/chips/tps65010.c 2008-04-27 22:08:10.000000000 +0200
+++ linux-2.6.26-rc0/drivers/i2c/chips/tps65010.c 2008-04-27 22:09:29.000000000 +0200
@@ -532,7 +532,8 @@ static int __exit tps65010_remove(struct
return 0;
}
-static int tps65010_probe(struct i2c_client *client)
+static int tps65010_probe(struct i2c_client *client,
+ const struct i2c_device_id *id)
{
struct tps65010 *tps;
int status;
--- linux-2.6.26-rc0.orig/drivers/i2c/chips/tsl2550.c 2008-04-27 22:05:00.000000000 +0200
+++ linux-2.6.26-rc0/drivers/i2c/chips/tsl2550.c 2008-04-27 22:09:29.000000000 +0200
@@ -364,7 +364,8 @@ static int tsl2550_init_client(struct i2
*/
static struct i2c_driver tsl2550_driver;
-static int __devinit tsl2550_probe(struct i2c_client *client)
+static int __devinit tsl2550_probe(struct i2c_client *client,
+ const struct i2c_device_id *id)
{
struct i2c_adapter *adapter = to_i2c_adapter(client->dev.parent);
struct tsl2550_data *data;
--- linux-2.6.26-rc0.orig/drivers/i2c/i2c-core.c 2008-04-27 22:07:17.000000000 +0200
+++ linux-2.6.26-rc0/drivers/i2c/i2c-core.c 2008-04-27 22:09:29.000000000 +0200
@@ -48,6 +48,17 @@ static DEFINE_IDR(i2c_adapter_idr);
/* ------------------------------------------------------------------------- */
+static const struct i2c_device_id *i2c_match_id(const struct i2c_device_id *id,
+ const struct i2c_client *client)
+{
+ while (id->name[0]) {
+ if (strcmp(client->name, id->name) == 0)
+ return id;
+ id++;
+ }
+ return NULL;
+}
+
static int i2c_device_match(struct device *dev, struct device_driver *drv)
{
struct i2c_client *client = to_i2c_client(dev);
@@ -59,6 +70,10 @@ static int i2c_device_match(struct devic
if (!is_newstyle_driver(driver))
return 0;
+ /* match on an id table if there is one */
+ if (driver->id_table)
+ return i2c_match_id(driver->id_table, client) != NULL;
+
/* new style drivers use the same kind of driver matching policy
* as platform devices or SPI: compare device and driver IDs.
*/
@@ -73,11 +88,17 @@ static int i2c_device_uevent(struct devi
struct i2c_client *client = to_i2c_client(dev);
/* by definition, legacy drivers can't hotplug */
- if (dev->driver || !client->driver_name)
+ if (dev->driver)
return 0;
- if (add_uevent_var(env, "MODALIAS=%s", client->driver_name))
- return -ENOMEM;
+ if (client->driver_name[0]) {
+ if (add_uevent_var(env, "MODALIAS=%s", client->driver_name))
+ return -ENOMEM;
+ } else {
+ if (add_uevent_var(env, "MODALIAS=%s%s",
+ I2C_MODULE_PREFIX, client->name))
+ return -ENOMEM;
+ }
dev_dbg(dev, "uevent\n");
return 0;
}
@@ -90,13 +111,19 @@ static int i2c_device_probe(struct devic
{
struct i2c_client *client = to_i2c_client(dev);
struct i2c_driver *driver = to_i2c_driver(dev->driver);
+ const struct i2c_device_id *id;
int status;
if (!driver->probe)
return -ENODEV;
client->driver = driver;
dev_dbg(dev, "probe\n");
- status = driver->probe(client);
+
+ if (driver->id_table)
+ id = i2c_match_id(driver->id_table, client);
+ else
+ id = NULL;
+ status = driver->probe(client, id);
if (status)
client->driver = NULL;
return status;
@@ -179,9 +206,9 @@ static ssize_t show_client_name(struct d
static ssize_t show_modalias(struct device *dev, struct device_attribute *attr, char *buf)
{
struct i2c_client *client = to_i2c_client(dev);
- return client->driver_name
+ return client->driver_name[0]
? sprintf(buf, "%s\n", client->driver_name)
- : 0;
+ : sprintf(buf, "%s%s\n", I2C_MODULE_PREFIX, client->name);
}
static struct device_attribute i2c_dev_attrs[] = {
@@ -300,15 +327,21 @@ void i2c_unregister_device(struct i2c_cl
EXPORT_SYMBOL_GPL(i2c_unregister_device);
-static int dummy_nop(struct i2c_client *client)
+static int dummy_probe(struct i2c_client *client,
+ const struct i2c_device_id *id)
+{
+ return 0;
+}
+
+static int dummy_remove(struct i2c_client *client)
{
return 0;
}
static struct i2c_driver dummy_driver = {
.driver.name = "dummy",
- .probe = dummy_nop,
- .remove = dummy_nop,
+ .probe = dummy_probe,
+ .remove = dummy_remove,
};
/**
--- linux-2.6.26-rc0.orig/drivers/media/video/cs5345.c 2008-04-27 22:05:00.000000000 +0200
+++ linux-2.6.26-rc0/drivers/media/video/cs5345.c 2008-04-27 22:09:29.000000000 +0200
@@ -142,7 +142,8 @@ static int cs5345_command(struct i2c_cli
/* ----------------------------------------------------------------------- */
-static int cs5345_probe(struct i2c_client *client)
+static int cs5345_probe(struct i2c_client *client,
+ const struct i2c_device_id *id)
{
/* Check if the adapter supports the needed features */
if (!i2c_check_functionality(client->adapter, I2C_FUNC_SMBUS_BYTE_DATA))
--- linux-2.6.26-rc0.orig/drivers/media/video/cs53l32a.c 2008-04-27 22:05:00.000000000 +0200
+++ linux-2.6.26-rc0/drivers/media/video/cs53l32a.c 2008-04-27 22:09:29.000000000 +0200
@@ -135,7 +135,8 @@ static int cs53l32a_command(struct i2c_c
* concerning the addresses: i2c wants 7 bit (without the r/w bit), so '>>1'
*/
-static int cs53l32a_probe(struct i2c_client *client)
+static int cs53l32a_probe(struct i2c_client *client,
+ const struct i2c_device_id *id)
{
int i;
--- linux-2.6.26-rc0.orig/drivers/media/video/cx25840/cx25840-core.c 2008-04-27 22:07:20.000000000 +0200
+++ linux-2.6.26-rc0/drivers/media/video/cx25840/cx25840-core.c 2008-04-27 22:09:29.000000000 +0200
@@ -1209,7 +1209,8 @@ static int cx25840_command(struct i2c_cl
/* ----------------------------------------------------------------------- */
-static int cx25840_probe(struct i2c_client *client)
+static int cx25840_probe(struct i2c_client *client,
+ const struct i2c_device_id *did)
{
struct cx25840_state *state;
u32 id;
--- linux-2.6.26-rc0.orig/drivers/media/video/m52790.c 2008-04-27 22:05:00.000000000 +0200
+++ linux-2.6.26-rc0/drivers/media/video/m52790.c 2008-04-27 22:09:29.000000000 +0200
@@ -126,7 +126,8 @@ static int m52790_command(struct i2c_cli
/* i2c implementation */
-static int m52790_probe(struct i2c_client *client)
+static int m52790_probe(struct i2c_client *client,
+ const struct i2c_device_id *id)
{
struct m52790_state *state;
--- linux-2.6.26-rc0.orig/drivers/media/video/msp3400-driver.c 2008-04-27 22:07:20.000000000 +0200
+++ linux-2.6.26-rc0/drivers/media/video/msp3400-driver.c 2008-04-27 22:09:29.000000000 +0200
@@ -805,7 +805,7 @@ static int msp_resume(struct i2c_client
/* ----------------------------------------------------------------------- */
-static int msp_probe(struct i2c_client *client)
+static int msp_probe(struct i2c_client *client, const struct i2c_device_id *id)
{
struct msp_state *state;
int (*thread_func)(void *data) = NULL;
--- linux-2.6.26-rc0.orig/drivers/media/video/mt9m001.c 2008-04-27 22:07:20.000000000 +0200
+++ linux-2.6.26-rc0/drivers/media/video/mt9m001.c 2008-04-27 22:09:29.000000000 +0200
@@ -620,7 +620,8 @@ static void mt9m001_video_remove(struct
soc_camera_video_stop(&mt9m001->icd);
}
-static int mt9m001_probe(struct i2c_client *client)
+static int mt9m001_probe(struct i2c_client *client,
+ const struct i2c_device_id *did)
{
struct mt9m001 *mt9m001;
struct soc_camera_device *icd;
--- linux-2.6.26-rc0.orig/drivers/media/video/mt9v022.c 2008-04-27 22:07:20.000000000 +0200
+++ linux-2.6.26-rc0/drivers/media/video/mt9v022.c 2008-04-27 22:09:29.000000000 +0200
@@ -745,7 +745,8 @@ static void mt9v022_video_remove(struct
soc_camera_video_stop(&mt9v022->icd);
}
-static int mt9v022_probe(struct i2c_client *client)
+static int mt9v022_probe(struct i2c_client *client,
+ const struct i2c_device_id *did)
{
struct mt9v022 *mt9v022;
struct soc_camera_device *icd;
--- linux-2.6.26-rc0.orig/drivers/media/video/saa7115.c 2008-04-27 22:07:20.000000000 +0200
+++ linux-2.6.26-rc0/drivers/media/video/saa7115.c 2008-04-27 22:09:29.000000000 +0200
@@ -1450,7 +1450,8 @@ static int saa7115_command(struct i2c_cl
/* ----------------------------------------------------------------------- */
-static int saa7115_probe(struct i2c_client *client)
+static int saa7115_probe(struct i2c_client *client,
+ const struct i2c_device_id *id)
{
struct saa711x_state *state;
int i;
--- linux-2.6.26-rc0.orig/drivers/media/video/saa7127.c 2008-04-27 22:05:00.000000000 +0200
+++ linux-2.6.26-rc0/drivers/media/video/saa7127.c 2008-04-27 22:09:29.000000000 +0200
@@ -661,7 +661,8 @@ static int saa7127_command(struct i2c_cl
/* ----------------------------------------------------------------------- */
-static int saa7127_probe(struct i2c_client *client)
+static int saa7127_probe(struct i2c_client *client,
+ const struct i2c_device_id *id)
{
struct saa7127_state *state;
struct v4l2_sliced_vbi_data vbi = { 0, 0, 0, 0 }; /* set to disabled */
--- linux-2.6.26-rc0.orig/drivers/media/video/saa717x.c 2008-04-27 22:07:20.000000000 +0200
+++ linux-2.6.26-rc0/drivers/media/video/saa717x.c 2008-04-27 22:09:29.000000000 +0200
@@ -1418,7 +1418,8 @@ static int saa717x_command(struct i2c_cl
/* i2c implementation */
/* ----------------------------------------------------------------------- */
-static int saa717x_probe(struct i2c_client *client)
+static int saa717x_probe(struct i2c_client *client,
+ const struct i2c_device_id *did)
{
struct saa717x_state *decoder;
u8 id = 0;
--- linux-2.6.26-rc0.orig/drivers/media/video/tcm825x.c 2008-04-27 22:07:20.000000000 +0200
+++ linux-2.6.26-rc0/drivers/media/video/tcm825x.c 2008-04-27 22:09:29.000000000 +0200
@@ -840,7 +840,8 @@ static struct v4l2_int_device tcm825x_in
},
};
-static int tcm825x_probe(struct i2c_client *client)
+static int tcm825x_probe(struct i2c_client *client,
+ const struct i2c_device_id *did)
{
struct tcm825x_sensor *sensor = &tcm825x;
int rval;
--- linux-2.6.26-rc0.orig/drivers/media/video/tlv320aic23b.c 2008-04-27 22:05:00.000000000 +0200
+++ linux-2.6.26-rc0/drivers/media/video/tlv320aic23b.c 2008-04-27 22:09:29.000000000 +0200
@@ -125,7 +125,8 @@ static int tlv320aic23b_command(struct i
* concerning the addresses: i2c wants 7 bit (without the r/w bit), so '>>1'
*/
-static int tlv320aic23b_probe(struct i2c_client *client)
+static int tlv320aic23b_probe(struct i2c_client *client,
+ const struct i2c_device_id *id)
{
struct tlv320aic23b_state *state;
--- linux-2.6.26-rc0.orig/drivers/media/video/tuner-core.c 2008-04-27 22:07:20.000000000 +0200
+++ linux-2.6.26-rc0/drivers/media/video/tuner-core.c 2008-04-27 22:09:29.000000000 +0200
@@ -1073,7 +1073,8 @@ static void tuner_lookup(struct i2c_adap
/* During client attach, set_type is called by adapter's attach_inform callback.
set_type must then be completed by tuner_probe.
*/
-static int tuner_probe(struct i2c_client *client)
+static int tuner_probe(struct i2c_client *client,
+ const struct i2c_device_id *id)
{
struct tuner *t;
struct tuner *radio;
--- linux-2.6.26-rc0.orig/drivers/media/video/tvaudio.c 2008-04-27 22:07:20.000000000 +0200
+++ linux-2.6.26-rc0/drivers/media/video/tvaudio.c 2008-04-27 22:09:29.000000000 +0200
@@ -1461,7 +1461,7 @@ static struct CHIPDESC chiplist[] = {
/* ---------------------------------------------------------------------- */
/* i2c registration */
-static int chip_probe(struct i2c_client *client)
+static int chip_probe(struct i2c_client *client, const struct i2c_device_id *id)
{
struct CHIPSTATE *chip;
struct CHIPDESC *desc;
--- linux-2.6.26-rc0.orig/drivers/media/video/upd64031a.c 2008-04-27 22:05:00.000000000 +0200
+++ linux-2.6.26-rc0/drivers/media/video/upd64031a.c 2008-04-27 22:09:29.000000000 +0200
@@ -195,7 +195,8 @@ static int upd64031a_command(struct i2c_
/* i2c implementation */
-static int upd64031a_probe(struct i2c_client *client)
+static int upd64031a_probe(struct i2c_client *client,
+ const struct i2c_device_id *id)
{
struct upd64031a_state *state;
int i;
--- linux-2.6.26-rc0.orig/drivers/media/video/upd64083.c 2008-04-27 22:05:00.000000000 +0200
+++ linux-2.6.26-rc0/drivers/media/video/upd64083.c 2008-04-27 22:09:29.000000000 +0200
@@ -172,7 +172,8 @@ static int upd64083_command(struct i2c_c
/* i2c implementation */
-static int upd64083_probe(struct i2c_client *client)
+static int upd64083_probe(struct i2c_client *client,
+ const struct i2c_device_id *id)
{
struct upd64083_state *state;
int i;
--- linux-2.6.26-rc0.orig/drivers/media/video/v4l2-common.c 2008-04-27 22:05:00.000000000 +0200
+++ linux-2.6.26-rc0/drivers/media/video/v4l2-common.c 2008-04-27 22:09:29.000000000 +0200
@@ -710,7 +710,8 @@ EXPORT_SYMBOL(v4l2_chip_ident_i2c_client
/* Helper function for I2C legacy drivers */
int v4l2_i2c_attach(struct i2c_adapter *adapter, int address, struct i2c_driver *driver,
- const char *name, int (*probe)(struct i2c_client *))
+ const char *name,
+ int (*probe)(struct i2c_client *, const struct i2c_device_id *))
{
struct i2c_client *client;
int err;
@@ -724,7 +725,7 @@ int v4l2_i2c_attach(struct i2c_adapter *
client->driver = driver;
strlcpy(client->name, name, sizeof(client->name));
- err = probe(client);
+ err = probe(client, NULL);
if (err == 0) {
i2c_attach_client(client);
} else {
--- linux-2.6.26-rc0.orig/drivers/media/video/vp27smpx.c 2008-04-27 22:05:00.000000000 +0200
+++ linux-2.6.26-rc0/drivers/media/video/vp27smpx.c 2008-04-27 22:09:29.000000000 +0200
@@ -121,7 +121,8 @@ static int vp27smpx_command(struct i2c_c
* concerning the addresses: i2c wants 7 bit (without the r/w bit), so '>>1'
*/
-static int vp27smpx_probe(struct i2c_client *client)
+static int vp27smpx_probe(struct i2c_client *client,
+ const struct i2c_device_id *id)
{
struct vp27smpx_state *state;
--- linux-2.6.26-rc0.orig/drivers/media/video/wm8739.c 2008-04-27 22:05:00.000000000 +0200
+++ linux-2.6.26-rc0/drivers/media/video/wm8739.c 2008-04-27 22:09:29.000000000 +0200
@@ -261,7 +261,8 @@ static int wm8739_command(struct i2c_cli
/* i2c implementation */
-static int wm8739_probe(struct i2c_client *client)
+static int wm8739_probe(struct i2c_client *client,
+ const struct i2c_device_id *id)
{
struct wm8739_state *state;
--- linux-2.6.26-rc0.orig/drivers/media/video/wm8775.c 2008-04-27 22:05:00.000000000 +0200
+++ linux-2.6.26-rc0/drivers/media/video/wm8775.c 2008-04-27 22:09:29.000000000 +0200
@@ -159,7 +159,8 @@ static int wm8775_command(struct i2c_cli
* concerning the addresses: i2c wants 7 bit (without the r/w bit), so '>>1'
*/
-static int wm8775_probe(struct i2c_client *client)
+static int wm8775_probe(struct i2c_client *client,
+ const struct i2c_device_id *id)
{
struct wm8775_state *state;
--- linux-2.6.26-rc0.orig/drivers/rtc/rtc-ds1307.c 2008-04-27 22:05:00.000000000 +0200
+++ linux-2.6.26-rc0/drivers/rtc/rtc-ds1307.c 2008-04-27 22:09:29.000000000 +0200
@@ -326,7 +326,8 @@ static struct bin_attribute nvram = {
static struct i2c_driver ds1307_driver;
-static int __devinit ds1307_probe(struct i2c_client *client)
+static int __devinit ds1307_probe(struct i2c_client *client,
+ const struct i2c_device_id *id)
{
struct ds1307 *ds1307;
int err = -ENODEV;
--- linux-2.6.26-rc0.orig/drivers/rtc/rtc-ds1374.c 2008-04-27 22:05:00.000000000 +0200
+++ linux-2.6.26-rc0/drivers/rtc/rtc-ds1374.c 2008-04-27 22:09:29.000000000 +0200
@@ -355,7 +355,8 @@ static const struct rtc_class_ops ds1374
.ioctl = ds1374_ioctl,
};
-static int ds1374_probe(struct i2c_client *client)
+static int ds1374_probe(struct i2c_client *client,
+ const struct i2c_device_id *id)
{
struct ds1374 *ds1374;
int ret;
--- linux-2.6.26-rc0.orig/drivers/rtc/rtc-m41t80.c 2008-04-27 22:05:00.000000000 +0200
+++ linux-2.6.26-rc0/drivers/rtc/rtc-m41t80.c 2008-04-27 22:09:29.000000000 +0200
@@ -756,7 +756,8 @@ static struct notifier_block wdt_notifie
*
*****************************************************************************
*/
-static int m41t80_probe(struct i2c_client *client)
+static int m41t80_probe(struct i2c_client *client,
+ const struct i2c_device_id *id)
{
int i, rc = 0;
struct rtc_device *rtc = NULL;
--- linux-2.6.26-rc0.orig/drivers/rtc/rtc-rs5c372.c 2008-04-27 22:05:00.000000000 +0200
+++ linux-2.6.26-rc0/drivers/rtc/rtc-rs5c372.c 2008-04-27 22:09:29.000000000 +0200
@@ -494,7 +494,8 @@ static void rs5c_sysfs_unregister(struct
static struct i2c_driver rs5c372_driver;
-static int rs5c372_probe(struct i2c_client *client)
+static int rs5c372_probe(struct i2c_client *client,
+ const struct i2c_device_id *id)
{
int err = 0;
struct rs5c372 *rs5c372;
--- linux-2.6.26-rc0.orig/drivers/rtc/rtc-s35390a.c 2008-04-27 22:05:00.000000000 +0200
+++ linux-2.6.26-rc0/drivers/rtc/rtc-s35390a.c 2008-04-27 22:09:29.000000000 +0200
@@ -195,7 +195,8 @@ static const struct rtc_class_ops s35390
static struct i2c_driver s35390a_driver;
-static int s35390a_probe(struct i2c_client *client)
+static int s35390a_probe(struct i2c_client *client,
+ const struct i2c_device_id *id)
{
int err;
unsigned int i;
--- linux-2.6.26-rc0.orig/include/linux/i2c.h 2008-04-27 22:05:00.000000000 +0200
+++ linux-2.6.26-rc0/include/linux/i2c.h 2008-04-27 22:09:29.000000000 +0200
@@ -126,7 +126,7 @@ struct i2c_driver {
* With the driver model, device enumeration is NEVER done by drivers;
* it's done by infrastructure. (NEW STYLE DRIVERS ONLY)
*/
- int (*probe)(struct i2c_client *);
+ int (*probe)(struct i2c_client *, const struct i2c_device_id *);
int (*remove)(struct i2c_client *);
/* driver model interfaces that don't relate to enumeration */
@@ -140,11 +140,10 @@ struct i2c_driver {
int (*command)(struct i2c_client *client,unsigned int cmd, void *arg);
struct device_driver driver;
+ const struct i2c_device_id *id_table;
};
#define to_i2c_driver(d) container_of(d, struct i2c_driver, driver)
-#define I2C_NAME_SIZE 20
-
/**
* struct i2c_client - represent an I2C slave device
* @flags: I2C_CLIENT_TEN indicates the device uses a ten bit chip address;
--- linux-2.6.26-rc0.orig/include/linux/mod_devicetable.h 2008-04-27 22:05:00.000000000 +0200
+++ linux-2.6.26-rc0/include/linux/mod_devicetable.h 2008-04-27 22:09:29.000000000 +0200
@@ -368,4 +368,15 @@ struct virtio_device_id {
};
#define VIRTIO_DEV_ANY_ID 0xffffffff
+/* i2c */
+
+#define I2C_NAME_SIZE 20
+#define I2C_MODULE_PREFIX "i2c:"
+
+struct i2c_device_id {
+ char name[I2C_NAME_SIZE];
+ kernel_ulong_t driver_data; /* Data private to the driver */
+};
+
+
#endif /* LINUX_MOD_DEVICETABLE_H */
--- linux-2.6.26-rc0.orig/include/media/v4l2-common.h 2008-04-27 22:05:00.000000000 +0200
+++ linux-2.6.26-rc0/include/media/v4l2-common.h 2008-04-27 22:09:29.000000000 +0200
@@ -107,9 +107,11 @@ int v4l2_chip_match_host(u32 id_type, u3
struct i2c_driver;
struct i2c_adapter;
struct i2c_client;
+struct i2c_device_id;
int v4l2_i2c_attach(struct i2c_adapter *adapter, int address, struct i2c_driver *driver,
- const char *name, int (*probe)(struct i2c_client *));
+ const char *name,
+ int (*probe)(struct i2c_client *, const struct i2c_device_id *));
/* ------------------------------------------------------------------------- */
--- linux-2.6.26-rc0.orig/include/media/v4l2-i2c-drv-legacy.h 2008-04-27 22:05:00.000000000 +0200
+++ linux-2.6.26-rc0/include/media/v4l2-i2c-drv-legacy.h 2008-04-27 22:09:29.000000000 +0200
@@ -25,7 +25,7 @@ struct v4l2_i2c_driver_data {
const char * const name;
int driverid;
int (*command)(struct i2c_client *client, unsigned int cmd, void *arg);
- int (*probe)(struct i2c_client *client);
+ int (*probe)(struct i2c_client *client, const struct i2c_device_id *id);
int (*remove)(struct i2c_client *client);
int (*suspend)(struct i2c_client *client, pm_message_t state);
int (*resume)(struct i2c_client *client);
--- linux-2.6.26-rc0.orig/include/media/v4l2-i2c-drv.h 2008-04-27 22:05:00.000000000 +0200
+++ linux-2.6.26-rc0/include/media/v4l2-i2c-drv.h 2008-04-27 22:09:29.000000000 +0200
@@ -30,7 +30,7 @@ struct v4l2_i2c_driver_data {
const char * const name;
int driverid;
int (*command)(struct i2c_client *client, unsigned int cmd, void *arg);
- int (*probe)(struct i2c_client *client);
+ int (*probe)(struct i2c_client *client, const struct i2c_device_id *id);
int (*remove)(struct i2c_client *client);
int (*suspend)(struct i2c_client *client, pm_message_t state);
int (*resume)(struct i2c_client *client);
--- linux-2.6.26-rc0.orig/scripts/mod/file2alias.c 2008-04-27 22:07:28.000000000 +0200
+++ linux-2.6.26-rc0/scripts/mod/file2alias.c 2008-04-27 22:09:29.000000000 +0200
@@ -576,6 +576,15 @@ static int do_virtio_entry(const char *f
return 1;
}
+/* Looks like: i2c:S */
+static int do_i2c_entry(const char *filename, struct i2c_device_id *id,
+ char *alias)
+{
+ sprintf(alias, I2C_MODULE_PREFIX "%s", id->name);
+
+ return 1;
+}
+
/* Ignore any prefix, eg. v850 prepends _ */
static inline int sym_is(const char *symbol, const char *name)
{
@@ -704,6 +713,10 @@ void handle_moddevtable(struct module *m
do_table(symval, sym->st_size,
sizeof(struct virtio_device_id), "virtio",
do_virtio_entry, mod);
+ else if (sym_is(symname, "__mod_i2c_device_table"))
+ do_table(symval, sym->st_size,
+ sizeof(struct i2c_device_id), "i2c",
+ do_i2c_entry, mod);
free(zeros);
}
--
Jean Delvare
^ permalink raw reply
* [PATCH 2/2] i2c: Convert most new-style drivers to use module aliasing
From: Jean Delvare @ 2008-04-28 9:53 UTC (permalink / raw)
To: Linux I2C
Cc: Laurent, Sievers, linuxppc-dev list, Paul Mundt, Scott Wood, Kay
In-Reply-To: <20080428113052.6d024bda@hyperion.delvare>
Based on earlier work by Jon Smirl and Jochen Friedrich.
Update most new-style i2c drivers to use standard module aliasing
instead of the old driver_name/type driver matching scheme. I've
left the video drivers apart (except for SoC camera drivers) as
they're a bit more diffcult to deal with, they'll have their own
patch later.
Signed-off-by: Jean Delvare <khali@linux-fr.org>
Cc: Jon Smirl <jonsmirl@gmail.com>
Cc: Jochen Friedrich <jochen@scram.de>
Cc: Kay Sievers <kay.sievers@vrfy.org>
---
arch/arm/mach-at91/board-csb337.c | 3 -
arch/arm/mach-at91/board-dk.c | 3 -
arch/arm/mach-at91/board-eb9200.c | 3 -
arch/arm/mach-iop32x/em7210.c | 3 -
arch/arm/mach-iop32x/glantank.c | 4 -
arch/arm/mach-iop32x/n2100.c | 4 -
arch/arm/mach-ixp4xx/dsmg600-setup.c | 2
arch/arm/mach-ixp4xx/nas100d-setup.c | 2
arch/arm/mach-ixp4xx/nslu2-setup.c | 2
arch/arm/mach-omap1/board-h2.c | 2
arch/arm/mach-omap1/board-h3.c | 3 -
arch/arm/mach-omap1/board-osk.c | 1
arch/arm/mach-orion5x/db88f5281-setup.c | 4 -
arch/arm/mach-orion5x/dns323-setup.c | 7 --
arch/arm/mach-orion5x/kurobox_pro-setup.c | 4 -
arch/arm/mach-orion5x/rd88f5182-setup.c | 4 -
arch/arm/mach-orion5x/ts209-setup.c | 3 -
arch/arm/mach-pxa/pcm990-baseboard.c | 5 -
arch/blackfin/mach-bf533/boards/stamp.c | 3 -
arch/blackfin/mach-bf537/boards/stamp.c | 3 -
arch/blackfin/mach-bf548/boards/ezkit.c | 2
arch/powerpc/sysdev/fsl_soc.c | 27 ++++------
arch/sh/boards/renesas/migor/setup.c | 3 -
arch/sh/boards/renesas/r7780rp/setup.c | 3 -
drivers/gpio/pca953x.c | 23 +-------
drivers/gpio/pcf857x.c | 33 +++++++-----
drivers/hwmon/f75375s.c | 23 ++++----
drivers/i2c/busses/i2c-taos-evm.c | 3 -
drivers/i2c/chips/ds1682.c | 7 ++
drivers/i2c/chips/menelaus.c | 7 ++
drivers/i2c/chips/tps65010.c | 29 ++++------
drivers/i2c/chips/tsl2550.c | 7 ++
drivers/media/video/mt9m001.c | 7 ++
drivers/media/video/mt9v022.c | 7 ++
drivers/rtc/rtc-ds1307.c | 63 +++++++++--------------
drivers/rtc/rtc-ds1374.c | 7 ++
drivers/rtc/rtc-m41t80.c | 78 +++++++----------------------
drivers/rtc/rtc-rs5c372.c | 24 ++++----
drivers/rtc/rtc-s35390a.c | 7 ++
include/linux/i2c.h | 12 ++--
40 files changed, 190 insertions(+), 247 deletions(-)
--- linux-2.6.26-rc0.orig/arch/arm/mach-at91/board-csb337.c 2008-04-27 22:07:12.000000000 +0200
+++ linux-2.6.26-rc0/arch/arm/mach-at91/board-csb337.c 2008-04-27 22:09:48.000000000 +0200
@@ -79,8 +79,7 @@ static struct at91_udc_data __initdata c
static struct i2c_board_info __initdata csb337_i2c_devices[] = {
{
- I2C_BOARD_INFO("rtc-ds1307", 0x68),
- .type = "ds1307",
+ I2C_BOARD_INFO("ds1307", 0x68),
},
};
--- linux-2.6.26-rc0.orig/arch/arm/mach-at91/board-dk.c 2008-04-27 22:04:59.000000000 +0200
+++ linux-2.6.26-rc0/arch/arm/mach-at91/board-dk.c 2008-04-27 22:09:48.000000000 +0200
@@ -132,8 +132,7 @@ static struct i2c_board_info __initdata
I2C_BOARD_INFO("x9429", 0x28),
},
{
- I2C_BOARD_INFO("at24c", 0x50),
- .type = "24c1024",
+ I2C_BOARD_INFO("24c1024", 0x50),
}
};
--- linux-2.6.26-rc0.orig/arch/arm/mach-at91/board-eb9200.c 2008-04-27 22:04:59.000000000 +0200
+++ linux-2.6.26-rc0/arch/arm/mach-at91/board-eb9200.c 2008-04-27 22:09:48.000000000 +0200
@@ -93,8 +93,7 @@ static struct at91_mmc_data __initdata e
static struct i2c_board_info __initdata eb9200_i2c_devices[] = {
{
- I2C_BOARD_INFO("at24c", 0x50),
- .type = "24c512",
+ I2C_BOARD_INFO("24c512", 0x50),
},
};
--- linux-2.6.26-rc0.orig/arch/arm/mach-iop32x/em7210.c 2008-04-27 22:04:59.000000000 +0200
+++ linux-2.6.26-rc0/arch/arm/mach-iop32x/em7210.c 2008-04-27 22:09:48.000000000 +0200
@@ -50,8 +50,7 @@ static struct sys_timer em7210_timer = {
*/
static struct i2c_board_info __initdata em7210_i2c_devices[] = {
{
- I2C_BOARD_INFO("rtc-rs5c372", 0x32),
- .type = "rs5c372a",
+ I2C_BOARD_INFO("rs5c372a", 0x32),
},
};
--- linux-2.6.26-rc0.orig/arch/arm/mach-iop32x/glantank.c 2008-04-27 22:04:59.000000000 +0200
+++ linux-2.6.26-rc0/arch/arm/mach-iop32x/glantank.c 2008-04-27 22:09:48.000000000 +0200
@@ -176,12 +176,10 @@ static struct f75375s_platform_data glan
static struct i2c_board_info __initdata glantank_i2c_devices[] = {
{
- I2C_BOARD_INFO("rtc-rs5c372", 0x32),
- .type = "rs5c372a",
+ I2C_BOARD_INFO("rs5c372a", 0x32),
},
{
I2C_BOARD_INFO("f75375", 0x2e),
- .type = "f75375",
.platform_data = &glantank_f75375s,
},
};
--- linux-2.6.26-rc0.orig/arch/arm/mach-iop32x/n2100.c 2008-04-27 22:04:59.000000000 +0200
+++ linux-2.6.26-rc0/arch/arm/mach-iop32x/n2100.c 2008-04-27 22:09:48.000000000 +0200
@@ -208,12 +208,10 @@ static struct f75375s_platform_data n210
static struct i2c_board_info __initdata n2100_i2c_devices[] = {
{
- I2C_BOARD_INFO("rtc-rs5c372", 0x32),
- .type = "rs5c372b",
+ I2C_BOARD_INFO("rs5c372b", 0x32),
},
{
I2C_BOARD_INFO("f75375", 0x2e),
- .type = "f75375",
.platform_data = &n2100_f75375s,
},
};
--- linux-2.6.26-rc0.orig/arch/arm/mach-ixp4xx/dsmg600-setup.c 2008-04-27 22:04:59.000000000 +0200
+++ linux-2.6.26-rc0/arch/arm/mach-ixp4xx/dsmg600-setup.c 2008-04-27 22:09:48.000000000 +0200
@@ -65,7 +65,7 @@ static struct platform_device dsmg600_i2
static struct i2c_board_info __initdata dsmg600_i2c_board_info [] = {
{
- I2C_BOARD_INFO("rtc-pcf8563", 0x51),
+ I2C_BOARD_INFO("pcf8563", 0x51),
},
};
--- linux-2.6.26-rc0.orig/arch/arm/mach-ixp4xx/nas100d-setup.c 2008-04-27 22:04:59.000000000 +0200
+++ linux-2.6.26-rc0/arch/arm/mach-ixp4xx/nas100d-setup.c 2008-04-27 22:09:48.000000000 +0200
@@ -54,7 +54,7 @@ static struct platform_device nas100d_fl
static struct i2c_board_info __initdata nas100d_i2c_board_info [] = {
{
- I2C_BOARD_INFO("rtc-pcf8563", 0x51),
+ I2C_BOARD_INFO("pcf8563", 0x51),
},
};
--- linux-2.6.26-rc0.orig/arch/arm/mach-ixp4xx/nslu2-setup.c 2008-04-27 22:04:59.000000000 +0200
+++ linux-2.6.26-rc0/arch/arm/mach-ixp4xx/nslu2-setup.c 2008-04-27 22:09:48.000000000 +0200
@@ -57,7 +57,7 @@ static struct i2c_gpio_platform_data nsl
static struct i2c_board_info __initdata nslu2_i2c_board_info [] = {
{
- I2C_BOARD_INFO("rtc-x1205", 0x6f),
+ I2C_BOARD_INFO("x1205", 0x6f),
},
};
--- linux-2.6.26-rc0.orig/arch/arm/mach-omap1/board-h2.c 2008-04-27 22:04:59.000000000 +0200
+++ linux-2.6.26-rc0/arch/arm/mach-omap1/board-h2.c 2008-04-27 22:09:48.000000000 +0200
@@ -351,11 +351,9 @@ static void __init h2_init_smc91x(void)
static struct i2c_board_info __initdata h2_i2c_board_info[] = {
{
I2C_BOARD_INFO("tps65010", 0x48),
- .type = "tps65010",
.irq = OMAP_GPIO_IRQ(58),
}, {
I2C_BOARD_INFO("isp1301_omap", 0x2d),
- .type = "isp1301_omap",
.irq = OMAP_GPIO_IRQ(2),
},
};
--- linux-2.6.26-rc0.orig/arch/arm/mach-omap1/board-h3.c 2008-04-27 22:04:59.000000000 +0200
+++ linux-2.6.26-rc0/arch/arm/mach-omap1/board-h3.c 2008-04-27 22:09:48.000000000 +0200
@@ -473,8 +473,7 @@ static struct omap_board_config_kernel h
static struct i2c_board_info __initdata h3_i2c_board_info[] = {
{
- I2C_BOARD_INFO("tps65010", 0x48),
- .type = "tps65013",
+ I2C_BOARD_INFO("tps65013", 0x48),
/* .irq = OMAP_GPIO_IRQ(??), */
},
};
--- linux-2.6.26-rc0.orig/arch/arm/mach-omap1/board-osk.c 2008-04-27 22:07:12.000000000 +0200
+++ linux-2.6.26-rc0/arch/arm/mach-omap1/board-osk.c 2008-04-27 22:09:48.000000000 +0200
@@ -254,7 +254,6 @@ static struct tps65010_board tps_board =
static struct i2c_board_info __initdata osk_i2c_board_info[] = {
{
I2C_BOARD_INFO("tps65010", 0x48),
- .type = "tps65010",
.irq = OMAP_GPIO_IRQ(OMAP_MPUIO(1)),
.platform_data = &tps_board,
--- linux-2.6.26-rc0.orig/arch/arm/mach-orion5x/db88f5281-setup.c 2008-04-27 22:07:12.000000000 +0200
+++ linux-2.6.26-rc0/arch/arm/mach-orion5x/db88f5281-setup.c 2008-04-27 22:57:29.000000000 +0200
@@ -292,9 +292,7 @@ static struct mv643xx_eth_platform_data
* RTC DS1339 on I2C bus
****************************************************************************/
static struct i2c_board_info __initdata db88f5281_i2c_rtc = {
- .driver_name = "rtc-ds1307",
- .type = "ds1339",
- .addr = 0x68,
+ I2C_BOARD_INFO("ds1339", 0x68),
};
/*****************************************************************************
--- linux-2.6.26-rc0.orig/arch/arm/mach-orion5x/dns323-setup.c 2008-04-27 22:07:12.000000000 +0200
+++ linux-2.6.26-rc0/arch/arm/mach-orion5x/dns323-setup.c 2008-04-27 22:09:48.000000000 +0200
@@ -220,19 +220,16 @@ static struct platform_device *dns323_pl
static struct i2c_board_info __initdata dns323_i2c_devices[] = {
{
I2C_BOARD_INFO("g760a", 0x3e),
- .type = "g760a",
},
#if 0
/* this entry requires the new-style driver model lm75 driver,
* for the meantime "insmod lm75.ko force_lm75=0,0x48" is needed */
{
- I2C_BOARD_INFO("lm75", 0x48),
- .type = "g751",
+ I2C_BOARD_INFO("g751", 0x48),
},
#endif
{
- I2C_BOARD_INFO("rtc-m41t80", 0x68),
- .type = "m41t80",
+ I2C_BOARD_INFO("m41t80", 0x68),
}
};
--- linux-2.6.26-rc0.orig/arch/arm/mach-orion5x/kurobox_pro-setup.c 2008-04-27 22:07:12.000000000 +0200
+++ linux-2.6.26-rc0/arch/arm/mach-orion5x/kurobox_pro-setup.c 2008-04-27 22:56:59.000000000 +0200
@@ -162,9 +162,7 @@ static struct mv643xx_eth_platform_data
* RTC 5C372a on I2C bus
****************************************************************************/
static struct i2c_board_info __initdata kurobox_pro_i2c_rtc = {
- .driver_name = "rtc-rs5c372",
- .type = "rs5c372a",
- .addr = 0x32,
+ I2C_BOARD_INFO("rs5c372a", 0x32),
};
/*****************************************************************************
--- linux-2.6.26-rc0.orig/arch/arm/mach-orion5x/rd88f5182-setup.c 2008-04-27 22:07:12.000000000 +0200
+++ linux-2.6.26-rc0/arch/arm/mach-orion5x/rd88f5182-setup.c 2008-04-27 22:58:02.000000000 +0200
@@ -224,9 +224,7 @@ static struct mv643xx_eth_platform_data
* RTC DS1338 on I2C bus
****************************************************************************/
static struct i2c_board_info __initdata rd88f5182_i2c_rtc = {
- .driver_name = "rtc-ds1307",
- .type = "ds1338",
- .addr = 0x68,
+ I2C_BOARD_INFO("ds1338", 0x68),
};
/*****************************************************************************
--- linux-2.6.26-rc0.orig/arch/arm/mach-orion5x/ts209-setup.c 2008-04-27 22:07:12.000000000 +0200
+++ linux-2.6.26-rc0/arch/arm/mach-orion5x/ts209-setup.c 2008-04-27 22:58:52.000000000 +0200
@@ -276,8 +276,7 @@ static void __init ts209_find_mac_addr(v
#define TS209_RTC_GPIO 3
static struct i2c_board_info __initdata qnap_ts209_i2c_rtc = {
- .driver_name = "rtc-s35390a",
- .addr = 0x30,
+ I2C_BOARD_INFO("s35390a", 0x30),
.irq = 0,
};
--- linux-2.6.26-rc0.orig/arch/arm/mach-pxa/pcm990-baseboard.c 2008-04-27 22:07:12.000000000 +0200
+++ linux-2.6.26-rc0/arch/arm/mach-pxa/pcm990-baseboard.c 2008-04-27 22:09:48.000000000 +0200
@@ -320,16 +320,13 @@ static struct soc_camera_link iclink[] =
static struct i2c_board_info __initdata pcm990_i2c_devices[] = {
{
/* Must initialize before the camera(s) */
- I2C_BOARD_INFO("pca953x", 0x41),
- .type = "pca9536",
+ I2C_BOARD_INFO("pca9536", 0x41),
.platform_data = &pca9536_data,
}, {
I2C_BOARD_INFO("mt9v022", 0x48),
- .type = "mt9v022",
.platform_data = &iclink[0], /* With extender */
}, {
I2C_BOARD_INFO("mt9m001", 0x5d),
- .type = "mt9m001",
.platform_data = &iclink[0], /* With extender */
},
};
--- linux-2.6.26-rc0.orig/arch/blackfin/mach-bf533/boards/stamp.c 2008-04-27 22:07:12.000000000 +0200
+++ linux-2.6.26-rc0/arch/blackfin/mach-bf533/boards/stamp.c 2008-04-27 22:09:48.000000000 +0200
@@ -499,20 +499,17 @@ static struct i2c_board_info __initdata
#if defined(CONFIG_JOYSTICK_AD7142) || defined(CONFIG_JOYSTICK_AD7142_MODULE)
{
I2C_BOARD_INFO("ad7142_joystick", 0x2C),
- .type = "ad7142_joystick",
.irq = 39,
},
#endif
#if defined(CONFIG_TWI_LCD) || defined(CONFIG_TWI_LCD_MODULE)
{
I2C_BOARD_INFO("pcf8574_lcd", 0x22),
- .type = "pcf8574_lcd",
},
#endif
#if defined(CONFIG_TWI_KEYPAD) || defined(CONFIG_TWI_KEYPAD_MODULE)
{
I2C_BOARD_INFO("pcf8574_keypad", 0x27),
- .type = "pcf8574_keypad",
.irq = 39,
},
#endif
--- linux-2.6.26-rc0.orig/arch/blackfin/mach-bf537/boards/stamp.c 2008-04-27 22:07:12.000000000 +0200
+++ linux-2.6.26-rc0/arch/blackfin/mach-bf537/boards/stamp.c 2008-04-27 22:09:48.000000000 +0200
@@ -751,20 +751,17 @@ static struct i2c_board_info __initdata
#if defined(CONFIG_JOYSTICK_AD7142) || defined(CONFIG_JOYSTICK_AD7142_MODULE)
{
I2C_BOARD_INFO("ad7142_joystick", 0x2C),
- .type = "ad7142_joystick",
.irq = 55,
},
#endif
#if defined(CONFIG_TWI_LCD) || defined(CONFIG_TWI_LCD_MODULE)
{
I2C_BOARD_INFO("pcf8574_lcd", 0x22),
- .type = "pcf8574_lcd",
},
#endif
#if defined(CONFIG_TWI_KEYPAD) || defined(CONFIG_TWI_KEYPAD_MODULE)
{
I2C_BOARD_INFO("pcf8574_keypad", 0x27),
- .type = "pcf8574_keypad",
.irq = 72,
},
#endif
--- linux-2.6.26-rc0.orig/arch/blackfin/mach-bf548/boards/ezkit.c 2008-04-27 22:07:12.000000000 +0200
+++ linux-2.6.26-rc0/arch/blackfin/mach-bf548/boards/ezkit.c 2008-04-27 22:09:48.000000000 +0200
@@ -641,13 +641,11 @@ static struct i2c_board_info __initdata
#if defined(CONFIG_TWI_LCD) || defined(CONFIG_TWI_LCD_MODULE)
{
I2C_BOARD_INFO("pcf8574_lcd", 0x22),
- .type = "pcf8574_lcd",
},
#endif
#if defined(CONFIG_TWI_KEYPAD) || defined(CONFIG_TWI_KEYPAD_MODULE)
{
I2C_BOARD_INFO("pcf8574_keypad", 0x27),
- .type = "pcf8574_keypad",
.irq = 212,
},
#endif
--- linux-2.6.26-rc0.orig/arch/powerpc/sysdev/fsl_soc.c 2008-04-27 22:07:13.000000000 +0200
+++ linux-2.6.26-rc0/arch/powerpc/sysdev/fsl_soc.c 2008-04-27 22:09:48.000000000 +0200
@@ -418,22 +418,21 @@ arch_initcall(gfar_of_init);
#include <linux/i2c.h>
struct i2c_driver_device {
char *of_device;
- char *i2c_driver;
char *i2c_type;
};
static struct i2c_driver_device i2c_devices[] __initdata = {
- {"ricoh,rs5c372a", "rtc-rs5c372", "rs5c372a",},
- {"ricoh,rs5c372b", "rtc-rs5c372", "rs5c372b",},
- {"ricoh,rv5c386", "rtc-rs5c372", "rv5c386",},
- {"ricoh,rv5c387a", "rtc-rs5c372", "rv5c387a",},
- {"dallas,ds1307", "rtc-ds1307", "ds1307",},
- {"dallas,ds1337", "rtc-ds1307", "ds1337",},
- {"dallas,ds1338", "rtc-ds1307", "ds1338",},
- {"dallas,ds1339", "rtc-ds1307", "ds1339",},
- {"dallas,ds1340", "rtc-ds1307", "ds1340",},
- {"stm,m41t00", "rtc-ds1307", "m41t00"},
- {"dallas,ds1374", "rtc-ds1374", "rtc-ds1374",},
+ {"ricoh,rs5c372a", "rs5c372a"},
+ {"ricoh,rs5c372b", "rs5c372b"},
+ {"ricoh,rv5c386", "rv5c386"},
+ {"ricoh,rv5c387a", "rv5c387a"},
+ {"dallas,ds1307", "ds1307"},
+ {"dallas,ds1337", "ds1337"},
+ {"dallas,ds1338", "ds1338"},
+ {"dallas,ds1339", "ds1339"},
+ {"dallas,ds1340", "ds1340"},
+ {"stm,m41t00", "m41t00"},
+ {"dallas,ds1374", "rtc-ds1374"},
};
static int __init of_find_i2c_driver(struct device_node *node,
@@ -444,9 +443,7 @@ static int __init of_find_i2c_driver(str
for (i = 0; i < ARRAY_SIZE(i2c_devices); i++) {
if (!of_device_is_compatible(node, i2c_devices[i].of_device))
continue;
- if (strlcpy(info->driver_name, i2c_devices[i].i2c_driver,
- KOBJ_NAME_LEN) >= KOBJ_NAME_LEN ||
- strlcpy(info->type, i2c_devices[i].i2c_type,
+ if (strlcpy(info->type, i2c_devices[i].i2c_type,
I2C_NAME_SIZE) >= I2C_NAME_SIZE)
return -ENOMEM;
return 0;
--- linux-2.6.26-rc0.orig/arch/sh/boards/renesas/migor/setup.c 2008-04-27 22:07:13.000000000 +0200
+++ linux-2.6.26-rc0/arch/sh/boards/renesas/migor/setup.c 2008-04-27 22:09:48.000000000 +0200
@@ -199,8 +199,7 @@ static struct platform_device *migor_dev
static struct i2c_board_info __initdata migor_i2c_devices[] = {
{
- I2C_BOARD_INFO("rtc-rs5c372", 0x32),
- .type = "rs5c372b",
+ I2C_BOARD_INFO("rs5c372b", 0x32),
},
{
I2C_BOARD_INFO("migor_ts", 0x51),
--- linux-2.6.26-rc0.orig/arch/sh/boards/renesas/r7780rp/setup.c 2008-04-27 22:07:13.000000000 +0200
+++ linux-2.6.26-rc0/arch/sh/boards/renesas/r7780rp/setup.c 2008-04-27 22:09:48.000000000 +0200
@@ -199,8 +199,7 @@ static struct platform_device smbus_devi
static struct i2c_board_info __initdata highlander_i2c_devices[] = {
{
- I2C_BOARD_INFO("rtc-rs5c372", 0x32),
- .type = "r2025sd",
+ I2C_BOARD_INFO("r2025sd", 0x32),
},
};
--- linux-2.6.26-rc0.orig/drivers/gpio/pca953x.c 2008-04-27 22:09:29.000000000 +0200
+++ linux-2.6.26-rc0/drivers/gpio/pca953x.c 2008-04-27 22:09:48.000000000 +0200
@@ -23,13 +23,7 @@
#define PCA953X_INVERT 2
#define PCA953X_DIRECTION 3
-/* This is temporary - in 2.6.26 i2c_driver_data should replace it. */
-struct pca953x_desc {
- char name[I2C_NAME_SIZE];
- unsigned long driver_data;
-};
-
-static const struct pca953x_desc pca953x_descs[] = {
+static const struct i2c_device_id pca953x_id[] = {
{ "pca9534", 8, },
{ "pca9535", 16, },
{ "pca9536", 4, },
@@ -37,7 +31,9 @@ static const struct pca953x_desc pca953x
{ "pca9538", 8, },
{ "pca9539", 16, },
/* REVISIT several pca955x parts should work here too */
+ { }
};
+MODULE_DEVICE_TABLE(i2c, pca953x_id);
struct pca953x_chip {
unsigned gpio_start;
@@ -192,26 +188,16 @@ static void pca953x_setup_gpio(struct pc
}
static int __devinit pca953x_probe(struct i2c_client *client,
- const struct i2c_device_id *did)
+ const struct i2c_device_id *id)
{
struct pca953x_platform_data *pdata;
struct pca953x_chip *chip;
int ret, i;
- const struct pca953x_desc *id = NULL;
pdata = client->dev.platform_data;
if (pdata == NULL)
return -ENODEV;
- /* this loop vanishes when we get i2c_device_id */
- for (i = 0; i < ARRAY_SIZE(pca953x_descs); i++)
- if (!strcmp(pca953x_descs[i].name, client->name)) {
- id = pca953x_descs + i;
- break;
- }
- if (!id)
- return -ENODEV;
-
chip = kzalloc(sizeof(struct pca953x_chip), GFP_KERNEL);
if (chip == NULL)
return -ENOMEM;
@@ -291,6 +277,7 @@ static struct i2c_driver pca953x_driver
},
.probe = pca953x_probe,
.remove = pca953x_remove,
+ .id_table = pca953x_id,
};
static int __init pca953x_init(void)
--- linux-2.6.26-rc0.orig/drivers/gpio/pcf857x.c 2008-04-27 22:09:29.000000000 +0200
+++ linux-2.6.26-rc0/drivers/gpio/pcf857x.c 2008-04-27 22:09:48.000000000 +0200
@@ -26,6 +26,21 @@
#include <asm/gpio.h>
+static const struct i2c_device_id pcf857x_id[] = {
+ { "pcf8574", 8 },
+ { "pca8574", 8 },
+ { "pca9670", 8 },
+ { "pca9672", 8 },
+ { "pca9674", 8 },
+ { "pcf8575", 16 },
+ { "pca8575", 16 },
+ { "pca9671", 16 },
+ { "pca9673", 16 },
+ { "pca9675", 16 },
+ { }
+};
+MODULE_DEVICE_TABLE(i2c, pcf857x_id);
+
/*
* The pcf857x, pca857x, and pca967x chips only expose one read and one
* write register. Writing a "one" bit (to match the reset state) lets
@@ -172,13 +187,8 @@ static int pcf857x_probe(struct i2c_clie
*
* NOTE: we don't distinguish here between *4 and *4a parts.
*/
- if (strcmp(client->name, "pcf8574") == 0
- || strcmp(client->name, "pca8574") == 0
- || strcmp(client->name, "pca9670") == 0
- || strcmp(client->name, "pca9672") == 0
- || strcmp(client->name, "pca9674") == 0
- ) {
- gpio->chip.ngpio = 8;
+ gpio->chip.ngpio = id->driver_data;
+ if (gpio->chip.ngpio == 8) {
gpio->chip.direction_input = pcf857x_input8;
gpio->chip.get = pcf857x_get8;
gpio->chip.direction_output = pcf857x_output8;
@@ -198,13 +208,7 @@ static int pcf857x_probe(struct i2c_clie
*
* NOTE: we don't distinguish here between '75 and '75c parts.
*/
- } else if (strcmp(client->name, "pcf8575") == 0
- || strcmp(client->name, "pca8575") == 0
- || strcmp(client->name, "pca9671") == 0
- || strcmp(client->name, "pca9673") == 0
- || strcmp(client->name, "pca9675") == 0
- ) {
- gpio->chip.ngpio = 16;
+ } else if (gpio->chip.ngpio == 16) {
gpio->chip.direction_input = pcf857x_input16;
gpio->chip.get = pcf857x_get16;
gpio->chip.direction_output = pcf857x_output16;
@@ -313,6 +317,7 @@ static struct i2c_driver pcf857x_driver
},
.probe = pcf857x_probe,
.remove = pcf857x_remove,
+ .id_table = pcf857x_id,
};
static int __init pcf857x_init(void)
--- linux-2.6.26-rc0.orig/drivers/hwmon/f75375s.c 2008-04-27 22:09:29.000000000 +0200
+++ linux-2.6.26-rc0/drivers/hwmon/f75375s.c 2008-04-27 22:09:48.000000000 +0200
@@ -129,12 +129,20 @@ static struct i2c_driver f75375_legacy_d
.detach_client = f75375_detach_client,
};
+static const struct i2c_device_id f75375_id[] = {
+ { "f75373", f75373 },
+ { "f75375", f75375 },
+ { }
+};
+MODULE_DEVICE_TABLE(i2c, f75375_id);
+
static struct i2c_driver f75375_driver = {
.driver = {
.name = "f75375",
},
.probe = f75375_probe,
.remove = f75375_remove,
+ .id_table = f75375_id,
};
static inline int f75375_read8(struct i2c_client *client, u8 reg)
@@ -645,15 +653,7 @@ static int f75375_probe(struct i2c_clien
i2c_set_clientdata(client, data);
data->client = client;
mutex_init(&data->update_lock);
-
- if (strcmp(client->name, "f75375") == 0)
- data->kind = f75375;
- else if (strcmp(client->name, "f75373") == 0)
- data->kind = f75373;
- else {
- dev_err(&client->dev, "Unsupported device: %s\n", client->name);
- return -ENODEV;
- }
+ data->kind = id->driver_data;
if ((err = sysfs_create_group(&client->dev.kobj, &f75375_group)))
goto exit_free;
@@ -714,6 +714,7 @@ static int f75375_detect(struct i2c_adap
u8 version = 0;
int err = 0;
const char *name = "";
+ struct i2c_device_id id;
if (!(client = kzalloc(sizeof(*client), GFP_KERNEL))) {
err = -ENOMEM;
@@ -750,7 +751,9 @@ static int f75375_detect(struct i2c_adap
if ((err = i2c_attach_client(client)))
goto exit_free;
- if ((err = f75375_probe(client, NULL)) < 0)
+ strlcpy(id.name, name, I2C_NAME_SIZE);
+ id.driver_data = kind;
+ if ((err = f75375_probe(client, &id)) < 0)
goto exit_detach;
return 0;
--- linux-2.6.26-rc0.orig/drivers/i2c/busses/i2c-taos-evm.c 2008-04-27 22:04:59.000000000 +0200
+++ linux-2.6.26-rc0/drivers/i2c/busses/i2c-taos-evm.c 2008-04-27 22:09:48.000000000 +0200
@@ -51,7 +51,6 @@ struct taos_data {
/* TAOS TSL2550 EVM */
static struct i2c_board_info tsl2550_info = {
I2C_BOARD_INFO("tsl2550", 0x39),
- .type = "tsl2550",
};
/* Instantiate i2c devices based on the adapter name */
@@ -59,7 +58,7 @@ static struct i2c_client *taos_instantia
{
if (!strncmp(adapter->name, "TAOS TSL2550 EVM", 16)) {
dev_info(&adapter->dev, "Instantiating device %s at 0x%02x\n",
- tsl2550_info.driver_name, tsl2550_info.addr);
+ tsl2550_info.type, tsl2550_info.addr);
return i2c_new_device(adapter, &tsl2550_info);
}
--- linux-2.6.26-rc0.orig/drivers/i2c/chips/ds1682.c 2008-04-27 22:09:29.000000000 +0200
+++ linux-2.6.26-rc0/drivers/i2c/chips/ds1682.c 2008-04-27 22:09:48.000000000 +0200
@@ -235,12 +235,19 @@ static int ds1682_remove(struct i2c_clie
return 0;
}
+static const struct i2c_device_id ds1682_id[] = {
+ { "ds1682", 0 },
+ { }
+};
+MODULE_DEVICE_TABLE(i2c, ds1682_id);
+
static struct i2c_driver ds1682_driver = {
.driver = {
.name = "ds1682",
},
.probe = ds1682_probe,
.remove = ds1682_remove,
+ .id_table = ds1682_id,
};
static int __init ds1682_init(void)
--- linux-2.6.26-rc0.orig/drivers/i2c/chips/menelaus.c 2008-04-27 22:09:29.000000000 +0200
+++ linux-2.6.26-rc0/drivers/i2c/chips/menelaus.c 2008-04-27 22:09:48.000000000 +0200
@@ -1243,12 +1243,19 @@ static int __exit menelaus_remove(struct
return 0;
}
+static const struct i2c_device_id menelaus_id[] = {
+ { "menelaus", 0 },
+ { }
+};
+MODULE_DEVICE_TABLE(i2c, menelaus_id);
+
static struct i2c_driver menelaus_i2c_driver = {
.driver = {
.name = DRIVER_NAME,
},
.probe = menelaus_probe,
.remove = __exit_p(menelaus_remove),
+ .id_table = menelaus_id,
};
static int __init menelaus_init(void)
--- linux-2.6.26-rc0.orig/drivers/i2c/chips/tps65010.c 2008-04-27 22:09:29.000000000 +0200
+++ linux-2.6.26-rc0/drivers/i2c/chips/tps65010.c 2008-04-27 22:09:48.000000000 +0200
@@ -64,7 +64,6 @@ static struct i2c_driver tps65010_driver
* as part of board setup by a bootloader.
*/
enum tps_model {
- TPS_UNKNOWN = 0,
TPS65010,
TPS65011,
TPS65012,
@@ -554,20 +553,7 @@ static int tps65010_probe(struct i2c_cli
mutex_init(&tps->lock);
INIT_DELAYED_WORK(&tps->work, tps65010_work);
tps->client = client;
-
- if (strcmp(client->name, "tps65010") == 0)
- tps->model = TPS65010;
- else if (strcmp(client->name, "tps65011") == 0)
- tps->model = TPS65011;
- else if (strcmp(client->name, "tps65012") == 0)
- tps->model = TPS65012;
- else if (strcmp(client->name, "tps65013") == 0)
- tps->model = TPS65013;
- else {
- dev_warn(&client->dev, "unknown chip '%s'\n", client->name);
- status = -ENODEV;
- goto fail1;
- }
+ tps->model = id->driver_data;
/* the IRQ is active low, but many gpio lines can't support that
* so this driver uses falling-edge triggers instead.
@@ -596,9 +582,6 @@ static int tps65010_probe(struct i2c_cli
case TPS65012:
tps->por = 1;
break;
- case TPS_UNKNOWN:
- printk(KERN_WARNING "%s: unknown TPS chip\n", DRIVER_NAME);
- break;
/* else CHGCONFIG.POR is replaced by AUA, enabling a WAIT mode */
}
tps->chgconf = i2c_smbus_read_byte_data(client, TPS_CHGCONFIG);
@@ -685,12 +668,22 @@ fail1:
return status;
}
+static const struct i2c_device_id tps65010_id[] = {
+ { "tps65010", TPS65010 },
+ { "tps65011", TPS65011 },
+ { "tps65012", TPS65012 },
+ { "tps65013", TPS65013 },
+ { }
+};
+MODULE_DEVICE_TABLE(i2c, tps65010_id);
+
static struct i2c_driver tps65010_driver = {
.driver = {
.name = "tps65010",
},
.probe = tps65010_probe,
.remove = __exit_p(tps65010_remove),
+ .id_table = tps65010_id,
};
/*-------------------------------------------------------------------------*/
--- linux-2.6.26-rc0.orig/drivers/i2c/chips/tsl2550.c 2008-04-27 22:09:29.000000000 +0200
+++ linux-2.6.26-rc0/drivers/i2c/chips/tsl2550.c 2008-04-27 22:09:48.000000000 +0200
@@ -452,6 +452,12 @@ static int tsl2550_resume(struct i2c_cli
#endif /* CONFIG_PM */
+static const struct i2c_device_id tsl2550_id[] = {
+ { "tsl2550", 0 },
+ { }
+};
+MODULE_DEVICE_TABLE(i2c, tsl2550_id);
+
static struct i2c_driver tsl2550_driver = {
.driver = {
.name = TSL2550_DRV_NAME,
@@ -461,6 +467,7 @@ static struct i2c_driver tsl2550_driver
.resume = tsl2550_resume,
.probe = tsl2550_probe,
.remove = __devexit_p(tsl2550_remove),
+ .id_table = tsl2550_id,
};
static int __init tsl2550_init(void)
--- linux-2.6.26-rc0.orig/drivers/media/video/mt9m001.c 2008-04-27 22:09:29.000000000 +0200
+++ linux-2.6.26-rc0/drivers/media/video/mt9m001.c 2008-04-27 22:09:48.000000000 +0200
@@ -697,12 +697,19 @@ static int mt9m001_remove(struct i2c_cli
return 0;
}
+static const struct i2c_device_id mt9m001_id[] = {
+ { "mt9m001", 0 },
+ { }
+};
+MODULE_DEVICE_TABLE(i2c, mt9m001_id);
+
static struct i2c_driver mt9m001_i2c_driver = {
.driver = {
.name = "mt9m001",
},
.probe = mt9m001_probe,
.remove = mt9m001_remove,
+ .id_table = mt9m001_id,
};
static int __init mt9m001_mod_init(void)
--- linux-2.6.26-rc0.orig/drivers/media/video/mt9v022.c 2008-04-27 22:09:29.000000000 +0200
+++ linux-2.6.26-rc0/drivers/media/video/mt9v022.c 2008-04-27 22:09:48.000000000 +0200
@@ -819,12 +819,19 @@ static int mt9v022_remove(struct i2c_cli
return 0;
}
+static const struct i2c_device_id mt9v022_id[] = {
+ { "mt9v022", 0 },
+ { }
+};
+MODULE_DEVICE_TABLE(i2c, mt9v022_id);
+
static struct i2c_driver mt9v022_i2c_driver = {
.driver = {
.name = "mt9v022",
},
.probe = mt9v022_probe,
.remove = mt9v022_remove,
+ .id_table = mt9v022_id,
};
static int __init mt9v022_mod_init(void)
--- linux-2.6.26-rc0.orig/drivers/rtc/rtc-ds1307.c 2008-04-27 22:09:29.000000000 +0200
+++ linux-2.6.26-rc0/drivers/rtc/rtc-ds1307.c 2008-04-28 09:26:39.000000000 +0200
@@ -99,45 +99,38 @@ struct ds1307 {
};
struct chip_desc {
- char name[9];
unsigned nvram56:1;
unsigned alarm:1;
- enum ds_type type;
};
-static const struct chip_desc chips[] = { {
- .name = "ds1307",
- .type = ds_1307,
+static const struct chip_desc chips[] = {
+[ds_1307] = {
.nvram56 = 1,
-}, {
- .name = "ds1337",
- .type = ds_1337,
+},
+[ds_1337] = {
.alarm = 1,
-}, {
- .name = "ds1338",
- .type = ds_1338,
+},
+[ds_1338] = {
.nvram56 = 1,
-}, {
- .name = "ds1339",
- .type = ds_1339,
+},
+[ds_1339] = {
.alarm = 1,
-}, {
- .name = "ds1340",
- .type = ds_1340,
-}, {
- .name = "m41t00",
- .type = m41t00,
+},
+[ds_1340] = {
+},
+[m41t00] = {
}, };
-static inline const struct chip_desc *find_chip(const char *s)
-{
- unsigned i;
-
- for (i = 0; i < ARRAY_SIZE(chips); i++)
- if (strnicmp(s, chips[i].name, sizeof chips[i].name) == 0)
- return &chips[i];
- return NULL;
-}
+static const struct i2c_device_id ds1307_id[] = {
+ { "ds1307", ds_1307 },
+ { "ds1337", ds_1337 },
+ { "ds1338", ds_1338 },
+ { "ds1339", ds_1339 },
+ { "ds1340", ds_1340 },
+ { "m41t00", m41t00 },
+ { }
+};
+MODULE_DEVICE_TABLE(i2c, ds1307_id);
static int ds1307_get_time(struct device *dev, struct rtc_time *t)
{
@@ -332,16 +325,9 @@ static int __devinit ds1307_probe(struct
struct ds1307 *ds1307;
int err = -ENODEV;
int tmp;
- const struct chip_desc *chip;
+ const struct chip_desc *chip = &chips[id->driver_data];
struct i2c_adapter *adapter = to_i2c_adapter(client->dev.parent);
- chip = find_chip(client->name);
- if (!chip) {
- dev_err(&client->dev, "unknown chip type '%s'\n",
- client->name);
- return -ENODEV;
- }
-
if (!i2c_check_functionality(adapter,
I2C_FUNC_I2C | I2C_FUNC_SMBUS_WRITE_BYTE_DATA))
return -EIO;
@@ -362,7 +348,7 @@ static int __devinit ds1307_probe(struct
ds1307->msg[1].len = sizeof(ds1307->regs);
ds1307->msg[1].buf = ds1307->regs;
- ds1307->type = chip->type;
+ ds1307->type = id->driver_data;
switch (ds1307->type) {
case ds_1337:
@@ -551,6 +537,7 @@ static struct i2c_driver ds1307_driver =
},
.probe = ds1307_probe,
.remove = __devexit_p(ds1307_remove),
+ .id_table = ds1307_id,
};
static int __init ds1307_init(void)
--- linux-2.6.26-rc0.orig/drivers/rtc/rtc-ds1374.c 2008-04-27 22:09:29.000000000 +0200
+++ linux-2.6.26-rc0/drivers/rtc/rtc-ds1374.c 2008-04-27 22:09:48.000000000 +0200
@@ -41,6 +41,12 @@
#define DS1374_REG_SR_AF 0x01 /* Alarm Flag */
#define DS1374_REG_TCR 0x09 /* Trickle Charge */
+static const struct i2c_device_id ds1374_id[] = {
+ { "ds1374", 0 },
+ { }
+};
+MODULE_DEVICE_TABLE(i2c, ds1374_id);
+
struct ds1374 {
struct i2c_client *client;
struct rtc_device *rtc;
@@ -430,6 +436,7 @@ static struct i2c_driver ds1374_driver =
},
.probe = ds1374_probe,
.remove = __devexit_p(ds1374_remove),
+ .id_table = ds1374_id,
};
static int __init ds1374_init(void)
--- linux-2.6.26-rc0.orig/drivers/rtc/rtc-m41t80.c 2008-04-27 22:09:29.000000000 +0200
+++ linux-2.6.26-rc0/drivers/rtc/rtc-m41t80.c 2008-04-27 22:09:48.000000000 +0200
@@ -60,48 +60,21 @@
#define DRV_VERSION "0.05"
-struct m41t80_chip_info {
- const char *name;
- u8 features;
-};
-
-static const struct m41t80_chip_info m41t80_chip_info_tbl[] = {
- {
- .name = "m41t80",
- .features = 0,
- },
- {
- .name = "m41t81",
- .features = M41T80_FEATURE_HT,
- },
- {
- .name = "m41t81s",
- .features = M41T80_FEATURE_HT | M41T80_FEATURE_BL,
- },
- {
- .name = "m41t82",
- .features = M41T80_FEATURE_HT | M41T80_FEATURE_BL,
- },
- {
- .name = "m41t83",
- .features = M41T80_FEATURE_HT | M41T80_FEATURE_BL,
- },
- {
- .name = "m41st84",
- .features = M41T80_FEATURE_HT | M41T80_FEATURE_BL,
- },
- {
- .name = "m41st85",
- .features = M41T80_FEATURE_HT | M41T80_FEATURE_BL,
- },
- {
- .name = "m41st87",
- .features = M41T80_FEATURE_HT | M41T80_FEATURE_BL,
- },
+static const struct i2c_device_id m41t80_id[] = {
+ { "m41t80", 0 },
+ { "m41t81", M41T80_FEATURE_HT },
+ { "m41t81s", M41T80_FEATURE_HT | M41T80_FEATURE_BL },
+ { "m41t82", M41T80_FEATURE_HT | M41T80_FEATURE_BL },
+ { "m41t83", M41T80_FEATURE_HT | M41T80_FEATURE_BL },
+ { "m41st84", M41T80_FEATURE_HT | M41T80_FEATURE_BL },
+ { "m41st85", M41T80_FEATURE_HT | M41T80_FEATURE_BL },
+ { "m41st87", M41T80_FEATURE_HT | M41T80_FEATURE_BL },
+ { }
};
+MODULE_DEVICE_TABLE(i2c, m41t80_id);
struct m41t80_data {
- const struct m41t80_chip_info *chip;
+ u8 features;
struct rtc_device *rtc;
};
@@ -208,7 +181,7 @@ static int m41t80_rtc_proc(struct device
struct m41t80_data *clientdata = i2c_get_clientdata(client);
u8 reg;
- if (clientdata->chip->features & M41T80_FEATURE_BL) {
+ if (clientdata->features & M41T80_FEATURE_BL) {
reg = i2c_smbus_read_byte_data(client, M41T80_REG_FLAGS);
seq_printf(seq, "battery\t\t: %s\n",
(reg & M41T80_FLAGS_BATT_LOW) ? "exhausted" : "ok");
@@ -759,10 +732,9 @@ static struct notifier_block wdt_notifie
static int m41t80_probe(struct i2c_client *client,
const struct i2c_device_id *id)
{
- int i, rc = 0;
+ int rc = 0;
struct rtc_device *rtc = NULL;
struct rtc_time tm;
- const struct m41t80_chip_info *chip;
struct m41t80_data *clientdata = NULL;
if (!i2c_check_functionality(client->adapter, I2C_FUNC_I2C
@@ -774,19 +746,6 @@ static int m41t80_probe(struct i2c_clien
dev_info(&client->dev,
"chip found, driver version " DRV_VERSION "\n");
- chip = NULL;
- for (i = 0; i < ARRAY_SIZE(m41t80_chip_info_tbl); i++) {
- if (!strcmp(m41t80_chip_info_tbl[i].name, client->name)) {
- chip = &m41t80_chip_info_tbl[i];
- break;
- }
- }
- if (!chip) {
- dev_err(&client->dev, "%s is not supported\n", client->name);
- rc = -ENODEV;
- goto exit;
- }
-
clientdata = kzalloc(sizeof(*clientdata), GFP_KERNEL);
if (!clientdata) {
rc = -ENOMEM;
@@ -802,7 +761,7 @@ static int m41t80_probe(struct i2c_clien
}
clientdata->rtc = rtc;
- clientdata->chip = chip;
+ clientdata->features = id->driver_data;
i2c_set_clientdata(client, clientdata);
/* Make sure HT (Halt Update) bit is cleared */
@@ -811,7 +770,7 @@ static int m41t80_probe(struct i2c_clien
goto ht_err;
if (rc & M41T80_ALHOUR_HT) {
- if (chip->features & M41T80_FEATURE_HT) {
+ if (clientdata->features & M41T80_FEATURE_HT) {
m41t80_get_datetime(client, &tm);
dev_info(&client->dev, "HT bit was set!\n");
dev_info(&client->dev,
@@ -843,7 +802,7 @@ static int m41t80_probe(struct i2c_clien
goto exit;
#ifdef CONFIG_RTC_DRV_M41T80_WDT
- if (chip->features & M41T80_FEATURE_HT) {
+ if (clientdata->features & M41T80_FEATURE_HT) {
rc = misc_register(&wdt_dev);
if (rc)
goto exit;
@@ -879,7 +838,7 @@ static int m41t80_remove(struct i2c_clie
struct rtc_device *rtc = clientdata->rtc;
#ifdef CONFIG_RTC_DRV_M41T80_WDT
- if (clientdata->chip->features & M41T80_FEATURE_HT) {
+ if (clientdata->features & M41T80_FEATURE_HT) {
misc_deregister(&wdt_dev);
unregister_reboot_notifier(&wdt_notifier);
}
@@ -897,6 +856,7 @@ static struct i2c_driver m41t80_driver =
},
.probe = m41t80_probe,
.remove = m41t80_remove,
+ .id_table = m41t80_id,
};
static int __init m41t80_rtc_init(void)
--- linux-2.6.26-rc0.orig/drivers/rtc/rtc-rs5c372.c 2008-04-27 22:09:29.000000000 +0200
+++ linux-2.6.26-rc0/drivers/rtc/rtc-rs5c372.c 2008-04-27 22:09:48.000000000 +0200
@@ -69,6 +69,15 @@ enum rtc_type {
rtc_rv5c387a,
};
+static const struct i2c_device_id rs5c372_id[] = {
+ { "rs5c372a", rtc_rs5c372a },
+ { "rs5c372b", rtc_rs5c372b },
+ { "rv5c386", rtc_rv5c386 },
+ { "rv5c387a", rtc_rv5c387a },
+ { }
+};
+MODULE_DEVICE_TABLE(i2c, rs5c372_id);
+
/* REVISIT: this assumes that:
* - we're in the 21st century, so it's safe to ignore the century
* bit for rv5c38[67] (REG_MONTH bit 7);
@@ -517,25 +526,13 @@ static int rs5c372_probe(struct i2c_clie
rs5c372->regs=&rs5c372->buf[1];
rs5c372->client = client;
+ rs5c372->type = id->driver_data;
i2c_set_clientdata(client, rs5c372);
err = rs5c_get_regs(rs5c372);
if (err < 0)
goto exit_kfree;
- if (strcmp(client->name, "rs5c372a") == 0)
- rs5c372->type = rtc_rs5c372a;
- else if (strcmp(client->name, "rs5c372b") == 0)
- rs5c372->type = rtc_rs5c372b;
- else if (strcmp(client->name, "rv5c386") == 0)
- rs5c372->type = rtc_rv5c386;
- else if (strcmp(client->name, "rv5c387a") == 0)
- rs5c372->type = rtc_rv5c387a;
- else {
- rs5c372->type = rtc_rs5c372b;
- dev_warn(&client->dev, "assuming rs5c372b\n");
- }
-
/* clock may be set for am/pm or 24 hr time */
switch (rs5c372->type) {
case rtc_rs5c372a:
@@ -652,6 +649,7 @@ static struct i2c_driver rs5c372_driver
},
.probe = rs5c372_probe,
.remove = rs5c372_remove,
+ .id_table = rs5c372_id,
};
static __init int rs5c372_init(void)
--- linux-2.6.26-rc0.orig/drivers/rtc/rtc-s35390a.c 2008-04-27 22:09:29.000000000 +0200
+++ linux-2.6.26-rc0/drivers/rtc/rtc-s35390a.c 2008-04-28 08:44:20.000000000 +0200
@@ -34,6 +34,12 @@
#define S35390A_FLAG_RESET 0x80
#define S35390A_FLAG_TEST 0x01
+static const struct i2c_device_id s35390a_id[] = {
+ { "s35390a", 0 },
+ { }
+};
+MODULE_DEVICE_TABLE(i2c, s35390a_id);
+
struct s35390a {
struct i2c_client *client[8];
struct rtc_device *rtc;
@@ -297,6 +303,7 @@ static struct i2c_driver s35390a_driver
},
.probe = s35390a_probe,
.remove = s35390a_remove,
+ .id_table = s35390a_id,
};
static int __init s35390a_rtc_init(void)
--- linux-2.6.26-rc0.orig/include/linux/i2c.h 2008-04-27 22:09:29.000000000 +0200
+++ linux-2.6.26-rc0/include/linux/i2c.h 2008-04-28 08:44:20.000000000 +0200
@@ -229,17 +229,17 @@ struct i2c_board_info {
};
/**
- * I2C_BOARD_INFO - macro used to list an i2c device and its driver
- * @driver: identifies the driver to use with the device
+ * I2C_BOARD_INFO - macro used to list an i2c device and its address
+ * @dev_type: identifies the device type
* @dev_addr: the device's address on the bus.
*
* This macro initializes essential fields of a struct i2c_board_info,
* declaring what has been provided on a particular board. Optional
- * fields (such as the chip type, its associated irq, or device-specific
- * platform_data) are provided using conventional syntax.
+ * fields (such as associated irq, or device-specific platform_data)
+ * are provided using conventional syntax.
*/
-#define I2C_BOARD_INFO(driver,dev_addr) \
- .driver_name = (driver), .addr = (dev_addr)
+#define I2C_BOARD_INFO(dev_type,dev_addr) \
+ .type = (dev_type), .addr = (dev_addr)
/* Add-on boards should register/unregister their devices; e.g. a board
--
Jean Delvare
^ permalink raw reply
* Predefined Compiler Flag for CROSS_COMPILE in ELDK
From: rodolfo @ 2008-04-28 11:27 UTC (permalink / raw)
To: Linuxppc embedded, Rodolfo
Hi,
I using ppc_4xx- cross-compiler for build linux in xup virtex II pro.
How can I change -mpcu compiler flag for a specific vallue for my
board/processor?
Thanks,
^ permalink raw reply
* Re: [PATCH 1/2] i2c: Add support for device alias names
From: Jon Smirl @ 2008-04-28 14:43 UTC (permalink / raw)
To: Jean Delvare
Cc: Kay Sievers, linuxppc-dev list, Paul Mundt, Linux I2C, Scott Wood
In-Reply-To: <20080428113901.2772e9d9@hyperion.delvare>
On 4/28/08, Jean Delvare <khali@linux-fr.org> wrote:
> Based on earlier work by Jon Smirl and Jochen Friedrich.
>
> This patch allows new-style i2c chip drivers to have alias names using
> the official kernel aliasing system and MODULE_DEVICE_TABLE(). At this
> point, the old i2c driver binding scheme (driver_name/type) is still
> supported.
>
> Signed-off-by: Jean Delvare <khali@linux-fr.org>
> Cc: Jochen Friedrich <jochen@scram.de>
> Cc: Jon Smirl <jonsmirl@gmail.com>
> Cc: Kay Sievers <kay.sievers@vrfy.org>
> ---
> One thing I am still not happy with is that the aliases created have a
> trailing "*":
>
> $ /sbin/modinfo lm90
> filename: /lib/modules/2.6.25-git11/kernel/drivers/hwmon/lm90.ko
> author: Jean Delvare <khali@linux-fr.org>
> description: LM90/ADM1032 driver
> license: GPL
> vermagic: 2.6.25-git11 mod_unload
> depends: hwmon
> alias: i2c:lm90*
> alias: i2c:adm1032*
> alias: i2c:lm99*
> alias: i2c:lm86*
> alias: i2c:max6657*
> alias: i2c:adt7461*
> alias: i2c:max6680*
> $
>
> This would cause trouble if one I2C chip name matches the beginning of
> another I2C chip name and both chips are supported by different
> drivers. This has yet to be seen, but still, I'd like to see this
> problem fixed quickly.
Trailing wildcard is always added by file2alias.c:
if (do_entry(mod->name, symval+i, alias)) {
/* Always end in a wildcard, for future extension */
if (alias[strlen(alias)-1] != '*')
strcat(alias, "*");
Can't the match order be controlled in the makefile? For example if
you had lm905* and lm90*, put lm905* into into the makefile first
which will cause it to appear in the alias file first. But that would
still cause problems if only lm90 was built and you had a lm905
device.
Alternatively you could change the code to append something like a
period to the name string.
sprintf(alias, I2C_MODULE_PREFIX "%s.", id->name);
I was using macros to alter the name strings to move the PowerPC names
into their own namespace.
--
Jon Smirl
jonsmirl@gmail.com
^ permalink raw reply
* Re: [PATCH] Add fast little-endian switch system call
From: Christoph Hellwig @ 2008-04-28 14:43 UTC (permalink / raw)
To: Paul Mackerras; +Cc: linux-arch, linuxppc-dev, mtk.manpages
In-Reply-To: <18453.18943.906693.409245@cargo.ozlabs.ibm.com>
Please see Michael Kerrisk on userspace ABI updates. A nice little
manpage for this gimmick would be helpful, and maybe help other
platforms that want one aswell to implement the same API.
On Mon, Apr 28, 2008 at 01:52:31PM +1000, Paul Mackerras wrote:
> This adds a system call on 64-bit platforms for switching between
> little-endian and big-endian modes that is much faster than doing a
> prctl call. This system call is handled as a special case right at
> the start of the system call entry code, and because it is a special
> case, it uses a system call number which is out of the range of
> normal system calls, namely 0x1ebe.
>
> Measurements with lmbench on a 4.2GHz POWER6 showed no measurable
> change in the speed of normal system calls with this patch.
>
> Switching endianness with this new system call takes around 60ns on a
> 4.2GHz POWER6, compared with around 300ns to switch endian mode with a
> prctl. This can provide a significant performance advantage for
> emulators for little-endian architectures that want to switch between
> big-endian and little-endian mode frequently, e.g. because they are
> generating instructions sequences on the fly and they want to run
> those sequences in little-endian mode.
>
> Signed-off-by: Paul Mackerras <paulus@samba.org>
> ---
>
> diff --git a/arch/powerpc/kernel/head_64.S b/arch/powerpc/kernel/head_64.S
> index 215973a..2eb49a7 100644
> --- a/arch/powerpc/kernel/head_64.S
> +++ b/arch/powerpc/kernel/head_64.S
> @@ -239,6 +239,10 @@ instruction_access_slb_pSeries:
> .globl system_call_pSeries
> system_call_pSeries:
> HMT_MEDIUM
> +BEGIN_FTR_SECTION
> + cmpdi r0,0x1ebe
> + beq- 1f
> +END_FTR_SECTION_IFSET(CPU_FTR_REAL_LE)
Am I missing something here or does this add a branch for every normal
syscall?
> mr r9,r13
> mfmsr r10
> mfspr r13,SPRN_SPRG3
> @@ -253,6 +257,13 @@ system_call_pSeries:
> rfid
> b . /* prevent speculative execution */
>
> +/* Fast LE/BE switch system call */
> +1: mfspr r12,SPRN_SRR1
> + xori r12,r12,MSR_LE
> + mtspr SPRN_SRR1,r12
> + rfid /* return to userspace */
> + b .
> +
> STD_EXCEPTION_PSERIES(0xd00, single_step)
> STD_EXCEPTION_PSERIES(0xe00, trap_0e)
>
> _______________________________________________
> Linuxppc-dev mailing list
> Linuxppc-dev@ozlabs.org
> https://ozlabs.org/mailman/listinfo/linuxppc-dev
---end quoted text---
^ permalink raw reply
* Re: [PATCH 1/2] i2c: Add support for device alias names
From: Kay Sievers @ 2008-04-28 15:07 UTC (permalink / raw)
To: Jean Delvare; +Cc: linuxppc-dev list, Paul Mundt, Scott Wood, Linux I2C
In-Reply-To: <20080428113901.2772e9d9@hyperion.delvare>
On Mon, 2008-04-28 at 11:39 +0200, Jean Delvare wrote:
> Based on earlier work by Jon Smirl and Jochen Friedrich.
>=20
> This patch allows new-style i2c chip drivers to have alias names using
> the official kernel aliasing system and MODULE_DEVICE_TABLE(). At this
> point, the old i2c driver binding scheme (driver_name/type) is still
> supported.
>=20
> Signed-off-by: Jean Delvare <khali@linux-fr.org>
> Cc: Jochen Friedrich <jochen@scram.de>
> Cc: Jon Smirl <jonsmirl@gmail.com>
> Cc: Kay Sievers <kay.sievers@vrfy.org>
> ---
> One thing I am still not happy with is that the aliases created have a
> trailing "*":
>=20
> $ /sbin/modinfo lm90
> filename: /lib/modules/2.6.25-git11/kernel/drivers/hwmon/lm90.ko
> author: Jean Delvare <khali@linux-fr.org>
> description: LM90/ADM1032 driver
> license: GPL
> vermagic: 2.6.25-git11 mod_unload
> depends: hwmon
> alias: i2c:lm90*
> alias: i2c:adm1032*
> alias: i2c:lm99*
> alias: i2c:lm86*
> alias: i2c:max6657*
> alias: i2c:adt7461*
> alias: i2c:max6680*
> $
>=20
> This would cause trouble if one I2C chip name matches the beginning of
> another I2C chip name and both chips are supported by different
> drivers. This has yet to be seen, but still, I'd like to see this
> problem fixed quickly.
=EF=BB=BFRight, the trailing "*" is not nice.
We should terminate the string, so the trailing "*" will not match
longer strings. The usual thing is to add a ":" to the end, which would
then show up as
alias: i2c:max6680:*
See DMI and ACPI:
alias dmi:*:svnFUJITSU:pnLifeBook*:pvr*:rvnFUJITSU:* apanel
alias acpi*:ASIM0000:* atlas_btns
If i2c device modaliases could ever contain multiple strings, it should
be:
alias: i2c*:max6680:*
=EF=BB=BFto match the module, regardless of the order of the strings in the
modalias:
Thanks,
Kay
^ permalink raw reply
* Re: filenames with spaces in /sys?
From: Scott Wood @ 2008-04-28 15:31 UTC (permalink / raw)
To: Christian Kujau; +Cc: linuxppc-dev, dwmw2
In-Reply-To: <alpine.DEB.1.10.0804272012000.11017@sheep.housecafe.de>
On Sun, Apr 27, 2008 at 08:35:51PM +0200, Christian Kujau wrote:
> I was a bit puzzled today when I came across
> /sys/devices/platform/pmu-battery.0/power_supply/PMU battery 0/power
> and thought to myself: why are there spaces in "PMU battery 0"?
Why not?
> Wouldn't ../pmu-battery.0/power_supply/PMU_battery_0/power be feasible too?
Feasible, yes, but uglier, and as you point out, changing it now would
risk breaking userspace for little gain.
> I find it rather annoying to special case the spaces whenever to look
> for something in /sys, when I'm so used not to when doing the same
> find/grep/xargs stuff in /usr/src/linux.
If userspace tools make it awkward to deal with filenames with spaces,
let's fix the userspace tools. /sys is certainly not the only place
they'll be found, and waging war against them is a battle best left for
a couple decades ago.
-Scott
^ permalink raw reply
* [RFC, PATCH 0/7] Power management patches from Scott Wood plus MPC8241 Linkstation
From: Guennadi Liakhovetski @ 2008-04-28 15:37 UTC (permalink / raw)
To: linuxppc-dev; +Cc: Scott Wood, linux-pm, Paul Mackerras
Hi all
as replies to this email I'm going to post a respin of the last version
from December 2007 of Scott's patches plus my patch for Linkstation
standby.
Scott, I upgraded your patches, please, verify, that they still function.
I added my Sof's as I'm now forwarding them, I believe, this is correct. I
tried to preserve original CC lists.
<remark>
Knowing how important power management on ARM systems is I'm a bit
confused about why this is not the case on _embedded_ powerpc.
</remark>
Thanks
Guennadi
---
Guennadi Liakhovetski
^ permalink raw reply
* [PATCH 1/7] pm: Add TLF_SLEEPING hack to delay interrupt delivery when waking from sleep.
From: Guennadi Liakhovetski @ 2008-04-28 15:37 UTC (permalink / raw)
To: linuxppc-dev; +Cc: Scott Wood, linux-pm, Paul Mackerras
In-Reply-To: <Pine.LNX.4.64.0804281714000.7897@axis700.grange>
The e300 core (and probably most other 6xx chips) can only come out of
sleep mode with an interrupt. However, interrupts are logically disabled
by the power management layer.
This hack extends the existing doze/nap hack to also suppress the running
of the interrupt handler when in sleep mode.
Signed-off-by: Scott Wood <scottwood@freescale.com>
Signed-off-by: Guennadi Liakhovetski <g.liakhovetski@gmx.de>
---
arch/powerpc/kernel/entry_32.S | 6 ++--
arch/powerpc/kernel/idle_6xx.S | 41 ++++++++++++++++++++++++++++++++++++-
include/asm-powerpc/thread_info.h | 2 +
3 files changed, 45 insertions(+), 4 deletions(-)
diff --git a/arch/powerpc/kernel/entry_32.S b/arch/powerpc/kernel/entry_32.S
index 69a91bd..4099a6f 100644
--- a/arch/powerpc/kernel/entry_32.S
+++ b/arch/powerpc/kernel/entry_32.S
@@ -138,8 +138,8 @@ transfer_to_handler:
#ifdef CONFIG_6xx
tophys(r9,r9) /* check local flags */
lwz r12,TI_LOCAL_FLAGS(r9)
- mtcrf 0x01,r12
- bt- 31-TLF_NAPPING,4f
+ andi. r8, r12, _TLF_NAPPING | _TLF_SLEEPING
+ bne- 4f
#endif /* CONFIG_6xx */
.globl transfer_to_handler_cont
transfer_to_handler_cont:
@@ -154,7 +154,7 @@ transfer_to_handler_cont:
RFI /* jump to handler, enable MMU */
#ifdef CONFIG_6xx
-4: rlwinm r12,r12,0,~_TLF_NAPPING
+4: rlwinm r12,r12,0,~(_TLF_NAPPING | _TLF_SLEEPING)
stw r12,TI_LOCAL_FLAGS(r9)
b power_save_6xx_restore
#endif
diff --git a/arch/powerpc/kernel/idle_6xx.S b/arch/powerpc/kernel/idle_6xx.S
index 01bcd52..341f474 100644
--- a/arch/powerpc/kernel/idle_6xx.S
+++ b/arch/powerpc/kernel/idle_6xx.S
@@ -147,16 +147,30 @@ END_FTR_SECTION_IFSET(CPU_FTR_ALTIVEC)
isync
b 1b
+#ifdef CONFIG_SUSPEND
+ret_from_sleep:
+ .long ret_from_except
+ .long ret_from_except
+#endif
+
/*
* Return from NAP/DOZE mode, restore some CPU specific registers,
* we are called with DR/IR still off and r2 containing physical
* address of current. R11 points to the exception frame (physical
- * address). We have to preserve r10.
+ * address). r8 contains _TLF_NAPPING or _TLF_SLEEPING. We have to
+ * preserve r10.
*/
_GLOBAL(power_save_6xx_restore)
lwz r9,_LINK(r11) /* interrupted in ppc6xx_idle: */
+#ifdef CONFIG_SUSPEND
+ andi. r12, r8, _TLF_SLEEPING
+#endif
stw r9,_NIP(r11) /* make it do a blr */
+#ifdef CONFIG_SUSPEND
+ bne- sleep_6xx_restore
+#endif
+
#ifdef CONFIG_SMP
mfspr r12,SPRN_SPRG3
lwz r11,TI_CPU(r12) /* get cpu number * 4 */
@@ -185,6 +199,31 @@ BEGIN_FTR_SECTION
END_FTR_SECTION_IFSET(CPU_FTR_DUAL_PLL_750FX)
b transfer_to_handler_cont
+#ifdef CONFIG_SUSPEND
+sleep_6xx_restore:
+ /*
+ * SLEEP mode is invoked through the PM subsystem, which means
+ * that interrupts should be disabled. However, the hardware
+ * requires them to be enabled to wake up. To prevent the
+ * interrupt from being visible to Linux, return immediately
+ * rather than run the interrupt handler.
+ */
+ lis r9, ret_from_sleep@h
+ ori r9, r9, ret_from_sleep@l
+ tophys(r9, r9)
+ mtlr r9
+
+ /*
+ * Disable interrupts, so that the interrupt doesn't happen
+ * again until the PM code sets MSR[EE].
+ */
+ lwz r9, _MSR(r11)
+ rlwinm r9, r9, 0, ~MSR_EE
+ stw r9, _MSR(r11)
+
+ b transfer_to_handler_cont
+#endif
+
.data
_GLOBAL(nap_save_msscr0)
diff --git a/include/asm-powerpc/thread_info.h b/include/asm-powerpc/thread_info.h
index 40d5f98..f7cb48b 100644
--- a/include/asm-powerpc/thread_info.h
+++ b/include/asm-powerpc/thread_info.h
@@ -151,8 +151,10 @@ static inline struct thread_info *current_thread_info(void)
/* Bits in local_flags */
/* Don't move TLF_NAPPING without adjusting the code in entry_32.S */
#define TLF_NAPPING 0 /* idle thread enabled NAP mode */
+#define TLF_SLEEPING 1 /* suspend code enabled SLEEP mode */
#define _TLF_NAPPING (1 << TLF_NAPPING)
+#define _TLF_SLEEPING (1 << TLF_SLEEPING)
#endif /* __KERNEL__ */
--
1.5.3.7
^ permalink raw reply related
* [PATCH 2/7] Add 6xx-style HID0_SLEEP support.
From: Guennadi Liakhovetski @ 2008-04-28 15:38 UTC (permalink / raw)
To: linuxppc-dev; +Cc: Scott Wood, linux-pm, Paul Mackerras
In-Reply-To: <Pine.LNX.4.64.0804281714000.7897@axis700.grange>
Signed-off-by: Scott Wood <scottwood@freescale.com>
Signed-off-by: Guennadi Liakhovetski <g.liakhovetski@gmx.de>
---
arch/powerpc/sysdev/6xx-suspend.S | 52 +++++++++++++++++++++++++++++++++++++
arch/powerpc/sysdev/Makefile | 4 +++
include/asm-powerpc/mpc6xx.h | 6 ++++
3 files changed, 62 insertions(+), 0 deletions(-)
create mode 100644 arch/powerpc/sysdev/6xx-suspend.S
create mode 100644 include/asm-powerpc/mpc6xx.h
diff --git a/arch/powerpc/sysdev/6xx-suspend.S b/arch/powerpc/sysdev/6xx-suspend.S
new file mode 100644
index 0000000..21cda08
--- /dev/null
+++ b/arch/powerpc/sysdev/6xx-suspend.S
@@ -0,0 +1,52 @@
+/*
+ * Enter and leave sleep state on chips with 6xx-style HID0
+ * power management bits, which don't leave sleep state via reset.
+ *
+ * Author: Scott Wood <scottwood@freescale.com>
+ *
+ * Copyright (c) 2006-2007 Freescale Semiconductor, Inc.
+ *
+ * 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 <asm/ppc_asm.h>
+#include <asm/reg.h>
+#include <asm/thread_info.h>
+#include <asm/asm-offsets.h>
+
+_GLOBAL(mpc6xx_enter_standby)
+ mflr r4
+
+ mfspr r5, SPRN_HID0
+ rlwinm r5, r5, 0, ~(HID0_DOZE | HID0_NAP)
+ oris r5, r5, HID0_SLEEP@h
+ mtspr SPRN_HID0, r5
+ isync
+
+ lis r5, ret_from_standby@h
+ ori r5, r5, ret_from_standby@l
+ mtlr r5
+
+ rlwinm r5, r1, 0, 0, 31-THREAD_SHIFT
+ lwz r6, TI_LOCAL_FLAGS(r5)
+ ori r6, r6, _TLF_SLEEPING
+ stw r6, TI_LOCAL_FLAGS(r5)
+
+ mfmsr r5
+ ori r5, r5, MSR_EE
+ oris r5, r5, MSR_POW@h
+ sync
+ mtmsr r5
+ isync
+
+1: b 1b
+
+ret_from_standby:
+ mfspr r5, SPRN_HID0
+ rlwinm r5, r5, 0, ~HID0_SLEEP
+ mtspr SPRN_HID0, r5
+
+ mtlr r4
+ blr
diff --git a/arch/powerpc/sysdev/Makefile b/arch/powerpc/sysdev/Makefile
index 99a77d7..df2b885 100644
--- a/arch/powerpc/sysdev/Makefile
+++ b/arch/powerpc/sysdev/Makefile
@@ -37,3 +37,7 @@ obj-$(CONFIG_PPC_DCR) += dcr.o
obj-$(CONFIG_8xx) += mpc8xx_pic.o cpm1.o
obj-$(CONFIG_UCODE_PATCH) += micropatch.o
endif
+
+ifeq ($(CONFIG_SUSPEND),y)
+obj-$(CONFIG_6xx) += 6xx-suspend.o
+endif
diff --git a/include/asm-powerpc/mpc6xx.h b/include/asm-powerpc/mpc6xx.h
new file mode 100644
index 0000000..effc229
--- /dev/null
+++ b/include/asm-powerpc/mpc6xx.h
@@ -0,0 +1,6 @@
+#ifndef __ASM_POWERPC_MPC6xx_H
+#define __ASM_POWERPC_MPC6xx_H
+
+void mpc6xx_enter_standby(void);
+
+#endif
--
1.5.3.7
^ permalink raw reply related
* [PATCH 3/7] mpc83xx: Power Management support
From: Guennadi Liakhovetski @ 2008-04-28 15:38 UTC (permalink / raw)
To: linuxppc-dev; +Cc: Scott Wood, linux-pm, Paul Mackerras
In-Reply-To: <Pine.LNX.4.64.0804281714000.7897@axis700.grange>
Basic PM support for 83xx. Standby is implemented as sleep.
Suspend-to-RAM is implemented as "deep sleep" (with the processor
turned off) on 831x.
Signed-off-by: Scott Wood <scottwood@freescale.com>
Signed-off-by: Guennadi Liakhovetski <g.liakhovetski@gmx.de>
---
The enabling of i-cache at the end of the suspend code somehow fell off of
the code that was sent out in the previous patch (it still works when
booting high, which is what I tested, but not booting low).
The rest of the patchset stays the same.
arch/powerpc/platforms/83xx/Kconfig | 5 +
arch/powerpc/platforms/83xx/Makefile | 1 +
arch/powerpc/platforms/83xx/suspend-asm.S | 539 +++++++++++++++++++++++++++++
arch/powerpc/platforms/83xx/suspend.c | 423 ++++++++++++++++++++++
arch/powerpc/sysdev/fsl_soc.c | 33 ++
arch/powerpc/sysdev/fsl_soc.h | 10 +
arch/powerpc/sysdev/ipic.c | 71 ++++
include/asm-powerpc/reg.h | 4 +
include/linux/fsl_devices.h | 24 ++
9 files changed, 1110 insertions(+), 0 deletions(-)
create mode 100644 arch/powerpc/platforms/83xx/suspend-asm.S
create mode 100644 arch/powerpc/platforms/83xx/suspend.c
diff -u a/arch/powerpc/Kconfig b/arch/powerpc/Kconfig
--- a/arch/powerpc/Kconfig
+++ b/arch/powerpc/Kconfig
@@ -192,7 +192,7 @@ config ARCH_HIBERNATION_POSSIBLE
config ARCH_SUSPEND_POSSIBLE
def_bool y
- depends on ADB_PMU || PPC_EFIKA || PPC_LITE5200
+ depends on ADB_PMU || PPC_EFIKA || PPC_LITE5200 || PPC_83xx
config PPC_DCR_NATIVE
bool
diff --git a/arch/powerpc/platforms/83xx/Kconfig b/arch/powerpc/platforms/83xx/Kconfig
index ec305f1..901dbaf 100644
--- a/arch/powerpc/platforms/83xx/Kconfig
+++ b/arch/powerpc/platforms/83xx/Kconfig
@@ -6,6 +6,11 @@ menuconfig MPC83xx
if MPC83xx
+config PPC_83xx_SUSPEND
+ bool
+ default y
+ depends on SUSPEND
+
config MPC831x_RDB
bool "Freescale MPC831x RDB"
select DEFAULT_UIMAGE
diff --git a/arch/powerpc/platforms/83xx/Makefile b/arch/powerpc/platforms/83xx/Makefile
index 5a98f88..944369e 100644
--- a/arch/powerpc/platforms/83xx/Makefile
+++ b/arch/powerpc/platforms/83xx/Makefile
@@ -3,6 +3,7 @@
#
obj-y := misc.o usb.o
obj-$(CONFIG_PCI) += pci.o
+obj-$(CONFIG_SUSPEND) += suspend.o suspend-asm.o
obj-$(CONFIG_MPC831x_RDB) += mpc831x_rdb.o
obj-$(CONFIG_MPC832x_RDB) += mpc832x_rdb.o
obj-$(CONFIG_MPC834x_MDS) += mpc834x_mds.o
diff --git a/arch/powerpc/platforms/83xx/suspend-asm.S b/arch/powerpc/platforms/83xx/suspend-asm.S
new file mode 100644
index 0000000..03e29a2
--- /dev/null
+++ b/arch/powerpc/platforms/83xx/suspend-asm.S
@@ -0,0 +1,539 @@
+/*
+ * Enter and leave sleep state on MPC83xx
+ *
+ * Author: Scott Wood <scottwood@freescale.com>
+ *
+ * Copyright (c) 2006 Freescale Semiconductor, Inc.
+ *
+ * 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 <asm/page.h>
+#include <asm/ppc_asm.h>
+#include <asm/reg.h>
+#include <asm/asm-offsets.h>
+
+#define SS_MEMSAVE 0x00
+#define SS_HID 0x08 /* 3 HIDs */
+#define SS_IABR 0x14 /* 2 IABRs */
+#define SS_IBCR 0x1c
+#define SS_DABR 0x20 /* 2 DABRs */
+#define SS_DBCR 0x28
+#define SS_SP 0x2c
+#define SS_SR 0x30 /* 16 segment registers */
+#define SS_CURRENT 0x70
+#define SS_MSR 0x74
+#define SS_SDR1 0x78
+#define SS_LR 0x7c
+#define SS_SPRG 0x80 /* 4 SPRGs */
+#define SS_DBAT 0x90 /* 8 DBATs */
+#define SS_IBAT 0xd0 /* 8 IBATs */
+#define SS_TB 0x110
+#define SS_CR 0x118
+#define SS_GPREG 0x11c /* r12-r31 */
+#define STATE_SAVE_SIZE 0x16c
+
+ .section .data
+ .align 5
+
+mpc83xx_sleep_save_area:
+ .space STATE_SAVE_SIZE
+immrbase:
+ .long 0
+
+ .section .text
+ .align 5
+
+ /* r3 = physical address of IMMR */
+_GLOBAL(mpc83xx_enter_deep_sleep)
+ /* Re-use the state saving/restoring code in
+ * arch/powerpc/kernel/swsusp_32.S, but have
+ * it call us instead of swsusp_save.
+ */
+
+ lis r4, immrbase@ha
+ stw r3, immrbase@l(r4)
+
+ /* The first 2 words of memory are used to communicate with the
+ * bootloader, to tell it how to resume.
+ *
+ * The first word is the magic number 0xf5153ae5, and the second
+ * is the pointer to mpc83xx_deep_resume.
+ *
+ * The original content of these two words is saved in the state
+ * save area.
+ */
+
+ lis r3, mpc83xx_sleep_save_area@h
+ ori r3, r3, mpc83xx_sleep_save_area@l
+
+ lis r4, KERNELBASE@h
+ lwz r5, 0(r4)
+ lwz r6, 4(r4)
+
+ stw r5, SS_MEMSAVE+0(r3)
+ stw r6, SS_MEMSAVE+4(r3)
+
+ mfspr r5, SPRN_HID0
+ mfspr r6, SPRN_HID1
+ mfspr r7, SPRN_HID2
+
+ stw r5, SS_HID+0(r3)
+ stw r6, SS_HID+4(r3)
+ stw r7, SS_HID+8(r3)
+
+ mfspr r4, SPRN_IABR
+ mfspr r5, SPRN_IABR2
+ mfspr r6, SPRN_IBCR
+ mfspr r7, SPRN_DABR
+ mfspr r8, SPRN_DABR2
+ mfspr r9, SPRN_DBCR
+
+ stw r4, SS_IABR+0(r3)
+ stw r5, SS_IABR+4(r3)
+ stw r6, SS_IBCR(r3)
+ stw r7, SS_DABR+0(r3)
+ stw r8, SS_DABR+4(r3)
+ stw r9, SS_DBCR(r3)
+
+ mfspr r4, SPRN_SPRG0
+ mfspr r5, SPRN_SPRG1
+ mfspr r6, SPRN_SPRG2
+ mfspr r7, SPRN_SPRG3
+ mfsdr1 r8
+
+ stw r4, SS_SPRG+0(r3)
+ stw r5, SS_SPRG+4(r3)
+ stw r6, SS_SPRG+8(r3)
+ stw r7, SS_SPRG+12(r3)
+ stw r8, SS_SDR1(r3)
+
+ mfspr r4, SPRN_DBAT0U
+ mfspr r5, SPRN_DBAT0L
+ mfspr r6, SPRN_DBAT1U
+ mfspr r7, SPRN_DBAT1L
+
+ stw r4, SS_DBAT+0x00(r3)
+ stw r5, SS_DBAT+0x04(r3)
+ stw r6, SS_DBAT+0x08(r3)
+ stw r7, SS_DBAT+0x0c(r3)
+
+ mfspr r4, SPRN_DBAT2U
+ mfspr r5, SPRN_DBAT2L
+ mfspr r6, SPRN_DBAT3U
+ mfspr r7, SPRN_DBAT3L
+
+ stw r4, SS_DBAT+0x10(r3)
+ stw r5, SS_DBAT+0x14(r3)
+ stw r6, SS_DBAT+0x18(r3)
+ stw r7, SS_DBAT+0x1c(r3)
+
+ mfspr r4, SPRN_DBAT4U
+ mfspr r5, SPRN_DBAT4L
+ mfspr r6, SPRN_DBAT5U
+ mfspr r7, SPRN_DBAT5L
+
+ stw r4, SS_DBAT+0x20(r3)
+ stw r5, SS_DBAT+0x24(r3)
+ stw r6, SS_DBAT+0x28(r3)
+ stw r7, SS_DBAT+0x2c(r3)
+
+ mfspr r4, SPRN_DBAT6U
+ mfspr r5, SPRN_DBAT6L
+ mfspr r6, SPRN_DBAT7U
+ mfspr r7, SPRN_DBAT7L
+
+ stw r4, SS_DBAT+0x30(r3)
+ stw r5, SS_DBAT+0x34(r3)
+ stw r6, SS_DBAT+0x38(r3)
+ stw r7, SS_DBAT+0x3c(r3)
+
+ mfspr r4, SPRN_IBAT0U
+ mfspr r5, SPRN_IBAT0L
+ mfspr r6, SPRN_IBAT1U
+ mfspr r7, SPRN_IBAT1L
+
+ stw r4, SS_IBAT+0x00(r3)
+ stw r5, SS_IBAT+0x04(r3)
+ stw r6, SS_IBAT+0x08(r3)
+ stw r7, SS_IBAT+0x0c(r3)
+
+ mfspr r4, SPRN_IBAT2U
+ mfspr r5, SPRN_IBAT2L
+ mfspr r6, SPRN_IBAT3U
+ mfspr r7, SPRN_IBAT3L
+
+ stw r4, SS_IBAT+0x10(r3)
+ stw r5, SS_IBAT+0x14(r3)
+ stw r6, SS_IBAT+0x18(r3)
+ stw r7, SS_IBAT+0x1c(r3)
+
+ mfspr r4, SPRN_IBAT4U
+ mfspr r5, SPRN_IBAT4L
+ mfspr r6, SPRN_IBAT5U
+ mfspr r7, SPRN_IBAT5L
+
+ stw r4, SS_IBAT+0x20(r3)
+ stw r5, SS_IBAT+0x24(r3)
+ stw r6, SS_IBAT+0x28(r3)
+ stw r7, SS_IBAT+0x2c(r3)
+
+ mfspr r4, SPRN_IBAT6U
+ mfspr r5, SPRN_IBAT6L
+ mfspr r6, SPRN_IBAT7U
+ mfspr r7, SPRN_IBAT7L
+
+ stw r4, SS_IBAT+0x30(r3)
+ stw r5, SS_IBAT+0x34(r3)
+ stw r6, SS_IBAT+0x38(r3)
+ stw r7, SS_IBAT+0x3c(r3)
+
+ mfmsr r4
+ mflr r5
+ mfcr r6
+
+ stw r4, SS_MSR(r3)
+ stw r5, SS_LR(r3)
+ stw r6, SS_CR(r3)
+ stw r1, SS_SP(r3)
+ stw r2, SS_CURRENT(r3)
+
+1: mftbu r4
+ mftb r5
+ mftbu r6
+ cmpw r4, r6
+ bne 1b
+
+ stw r4, SS_TB+0(r3)
+ stw r5, SS_TB+4(r3)
+
+ stmw r12, SS_GPREG(r3)
+
+ li r4, 0
+ addi r6, r3, SS_SR-4
+1: mfsrin r5, r4
+ stwu r5, 4(r6)
+ addis r4, r4, 0x1000
+ cmpwi r4, 0
+ bne 1b
+
+ /* Disable machine checks and critical exceptions */
+ mfmsr r4
+ rlwinm r4, r4, 0, ~MSR_CE
+ rlwinm r4, r4, 0, ~MSR_ME
+ mtmsr r4
+ isync
+
+#define TMP_VIRT_IMMR 0xf0000000
+#define DEFAULT_IMMR_VALUE 0xff400000
+#define IMMRBAR_BASE 0x0000
+
+ lis r4, immrbase@ha
+ lwz r4, immrbase@l(r4)
+
+ /* Use DBAT0 to address the current IMMR space */
+
+ ori r4, r4, 0x002a
+ mtspr SPRN_DBAT0L, r4
+ lis r8, TMP_VIRT_IMMR@h
+ ori r4, r8, 0x001e /* 1 MByte accessable from Kernel Space only */
+ mtspr SPRN_DBAT0U, r4
+ isync
+
+ /* Use DBAT1 to address the original IMMR space */
+
+ lis r4, DEFAULT_IMMR_VALUE@h
+ ori r4, r4, 0x002a
+ mtspr SPRN_DBAT1L, r4
+ lis r9, (TMP_VIRT_IMMR + 0x01000000)@h
+ ori r4, r9, 0x001e /* 1 MByte accessable from Kernel Space only */
+ mtspr SPRN_DBAT1U, r4
+ isync
+
+ /* Use DBAT2 to address the beginning of RAM. This isn't done
+ * using the normal virtual mapping, because with page debugging
+ * enabled it will be read-only. */
+
+ li r4, 0x0002
+ mtspr SPRN_DBAT2L, r4
+ lis r4, KERNELBASE@h
+ ori r4, r4, 0x001e /* 1 MByte accessable from Kernel Space only */
+ mtspr SPRN_DBAT2U, r4
+ isync
+
+ /* Flush the cache with our BAT, as there will be TLB misses
+ * otherwise if page debugging is enabled, and these misses
+ * will disturb the PLRU algorithm.
+ */
+
+ bl __flush_disable_L1
+
+ /* Keep the i-cache enabled, so the hack below for low-boot
+ * flash will work.
+ */
+ mfspr r3, SPRN_HID0
+ ori r3, r3, HID0_ICE
+ mtspr SPRN_HID0, r3
+ isync
+
+ lis r6, 0xf515
+ ori r6, r6, 0x3ae5
+
+ lis r7, mpc83xx_deep_resume@h
+ ori r7, r7, mpc83xx_deep_resume@l
+ tophys(r7, r7)
+
+ lis r5, KERNELBASE@h
+ stw r6, 0(r5)
+ stw r7, 4(r5)
+
+ /* Reset BARs */
+
+ li r4, 0
+ stw r4, 0x0024(r8)
+ stw r4, 0x002c(r8)
+ stw r4, 0x0034(r8)
+ stw r4, 0x003c(r8)
+ stw r4, 0x0064(r8)
+ stw r4, 0x006c(r8)
+
+ /* Rev 1 of the 8313 has problems with wakeup events that are
+ * pending during the transition to deep sleep state (such as if
+ * the PCI host sets the state to D3 and then D0 in rapid
+ * succession). This check shrinks the race window somewhat.
+ *
+ * See erratum PCI23, though the problem is not limited
+ * to PCI.
+ */
+
+ lwz r3, 0x0b04(r8)
+ andi. r3, r3, 1
+ bne- mpc83xx_deep_resume
+
+ /* Move IMMR back to the default location, following the
+ * procedure specified in the MPC8313 manual.
+ */
+ lwz r4, IMMRBAR_BASE(r8)
+ isync
+ lis r4, DEFAULT_IMMR_VALUE@h
+ stw r4, IMMRBAR_BASE(r8)
+ lis r4, KERNELBASE@h
+ lwz r4, 0(r4)
+ isync
+ lwz r4, IMMRBAR_BASE(r9)
+ mr r8, r9
+ isync
+
+ /* Check the Reset Configuration Word to see whether flash needs
+ * to be mapped at a low address or a high address.
+ */
+
+ lwz r4, 0x0904(r8)
+ andis. r4, r4, 0x0400
+ li r4, 0
+ beq boot_low
+ lis r4, 0xff80
+boot_low:
+ stw r4, 0x0020(r8)
+ lis r7, 0x8000
+ ori r7, r7, 0x0016
+
+ mfspr r5, SPRN_HID0
+ rlwinm r5, r5, 0, ~(HID0_DOZE | HID0_NAP)
+ oris r5, r5, HID0_SLEEP@h
+ mtspr SPRN_HID0, r5
+ isync
+
+ mfmsr r5
+ oris r5, r5, MSR_POW@h
+
+ /* Enable the flash mapping at the appropriate address. This
+ * mapping will override the RAM mapping, so there's no need to
+ * disable the latter. This must be done inside the same cache
+ * line as setting MSR_POW, so that no instruction fetches from
+ * RAM happen after the flash mapping is turned on.
+ */
+
+ .align 5
+ stw r7, 0x0024(r8)
+ sync
+ isync
+ mtmsr r5
+ isync
+1: b 1b
+
+mpc83xx_deep_resume:
+ lis r4, 1f@h
+ ori r4, r4, 1f@l
+ tophys(r4, r4)
+ mtsrr0 r4
+
+ mfmsr r4
+ rlwinm r4, r4, 0, ~(MSR_IR | MSR_DR)
+ mtsrr1 r4
+
+ rfi
+
+1: tlbia
+ bl __inval_enable_L1
+
+ lis r3, mpc83xx_sleep_save_area@h
+ ori r3, r3, mpc83xx_sleep_save_area@l
+ tophys(r3, r3)
+
+ lwz r5, SS_MEMSAVE+0(r3)
+ lwz r6, SS_MEMSAVE+4(r3)
+
+ stw r5, 0(0)
+ stw r6, 4(0)
+
+ lwz r5, SS_HID+0(r3)
+ lwz r6, SS_HID+4(r3)
+ lwz r7, SS_HID+8(r3)
+
+ mtspr SPRN_HID0, r5
+ mtspr SPRN_HID1, r6
+ mtspr SPRN_HID2, r7
+
+ lwz r4, SS_IABR+0(r3)
+ lwz r5, SS_IABR+4(r3)
+ lwz r6, SS_IBCR(r3)
+ lwz r7, SS_DABR+0(r3)
+ lwz r8, SS_DABR+4(r3)
+ lwz r9, SS_DBCR(r3)
+
+ mtspr SPRN_IABR, r4
+ mtspr SPRN_IABR2, r5
+ mtspr SPRN_IBCR, r6
+ mtspr SPRN_DABR, r7
+ mtspr SPRN_DABR2, r8
+ mtspr SPRN_DBCR, r9
+
+ li r4, 0
+ addi r6, r3, SS_SR-4
+1: lwzu r5, 4(r6)
+ mtsrin r5, r4
+ addis r4, r4, 0x1000
+ cmpwi r4, 0
+ bne 1b
+
+ lwz r4, SS_DBAT+0x00(r3)
+ lwz r5, SS_DBAT+0x04(r3)
+ lwz r6, SS_DBAT+0x08(r3)
+ lwz r7, SS_DBAT+0x0c(r3)
+
+ mtspr SPRN_DBAT0U, r4
+ mtspr SPRN_DBAT0L, r5
+ mtspr SPRN_DBAT1U, r6
+ mtspr SPRN_DBAT1L, r7
+
+ lwz r4, SS_DBAT+0x10(r3)
+ lwz r5, SS_DBAT+0x14(r3)
+ lwz r6, SS_DBAT+0x18(r3)
+ lwz r7, SS_DBAT+0x1c(r3)
+
+ mtspr SPRN_DBAT2U, r4
+ mtspr SPRN_DBAT2L, r5
+ mtspr SPRN_DBAT3U, r6
+ mtspr SPRN_DBAT3L, r7
+
+ lwz r4, SS_DBAT+0x20(r3)
+ lwz r5, SS_DBAT+0x24(r3)
+ lwz r6, SS_DBAT+0x28(r3)
+ lwz r7, SS_DBAT+0x2c(r3)
+
+ mtspr SPRN_DBAT4U, r4
+ mtspr SPRN_DBAT4L, r5
+ mtspr SPRN_DBAT5U, r6
+ mtspr SPRN_DBAT5L, r7
+
+ lwz r4, SS_DBAT+0x30(r3)
+ lwz r5, SS_DBAT+0x34(r3)
+ lwz r6, SS_DBAT+0x38(r3)
+ lwz r7, SS_DBAT+0x3c(r3)
+
+ mtspr SPRN_DBAT6U, r4
+ mtspr SPRN_DBAT6L, r5
+ mtspr SPRN_DBAT7U, r6
+ mtspr SPRN_DBAT7L, r7
+
+ lwz r4, SS_IBAT+0x00(r3)
+ lwz r5, SS_IBAT+0x04(r3)
+ lwz r6, SS_IBAT+0x08(r3)
+ lwz r7, SS_IBAT+0x0c(r3)
+
+ mtspr SPRN_IBAT0U, r4
+ mtspr SPRN_IBAT0L, r5
+ mtspr SPRN_IBAT1U, r6
+ mtspr SPRN_IBAT1L, r7
+
+ lwz r4, SS_IBAT+0x10(r3)
+ lwz r5, SS_IBAT+0x14(r3)
+ lwz r6, SS_IBAT+0x18(r3)
+ lwz r7, SS_IBAT+0x1c(r3)
+
+ mtspr SPRN_IBAT2U, r4
+ mtspr SPRN_IBAT2L, r5
+ mtspr SPRN_IBAT3U, r6
+ mtspr SPRN_IBAT3L, r7
+
+ lwz r4, SS_IBAT+0x20(r3)
+ lwz r5, SS_IBAT+0x24(r3)
+ lwz r6, SS_IBAT+0x28(r3)
+ lwz r7, SS_IBAT+0x2c(r3)
+
+ mtspr SPRN_IBAT4U, r4
+ mtspr SPRN_IBAT4L, r5
+ mtspr SPRN_IBAT5U, r6
+ mtspr SPRN_IBAT5L, r7
+
+ lwz r4, SS_IBAT+0x30(r3)
+ lwz r5, SS_IBAT+0x34(r3)
+ lwz r6, SS_IBAT+0x38(r3)
+ lwz r7, SS_IBAT+0x3c(r3)
+
+ mtspr SPRN_IBAT6U, r4
+ mtspr SPRN_IBAT6L, r5
+ mtspr SPRN_IBAT7U, r6
+ mtspr SPRN_IBAT7L, r7
+
+ lwz r4, SS_SPRG+0(r3)
+ lwz r5, SS_SPRG+4(r3)
+ lwz r6, SS_SPRG+8(r3)
+ lwz r7, SS_SPRG+12(r3)
+ lwz r8, SS_SDR1(r3)
+
+ mtspr SPRN_SPRG0, r4
+ mtspr SPRN_SPRG1, r5
+ mtspr SPRN_SPRG2, r6
+ mtspr SPRN_SPRG3, r7
+ mtsdr1 r8
+
+ lwz r4, SS_MSR(r3)
+ lwz r5, SS_LR(r3)
+ lwz r6, SS_CR(r3)
+ lwz r1, SS_SP(r3)
+ lwz r2, SS_CURRENT(r3)
+
+ mtsrr1 r4
+ mtsrr0 r5
+ mtcr r6
+
+ li r4, 0
+ mtspr SPRN_TBWL, r4
+
+ lwz r4, SS_TB+0(r3)
+ lwz r5, SS_TB+4(r3)
+
+ mtspr SPRN_TBWU, r4
+ mtspr SPRN_TBWL, r5
+
+ lmw r12, SS_GPREG(r3)
+
+ /* Kick decrementer */
+ li r0, 1
+ mtdec r0
+
+ rfi
diff --git a/arch/powerpc/platforms/83xx/suspend.c b/arch/powerpc/platforms/83xx/suspend.c
new file mode 100644
index 0000000..61bca38
--- /dev/null
+++ b/arch/powerpc/platforms/83xx/suspend.c
@@ -0,0 +1,423 @@
+/*
+ * MPC83xx suspend support
+ *
+ * Author: Scott Wood <scottwood@freescale.com>
+ *
+ * Copyright (c) 2006-2007 Freescale Semiconductor, Inc.
+ *
+ * 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/init.h>
+#include <linux/pm.h>
+#include <linux/types.h>
+#include <linux/ioport.h>
+#include <linux/interrupt.h>
+#include <linux/wait.h>
+#include <linux/kthread.h>
+#include <linux/freezer.h>
+#include <linux/suspend.h>
+#include <linux/fsl_devices.h>
+#include <linux/of_platform.h>
+
+#include <asm/reg.h>
+#include <asm/io.h>
+#include <asm/time.h>
+#include <asm/mpc6xx.h>
+
+#include <sysdev/fsl_soc.h>
+
+#define PMCCR1_NEXT_STATE 0x0C /* Next state for power management */
+#define PMCCR1_NEXT_STATE_SHIFT 2
+#define PMCCR1_CURR_STATE 0x03 /* Current state for power management*/
+#define IMMR_RCW_OFFSET 0x900
+#define RCW_PCI_HOST 0x80000000
+
+void mpc83xx_enter_deep_sleep(phys_addr_t immrbase);
+
+struct mpc83xx_pmc {
+ u32 config;
+#define PMCCR_DLPEN 2 /* DDR SDRAM low power enable */
+#define PMCCR_SLPEN 1 /* System low power enable */
+
+ u32 event;
+ u32 mask;
+/* All but PMCI are deep-sleep only */
+#define PMCER_GPIO 0x100
+#define PMCER_PCI 0x080
+#define PMCER_USB 0x040
+#define PMCER_ETSEC1 0x020
+#define PMCER_ETSEC2 0x010
+#define PMCER_TIMER 0x008
+#define PMCER_INT1 0x004
+#define PMCER_INT2 0x002
+#define PMCER_PMCI 0x001
+#define PMCER_ALL 0x1FF
+
+ /* deep-sleep only */
+ u32 config1;
+#define PMCCR1_USE_STATE 0x80000000
+#define PMCCR1_PME_EN 0x00000080
+#define PMCCR1_ASSERT_PME 0x00000040
+#define PMCCR1_POWER_OFF 0x00000020
+
+ /* deep-sleep only */
+ u32 config2;
+};
+
+struct mpc83xx_rcw {
+ u32 rcwlr;
+ u32 rcwhr;
+};
+
+struct mpc83xx_clock {
+ u32 spmr;
+ u32 occr;
+ u32 sccr;
+};
+
+struct pmc_type {
+ int has_deep_sleep;
+};
+
+static struct of_device *pmc_dev;
+static int has_deep_sleep, deep_sleeping;
+static int pmc_irq;
+static struct mpc83xx_pmc __iomem *pmc_regs;
+static struct mpc83xx_clock __iomem *clock_regs;
+static int is_pci_agent, wake_from_pci;
+static phys_addr_t immrbase;
+static int pci_pm_state;
+static DECLARE_WAIT_QUEUE_HEAD(agent_wq);
+
+static u32 saved_sccr;
+static DEFINE_SPINLOCK(device_sleep_lock);
+
+void fsl_sleep_device(struct fsl_sleep_platform_data *data)
+{
+ if (clock_regs && data->sccr_mask) {
+ unsigned long flags;
+ u32 sccr;
+
+ spin_lock_irqsave(&device_sleep_lock, flags);
+ sccr = in_be32(&clock_regs->sccr);
+
+ saved_sccr &= ~data->sccr_mask;
+ saved_sccr |= sccr & data->sccr_mask;
+
+ out_be32(&clock_regs->sccr, sccr & ~data->sccr_mask);
+ spin_unlock_irqrestore(&device_sleep_lock, flags);
+ }
+}
+EXPORT_SYMBOL(fsl_sleep_device);
+
+void fsl_wake_device(struct fsl_sleep_platform_data *data)
+{
+ if (clock_regs && data->sccr_mask) {
+ unsigned long flags;
+ u32 sccr;
+
+ spin_lock_irqsave(&device_sleep_lock, flags);
+
+ sccr = in_be32(&clock_regs->sccr);
+ sccr |= saved_sccr & data->sccr_mask;
+ out_be32(&clock_regs->sccr, sccr);
+
+ spin_unlock_irqrestore(&device_sleep_lock, flags);
+ }
+}
+EXPORT_SYMBOL(fsl_wake_device);
+
+int fsl_deep_sleep(void)
+{
+ return deep_sleeping;
+}
+
+static int mpc83xx_change_state(void)
+{
+ u32 curr_state;
+ u32 reg_cfg1 = in_be32(&pmc_regs->config1);
+
+ if (is_pci_agent) {
+ pci_pm_state = (reg_cfg1 & PMCCR1_NEXT_STATE) >>
+ PMCCR1_NEXT_STATE_SHIFT;
+ curr_state = reg_cfg1 & PMCCR1_CURR_STATE;
+
+ if (curr_state != pci_pm_state) {
+ reg_cfg1 &= ~PMCCR1_CURR_STATE;
+ reg_cfg1 |= pci_pm_state;
+ out_be32(&pmc_regs->config1, reg_cfg1);
+
+ wake_up(&agent_wq);
+ return 1;
+ }
+ }
+
+ return 0;
+}
+
+static irqreturn_t pmc_irq_handler(int irq, void *dev_id)
+{
+ u32 event = in_be32(&pmc_regs->event);
+ int ret = IRQ_NONE;
+
+ if (mpc83xx_change_state())
+ ret = IRQ_HANDLED;
+
+ if (event) {
+ out_be32(&pmc_regs->event, event);
+ ret = IRQ_HANDLED;
+ }
+
+ return ret;
+}
+
+static int mpc83xx_suspend_enter(suspend_state_t state)
+{
+ int ret = -EAGAIN;
+
+ /* Don't go to sleep if there's a race where pci_pm_state changes
+ * between the agent thread checking it and the PM code disabling
+ * interrupts.
+ */
+ if (wake_from_pci) {
+ if (pci_pm_state != (deep_sleeping ? 3 : 2))
+ goto out;
+
+ out_be32(&pmc_regs->config1,
+ in_be32(&pmc_regs->config1) | PMCCR1_PME_EN);
+ }
+
+ /* Put the system into low-power mode and the RAM
+ * into self-refresh mode once the core goes to
+ * sleep.
+ */
+
+ out_be32(&pmc_regs->config, PMCCR_SLPEN | PMCCR_DLPEN);
+
+ /* If it has deep sleep (i.e. it's an 831x or compatible),
+ * disable power to the core upon entering sleep mode. This will
+ * require going through the boot firmware upon a wakeup event.
+ */
+
+ if (deep_sleeping) {
+ out_be32(&pmc_regs->mask, PMCER_ALL);
+
+ out_be32(&pmc_regs->config1,
+ in_be32(&pmc_regs->config1) | PMCCR1_POWER_OFF);
+
+ enable_kernel_fp();
+
+ mpc83xx_enter_deep_sleep(immrbase);
+
+ out_be32(&pmc_regs->config1,
+ in_be32(&pmc_regs->config1) & ~PMCCR1_POWER_OFF);
+
+ out_be32(&pmc_regs->mask, PMCER_PMCI);
+ } else {
+ out_be32(&pmc_regs->mask, PMCER_PMCI);
+
+ mpc6xx_enter_standby();
+ }
+
+ ret = 0;
+
+out:
+ out_be32(&pmc_regs->config1,
+ in_be32(&pmc_regs->config1) & ~PMCCR1_PME_EN);
+
+ return ret;
+}
+
+static void mpc83xx_suspend_finish(void)
+{
+ deep_sleeping = 0;
+}
+
+static int mpc83xx_suspend_valid(suspend_state_t state)
+{
+ return state == PM_SUSPEND_STANDBY || state == PM_SUSPEND_MEM;
+}
+
+static int mpc83xx_suspend_set_target(suspend_state_t state)
+{
+ switch (state) {
+ case PM_SUSPEND_STANDBY:
+ deep_sleeping = 0;
+ return 0;
+
+ case PM_SUSPEND_MEM:
+ if (has_deep_sleep)
+ deep_sleeping = 1;
+
+ return 0;
+
+ default:
+ return -EINVAL;
+ }
+}
+
+static int agent_thread_fn(void *data)
+{
+ while (1) {
+ wait_event_interruptible(agent_wq, pci_pm_state >= 2);
+ try_to_freeze();
+
+ if (signal_pending(current) || pci_pm_state < 2)
+ continue;
+
+ /* With a preemptible kernel (or SMP), this could race with a
+ * userspace-driven suspend request. It's probably best to
+ * avoid mixing the two with such a configuration (or else fix
+ * it by adding a mutex to state_store that we can synchronize
+ * with).
+ */
+
+ wake_from_pci = 1;
+
+ pm_suspend(pci_pm_state == 3 ? PM_SUSPEND_MEM :
+ PM_SUSPEND_STANDBY);
+
+ wake_from_pci = 0;
+ }
+
+ return 0;
+}
+
+void mpc83xx_set_agent(void)
+{
+ out_be32(&pmc_regs->config1, PMCCR1_USE_STATE);
+ out_be32(&pmc_regs->mask, PMCER_PMCI);
+
+ kthread_run(agent_thread_fn, NULL, "PCI power mgt");
+}
+
+static int mpc83xx_is_pci_agent(void)
+{
+ struct mpc83xx_rcw __iomem *rcw_regs;
+ int ret;
+
+ rcw_regs = ioremap(get_immrbase() + IMMR_RCW_OFFSET,
+ sizeof(struct mpc83xx_rcw));
+
+ if (!rcw_regs)
+ return -ENOMEM;
+
+ ret = !(in_be32(&rcw_regs->rcwhr) & RCW_PCI_HOST);
+
+ iounmap(rcw_regs);
+ return ret;
+}
+
+static struct platform_suspend_ops mpc83xx_suspend_ops = {
+ .valid = mpc83xx_suspend_valid,
+ .set_target = mpc83xx_suspend_set_target,
+ .enter = mpc83xx_suspend_enter,
+ .finish = mpc83xx_suspend_finish,
+};
+
+static int pmc_probe(struct of_device *ofdev,
+ const struct of_device_id *match)
+{
+ struct device_node *np = ofdev->node;
+ struct resource res;
+ struct pmc_type *type = match->data;
+ int ret = 0;
+
+ has_deep_sleep = type->has_deep_sleep;
+ immrbase = get_immrbase();
+ pmc_dev = ofdev;
+
+ is_pci_agent = mpc83xx_is_pci_agent();
+ if (is_pci_agent < 0)
+ return is_pci_agent;
+
+ ret = of_address_to_resource(np, 0, &res);
+ if (ret)
+ return -ENODEV;
+
+ pmc_irq = irq_of_parse_and_map(np, 0);
+ if (pmc_irq != NO_IRQ) {
+ ret = request_irq(pmc_irq, pmc_irq_handler, IRQF_SHARED,
+ "pmc", ofdev);
+
+ if (ret)
+ return -EBUSY;
+ }
+
+ pmc_regs = ioremap(res.start, sizeof(struct mpc83xx_pmc));
+
+ if (!pmc_regs) {
+ ret = -ENOMEM;
+ goto out;
+ }
+
+ ret = of_address_to_resource(np, 1, &res);
+ if (ret) {
+ ret = -ENODEV;
+ goto out_pmc;
+ }
+
+ clock_regs = ioremap(res.start, sizeof(struct mpc83xx_pmc));
+
+ if (!clock_regs) {
+ ret = -ENOMEM;
+ goto out_pmc;
+ }
+
+ if (is_pci_agent)
+ mpc83xx_set_agent();
+
+ suspend_set_ops(&mpc83xx_suspend_ops);
+ return 0;
+
+out_pmc:
+ iounmap(pmc_regs);
+out:
+ if (pmc_irq != NO_IRQ)
+ free_irq(pmc_irq, ofdev);
+
+ return ret;
+}
+
+static int pmc_remove(struct of_device *ofdev)
+{
+ return -EPERM;
+};
+
+static struct pmc_type pmc_types[] = {
+ {
+ .has_deep_sleep = 1,
+ },
+ {
+ .has_deep_sleep = 0,
+ }
+};
+
+static struct of_device_id pmc_match[] = {
+ {
+ .compatible = "fsl,mpc8313-pmc",
+ .data = &pmc_types[0],
+ },
+ {
+ .compatible = "fsl,mpc8349-pmc",
+ .data = &pmc_types[1],
+ },
+ {}
+};
+
+static struct of_platform_driver pmc_driver = {
+ .name = "mpc83xx-pmc",
+ .match_table = pmc_match,
+ .probe = pmc_probe,
+ .remove = pmc_remove
+};
+
+static int pmc_init(void)
+{
+ return of_register_platform_driver(&pmc_driver);
+}
+
+module_init(pmc_init);
diff --git a/arch/powerpc/sysdev/fsl_soc.c b/arch/powerpc/sysdev/fsl_soc.c
index e1ba33c..d5fd916 100644
--- a/arch/powerpc/sysdev/fsl_soc.c
+++ b/arch/powerpc/sysdev/fsl_soc.c
@@ -207,6 +207,33 @@ static int __init of_add_fixed_phys(void)
arch_initcall(of_add_fixed_phys);
#endif /* CONFIG_FIXED_PHY */
+int fsl_sleep_init(struct fsl_sleep_platform_data *sleep,
+ struct device_node *node)
+{
+ int proplen, ret = -ENODEV;
+ const u32 *sleepdata = of_get_property(node, "sleep", &proplen);
+ struct device_node *sleep_controller;
+
+ if (!sleepdata || proplen != 8)
+ return -ENODEV;
+
+ sleep_controller = of_find_node_by_phandle(sleepdata[0]);
+ if (!sleep_controller)
+ return -ENODEV;
+
+ /* There can only be one fsl,mpc83xx-pmc device in the system;
+ * it is assumed that it is the one that the pmc driver matches.
+ */
+ if (of_device_is_compatible(sleep_controller, "fsl,mpc83xx-pmc")) {
+ sleep->sccr_mask = sleepdata[1];
+ ret = 0;
+ }
+
+ of_node_put(sleep_controller);
+ return ret;
+}
+EXPORT_SYMBOL(fsl_sleep_init);
+
static int __init gfar_mdio_of_init(void)
{
struct device_node *np = NULL;
@@ -396,6 +423,8 @@ static int __init gfar_of_init(void)
of_node_put(mdio);
}
+ fsl_sleep_init(&gfar_data.sleep, np);
+
ret =
platform_device_add_data(gfar_dev, &gfar_data,
sizeof(struct
@@ -647,6 +676,8 @@ static int __init fsl_usb_of_init(void)
prop = of_get_property(np, "phy_type", NULL);
usb_data.phy_mode = determine_usb_phy(prop);
+ fsl_sleep_init(&usb_data.sleep, np);
+
ret =
platform_device_add_data(usb_dev_mph, &usb_data,
sizeof(struct
@@ -710,6 +741,8 @@ static int __init fsl_usb_of_init(void)
prop = of_get_property(np, "phy_type", NULL);
usb_data.phy_mode = determine_usb_phy(prop);
+ fsl_sleep_init(&usb_data.sleep, np);
+
if (usb_dev_dr_host) {
usb_dev_dr_host->dev.coherent_dma_mask = 0xffffffffUL;
usb_dev_dr_host->dev.dma_mask = &usb_dev_dr_host->
diff --git a/arch/powerpc/sysdev/fsl_soc.h b/arch/powerpc/sysdev/fsl_soc.h
index 74c4a96..fb52d39 100644
--- a/arch/powerpc/sysdev/fsl_soc.h
+++ b/arch/powerpc/sysdev/fsl_soc.h
@@ -10,12 +10,22 @@ extern u32 get_baudrate(void);
extern u32 fsl_get_sys_freq(void);
struct spi_board_info;
+struct fsl_sleep_platform_data;
+struct device_node;
extern int fsl_spi_init(struct spi_board_info *board_infos,
unsigned int num_board_infos,
void (*activate_cs)(u8 cs, u8 polarity),
void (*deactivate_cs)(u8 cs, u8 polarity));
+int fsl_sleep_init(struct fsl_sleep_platform_data *sleep,
+ struct device_node *node);
+
+/* Calls to fsl_sleep_dev and fsl_wake_dev cannot be nested. */
+void fsl_sleep_dev(struct fsl_sleep_platform_data *sleep);
+void fsl_wake_dev(struct fsl_sleep_platform_data *sleep);
+
extern void fsl_rstcr_restart(char *cmd);
+
#endif
#endif
diff --git a/arch/powerpc/sysdev/ipic.c b/arch/powerpc/sysdev/ipic.c
index 05a56e5..e2388cf 100644
--- a/arch/powerpc/sysdev/ipic.c
+++ b/arch/powerpc/sysdev/ipic.c
@@ -22,6 +22,7 @@
#include <linux/device.h>
#include <linux/bootmem.h>
#include <linux/spinlock.h>
+#include <linux/fsl_devices.h>
#include <asm/irq.h>
#include <asm/io.h>
#include <asm/prom.h>
@@ -893,8 +894,78 @@ unsigned int ipic_get_irq(void)
return irq_linear_revmap(primary_ipic->irqhost, irq);
}
+#ifdef CONFIG_PM
+static struct {
+ u32 sicfr;
+ u32 siprr[2];
+ u32 simsr[2];
+ u32 sicnr;
+ u32 smprr[2];
+ u32 semsr;
+ u32 secnr;
+ u32 sermr;
+ u32 sercr;
+} ipic_saved_state;
+
+static int ipic_suspend(struct sys_device *sdev, pm_message_t state)
+{
+ struct ipic *ipic = primary_ipic;
+
+ ipic_saved_state.sicfr = ipic_read(ipic->regs, IPIC_SICFR);
+ ipic_saved_state.siprr[0] = ipic_read(ipic->regs, IPIC_SIPRR_A);
+ ipic_saved_state.siprr[1] = ipic_read(ipic->regs, IPIC_SIPRR_D);
+ ipic_saved_state.simsr[0] = ipic_read(ipic->regs, IPIC_SIMSR_H);
+ ipic_saved_state.simsr[1] = ipic_read(ipic->regs, IPIC_SIMSR_L);
+ ipic_saved_state.sicnr = ipic_read(ipic->regs, IPIC_SICNR);
+ ipic_saved_state.smprr[0] = ipic_read(ipic->regs, IPIC_SMPRR_A);
+ ipic_saved_state.smprr[1] = ipic_read(ipic->regs, IPIC_SMPRR_B);
+ ipic_saved_state.semsr = ipic_read(ipic->regs, IPIC_SEMSR);
+ ipic_saved_state.secnr = ipic_read(ipic->regs, IPIC_SECNR);
+ ipic_saved_state.sermr = ipic_read(ipic->regs, IPIC_SERMR);
+ ipic_saved_state.sercr = ipic_read(ipic->regs, IPIC_SERCR);
+
+ if (fsl_deep_sleep()) {
+ /* In deep sleep, make sure there can be no
+ * pending interrupts, as this can cause
+ * problems on 831x.
+ */
+ ipic_write(ipic->regs, IPIC_SIMSR_H, 0);
+ ipic_write(ipic->regs, IPIC_SIMSR_L, 0);
+ ipic_write(ipic->regs, IPIC_SEMSR, 0);
+ ipic_write(ipic->regs, IPIC_SERMR, 0);
+ }
+
+ return 0;
+}
+
+static int ipic_resume(struct sys_device *sdev)
+{
+ struct ipic *ipic = primary_ipic;
+
+ ipic_write(ipic->regs, IPIC_SICFR, ipic_saved_state.sicfr);
+ ipic_write(ipic->regs, IPIC_SIPRR_A, ipic_saved_state.siprr[0]);
+ ipic_write(ipic->regs, IPIC_SIPRR_D, ipic_saved_state.siprr[1]);
+ ipic_write(ipic->regs, IPIC_SIMSR_H, ipic_saved_state.simsr[0]);
+ ipic_write(ipic->regs, IPIC_SIMSR_L, ipic_saved_state.simsr[1]);
+ ipic_write(ipic->regs, IPIC_SICNR, ipic_saved_state.sicnr);
+ ipic_write(ipic->regs, IPIC_SMPRR_A, ipic_saved_state.smprr[0]);
+ ipic_write(ipic->regs, IPIC_SMPRR_B, ipic_saved_state.smprr[1]);
+ ipic_write(ipic->regs, IPIC_SEMSR, ipic_saved_state.semsr);
+ ipic_write(ipic->regs, IPIC_SECNR, ipic_saved_state.secnr);
+ ipic_write(ipic->regs, IPIC_SERMR, ipic_saved_state.sermr);
+ ipic_write(ipic->regs, IPIC_SERCR, ipic_saved_state.sercr);
+
+ return 0;
+}
+#else
+#define ipic_suspend NULL
+#define ipic_resume NULL
+#endif
+
static struct sysdev_class ipic_sysclass = {
.name = "ipic",
+ .suspend = ipic_suspend,
+ .resume = ipic_resume,
};
static struct sys_device device_ipic = {
diff --git a/include/asm-powerpc/reg.h b/include/asm-powerpc/reg.h
index 1f68504..68968c1 100644
--- a/include/asm-powerpc/reg.h
+++ b/include/asm-powerpc/reg.h
@@ -153,10 +153,12 @@
#define CTRL_RUNLATCH 0x1
#define SPRN_DABR 0x3F5 /* Data Address Breakpoint Register */
#define DABR_TRANSLATION (1UL << 2)
+#define SPRN_DABR2 0x13D /* 83xx */
#define SPRN_DABRX 0x3F7 /* Data Address Breakpoint Register Extension */
#define DABRX_USER (1UL << 0)
#define DABRX_KERNEL (1UL << 1)
#define SPRN_DAR 0x013 /* Data Address Register */
+#define SPRN_DBCR 0x136 /* 83xx Data Breakpoint Control Reg */
#define SPRN_DSISR 0x012 /* Data Storage Interrupt Status Register */
#define DSISR_NOHPTE 0x40000000 /* no translation found */
#define DSISR_PROTFAULT 0x08000000 /* protection fault */
@@ -262,6 +264,8 @@
#define HID1_PS (1<<16) /* 750FX PLL selection */
#define SPRN_HID2 0x3F8 /* Hardware Implementation Register 2 */
#define SPRN_IABR 0x3F2 /* Instruction Address Breakpoint Register */
+#define SPRN_IABR2 0x3FA /* 83xx */
+#define SPRN_IBCR 0x135 /* 83xx Insn Breakpoint Control Reg */
#define SPRN_HID4 0x3F4 /* 970 HID4 */
#define SPRN_HID5 0x3F6 /* 970 HID5 */
#define SPRN_HID6 0x3F9 /* BE HID 6 */
diff --git a/include/linux/fsl_devices.h b/include/linux/fsl_devices.h
index 1831b19..5cec939 100644
--- a/include/linux/fsl_devices.h
+++ b/include/linux/fsl_devices.h
@@ -45,10 +45,27 @@
*
*/
+struct fsl_sleep_platform_data {
+ /*
+ * The bits set in this mask will be cleared in the SCCR
+ * when put to sleep, and restored on wakeup.
+ */
+ u32 sccr_mask;
+};
+
+/*
+ * Calls to fsl_sleep_device do not nest -- if you call
+ * sleep twice without an intervening wake, you will not
+ * be able to wake the device again.
+ */
+void fsl_sleep_device(struct fsl_sleep_platform_data *data);
+void fsl_wake_device(struct fsl_sleep_platform_data *data);
+
struct gianfar_platform_data {
/* device specific information */
u32 device_flags;
/* board specific information */
+ struct fsl_sleep_platform_data sleep;
u32 board_flags;
char bus_id[MII_BUS_ID_SIZE];
u32 phy_id;
@@ -104,6 +121,7 @@ struct fsl_usb2_platform_data {
enum fsl_usb2_operating_modes operating_mode;
enum fsl_usb2_phy_modes phy_mode;
unsigned int port_enables;
+ struct fsl_sleep_platform_data sleep;
};
/* Flags in fsl_usb2_mph_platform_data */
@@ -126,5 +144,11 @@ struct mpc8xx_pcmcia_ops {
int(*voltage_set)(int slot, int vcc, int vpp);
};
+/* Returns non-zero if the current suspend operation would
+ * lead to a deep sleep (i.e. power removed from the core,
+ * instead of just the clock).
+ */
+int fsl_deep_sleep(void);
+
#endif /* _FSL_DEVICE_H_ */
#endif /* __KERNEL__ */
--
1.5.3.7
^ permalink raw reply related
* [PATCH 4/7] mpc83xx: timer driver for PM wakeup
From: Guennadi Liakhovetski @ 2008-04-28 15:39 UTC (permalink / raw)
To: linuxppc-dev; +Cc: Scott Wood, linux-pm, Paul Mackerras
In-Reply-To: <Pine.LNX.4.64.0804281714000.7897@axis700.grange>
This is a driver for the mpc83xx's GTM4 timer. It's functionality
is limited to providing a wakeup source for suspend-to-RAM.
Signed-off-by: Scott Wood <scottwood@freescale.com>
Signed-off-by: Guennadi Liakhovetski <g.liakhovetski@gmx.de>
---
arch/powerpc/platforms/83xx/Kconfig | 9 +
arch/powerpc/platforms/83xx/Makefile | 1 +
arch/powerpc/platforms/83xx/timer.c | 299 ++++++++++++++++++++++++++++++++++
3 files changed, 309 insertions(+), 0 deletions(-)
create mode 100644 arch/powerpc/platforms/83xx/timer.c
diff --git a/arch/powerpc/platforms/83xx/Kconfig b/arch/powerpc/platforms/83xx/Kconfig
index 901dbaf..800f547 100644
--- a/arch/powerpc/platforms/83xx/Kconfig
+++ b/arch/powerpc/platforms/83xx/Kconfig
@@ -80,6 +80,15 @@ config PPC_83xx_SUSPEND
This option enables support for the Wind River SBC834x board.
endif
+
+config MPC83xx_GTM
+ tristate "83xx General-Purpose Timers for PM wakeup"
+ help
+ This enables a driver for the GTM4 timer, to be used
+ as a wakeup source for suspend-to-RAM. To arm the
+ timer, write the number of seconds until expiration
+ to the "timeout" file in the device's sysfs directory.
+ To disarm, write 0 to the "timeout" file.
# used for usb
config PPC_MPC831x
diff --git a/arch/powerpc/platforms/83xx/Makefile b/arch/powerpc/platforms/83xx/Makefile
index 944369e..bcc1003 100644
--- a/arch/powerpc/platforms/83xx/Makefile
+++ b/arch/powerpc/platforms/83xx/Makefile
@@ -4,6 +4,7 @@
obj-y := misc.o usb.o
obj-$(CONFIG_PCI) += pci.o
obj-$(CONFIG_SUSPEND) += suspend.o suspend-asm.o
+obj-$(CONFIG_MPC83xx_GTM) += timer.o
obj-$(CONFIG_MPC831x_RDB) += mpc831x_rdb.o
obj-$(CONFIG_MPC832x_RDB) += mpc832x_rdb.o
obj-$(CONFIG_MPC834x_MDS) += mpc834x_mds.o
diff --git a/arch/powerpc/platforms/83xx/timer.c b/arch/powerpc/platforms/83xx/timer.c
new file mode 100644
index 0000000..7fc6048
--- /dev/null
+++ b/arch/powerpc/platforms/83xx/timer.c
@@ -0,0 +1,300 @@
+/*
+ * MPC83xx Global Timer4 support
+ *
+ * This driver is currently specific to timer 4 in 16-bit mode,
+ * as that is all that can be used as a wakeup source for deep sleep
+ * on the MPC8313.
+ *
+ * Copyright (c) 2007 Freescale Semiconductor, Inc.
+ *
+ * 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/kernel.h>
+#include <linux/init.h>
+#include <linux/sched.h>
+#include <linux/errno.h>
+#include <linux/module.h>
+#include <linux/mm.h>
+#include <linux/delay.h>
+#include <linux/fs.h>
+#include <linux/string.h>
+#include <linux/interrupt.h>
+#include <linux/sysfs.h>
+#include <linux/of_platform.h>
+
+#include <asm/io.h>
+#include <asm/irq.h>
+
+#include <sysdev/fsl_soc.h>
+
+#define MDR_ICLK_DIV16 0x0004
+
+struct gtm_regs {
+ u8 cfr1; /* Timer1/2 Configuration */
+ #define CFR1_PCAS 0x80 /* Pair Cascade mode */
+ #define CFR1_BCM 0x40 /* Backward compatible mode */
+ #define CFR1_STP2 0x20 /* Stop timer */
+ #define CFR1_RST2 0x10 /* Reset timer */
+ #define CFR1_GM2 0x08 /* Gate mode for pin 2 */
+ #define CFR1_GM1 0x04 /* Gate mode for pin 1 */
+ #define CFR1_STP1 0x02 /* Stop timer */
+ #define CFR1_RST1 0x01 /* Reset timer */
+ #define CFR1_RES ~(CFR1_PCAS | CFR1_STP2 | CFR1_RST2 | CFR1_GM2 |\
+ CFR1_GM1 | CFR1_STP1 | CFR1_RST1)
+
+ u8 res0[3];
+ u8 cfr2; /* Timer3/4 Configuration */
+ #define CFR2_PCAS 0x80 /* Pair Cascade mode */
+ #define CFR2_SCAS 0x40 /* Super Cascade mode */
+ #define CFR2_STP4 0x20 /* Stop timer */
+ #define CFR2_RST4 0x10 /* Reset timer */
+ #define CFR2_GM4 0x08 /* Gate mode for pin 4 */
+ #define CFR2_GM3 0x04 /* Gate mode for pin 3 */
+ #define CFR2_STP3 0x02 /* Stop timer */
+ #define CFR2_RST3 0x01 /* Reset timer */
+
+ u8 res1[11];
+ u16 mdr1; /* Timer1 Mode Register */
+ #define MDR_SPS 0xff00 /* Secondary Prescaler value (256) */
+ #define MDR_CE 0x00c0 /* Capture edge and enable interrupt */
+ #define MDR_OM 0x0020 /* Output mode */
+ #define MDR_ORI 0x0010 /* Output reference interrupt enable */
+ #define MDR_FRR 0x0008 /* Free run/restart */
+ #define MDR_ICLK 0x0006 /* Input clock source for the timer */
+ #define MDR_GE 0x0001 /* Gate enable */
+
+ u16 mdr2; /* Timer2 Mode Register */
+ u16 rfr1; /* Timer1 Reference Register */
+ u16 rfr2; /* Timer2 Reference Register */
+ u16 cpr1; /* Timer1 Capture Register */
+ u16 cpr2; /* Timer2 Capture Register */
+ u16 cnr1; /* Timer1 Counter Register */
+ u16 cnr2; /* Timer2 Counter Register */
+ u16 mdr3; /* Timer3 Mode Register */
+ u16 mdr4; /* Timer4 Mode Register */
+ u16 rfr3; /* Timer3 Reference Register */
+ u16 rfr4; /* Timer4 Reference Register */
+ u16 cpr3; /* Timer3 Capture Register */
+ u16 cpr4; /* Timer4 Capture Register */
+ u16 cnr3; /* Timer3 Counter Register */
+ u16 cnr4; /* Timer4 Counter Register */
+ u16 evr1; /* Timer1 Event Register */
+ u16 evr2; /* Timer2 Event Register */
+ u16 evr3; /* Timer3 Event Register */
+ u16 evr4; /* Timer4 Event Register */
+ #define GTEVR_REF 0x0002 /* Output reference event */
+ #define GTEVR_CAP 0x0001 /* Counter Capture event */
+ #define GTEVR_RES ~(EVR_CAP|EVR_REF)
+
+ u16 psr1; /* Timer1 Prescaler Register */
+ u16 psr2; /* Timer2 Prescaler Register */
+ u16 psr3; /* Timer3 Prescaler Register */
+ u16 psr4; /* Timer4 Prescaler Register */
+ #define GTPSR_PPS 0x00FF /* Primary Prescaler Bits (256). */
+ #define GTPSR_RES ~(GTPSR_PPS)
+};
+
+struct gtm_priv {
+ struct gtm_regs __iomem *regs;
+ int irq;
+ int ticks_per_sec;
+ spinlock_t lock;
+};
+
+static irqreturn_t fsl_gtm_isr(int irq, void *dev_id)
+{
+ struct gtm_priv *priv = dev_id;
+ unsigned long flags;
+ u16 event;
+
+ spin_lock_irqsave(&priv->lock, flags);
+
+ event = in_be16(&priv->regs->evr4);
+ out_be16(&priv->regs->evr4, event);
+
+ if (event & GTEVR_REF)
+ out_8(&priv->regs->cfr2, CFR2_STP4);
+
+ spin_unlock_irqrestore(&priv->lock, flags);
+ return event ? IRQ_HANDLED : IRQ_NONE;
+}
+
+static ssize_t gtm_timeout_store(struct device *dev,
+ struct device_attribute *attr,
+ const char *buf, size_t count)
+{
+ struct gtm_priv *priv = dev_get_drvdata(dev);
+ unsigned long interval = simple_strtoul(buf, NULL, 0);
+
+ if (interval > 0xffff) {
+ dev_dbg(dev, "gtm: interval %lu (in ns) too long\n", interval);
+ return -EINVAL;
+ }
+
+ interval *= priv->ticks_per_sec;
+
+ if (interval > 0xffff) {
+ dev_dbg(dev, "gtm: interval %lu (in ticks) too long\n",
+ interval);
+ return -EINVAL;
+ }
+
+ spin_lock_irq(&priv->lock);
+
+ /* reset timer 4 */
+ out_8(&priv->regs->cfr2, CFR2_STP3 | CFR2_STP4);
+
+ if (interval != 0) {
+ out_8(&priv->regs->cfr2, CFR2_GM4 | CFR2_RST4 | CFR2_STP4);
+ /* clear events */
+ out_be16(&priv->regs->evr4, GTEVR_REF | GTEVR_CAP);
+ /* maximum primary prescale (256) */
+ out_be16(&priv->regs->psr4, GTPSR_PPS);
+ /* clear current counter */
+ out_be16(&priv->regs->cnr4, 0x0);
+ /* set count limit */
+ out_be16(&priv->regs->rfr4, interval);
+ out_be16(&priv->regs->mdr4, MDR_SPS | MDR_ORI | MDR_FRR |
+ MDR_ICLK_DIV16);
+ /* start timer */
+ out_8(&priv->regs->cfr2, CFR2_GM4 | CFR2_STP3 | CFR2_RST4);
+ }
+
+ spin_unlock_irq(&priv->lock);
+ return count;
+}
+
+static ssize_t gtm_timeout_show(struct device *dev,
+ struct device_attribute *attr,
+ char *buf)
+{
+ struct gtm_priv *priv = dev_get_drvdata(dev);
+ int timeout = 0;
+
+ spin_lock_irq(&priv->lock);
+
+ if (!(in_8(&priv->regs->cfr2) & CFR2_STP4)) {
+ timeout = in_be16(&priv->regs->rfr4) -
+ in_be16(&priv->regs->cnr4);
+ timeout += priv->ticks_per_sec - 1;
+ timeout /= priv->ticks_per_sec;
+ }
+
+ spin_unlock_irq(&priv->lock);
+ return sprintf(buf, "%u\n", timeout);
+}
+
+static DEVICE_ATTR(timeout, 0660, gtm_timeout_show, gtm_timeout_store);
+
+static int __devinit gtm_probe(struct of_device *dev,
+ const struct of_device_id *match)
+{
+ struct device_node *np = dev->node;
+ struct resource res;
+ int ret = 0;
+ u32 busfreq = fsl_get_sys_freq();
+ struct gtm_priv *priv;
+
+ if (busfreq == 0) {
+ dev_err(&dev->dev, "gtm: No bus frequency in device tree.\n");
+ return -ENODEV;
+ }
+
+ priv = kmalloc(sizeof(struct gtm_priv), GFP_KERNEL);
+ if (!priv)
+ return -ENOMEM;
+
+ spin_lock_init(&priv->lock);
+ dev_set_drvdata(&dev->dev, priv);
+
+ ret = of_address_to_resource(np, 0, &res);
+ if (ret)
+ goto out;
+
+ priv->irq = irq_of_parse_and_map(np, 0);
+ if (priv->irq == NO_IRQ) {
+ dev_err(&dev->dev, "mpc83xx-gtm exists in device tree "
+ "without an IRQ.\n");
+ ret = -ENODEV;
+ goto out;
+ }
+
+ ret = request_irq(priv->irq, fsl_gtm_isr, 0, "gtm timer", priv);
+ if (ret)
+ goto out;
+
+ priv->regs = ioremap(res.start, sizeof(struct gtm_regs));
+ if (!priv->regs) {
+ ret = -ENOMEM;
+ goto out;
+ }
+
+ /* Disable the unused clocks to save power. */
+ out_8(&priv->regs->cfr1, CFR1_STP1 | CFR1_STP2);
+ out_8(&priv->regs->cfr2, CFR2_STP3 | CFR2_STP4);
+
+ /*
+ * Maximum prescaling is used (input clock/16, 256 primary prescaler,
+ * 256 secondary prescaler) to maximize the timer's range. With a
+ * bus clock of 133MHz, this yields a maximum interval of 516
+ * seconds while retaining subsecond precision. Since only
+ * timer 4 is supported for wakeup on the 8313, and timer 4
+ * is the LSB when chained, we can't use chaining to increase
+ * the range.
+ */
+ priv->ticks_per_sec = busfreq / (16*256*256);
+
+ ret = device_create_file(&dev->dev, &dev_attr_timeout);
+ if (ret)
+ goto out;
+
+ return 0;
+
+out:
+ dev_set_drvdata(&dev->dev, NULL);
+ kfree(priv);
+ return ret;
+}
+
+static int __devexit gtm_remove(struct of_device *dev)
+{
+ struct gtm_priv *priv = dev_get_drvdata(&dev->dev);
+
+ device_remove_file(&dev->dev, &dev_attr_timeout);
+ free_irq(priv->irq, priv);
+ iounmap(priv->regs);
+
+ dev_set_drvdata(&dev->dev, NULL);
+ kfree(priv);
+ return 0;
+}
+
+static struct of_device_id gtm_match[] = {
+ {
+ .compatible = "fsl,mpc8313-gtm",
+ },
+ {},
+};
+
+static struct of_platform_driver gtm_driver = {
+ .name = "mpc83xx-gtm",
+ .match_table = gtm_match,
+ .probe = gtm_probe,
+ .remove = __devexit_p(gtm_remove)
+};
+
+static int __init gtm_init(void)
+{
+ return of_register_platform_driver(>m_driver);
+}
+
+static void __exit gtm_exit(void)
+{
+ of_unregister_platform_driver(>m_driver);
+}
+
+module_init(gtm_init);
+module_exit(gtm_exit);
--
1.5.3.7
^ permalink raw reply related
* [PATCH 5/7] gianfar: Add flags for magic packet and MDIO.
From: Guennadi Liakhovetski @ 2008-04-28 15:39 UTC (permalink / raw)
To: linuxppc-dev; +Cc: Scott Wood, linux-pm, Paul Mackerras
In-Reply-To: <Pine.LNX.4.64.0804281714000.7897@axis700.grange>
The magic packet flag indicates that the hardware has this
capability. The MDIO flag indicates that this device's
registers contain active MDIO registers, and thus this
device should not be put to sleep.
Signed-off-by: Scott Wood <scottwood@freescale.com>
Signed-off-by: Guennadi Liakhovetski <g.liakhovetski@gmx.de>
---
arch/powerpc/sysdev/fsl_soc.c | 7 +++++++
include/linux/fsl_devices.h | 2 ++
2 files changed, 9 insertions(+), 0 deletions(-)
diff --git a/arch/powerpc/sysdev/fsl_soc.c b/arch/powerpc/sysdev/fsl_soc.c
index d5fd916..032b8e8 100644
--- a/arch/powerpc/sysdev/fsl_soc.c
+++ b/arch/powerpc/sysdev/fsl_soc.c
@@ -324,6 +324,9 @@ static int __init gfar_of_init(void)
else
gfar_data.interface = PHY_INTERFACE_MODE_MII;
+ if (of_get_property(np, "fsl,magic-packet", NULL))
+ gfar_data.device_flags |= FSL_GIANFAR_DEV_HAS_MAGIC_PACKET;
+
ph = of_get_property(np, "phy-handle", NULL);
if (ph == NULL) {
u32 *fixed_link;
@@ -345,6 +348,10 @@ static int __init gfar_of_init(void)
snprintf(gfar_data.bus_id, MII_BUS_ID_SIZE, "%x",
res.start);
+ if (res.start >= gfar_dev->resource[0].start &&
+ res.start < gfar_dev->resource[0].end)
+ gfar_data.device_flags |= FSL_GIANFAR_DEV_HAS_MDIO;
+
of_node_put(phy);
of_node_put(mdio);
}
diff --git a/include/linux/fsl_devices.h b/include/linux/fsl_devices.h
index 5cec939..81fcc67 100644
--- a/include/linux/fsl_devices.h
+++ b/include/linux/fsl_devices.h
@@ -87,6 +87,8 @@ struct gianfar_mdio_data {
#define FSL_GIANFAR_DEV_HAS_VLAN 0x00000020
#define FSL_GIANFAR_DEV_HAS_EXTENDED_HASH 0x00000040
#define FSL_GIANFAR_DEV_HAS_PADDING 0x00000080
+#define FSL_GIANFAR_DEV_HAS_MAGIC_PACKET 0x00000100
+#define FSL_GIANFAR_DEV_HAS_MDIO 0x00000200
/* Flags in gianfar_platform_data */
#define FSL_GIANFAR_BRD_HAS_PHY_INTR 0x00000001 /* set or use a timer */
--
1.5.3.7
^ permalink raw reply related
* [PATCH 6/7] gianfar: Magic Packet and suspend/resume support.
From: Guennadi Liakhovetski @ 2008-04-28 15:40 UTC (permalink / raw)
To: linuxppc-dev; +Cc: Scott Wood, jgarzik, linux-pm, Paul Mackerras, netdev
In-Reply-To: <Pine.LNX.4.64.0804281714000.7897@axis700.grange>
Signed-off-by: Scott Wood <scottwood@freescale.com>
Signed-off-by: Guennadi Liakhovetski <g.liakhovetski@gmx.de>
---
This patch has already been acked by Jeff Garzik:
>From jgarzik@pobox.com Fri Dec 14 20:28:38 2007
Date: Fri, 14 Dec 2007 15:24:29 -0500
From: Jeff Garzik <jgarzik@pobox.com>
To: Scott Wood <scottwood@freescale.com>
Cc: linuxppc-dev@ozlabs.org, paulus@samba.org, netdev@vger.kernel.org
Subject: Re: [PATCH 8/8] gianfar: Magic Packet and suspend/resume support.
Scott Wood wrote:
> Signed-off-by: Scott Wood <scottwood@freescale.com>
> ---
> Jeff, can you ack this to go through Paul's tree
> (assuming nothing wrong with it)?
>
> drivers/net/gianfar.c | 137 ++++++++++++++++++++++++++++++++++++++++-
> drivers/net/gianfar.h | 13 +++-
> drivers/net/gianfar_ethtool.c | 41 ++++++++++++-
> 3 files changed, 185 insertions(+), 6 deletions(-)
ACK
drivers/net/gianfar.c | 137 ++++++++++++++++++++++++++++++++++++++++-
drivers/net/gianfar.h | 13 +++-
drivers/net/gianfar_ethtool.c | 41 ++++++++++++-
3 files changed, 185 insertions(+), 6 deletions(-)
diff --git a/drivers/net/gianfar.c b/drivers/net/gianfar.c
index 0431e9e..2c1b8d5 100644
--- a/drivers/net/gianfar.c
+++ b/drivers/net/gianfar.c
@@ -142,6 +142,7 @@ int gfar_clean_rx_ring(struct net_device *dev, int rx_work_limit);
static int gfar_process_frame(struct net_device *dev, struct sk_buff *skb, int length);
static void gfar_vlan_rx_register(struct net_device *netdev,
struct vlan_group *grp);
+static void gfar_halt_nodisable(struct net_device *dev);
void gfar_halt(struct net_device *dev);
void gfar_start(struct net_device *dev);
static void gfar_clear_exact_match(struct net_device *dev);
@@ -216,6 +217,7 @@ static int gfar_probe(struct platform_device *pdev)
spin_lock_init(&priv->txlock);
spin_lock_init(&priv->rxlock);
+ spin_lock_init(&priv->bflock);
platform_set_drvdata(pdev, dev);
@@ -393,6 +395,122 @@ static int gfar_remove(struct platform_device *pdev)
return 0;
}
+#ifdef CONFIG_PM
+static int gfar_suspend(struct platform_device *pdev, pm_message_t state)
+{
+ struct net_device *dev = platform_get_drvdata(pdev);
+ struct gfar_private *priv = netdev_priv(dev);
+ unsigned long flags;
+ u32 tempval;
+
+ int magic_packet = priv->wol_en &&
+ (priv->einfo->device_flags & FSL_GIANFAR_DEV_HAS_MAGIC_PACKET);
+
+ netif_device_detach(dev);
+
+ if (netif_running(dev)) {
+ spin_lock_irqsave(&priv->txlock, flags);
+ spin_lock(&priv->rxlock);
+
+ gfar_halt_nodisable(dev);
+
+ /* Disable Tx, and Rx if wake-on-LAN is disabled. */
+ tempval = gfar_read(&priv->regs->maccfg1);
+
+ tempval &= ~MACCFG1_TX_EN;
+
+ if (!magic_packet)
+ tempval &= ~MACCFG1_RX_EN;
+
+ gfar_write(&priv->regs->maccfg1, tempval);
+
+ spin_unlock(&priv->rxlock);
+ spin_unlock_irqrestore(&priv->txlock, flags);
+
+#ifdef CONFIG_GFAR_NAPI
+ napi_disable(&priv->napi);
+#endif
+
+ if (magic_packet) {
+ /* Enable interrupt on Magic Packet */
+ gfar_write(&priv->regs->imask, IMASK_MAG);
+
+ /* Enable Magic Packet mode */
+ tempval = gfar_read(&priv->regs->maccfg2);
+ tempval |= MACCFG2_MPEN;
+ gfar_write(&priv->regs->maccfg2, tempval);
+ } else {
+ phy_stop(priv->phydev);
+ }
+ }
+
+ if (!magic_packet || !netif_running(dev)) {
+ /* The device with the MDIO in its register block must
+ * not be put to sleep if any other network devices
+ * using the same MDIO are active. Ideally, some sort
+ * of reference counting could be done, but for now
+ * just don't put the MDIO-containing dev to sleep
+ * at all.
+ */
+ if (!(priv->einfo->device_flags & FSL_GIANFAR_DEV_HAS_MDIO)) {
+ fsl_sleep_device(&priv->einfo->sleep);
+ priv->suspended = 1;
+ }
+ }
+
+ return 0;
+}
+
+static int gfar_resume(struct platform_device *pdev)
+{
+ struct net_device *dev = platform_get_drvdata(pdev);
+ struct gfar_private *priv = netdev_priv(dev);
+ unsigned long flags;
+ u32 tempval;
+ int magic_packet = priv->wol_en &&
+ (priv->einfo->device_flags & FSL_GIANFAR_DEV_HAS_MAGIC_PACKET);
+
+ if (priv->suspended) {
+ fsl_wake_device(&priv->einfo->sleep);
+ priv->suspended = 0;
+ }
+
+ if (!netif_running(dev)) {
+ netif_device_attach(dev);
+ return 0;
+ }
+
+ if (!magic_packet && priv->phydev)
+ phy_start(priv->phydev);
+
+ /* Disable Magic Packet mode, in case something
+ * else woke us up.
+ */
+
+ spin_lock_irqsave(&priv->txlock, flags);
+ spin_lock(&priv->rxlock);
+
+ tempval = gfar_read(&priv->regs->maccfg2);
+ tempval &= ~MACCFG2_MPEN;
+ gfar_write(&priv->regs->maccfg2, tempval);
+
+ gfar_start(dev);
+
+ spin_unlock(&priv->rxlock);
+ spin_unlock_irqrestore(&priv->txlock, flags);
+
+ netif_device_attach(dev);
+
+#ifdef CONFIG_GFAR_NAPI
+ napi_enable(&priv->napi);
+#endif
+
+ return 0;
+}
+#else
+#define gfar_suspend NULL
+#define gfar_resume NULL
+#endif
/* Reads the controller's registers to determine what interface
* connects it to the PHY.
@@ -547,7 +665,7 @@ static void init_registers(struct net_device *dev)
/* Halt the receive and transmit queues */
-void gfar_halt(struct net_device *dev)
+static void gfar_halt_nodisable(struct net_device *dev)
{
struct gfar_private *priv = netdev_priv(dev);
struct gfar __iomem *regs = priv->regs;
@@ -570,6 +688,14 @@ void gfar_halt(struct net_device *dev)
(IEVENT_GRSC | IEVENT_GTSC)))
cpu_relax();
}
+}
+
+/* Halt the receive and transmit queues */
+void gfar_halt(struct net_device *dev)
+{
+ struct gfar_private *priv = netdev_priv(dev);
+ struct gfar __iomem *regs = priv->regs;
+ u32 tempval;
/* Disable Rx and Tx */
tempval = gfar_read(®s->maccfg1);
@@ -1909,7 +2035,12 @@ static irqreturn_t gfar_error(int irq, void *dev_id)
u32 events = gfar_read(&priv->regs->ievent);
/* Clear IEVENT */
- gfar_write(&priv->regs->ievent, IEVENT_ERR_MASK);
+ gfar_write(&priv->regs->ievent, events & IEVENT_ERR_MASK);
+
+ /* Magic Packet is not an error. */
+ if ((priv->einfo->device_flags & FSL_GIANFAR_DEV_HAS_MAGIC_PACKET) &&
+ (events & IEVENT_MAG))
+ events &= ~IEVENT_MAG;
/* Hmm... */
if (netif_msg_rx_err(priv) || netif_msg_tx_err(priv))
@@ -1979,6 +2110,8 @@ static irqreturn_t gfar_error(int irq, void *dev_id)
static struct platform_driver gfar_driver = {
.probe = gfar_probe,
.remove = gfar_remove,
+ .suspend = gfar_suspend,
+ .resume = gfar_resume,
.driver = {
.name = "fsl-gianfar",
},
diff --git a/drivers/net/gianfar.h b/drivers/net/gianfar.h
index 46cd773..922ed36 100644
--- a/drivers/net/gianfar.h
+++ b/drivers/net/gianfar.h
@@ -162,6 +162,7 @@ extern const char gfar_driver_version[];
#define MACCFG2_GMII 0x00000200
#define MACCFG2_HUGEFRAME 0x00000020
#define MACCFG2_LENGTHCHECK 0x00000010
+#define MACCFG2_MPEN 0x00000008
#define ECNTRL_INIT_SETTINGS 0x00001000
#define ECNTRL_TBI_MODE 0x00000020
@@ -234,6 +235,7 @@ extern const char gfar_driver_version[];
#define IEVENT_CRL 0x00020000
#define IEVENT_XFUN 0x00010000
#define IEVENT_RXB0 0x00008000
+#define IEVENT_MAG 0x00000800
#define IEVENT_GRSC 0x00000100
#define IEVENT_RXF0 0x00000080
#define IEVENT_FIR 0x00000008
@@ -245,7 +247,8 @@ extern const char gfar_driver_version[];
#define IEVENT_ERR_MASK \
(IEVENT_RXC | IEVENT_BSY | IEVENT_EBERR | IEVENT_MSRO | \
IEVENT_BABT | IEVENT_TXC | IEVENT_TXE | IEVENT_LC \
- | IEVENT_CRL | IEVENT_XFUN | IEVENT_DPE | IEVENT_PERR)
+ | IEVENT_CRL | IEVENT_XFUN | IEVENT_DPE | IEVENT_PERR \
+ | IEVENT_MAG)
#define IMASK_INIT_CLEAR 0x00000000
#define IMASK_BABR 0x80000000
@@ -263,6 +266,7 @@ extern const char gfar_driver_version[];
#define IMASK_CRL 0x00020000
#define IMASK_XFUN 0x00010000
#define IMASK_RXB0 0x00008000
+#define IMASK_MAG 0x00000800
#define IMASK_GTSC 0x00000100
#define IMASK_RXFEN0 0x00000080
#define IMASK_FIR 0x00000008
@@ -726,10 +730,15 @@ struct gfar_private {
unsigned int fifo_starve;
unsigned int fifo_starve_off;
+ /* Bitfield update lock */
+ spinlock_t bflock;
+
unsigned char vlan_enable:1,
rx_csum_enable:1,
extended_hash:1,
- bd_stash_en:1;
+ bd_stash_en:1,
+ wol_en:1, /* Wake-on-LAN enabled */
+ suspended:1;
unsigned short padding;
unsigned int interruptTransmit;
diff --git a/drivers/net/gianfar_ethtool.c b/drivers/net/gianfar_ethtool.c
index 6007147..fb7d3cc 100644
--- a/drivers/net/gianfar_ethtool.c
+++ b/drivers/net/gianfar_ethtool.c
@@ -479,14 +479,13 @@ static int gfar_sringparam(struct net_device *dev, struct ethtool_ringparam *rva
static int gfar_set_rx_csum(struct net_device *dev, uint32_t data)
{
struct gfar_private *priv = netdev_priv(dev);
+ unsigned long flags;
int err = 0;
if (!(priv->einfo->device_flags & FSL_GIANFAR_DEV_HAS_CSUM))
return -EOPNOTSUPP;
if (dev->flags & IFF_UP) {
- unsigned long flags;
-
/* Halt TX and RX, and process the frames which
* have already been received */
spin_lock_irqsave(&priv->txlock, flags);
@@ -502,7 +501,9 @@ static int gfar_set_rx_csum(struct net_device *dev, uint32_t data)
stop_gfar(dev);
}
+ spin_lock_irqsave(&priv->bflock, flags);
priv->rx_csum_enable = data;
+ spin_unlock_irqrestore(&priv->bflock, flags);
if (dev->flags & IFF_UP)
err = startup_gfar(dev);
@@ -564,6 +565,38 @@ static void gfar_set_msglevel(struct net_device *dev, uint32_t data)
priv->msg_enable = data;
}
+#ifdef CONFIG_PM
+static void gfar_get_wol(struct net_device *dev, struct ethtool_wolinfo *wol)
+{
+ struct gfar_private *priv = netdev_priv(dev);
+
+ if (priv->einfo->device_flags & FSL_GIANFAR_DEV_HAS_MAGIC_PACKET) {
+ wol->supported = WAKE_MAGIC;
+ wol->wolopts = priv->wol_en ? WAKE_MAGIC : 0;
+ } else {
+ wol->supported = wol->wolopts = 0;
+ }
+}
+
+static int gfar_set_wol(struct net_device *dev, struct ethtool_wolinfo *wol)
+{
+ struct gfar_private *priv = netdev_priv(dev);
+ unsigned long flags;
+
+ if (!(priv->einfo->device_flags & FSL_GIANFAR_DEV_HAS_MAGIC_PACKET) &&
+ wol->wolopts != 0)
+ return -EINVAL;
+
+ if (wol->wolopts & ~WAKE_MAGIC)
+ return -EINVAL;
+
+ spin_lock_irqsave(&priv->bflock, flags);
+ priv->wol_en = wol->wolopts & WAKE_MAGIC ? 1 : 0;
+ spin_unlock_irqrestore(&priv->bflock, flags);
+
+ return 0;
+}
+#endif
const struct ethtool_ops gfar_ethtool_ops = {
.get_settings = gfar_gsettings,
@@ -585,4 +618,8 @@ const struct ethtool_ops gfar_ethtool_ops = {
.set_tx_csum = gfar_set_tx_csum,
.get_msglevel = gfar_get_msglevel,
.set_msglevel = gfar_set_msglevel,
+#ifdef CONFIG_PM
+ .get_wol = gfar_get_wol,
+ .set_wol = gfar_set_wol,
+#endif
};
--
1.5.3.7
_______________________________________________
Linuxppc-dev mailing list
Linuxppc-dev@ozlabs.org
https://ozlabs.org/mailman/listinfo/linuxppc-dev
^ permalink raw reply related
* [PATCH 7/7] linkstation: implement standby
From: Guennadi Liakhovetski @ 2008-04-28 15:40 UTC (permalink / raw)
To: linuxppc-dev
Cc: Stephen Rothwell, Paul Mackerras, Pavel Machek, Scott Wood,
linux-pm, Johannes Berg
In-Reply-To: <Pine.LNX.4.64.0804281714000.7897@axis700.grange>
Implement suspend/resume for "mpc10x" compatible fsl host PCI controllers,
use it for linkstation standby. This is version 3, updated to the current
powerpc git tree. Depends as before on TLF_SLEEPING and HID0_SLEEP patches
from Scott Wood.
Signed-off-by: Guennadi Liakhovetski <g.liakhovetski@gmx.de>
---
diff --git a/arch/powerpc/Kconfig b/arch/powerpc/Kconfig
index 20f45a8..693da18 100644
--- a/arch/powerpc/Kconfig
+++ b/arch/powerpc/Kconfig
@@ -192,7 +192,7 @@ config ARCH_HIBERNATION_POSSIBLE
config ARCH_SUSPEND_POSSIBLE
def_bool y
- depends on ADB_PMU || PPC_EFIKA || PPC_LITE5200 || PPC_83xx
+ depends on ADB_PMU || PPC_EFIKA || PPC_LITE5200 || PPC_83xx || MPC10X_BRIDGE
config PPC_DCR_NATIVE
bool
diff --git a/arch/powerpc/platforms/embedded6xx/linkstation.c b/arch/powerpc/platforms/embedded6xx/linkstation.c
index eb5d74e..3bab51f 100644
--- a/arch/powerpc/platforms/embedded6xx/linkstation.c
+++ b/arch/powerpc/platforms/embedded6xx/linkstation.c
@@ -197,3 +197,54 @@ define_machine(linkstation){
.halt = linkstation_halt,
.calibrate_decr = generic_calibrate_decr,
};
+
+#ifdef CONFIG_PM_SLEEP
+
+#include <linux/suspend.h>
+#include <linux/serial_reg.h>
+#include <sysdev/fsl_soc.h>
+#include <asm/mpc6xx.h>
+
+static int ls_pm_valid(suspend_state_t state)
+{
+ switch (state) {
+ case PM_SUSPEND_STANDBY:
+ return 1;
+ default:
+ return 0;
+ }
+}
+
+static int ls_pm_enter(suspend_state_t state)
+{
+ u64 tb;
+
+ /* Get timebase */
+ tb = get_tb();
+
+ /* put CPU to sleep, re-enabling interrupts */
+ mpc6xx_enter_standby();
+
+ local_irq_disable();
+
+ set_tb(tb >> 32, tb & 0xfffffffful);
+
+ return 0;
+}
+
+static struct platform_suspend_ops ls_pm_ops = {
+ .valid = ls_pm_valid,
+ .enter = ls_pm_enter,
+};
+
+static int __init ls_pm_init(void)
+{
+ if (!machine_is(linkstation))
+ return -ENODEV;
+
+ suspend_set_ops(&ls_pm_ops);
+ return 0;
+}
+
+device_initcall(ls_pm_init);
+#endif
diff --git a/arch/powerpc/sysdev/Kconfig b/arch/powerpc/sysdev/Kconfig
index 72fb35b..4df3230 100644
--- a/arch/powerpc/sysdev/Kconfig
+++ b/arch/powerpc/sysdev/Kconfig
@@ -6,3 +6,6 @@ config PPC4xx_PCI_EXPRESS
bool
depends on PCI && 4xx
default n
+
+config MPC10X_PM
+ def_bool FSL_SOC && PCI && PM_SLEEP
diff --git a/arch/powerpc/sysdev/Makefile b/arch/powerpc/sysdev/Makefile
index 2cc5052..0b90cc8 100644
--- a/arch/powerpc/sysdev/Makefile
+++ b/arch/powerpc/sysdev/Makefile
@@ -48,3 +48,5 @@ endif
ifeq ($(CONFIG_SUSPEND),y)
obj-$(CONFIG_6xx) += 6xx-suspend.o
endif
+
+obj-$(CONFIG_MPC10X_PM) += mpc10x_pm.o
diff -u /dev/null b/arch/powerpc/sysdev/mpc10x_pm.c
new file mode 100644
index 0000000..6bd773b
--- /dev/null 2008-04-28 10:35:13.531006534 +0200
+++ b/arch/powerpc/sysdev/mpc10x_pm.c 2008-04-25 21:18:19.000000000 +0200
@@ -0,0 +1,73 @@
+/*
+ * Power-management driver for MPC8241 host-PCI controller
+ *
+ * Copyright (C) 2007 G. Liakhovetski (g.liakhovetski@gmx.de)
+ *
+ * This file is licensed under the terms of the GNU General Public License
+ * version 2. This program is licensed "as is" without any warranty of
+ * any kind, whether express or implied.
+ */
+
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/pci.h>
+#include <linux/pm.h>
+
+#include <asm/pci-bridge.h>
+
+#define MPC10X_LP_REF_EN (1<<12)
+#define MPC10X_PM (1<<7)
+#define MPC10X_DOZE (1<<5)
+#define MPC10X_NAP (1<<4)
+#define MPC10X_SLEEP (1<<3)
+
+static int __devinit mpc10x_pm_probe(struct pci_dev *pdev,
+ const struct pci_device_id *id)
+{
+ return 0;
+}
+
+static int mpc10x_pm_suspend_late(struct pci_dev *dev, pm_message_t state)
+{
+ u16 pmcr1;
+
+ pci_read_config_word(dev, 0x70, &pmcr1);
+ pmcr1 &= ~(MPC10X_DOZE | MPC10X_NAP);
+ pmcr1 |= MPC10X_PM | MPC10X_SLEEP | MPC10X_LP_REF_EN;
+ pci_write_config_word(dev, 0x70, pmcr1);
+
+ return 0;
+}
+
+static int mpc10x_pm_resume_early(struct pci_dev *dev)
+{
+ u16 pmcr1;
+
+ pci_read_config_word(dev, 0x70, &pmcr1);
+ pmcr1 &= ~(MPC10X_PM | MPC10X_DOZE | MPC10X_SLEEP | MPC10X_NAP | MPC10X_LP_REF_EN);
+ pci_write_config_word(dev, 0x70, pmcr1);
+
+ return 0;
+}
+
+static struct pci_device_id mpc10x_pm_pci_tbl[] = {
+ { PCI_VENDOR_ID_MOTOROLA, PCI_DEVICE_ID_MOTOROLA_MPC8241,
+ PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 },
+ { }
+};
+MODULE_DEVICE_TABLE(pci, mpc10x_pm_pci_tbl);
+
+static struct pci_driver mpc10x_pm_driver = {
+ .name = "mpc10x-pm",
+ .id_table = mpc10x_pm_pci_tbl,
+ .resume_early = mpc10x_pm_resume_early,
+ .suspend_late = mpc10x_pm_suspend_late,
+ .probe = mpc10x_pm_probe,
+};
+
+static int __init mpc10x_pm_init(void)
+{
+ return pci_register_driver(&mpc10x_pm_driver);
+}
+
+device_initcall(mpc10x_pm_init);
diff --git a/include/asm-powerpc/mpc6xx.h b/include/asm-powerpc/mpc6xx.h
index effc229..9bdf8b4 100644
--- a/include/asm-powerpc/mpc6xx.h
+++ b/include/asm-powerpc/mpc6xx.h
@@ -1,6 +1,6 @@
#ifndef __ASM_POWERPC_MPC6xx_H
#define __ASM_POWERPC_MPC6xx_H
-void mpc6xx_enter_standby(void);
+extern void mpc6xx_enter_standby(void);
#endif
diff --git a/include/linux/pci_ids.h b/include/linux/pci_ids.h
index 70eb3c8..9eb84cc 100644
--- a/include/linux/pci_ids.h
+++ b/include/linux/pci_ids.h
@@ -800,6 +800,7 @@
#define PCI_DEVICE_ID_MOTOROLA_MPC105 0x0001
#define PCI_DEVICE_ID_MOTOROLA_MPC106 0x0002
#define PCI_DEVICE_ID_MOTOROLA_MPC107 0x0004
+#define PCI_DEVICE_ID_MOTOROLA_MPC8241 0x0006
#define PCI_DEVICE_ID_MOTOROLA_RAVEN 0x4801
#define PCI_DEVICE_ID_MOTOROLA_FALCON 0x4802
#define PCI_DEVICE_ID_MOTOROLA_HAWK 0x4803
^ permalink raw reply related
* Re: [PATCH 1/2] i2c: Add support for device alias names
From: Jean Delvare @ 2008-04-28 15:40 UTC (permalink / raw)
To: Kay Sievers; +Cc: linuxppc-dev list, Paul Mundt, Scott Wood, Jon, Linux I2C
In-Reply-To: <1209395245.3666.9.camel@linux.site>
Hi Kay,
On Mon, 28 Apr 2008 17:07:25 +0200, Kay Sievers wrote:
> On Mon, 2008-04-28 at 11:39 +0200, Jean Delvare wrote:
> > One thing I am still not happy with is that the aliases created have a
> > trailing "*":
> >=20
> > $ /sbin/modinfo lm90
> > filename: /lib/modules/2.6.25-git11/kernel/drivers/hwmon/lm90.ko
> > author: Jean Delvare <khali@linux-fr.org>
> > description: LM90/ADM1032 driver
> > license: GPL
> > vermagic: 2.6.25-git11 mod_unload
> > depends: hwmon
> > alias: i2c:lm90*
> > alias: i2c:adm1032*
> > alias: i2c:lm99*
> > alias: i2c:lm86*
> > alias: i2c:max6657*
> > alias: i2c:adt7461*
> > alias: i2c:max6680*
> > $
> >=20
> > This would cause trouble if one I2C chip name matches the beginning of
> > another I2C chip name and both chips are supported by different
> > drivers. This has yet to be seen, but still, I'd like to see this
> > problem fixed quickly.
>=20
> =EF=BB=BFRight, the trailing "*" is not nice.
>=20
> We should terminate the string, so the trailing "*" will not match
> longer strings. The usual thing is to add a ":" to the end, which would
> then show up as
> alias: i2c:max6680:*
>=20
> See DMI and ACPI:
> alias dmi:*:svnFUJITSU:pnLifeBook*:pvr*:rvnFUJITSU:* apanel
> alias acpi*:ASIM0000:* atlas_btns
I didn't know about these cases, thanks for the hint.
>=20
> If i2c device modaliases could ever contain multiple strings, it should
> be:
> alias: i2c*:max6680:*
> =EF=BB=BFto match the module, regardless of the order of the strings in t=
he
> modalias:
Why would i2c device modaliases ever contain multiple strings? A device
can't have multiple names, can it?
Adding a ":" at the end of the i2c device names solves the problem I
was mentioning, sure, but why don't we simply remove the trailing "*",
instead of trying to work around it? A trailing "*" simply makes no
sense for aliases which are simple device names. This is not only i2c
devices, but also platform devices, acpi, dmi, pnp... Looking at the
various device types handled by file2alias.c, it seems that most of
them don't need the trailing "*", and many of them have the problem I
was mentioning.
Can't we just stop handle_moddevtable() from adding a tailing "*"
automatically, and just let the device types which need it, add it on
their own?
Thanks,
--=20
Jean Delvare
^ permalink raw reply
* suggestions on handling additional exception levels on ppc32
From: Kumar Gala @ 2008-04-28 15:40 UTC (permalink / raw)
To: linuxppc-dev@ozlabs.org list
I'm looking at fixing an issue parts that have multiple exception
levels (e300, 40x, booke).
One of the issues is the transfer_to_handler patch in entry_32.S
doesn't use the proper save/restore registers to transfer to C code.
The following bit of code is what I'm having issues with:
.globl transfer_to_handler_cont
transfer_to_handler_cont:
3:
mflr r9
lwz r11,0(r9) /* virtual address of handler
*/
lwz r9,4(r9) /* where to go when done */
mtspr SPRN_SRR0,r11
mtspr SPRN_SRR1,r10
mtlr r9
SYNC
RFI /* jump to handler, enable
MMU */
A few possibilities:
* introduce an additional function pointer as part of
EXC_XFER_TEMPLATE() to specifies the type of handler (normal, crit,
dbg, mcheck)
* use the traps field low order bits to determine normal, crit, dbg,
mcheck at run time.
* duplicate the code paths for each exception level
suggestions?
- k
^ permalink raw reply
* Re: [PATCH] Add fast little-endian switch system call
From: Michael Kerrisk @ 2008-04-28 15:42 UTC (permalink / raw)
To: Christoph Hellwig; +Cc: linux-arch, linuxppc-dev, Paul Mackerras, mtk.manpages
In-Reply-To: <20080428144332.GA17109@lst.de>
On Mon, Apr 28, 2008 at 4:43 PM, Christoph Hellwig <hch@lst.de> wrote:
> Please see Michael Kerrisk on userspace ABI updates. A nice little
> manpage for this gimmick would be helpful, and maybe help other
> platforms that want one aswell to implement the same API.
Thanks Chrsitoph. I'm not on any of these lists at the moment.
Paul -- is this syscall defintely going in? Could you write a short
description for userland programmers? I'll do the grotty *roff stuff.
> On Mon, Apr 28, 2008 at 01:52:31PM +1000, Paul Mackerras wrote:
> > This adds a system call on 64-bit platforms for switching between
> > little-endian and big-endian modes that is much faster than doing a
> > prctl call. This system call is handled as a special case right at
> > the start of the system call entry code, and because it is a special
> > case, it uses a system call number which is out of the range of
> > normal system calls, namely 0x1ebe.
> >
> > Measurements with lmbench on a 4.2GHz POWER6 showed no measurable
> > change in the speed of normal system calls with this patch.
> >
> > Switching endianness with this new system call takes around 60ns on a
> > 4.2GHz POWER6, compared with around 300ns to switch endian mode with a
> > prctl. This can provide a significant performance advantage for
> > emulators for little-endian architectures that want to switch between
> > big-endian and little-endian mode frequently, e.g. because they are
> > generating instructions sequences on the fly and they want to run
> > those sequences in little-endian mode.
> >
> > Signed-off-by: Paul Mackerras <paulus@samba.org>
> > ---
> >
> > diff --git a/arch/powerpc/kernel/head_64.S b/arch/powerpc/kernel/head_64.S
> > index 215973a..2eb49a7 100644
> > --- a/arch/powerpc/kernel/head_64.S
> > +++ b/arch/powerpc/kernel/head_64.S
> > @@ -239,6 +239,10 @@ instruction_access_slb_pSeries:
> > .globl system_call_pSeries
> > system_call_pSeries:
> > HMT_MEDIUM
> > +BEGIN_FTR_SECTION
> > + cmpdi r0,0x1ebe
> > + beq- 1f
> > +END_FTR_SECTION_IFSET(CPU_FTR_REAL_LE)
>
> Am I missing something here or does this add a branch for every normal
> syscall?
>
> > mr r9,r13
> > mfmsr r10
> > mfspr r13,SPRN_SPRG3
> > @@ -253,6 +257,13 @@ system_call_pSeries:
> > rfid
> > b . /* prevent speculative execution */
> >
> > +/* Fast LE/BE switch system call */
> > +1: mfspr r12,SPRN_SRR1
> > + xori r12,r12,MSR_LE
> > + mtspr SPRN_SRR1,r12
> > + rfid /* return to userspace */
> > + b .
> > +
> > STD_EXCEPTION_PSERIES(0xd00, single_step)
> > STD_EXCEPTION_PSERIES(0xe00, trap_0e)
> >
> > _______________________________________________
> > Linuxppc-dev mailing list
> > Linuxppc-dev@ozlabs.org
> > https://ozlabs.org/mailman/listinfo/linuxppc-dev
> ---end quoted text---
>
--
Michael Kerrisk
Linux man-pages maintainer; http://www.kernel.org/doc/man-pages/
Found a bug? http://www.kernel.org/doc/man-pages/reporting_bugs.html
^ 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