From 18801be7f805b891876a6676ec7fac2e1acdec13 Mon Sep 17 00:00:00 2001 From: Magnus Damm Date: Thu, 25 Dec 2008 18:17:09 +0900 Subject: sh: make gpio_get/set_value() O(1) This patch modifies the table based SuperH gpio implementation to make use of direct table lookups. With this change the functions gpio_get_value() and gpio_set_value() are O(1). Tested on Migo-R using bitbanging mmc. Performance is improved from 11 KBytes/s to 26 Kbytes/s. Signed-off-by: Magnus Damm Signed-off-by: Paul Mundt --- arch/sh/include/asm/gpio.h | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) (limited to 'arch/sh/include/asm') diff --git a/arch/sh/include/asm/gpio.h b/arch/sh/include/asm/gpio.h index 90673658eb1..942fefa61c7 100644 --- a/arch/sh/include/asm/gpio.h +++ b/arch/sh/include/asm/gpio.h @@ -20,7 +20,7 @@ #endif typedef unsigned short pinmux_enum_t; -typedef unsigned char pinmux_flag_t; +typedef unsigned short pinmux_flag_t; #define PINMUX_TYPE_NONE 0 #define PINMUX_TYPE_FUNCTION 1 @@ -34,6 +34,11 @@ typedef unsigned char pinmux_flag_t; #define PINMUX_FLAG_WANT_PULLUP (1 << 3) #define PINMUX_FLAG_WANT_PULLDOWN (1 << 4) +#define PINMUX_FLAG_DBIT_SHIFT 5 +#define PINMUX_FLAG_DBIT (0x1f << PINMUX_FLAG_DBIT_SHIFT) +#define PINMUX_FLAG_DREG_SHIFT 10 +#define PINMUX_FLAG_DREG (0x3f << PINMUX_FLAG_DREG_SHIFT) + struct pinmux_gpio { pinmux_enum_t enum_id; pinmux_flag_t flags; -- cgit v1.2.3 From 3292094e88ce6b76714dad8ec4b43d7c5c12ada2 Mon Sep 17 00:00:00 2001 From: Magnus Damm Date: Thu, 25 Dec 2008 18:17:26 +0900 Subject: sh: lockless gpio_set_value() This patch optimizes the gpio data register handling for gpio_set_value(). Instead of using the good old spinlock-plus-read-modify-write strategy we now use a shadow register and atomic operations. This improves the bitbanging mmc performance on Migo-R from 26 Kbytes/s to 40 Kbytes/s. Signed-off-by: Magnus Damm Signed-off-by: Paul Mundt --- arch/sh/include/asm/gpio.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'arch/sh/include/asm') diff --git a/arch/sh/include/asm/gpio.h b/arch/sh/include/asm/gpio.h index 942fefa61c7..46a6d7914df 100644 --- a/arch/sh/include/asm/gpio.h +++ b/arch/sh/include/asm/gpio.h @@ -59,7 +59,7 @@ struct pinmux_cfg_reg { .enum_ids = (pinmux_enum_t [(r_width / f_width) * (1 << f_width)]) \ struct pinmux_data_reg { - unsigned long reg, reg_width; + unsigned long reg, reg_width, reg_shadow; pinmux_enum_t *enum_ids; }; -- cgit v1.2.3 From 69edbba0021a48fe034849501513930f6175cb5d Mon Sep 17 00:00:00 2001 From: Magnus Damm Date: Thu, 25 Dec 2008 18:17:34 +0900 Subject: sh: use gpiolib This patch updates the SuperH gpio code to make use of gpiolib. The gpiolib callbacks get() and set() are lockless, but we use our own spinlock for the other operations to make sure hardware register bitfield accesses stay atomic. Signed-off-by: Magnus Damm Signed-off-by: Paul Mundt --- arch/sh/include/asm/gpio.h | 61 ++++++++++++++++++++++++++-------------------- 1 file changed, 35 insertions(+), 26 deletions(-) (limited to 'arch/sh/include/asm') diff --git a/arch/sh/include/asm/gpio.h b/arch/sh/include/asm/gpio.h index 46a6d7914df..61f93da2c62 100644 --- a/arch/sh/include/asm/gpio.h +++ b/arch/sh/include/asm/gpio.h @@ -19,6 +19,40 @@ #include #endif +#define ARCH_NR_GPIOS 512 +#include + +#ifdef CONFIG_GPIOLIB + +static inline int gpio_get_value(unsigned gpio) +{ + return __gpio_get_value(gpio); +} + +static inline void gpio_set_value(unsigned gpio, int value) +{ + __gpio_set_value(gpio, value); +} + +static inline int gpio_cansleep(unsigned gpio) +{ + return __gpio_cansleep(gpio); +} + +static inline int gpio_to_irq(unsigned gpio) +{ + WARN_ON(1); + return -ENOSYS; +} + +static inline int irq_to_gpio(unsigned int irq) +{ + WARN_ON(1); + return -EINVAL; +} + +#endif /* CONFIG_GPIOLIB */ + typedef unsigned short pinmux_enum_t; typedef unsigned short pinmux_flag_t; @@ -94,34 +128,9 @@ struct pinmux_info { unsigned int gpio_data_size; unsigned long *gpio_in_use; + struct gpio_chip chip; }; int register_pinmux(struct pinmux_info *pip); -int __gpio_request(unsigned gpio); -static inline int gpio_request(unsigned gpio, const char *label) -{ - return __gpio_request(gpio); -} -void gpio_free(unsigned gpio); -int gpio_direction_input(unsigned gpio); -int gpio_direction_output(unsigned gpio, int value); -int gpio_get_value(unsigned gpio); -void gpio_set_value(unsigned gpio, int value); - -/* IRQ modes are unspported */ -static inline int gpio_to_irq(unsigned gpio) -{ - WARN_ON(1); - return -EINVAL; -} - -static inline int irq_to_gpio(unsigned irq) -{ - WARN_ON(1); - return -EINVAL; -} - -#include - #endif /* __ASM_SH_GPIO_H */ -- cgit v1.2.3 From 42990701f938b9318e46102d9919ceb28e5b0e6d Mon Sep 17 00:00:00 2001 From: Matt Fleming Date: Tue, 20 Jan 2009 21:14:37 +0000 Subject: sh: Relax inline assembly constraints When dereferencing the memory address contained in a register and modifying the value at that memory address, the register should not be listed in the inline asm outputs. The value at the memory address is an output (which is taken care of with the "memory" clobber), not the register. Signed-off-by: Matt Fleming Signed-off-by: Paul Mundt --- arch/sh/include/asm/bitops-llsc.h | 72 +++++++++++++++++++------------------- arch/sh/include/asm/cmpxchg-llsc.h | 38 ++++++++++---------- 2 files changed, 55 insertions(+), 55 deletions(-) (limited to 'arch/sh/include/asm') diff --git a/arch/sh/include/asm/bitops-llsc.h b/arch/sh/include/asm/bitops-llsc.h index 1d2fc0b010a..d8328be0619 100644 --- a/arch/sh/include/asm/bitops-llsc.h +++ b/arch/sh/include/asm/bitops-llsc.h @@ -1,7 +1,7 @@ #ifndef __ASM_SH_BITOPS_LLSC_H #define __ASM_SH_BITOPS_LLSC_H -static inline void set_bit(int nr, volatile void * addr) +static inline void set_bit(int nr, volatile void *addr) { int mask; volatile unsigned int *a = addr; @@ -13,16 +13,16 @@ static inline void set_bit(int nr, volatile void * addr) __asm__ __volatile__ ( "1: \n\t" "movli.l @%1, %0 ! set_bit \n\t" - "or %3, %0 \n\t" + "or %2, %0 \n\t" "movco.l %0, @%1 \n\t" "bf 1b \n\t" - : "=&z" (tmp), "=r" (a) - : "1" (a), "r" (mask) + : "=&z" (tmp) + : "r" (a), "r" (mask) : "t", "memory" ); } -static inline void clear_bit(int nr, volatile void * addr) +static inline void clear_bit(int nr, volatile void *addr) { int mask; volatile unsigned int *a = addr; @@ -34,16 +34,16 @@ static inline void clear_bit(int nr, volatile void * addr) __asm__ __volatile__ ( "1: \n\t" "movli.l @%1, %0 ! clear_bit \n\t" - "and %3, %0 \n\t" + "and %2, %0 \n\t" "movco.l %0, @%1 \n\t" "bf 1b \n\t" - : "=&z" (tmp), "=r" (a) - : "1" (a), "r" (~mask) + : "=&z" (tmp) + : "r" (a), "r" (~mask) : "t", "memory" ); } -static inline void change_bit(int nr, volatile void * addr) +static inline void change_bit(int nr, volatile void *addr) { int mask; volatile unsigned int *a = addr; @@ -55,16 +55,16 @@ static inline void change_bit(int nr, volatile void * addr) __asm__ __volatile__ ( "1: \n\t" "movli.l @%1, %0 ! change_bit \n\t" - "xor %3, %0 \n\t" + "xor %2, %0 \n\t" "movco.l %0, @%1 \n\t" "bf 1b \n\t" - : "=&z" (tmp), "=r" (a) - : "1" (a), "r" (mask) + : "=&z" (tmp) + : "r" (a), "r" (mask) : "t", "memory" ); } -static inline int test_and_set_bit(int nr, volatile void * addr) +static inline int test_and_set_bit(int nr, volatile void *addr) { int mask, retval; volatile unsigned int *a = addr; @@ -75,21 +75,21 @@ static inline int test_and_set_bit(int nr, volatile void * addr) __asm__ __volatile__ ( "1: \n\t" - "movli.l @%1, %0 ! test_and_set_bit \n\t" - "mov %0, %2 \n\t" - "or %4, %0 \n\t" - "movco.l %0, @%1 \n\t" + "movli.l @%2, %0 ! test_and_set_bit \n\t" + "mov %0, %1 \n\t" + "or %3, %0 \n\t" + "movco.l %0, @%2 \n\t" "bf 1b \n\t" - "and %4, %2 \n\t" - : "=&z" (tmp), "=r" (a), "=&r" (retval) - : "1" (a), "r" (mask) + "and %3, %1 \n\t" + : "=&z" (tmp), "=&r" (retval) + : "r" (a), "r" (mask) : "t", "memory" ); return retval != 0; } -static inline int test_and_clear_bit(int nr, volatile void * addr) +static inline int test_and_clear_bit(int nr, volatile void *addr) { int mask, retval; volatile unsigned int *a = addr; @@ -100,22 +100,22 @@ static inline int test_and_clear_bit(int nr, volatile void * addr) __asm__ __volatile__ ( "1: \n\t" - "movli.l @%1, %0 ! test_and_clear_bit \n\t" - "mov %0, %2 \n\t" - "and %5, %0 \n\t" - "movco.l %0, @%1 \n\t" + "movli.l @%2, %0 ! test_and_clear_bit \n\t" + "mov %0, %1 \n\t" + "and %4, %0 \n\t" + "movco.l %0, @%2 \n\t" "bf 1b \n\t" - "and %4, %2 \n\t" + "and %3, %1 \n\t" "synco \n\t" - : "=&z" (tmp), "=r" (a), "=&r" (retval) - : "1" (a), "r" (mask), "r" (~mask) + : "=&z" (tmp), "=&r" (retval) + : "r" (a), "r" (mask), "r" (~mask) : "t", "memory" ); return retval != 0; } -static inline int test_and_change_bit(int nr, volatile void * addr) +static inline int test_and_change_bit(int nr, volatile void *addr) { int mask, retval; volatile unsigned int *a = addr; @@ -126,15 +126,15 @@ static inline int test_and_change_bit(int nr, volatile void * addr) __asm__ __volatile__ ( "1: \n\t" - "movli.l @%1, %0 ! test_and_change_bit \n\t" - "mov %0, %2 \n\t" - "xor %4, %0 \n\t" - "movco.l %0, @%1 \n\t" + "movli.l @%2, %0 ! test_and_change_bit \n\t" + "mov %0, %1 \n\t" + "xor %3, %0 \n\t" + "movco.l %0, @%2 \n\t" "bf 1b \n\t" - "and %4, %2 \n\t" + "and %3, %1 \n\t" "synco \n\t" - : "=&z" (tmp), "=r" (a), "=&r" (retval) - : "1" (a), "r" (mask) + : "=&z" (tmp), "=&r" (retval) + : "r" (a), "r" (mask) : "t", "memory" ); diff --git a/arch/sh/include/asm/cmpxchg-llsc.h b/arch/sh/include/asm/cmpxchg-llsc.h index aee3bf28658..0fac3da536c 100644 --- a/arch/sh/include/asm/cmpxchg-llsc.h +++ b/arch/sh/include/asm/cmpxchg-llsc.h @@ -8,14 +8,14 @@ static inline unsigned long xchg_u32(volatile u32 *m, unsigned long val) __asm__ __volatile__ ( "1: \n\t" - "movli.l @%1, %0 ! xchg_u32 \n\t" - "mov %0, %2 \n\t" - "mov %4, %0 \n\t" - "movco.l %0, @%1 \n\t" + "movli.l @%2, %0 ! xchg_u32 \n\t" + "mov %0, %1 \n\t" + "mov %3, %0 \n\t" + "movco.l %0, @%2 \n\t" "bf 1b \n\t" "synco \n\t" - : "=&z"(tmp), "=r" (m), "=&r" (retval) - : "1" (m), "r" (val) + : "=&z"(tmp), "=&r" (retval) + : "r" (m), "r" (val) : "t", "memory" ); @@ -29,14 +29,14 @@ static inline unsigned long xchg_u8(volatile u8 *m, unsigned long val) __asm__ __volatile__ ( "1: \n\t" - "movli.l @%1, %0 ! xchg_u8 \n\t" - "mov %0, %2 \n\t" - "mov %4, %0 \n\t" - "movco.l %0, @%1 \n\t" + "movli.l @%2, %0 ! xchg_u8 \n\t" + "mov %0, %1 \n\t" + "mov %3, %0 \n\t" + "movco.l %0, @%2 \n\t" "bf 1b \n\t" "synco \n\t" - : "=&z"(tmp), "=r" (m), "=&r" (retval) - : "1" (m), "r" (val & 0xff) + : "=&z"(tmp), "=&r" (retval) + : "r" (m), "r" (val & 0xff) : "t", "memory" ); @@ -51,17 +51,17 @@ __cmpxchg_u32(volatile int *m, unsigned long old, unsigned long new) __asm__ __volatile__ ( "1: \n\t" - "movli.l @%1, %0 ! __cmpxchg_u32 \n\t" - "mov %0, %2 \n\t" - "cmp/eq %2, %4 \n\t" + "movli.l @%2, %0 ! __cmpxchg_u32 \n\t" + "mov %0, %1 \n\t" + "cmp/eq %1, %3 \n\t" "bf 2f \n\t" - "mov %5, %0 \n\t" + "mov %3, %0 \n\t" "2: \n\t" - "movco.l %0, @%1 \n\t" + "movco.l %0, @%2 \n\t" "bf 1b \n\t" "synco \n\t" - : "=&z" (tmp), "=r" (m), "=&r" (retval) - : "1" (m), "r" (old), "r" (new) + : "=&z" (tmp), "=&r" (retval) + : "r" (m), "r" (old), "r" (new) : "t", "memory" ); -- cgit v1.2.3 From 84fdf6cda30df72994baa2496da86787fb44cbb4 Mon Sep 17 00:00:00 2001 From: Matt Fleming Date: Tue, 20 Jan 2009 21:14:38 +0000 Subject: sh: Use the atomic_t "counter" member Now that atomic_t is a generic opaque type for all architectures, it is unwise to use intimate knowledge of its internals when manipulating it. Instead of relying on the "counter" member being at offset 0 from the beginning of an atomic_t, explicitly reference the member. This guards us from any changes to the layout of the beginning of the atomic_t type. Signed-off-by: Matt Fleming Signed-off-by: Paul Mundt --- arch/sh/include/asm/atomic-irq.h | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) (limited to 'arch/sh/include/asm') diff --git a/arch/sh/include/asm/atomic-irq.h b/arch/sh/include/asm/atomic-irq.h index 74f7943cff6..a0b348068ca 100644 --- a/arch/sh/include/asm/atomic-irq.h +++ b/arch/sh/include/asm/atomic-irq.h @@ -11,7 +11,7 @@ static inline void atomic_add(int i, atomic_t *v) unsigned long flags; local_irq_save(flags); - *(long *)v += i; + v->counter += i; local_irq_restore(flags); } @@ -20,7 +20,7 @@ static inline void atomic_sub(int i, atomic_t *v) unsigned long flags; local_irq_save(flags); - *(long *)v -= i; + v->counter -= i; local_irq_restore(flags); } @@ -29,9 +29,9 @@ static inline int atomic_add_return(int i, atomic_t *v) unsigned long temp, flags; local_irq_save(flags); - temp = *(long *)v; + temp = v->counter; temp += i; - *(long *)v = temp; + v->counter = temp; local_irq_restore(flags); return temp; @@ -42,9 +42,9 @@ static inline int atomic_sub_return(int i, atomic_t *v) unsigned long temp, flags; local_irq_save(flags); - temp = *(long *)v; + temp = v->counter; temp -= i; - *(long *)v = temp; + v->counter = temp; local_irq_restore(flags); return temp; @@ -55,7 +55,7 @@ static inline void atomic_clear_mask(unsigned int mask, atomic_t *v) unsigned long flags; local_irq_save(flags); - *(long *)v &= ~mask; + v->counter &= ~mask; local_irq_restore(flags); } @@ -64,7 +64,7 @@ static inline void atomic_set_mask(unsigned int mask, atomic_t *v) unsigned long flags; local_irq_save(flags); - *(long *)v |= mask; + v->counter |= mask; local_irq_restore(flags); } -- cgit v1.2.3 From dc66ff6220f0a6c938df41add526d645852d9a75 Mon Sep 17 00:00:00 2001 From: Roel Kluin Date: Thu, 22 Jan 2009 15:16:14 +0000 Subject: SH: fix start_thread and user_stack_pointer macros Fix macros start_thread and user_stack_pointer. When these macros aren't called with a variable named regs as second argument, this will result in a build failure. Signed-off-by: Roel Kluin Signed-off-by: Paul Mundt --- arch/sh/include/asm/kprobes.h | 2 +- arch/sh/include/asm/processor_32.h | 12 ++++++------ arch/sh/include/asm/processor_64.h | 14 +++++++------- 3 files changed, 14 insertions(+), 14 deletions(-) (limited to 'arch/sh/include/asm') diff --git a/arch/sh/include/asm/kprobes.h b/arch/sh/include/asm/kprobes.h index 6078d8e551d..613644a758e 100644 --- a/arch/sh/include/asm/kprobes.h +++ b/arch/sh/include/asm/kprobes.h @@ -16,7 +16,7 @@ typedef u16 kprobe_opcode_t; ? (MAX_STACK_SIZE) \ : (((unsigned long)current_thread_info()) + THREAD_SIZE - (ADDR))) -#define regs_return_value(regs) ((regs)->regs[0]) +#define regs_return_value(_regs) ((_regs)->regs[0]) #define flush_insn_slot(p) do { } while (0) #define kretprobe_blacklist_size 0 diff --git a/arch/sh/include/asm/processor_32.h b/arch/sh/include/asm/processor_32.h index d79063c5eb9..dcaed24c71f 100644 --- a/arch/sh/include/asm/processor_32.h +++ b/arch/sh/include/asm/processor_32.h @@ -108,12 +108,12 @@ extern int ubc_usercnt; /* * Do necessary setup to start up a newly executed thread. */ -#define start_thread(regs, new_pc, new_sp) \ +#define start_thread(_regs, new_pc, new_sp) \ set_fs(USER_DS); \ - regs->pr = 0; \ - regs->sr = SR_FD; /* User mode. */ \ - regs->pc = new_pc; \ - regs->regs[15] = new_sp + _regs->pr = 0; \ + _regs->sr = SR_FD; /* User mode. */ \ + _regs->pc = new_pc; \ + _regs->regs[15] = new_sp /* Forward declaration, a strange C thing */ struct task_struct; @@ -189,7 +189,7 @@ extern unsigned long get_wchan(struct task_struct *p); #define KSTK_EIP(tsk) (task_pt_regs(tsk)->pc) #define KSTK_ESP(tsk) (task_pt_regs(tsk)->regs[15]) -#define user_stack_pointer(regs) ((regs)->regs[15]) +#define user_stack_pointer(_regs) ((_regs)->regs[15]) #if defined(CONFIG_CPU_SH2A) || defined(CONFIG_CPU_SH3) || \ defined(CONFIG_CPU_SH4) diff --git a/arch/sh/include/asm/processor_64.h b/arch/sh/include/asm/processor_64.h index 803177fcf08..5727d31b0cc 100644 --- a/arch/sh/include/asm/processor_64.h +++ b/arch/sh/include/asm/processor_64.h @@ -145,13 +145,13 @@ struct thread_struct { */ #define SR_USER (SR_MMU | SR_FD) -#define start_thread(regs, new_pc, new_sp) \ +#define start_thread(_regs, new_pc, new_sp) \ set_fs(USER_DS); \ - regs->sr = SR_USER; /* User mode. */ \ - regs->pc = new_pc - 4; /* Compensate syscall exit */ \ - regs->pc |= 1; /* Set SHmedia ! */ \ - regs->regs[18] = 0; \ - regs->regs[15] = new_sp + _regs->sr = SR_USER; /* User mode. */ \ + _regs->pc = new_pc - 4; /* Compensate syscall exit */ \ + _regs->pc |= 1; /* Set SHmedia ! */ \ + _regs->regs[18] = 0; \ + _regs->regs[15] = new_sp /* Forward declaration, a strange C thing */ struct task_struct; @@ -226,7 +226,7 @@ extern unsigned long get_wchan(struct task_struct *p); #define KSTK_EIP(tsk) ((tsk)->thread.pc) #define KSTK_ESP(tsk) ((tsk)->thread.sp) -#define user_stack_pointer(regs) ((regs)->regs[15]) +#define user_stack_pointer(_regs) ((_regs)->regs[15]) #endif /* __ASSEMBLY__ */ #endif /* __ASM_SH_PROCESSOR_64_H */ -- cgit v1.2.3 From 955c0778723501cc16fec40501cd54b7e72d3e74 Mon Sep 17 00:00:00 2001 From: Magnus Damm Date: Thu, 22 Jan 2009 09:55:31 +0000 Subject: sh: rework clocksource and sched_clock Rework and simplify the sched_clock and clocksource code. Instead of registering the clocksource in a shared file we move it into the tmu driver. Also, add code to handle sched_clock in the case of no clocksource. Signed-off-by: Magnus Damm Signed-off-by: Paul Mundt --- arch/sh/include/asm/timer.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'arch/sh/include/asm') diff --git a/arch/sh/include/asm/timer.h b/arch/sh/include/asm/timer.h index a7ca3a195bb..4c3b66e30af 100644 --- a/arch/sh/include/asm/timer.h +++ b/arch/sh/include/asm/timer.h @@ -9,7 +9,6 @@ struct sys_timer_ops { int (*init)(void); int (*start)(void); int (*stop)(void); - cycle_t (*read)(void); #ifndef CONFIG_GENERIC_TIME unsigned long (*get_offset)(void); #endif @@ -39,6 +38,7 @@ struct sys_timer *get_sys_timer(void); /* arch/sh/kernel/time.c */ void handle_timer_tick(void); -extern unsigned long sh_hpt_frequency; + +extern struct clocksource clocksource_sh; #endif /* __ASM_SH_TIMER_H */ -- cgit v1.2.3 From cb9eff097831007afb30d64373f29d99825d0068 Mon Sep 17 00:00:00 2001 From: Patrick Ohly Date: Thu, 12 Feb 2009 05:03:36 +0000 Subject: net: new user space API for time stamping of incoming and outgoing packets User space can request hardware and/or software time stamping. Reporting of the result(s) via a new control message is enabled separately for each field in the message because some of the fields may require additional computation and thus cause overhead. User space can tell the different kinds of time stamps apart and choose what suits its needs. When a TX timestamp operation is requested, the TX skb will be cloned and the clone will be time stamped (in hardware or software) and added to the socket error queue of the skb, if the skb has a socket associated with it. The actual TX timestamp will reach userspace as a RX timestamp on the cloned packet. If timestamping is requested and no timestamping is done in the device driver (potentially this may use hardware timestamping), it will be done in software after the device's start_hard_xmit routine. Signed-off-by: Patrick Ohly Signed-off-by: David S. Miller --- arch/sh/include/asm/socket.h | 3 +++ 1 file changed, 3 insertions(+) (limited to 'arch/sh/include/asm') diff --git a/arch/sh/include/asm/socket.h b/arch/sh/include/asm/socket.h index 6d4bf651295..345653b9682 100644 --- a/arch/sh/include/asm/socket.h +++ b/arch/sh/include/asm/socket.h @@ -54,4 +54,7 @@ #define SO_MARK 36 +#define SO_TIMESTAMPING 37 +#define SCM_TIMESTAMPING SO_TIMESTAMPING + #endif /* __ASM_SH_SOCKET_H */ -- cgit v1.2.3 From 4f099ebb27211d378304ddcfa507097f5128f5b9 Mon Sep 17 00:00:00 2001 From: Magnus Damm Date: Mon, 23 Feb 2009 07:16:34 +0000 Subject: sh: remove EXPEVT vector from stack on sh3/sh4/sh4a Remove EXPEVT vector from the stack, lookup_exception_vector() for sh3/sh4/sh4a is already using k2 to get the vector. Signed-off-by: Magnus Damm Signed-off-by: Paul Mundt --- arch/sh/include/asm/ptrace.h | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) (limited to 'arch/sh/include/asm') diff --git a/arch/sh/include/asm/ptrace.h b/arch/sh/include/asm/ptrace.h index 12912ab80c1..81c6568fdb3 100644 --- a/arch/sh/include/asm/ptrace.h +++ b/arch/sh/include/asm/ptrace.h @@ -122,14 +122,12 @@ extern void user_disable_single_step(struct task_struct *); #ifdef CONFIG_SH_DSP #define task_pt_regs(task) \ ((struct pt_regs *) (task_stack_page(task) + THREAD_SIZE \ - - sizeof(struct pt_dspregs) - sizeof(unsigned long)) - 1) + - sizeof(struct pt_dspregs)) - 1) #define task_pt_dspregs(task) \ - ((struct pt_dspregs *) (task_stack_page(task) + THREAD_SIZE \ - - sizeof(unsigned long)) - 1) + ((struct pt_dspregs *) (task_stack_page(task) + THREAD_SIZE) - 1) #else #define task_pt_regs(task) \ - ((struct pt_regs *) (task_stack_page(task) + THREAD_SIZE \ - - sizeof(unsigned long)) - 1) + ((struct pt_regs *) (task_stack_page(task) + THREAD_SIZE) - 1) #endif static inline unsigned long profile_pc(struct pt_regs *regs) -- cgit v1.2.3 From 0197f21ca5c5ed0df2a14a60ef073e8163e6533b Mon Sep 17 00:00:00 2001 From: Magnus Damm Date: Fri, 27 Feb 2009 16:41:17 +0900 Subject: sh: prefetch early exception data on sh4/sh4a. Prefetch early exception data. There is unused space in our exception handler cache line anyway, so this is almost free. Signed-off-by: Magnus Damm Signed-off-by: Paul Mundt --- arch/sh/include/asm/entry-macros.S | 5 +++++ 1 file changed, 5 insertions(+) (limited to 'arch/sh/include/asm') diff --git a/arch/sh/include/asm/entry-macros.S b/arch/sh/include/asm/entry-macros.S index 2dab0b8d945..3a4752a6572 100644 --- a/arch/sh/include/asm/entry-macros.S +++ b/arch/sh/include/asm/entry-macros.S @@ -31,3 +31,8 @@ #endif .endm +#if defined(CONFIG_CPU_SH2A) || defined(CONFIG_CPU_SH4) +# define PREF(x) pref @x +#else +# define PREF(x) nop +#endif -- cgit v1.2.3 From a73090ffaf0f6853880d9ac3fff7e5d88215131a Mon Sep 17 00:00:00 2001 From: Paul Mundt Date: Fri, 27 Feb 2009 16:42:05 +0900 Subject: sh: Disable unsupportable prefetching on SH-3. The SH-3 does not support 'pref'-based prefetching, only SH-2A and SH-4A parts do. Remove SH-3 from the list. Signed-off-by: Paul Mundt --- arch/sh/include/asm/processor_32.h | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) (limited to 'arch/sh/include/asm') diff --git a/arch/sh/include/asm/processor_32.h b/arch/sh/include/asm/processor_32.h index dcaed24c71f..efdd78a53b1 100644 --- a/arch/sh/include/asm/processor_32.h +++ b/arch/sh/include/asm/processor_32.h @@ -191,8 +191,7 @@ extern unsigned long get_wchan(struct task_struct *p); #define user_stack_pointer(_regs) ((_regs)->regs[15]) -#if defined(CONFIG_CPU_SH2A) || defined(CONFIG_CPU_SH3) || \ - defined(CONFIG_CPU_SH4) +#if defined(CONFIG_CPU_SH2A) || defined(CONFIG_CPU_SH4) #define PREFETCH_STRIDE L1_CACHE_BYTES #define ARCH_HAS_PREFETCH #define ARCH_HAS_PREFETCHW -- cgit v1.2.3 From 55ba99eb211a06709237cb322ecd8c8b6faf6159 Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Tue, 3 Mar 2009 15:40:25 +0900 Subject: sh: Add support for SH7786 CPU subtype. This adds preliminary support for the SH7786 CPU subtype. While this is a dual-core CPU, only UP is supported for now. L2 cache support is likewise not yet implemented. More information on this particular CPU subtype is available at: http://www.renesas.com/fmwk.jsp?cnt=sh7786_root.jsp&fp=/products/mpumcu/superh_family/sh7780_series/sh7786_group/ Signed-off-by: Kuninori Morimoto Signed-off-by: Paul Mundt --- arch/sh/include/asm/processor.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'arch/sh/include/asm') diff --git a/arch/sh/include/asm/processor.h b/arch/sh/include/asm/processor.h index 1ef4b24d761..1fd58b42143 100644 --- a/arch/sh/include/asm/processor.h +++ b/arch/sh/include/asm/processor.h @@ -31,7 +31,7 @@ enum cpu_type { CPU_SH7760, CPU_SH4_202, CPU_SH4_501, /* SH-4A types */ - CPU_SH7763, CPU_SH7770, CPU_SH7780, CPU_SH7781, CPU_SH7785, + CPU_SH7763, CPU_SH7770, CPU_SH7780, CPU_SH7781, CPU_SH7785, CPU_SH7786, CPU_SH7723, CPU_SHX3, /* SH4AL-DSP types */ -- cgit v1.2.3 From 2ef7f0dab6b3d171b6aff00a47077385ae3155b5 Mon Sep 17 00:00:00 2001 From: Magnus Damm Date: Fri, 6 Mar 2009 09:47:02 +0000 Subject: sh: hibernation support Add Suspend-to-disk / swsusp / CONFIG_HIBERNATION support to the SuperH architecture. To suspend, use "swapon /dev/sda2; echo disk > /sys/power/state" To resume, pass "resume=/dev/sda2" on the kernel command line. The patch "pm: rework includes, remove arch ifdefs V2" is needed to allow the generic swsusp code to build properly. Hibernation is not enabled with this patch though, a patch setting ARCH_HIBERNATION_POSSIBLE will be submitted later. Signed-off-by: Magnus Damm Signed-off-by: Paul Mundt --- arch/sh/include/asm/sections.h | 1 + arch/sh/include/asm/suspend.h | 13 +++++++++++++ 2 files changed, 14 insertions(+) create mode 100644 arch/sh/include/asm/suspend.h (limited to 'arch/sh/include/asm') diff --git a/arch/sh/include/asm/sections.h b/arch/sh/include/asm/sections.h index 8f8f4ad400d..01a4076a371 100644 --- a/arch/sh/include/asm/sections.h +++ b/arch/sh/include/asm/sections.h @@ -3,6 +3,7 @@ #include +extern void __nosave_begin, __nosave_end; extern long __machvec_start, __machvec_end; extern char __uncached_start, __uncached_end; extern char _ebss[]; diff --git a/arch/sh/include/asm/suspend.h b/arch/sh/include/asm/suspend.h new file mode 100644 index 00000000000..5d6d8aba568 --- /dev/null +++ b/arch/sh/include/asm/suspend.h @@ -0,0 +1,13 @@ +#ifndef _ASM_SH_SUSPEND_H +#define _ASM_SH_SUSPEND_H + +static inline int arch_prepare_suspend(void) { return 0; } + +#include + +struct swsusp_arch_regs { + struct pt_regs user_regs; + unsigned long bank1_regs[8]; +}; + +#endif /* _ASM_SH_SUSPEND_H */ -- cgit v1.2.3 From 2f47f44790a9c8fc43e515df3c6be19a35ee5de5 Mon Sep 17 00:00:00 2001 From: Yoshihiro Shimoda Date: Tue, 10 Mar 2009 15:49:54 +0900 Subject: sh: Support fixed 32-bit PMB mappings from bootloader. This provides a method for supporting fixed PMB mappings inherited from the bootloader, as an alternative to the dynamic PMB mapping currently used by the kernel. In the future these methods will be combined. P1/P2 area is handled like a regular 29-bit physical address, and local bus device are assigned P3 area addresses. Signed-off-by: Yoshihiro Shimoda Signed-off-by: Paul Mundt --- arch/sh/include/asm/addrspace.h | 4 ++-- arch/sh/include/asm/io.h | 4 ++-- arch/sh/include/asm/page.h | 7 ++++++- 3 files changed, 10 insertions(+), 5 deletions(-) (limited to 'arch/sh/include/asm') diff --git a/arch/sh/include/asm/addrspace.h b/arch/sh/include/asm/addrspace.h index 36736c7e93d..80d40813e05 100644 --- a/arch/sh/include/asm/addrspace.h +++ b/arch/sh/include/asm/addrspace.h @@ -31,7 +31,7 @@ /* Returns the physical address of a PnSEG (n=1,2) address */ #define PHYSADDR(a) (((unsigned long)(a)) & 0x1fffffff) -#ifdef CONFIG_29BIT +#if defined(CONFIG_29BIT) || defined(CONFIG_PMB_FIXED) /* * Map an address to a certain privileged segment */ @@ -43,7 +43,7 @@ ((__typeof__(a))(((unsigned long)(a) & 0x1fffffff) | P3SEG)) #define P4SEGADDR(a) \ ((__typeof__(a))(((unsigned long)(a) & 0x1fffffff) | P4SEG)) -#endif /* 29BIT */ +#endif /* 29BIT || PMB_FIXED */ #endif /* P1SEG */ /* Check if an address can be reached in 29 bits */ diff --git a/arch/sh/include/asm/io.h b/arch/sh/include/asm/io.h index 61f6dae4053..0454f8d6805 100644 --- a/arch/sh/include/asm/io.h +++ b/arch/sh/include/asm/io.h @@ -238,7 +238,7 @@ extern void onchip_unmap(unsigned long vaddr); static inline void __iomem * __ioremap_mode(unsigned long offset, unsigned long size, unsigned long flags) { -#ifdef CONFIG_SUPERH32 +#if defined(CONFIG_SUPERH32) && !defined(CONFIG_PMB_FIXED) unsigned long last_addr = offset + size - 1; #endif void __iomem *ret; @@ -247,7 +247,7 @@ __ioremap_mode(unsigned long offset, unsigned long size, unsigned long flags) if (ret) return ret; -#ifdef CONFIG_SUPERH32 +#if defined(CONFIG_SUPERH32) && !defined(CONFIG_PMB_FIXED) /* * For P1 and P2 space this is trivial, as everything is already * mapped. Uncached access for P1 addresses are done through P2. diff --git a/arch/sh/include/asm/page.h b/arch/sh/include/asm/page.h index 5871d78e47e..9c6d21ec024 100644 --- a/arch/sh/include/asm/page.h +++ b/arch/sh/include/asm/page.h @@ -129,7 +129,12 @@ typedef struct page *pgtable_t; * is not visible (it is part of the PMB mapping) and so needs to be * added or subtracted as required. */ -#ifdef CONFIG_32BIT +#if defined(CONFIG_PMB_FIXED) +/* phys = virt - PAGE_OFFSET - (__MEMORY_START & 0xe0000000) */ +#define PMB_OFFSET (PAGE_OFFSET - PXSEG(__MEMORY_START)) +#define __pa(x) ((unsigned long)(x) - PMB_OFFSET) +#define __va(x) ((void *)((unsigned long)(x) + PMB_OFFSET)) +#elif defined(CONFIG_32BIT) #define __pa(x) ((unsigned long)(x)-PAGE_OFFSET+__MEMORY_START) #define __va(x) ((void *)((unsigned long)(x)+PAGE_OFFSET-__MEMORY_START)) #else -- cgit v1.2.3 From 71b973a42c5456824c8712e00659d9616d395919 Mon Sep 17 00:00:00 2001 From: Nobuhiro Iwamatsu Date: Tue, 10 Mar 2009 17:26:49 +0900 Subject: sh: dma-sh updates for multi IRQ and new SH-4A CPUs. This adds DMA support for newer SH-4A CPUs, particularly SH7763/64/80/85. This also enables multi IRQ support for platforms that have multiple vectors bound to the same IRQ source. Signed-off-by: Nobuhiro Iwamatsu Signed-off-by: Yoshihiro Shimoda Signed-off-by: Paul Mundt --- arch/sh/include/asm/dma-sh.h | 117 +++++++++++++++++++++++++++++++++++++++++++ arch/sh/include/asm/dma.h | 4 +- 2 files changed, 119 insertions(+), 2 deletions(-) create mode 100644 arch/sh/include/asm/dma-sh.h (limited to 'arch/sh/include/asm') diff --git a/arch/sh/include/asm/dma-sh.h b/arch/sh/include/asm/dma-sh.h new file mode 100644 index 00000000000..e873ecaa506 --- /dev/null +++ b/arch/sh/include/asm/dma-sh.h @@ -0,0 +1,117 @@ +/* + * arch/sh/include/asm/dma-sh.h + * + * Copyright (C) 2000 Takashi YOSHII + * Copyright (C) 2003 Paul Mundt + * + * This file is subject to the terms and conditions of the GNU General Public + * License. See the file "COPYING" in the main directory of this archive + * for more details. + */ +#ifndef __DMA_SH_H +#define __DMA_SH_H + +#include + +/* DMAOR contorl: The DMAOR access size is different by CPU.*/ +#if defined(CONFIG_CPU_SUBTYPE_SH7723) || \ + defined(CONFIG_CPU_SUBTYPE_SH7780) || \ + defined(CONFIG_CPU_SUBTYPE_SH7785) +#define dmaor_read_reg(n) \ + (n ? ctrl_inw(SH_DMAC_BASE1 + DMAOR) \ + : ctrl_inw(SH_DMAC_BASE0 + DMAOR)) +#define dmaor_write_reg(n, data) \ + (n ? ctrl_outw(data, SH_DMAC_BASE1 + DMAOR) \ + : ctrl_outw(data, SH_DMAC_BASE0 + DMAOR)) +#else /* Other CPU */ +#define dmaor_read_reg(n) ctrl_inw(SH_DMAC_BASE0 + DMAOR) +#define dmaor_write_reg(n, data) ctrl_outw(data, SH_DMAC_BASE0 + DMAOR) +#endif + +static int dmte_irq_map[] __maybe_unused = { +#if (CONFIG_NR_ONCHIP_DMA_CHANNELS >= 4) + DMTE0_IRQ, + DMTE0_IRQ + 1, + DMTE0_IRQ + 2, + DMTE0_IRQ + 3, +#endif +#if (CONFIG_NR_ONCHIP_DMA_CHANNELS >= 6) + DMTE4_IRQ, + DMTE4_IRQ + 1, +#endif +#if (CONFIG_NR_ONCHIP_DMA_CHANNELS >= 8) + DMTE6_IRQ, + DMTE6_IRQ + 1, +#endif +#if (CONFIG_NR_ONCHIP_DMA_CHANNELS >= 12) + DMTE8_IRQ, + DMTE9_IRQ, + DMTE10_IRQ, + DMTE11_IRQ, +#endif +}; + +/* Definitions for the SuperH DMAC */ +#define REQ_L 0x00000000 +#define REQ_E 0x00080000 +#define RACK_H 0x00000000 +#define RACK_L 0x00040000 +#define ACK_R 0x00000000 +#define ACK_W 0x00020000 +#define ACK_H 0x00000000 +#define ACK_L 0x00010000 +#define DM_INC 0x00004000 +#define DM_DEC 0x00008000 +#define SM_INC 0x00001000 +#define SM_DEC 0x00002000 +#define RS_IN 0x00000200 +#define RS_OUT 0x00000300 +#define TS_BLK 0x00000040 +#define TM_BUR 0x00000020 +#define CHCR_DE 0x00000001 +#define CHCR_TE 0x00000002 +#define CHCR_IE 0x00000004 + +/* DMAOR definitions */ +#define DMAOR_AE 0x00000004 +#define DMAOR_NMIF 0x00000002 +#define DMAOR_DME 0x00000001 + +/* + * Define the default configuration for dual address memory-memory transfer. + * The 0x400 value represents auto-request, external->external. + */ +#define RS_DUAL (DM_INC | SM_INC | 0x400 | TS_32) + +/* DMA base address */ +static u32 dma_base_addr[] __maybe_unused = { +#if (CONFIG_NR_ONCHIP_DMA_CHANNELS >= 4) + SH_DMAC_BASE0 + 0x00, /* channel 0 */ + SH_DMAC_BASE0 + 0x10, + SH_DMAC_BASE0 + 0x20, + SH_DMAC_BASE0 + 0x30, +#endif +#if (CONFIG_NR_ONCHIP_DMA_CHANNELS >= 6) + SH_DMAC_BASE0 + 0x50, + SH_DMAC_BASE0 + 0x60, +#endif +#if (CONFIG_NR_ONCHIP_DMA_CHANNELS >= 8) + SH_DMAC_BASE1 + 0x00, + SH_DMAC_BASE1 + 0x10, +#endif +#if (CONFIG_NR_ONCHIP_DMA_CHANNELS >= 12) + SH_DMAC_BASE1 + 0x20, + SH_DMAC_BASE1 + 0x30, + SH_DMAC_BASE1 + 0x50, + SH_DMAC_BASE1 + 0x60, /* channel 11 */ +#endif +}; + +/* DMA register */ +#define SAR 0x00 +#define DAR 0x04 +#define TCR 0x08 +#define CHCR 0x0C +#define DMAOR 0x40 + +#endif /* __DMA_SH_H */ diff --git a/arch/sh/include/asm/dma.h b/arch/sh/include/asm/dma.h index beca7128e2a..6bd17847387 100644 --- a/arch/sh/include/asm/dma.h +++ b/arch/sh/include/asm/dma.h @@ -25,9 +25,9 @@ #define MAX_DMA_ADDRESS (PAGE_OFFSET+0x10000000) #ifdef CONFIG_NR_DMA_CHANNELS -# define MAX_DMA_CHANNELS (CONFIG_NR_DMA_CHANNELS) +# define MAX_DMA_CHANNELS (CONFIG_NR_DMA_CHANNELS) #else -# define MAX_DMA_CHANNELS (CONFIG_NR_ONCHIP_DMA_CHANNELS) +# define MAX_DMA_CHANNELS (CONFIG_NR_ONCHIP_DMA_CHANNELS) #endif /* -- cgit v1.2.3 From d680c76eccd9222031ee30dcee5fdedba2467610 Mon Sep 17 00:00:00 2001 From: Francesco VIRLINZI Date: Wed, 11 Mar 2009 07:40:54 +0000 Subject: sh: clkfwk: add clk_set_parent/clk_get_parent This patch adds the clk_set_parent/clk_get_parent routines to the sh clock framework. Signed-off-by: Francesco Virlinzi Signed-off-by: Paul Mundt --- arch/sh/include/asm/clock.h | 1 + 1 file changed, 1 insertion(+) (limited to 'arch/sh/include/asm') diff --git a/arch/sh/include/asm/clock.h b/arch/sh/include/asm/clock.h index f9c88583d90..2f6c9627bc1 100644 --- a/arch/sh/include/asm/clock.h +++ b/arch/sh/include/asm/clock.h @@ -15,6 +15,7 @@ struct clk_ops { void (*disable)(struct clk *clk); void (*recalc)(struct clk *clk); int (*set_rate)(struct clk *clk, unsigned long rate, int algo_id); + int (*set_parent)(struct clk *clk, struct clk *parent); long (*round_rate)(struct clk *clk, unsigned long rate); }; -- cgit v1.2.3 From 039a718ebb37298de87801288673859ac40b6fc4 Mon Sep 17 00:00:00 2001 From: Nobuhiro Iwamatsu Date: Thu, 12 Mar 2009 06:34:39 +0000 Subject: sh: Revert CONFIG_NR_ONCHIP_DMA_CHANNELS to MAX_DMA_CHANNELS Signed-off-by: Nobuhiro Iwamatsu Signed-off-by: Paul Mundt --- arch/sh/include/asm/dma-sh.h | 17 +++++++++-------- 1 file changed, 9 insertions(+), 8 deletions(-) (limited to 'arch/sh/include/asm') diff --git a/arch/sh/include/asm/dma-sh.h b/arch/sh/include/asm/dma-sh.h index e873ecaa506..0c8f8e14622 100644 --- a/arch/sh/include/asm/dma-sh.h +++ b/arch/sh/include/asm/dma-sh.h @@ -11,6 +11,7 @@ #ifndef __DMA_SH_H #define __DMA_SH_H +#include #include /* DMAOR contorl: The DMAOR access size is different by CPU.*/ @@ -29,21 +30,21 @@ #endif static int dmte_irq_map[] __maybe_unused = { -#if (CONFIG_NR_ONCHIP_DMA_CHANNELS >= 4) +#if (MAX_DMA_CHANNELS >= 4) DMTE0_IRQ, DMTE0_IRQ + 1, DMTE0_IRQ + 2, DMTE0_IRQ + 3, #endif -#if (CONFIG_NR_ONCHIP_DMA_CHANNELS >= 6) +#if (MAX_DMA_CHANNELS >= 6) DMTE4_IRQ, DMTE4_IRQ + 1, #endif -#if (CONFIG_NR_ONCHIP_DMA_CHANNELS >= 8) +#if (MAX_DMA_CHANNELS >= 8) DMTE6_IRQ, DMTE6_IRQ + 1, #endif -#if (CONFIG_NR_ONCHIP_DMA_CHANNELS >= 12) +#if (MAX_DMA_CHANNELS >= 12) DMTE8_IRQ, DMTE9_IRQ, DMTE10_IRQ, @@ -85,21 +86,21 @@ static int dmte_irq_map[] __maybe_unused = { /* DMA base address */ static u32 dma_base_addr[] __maybe_unused = { -#if (CONFIG_NR_ONCHIP_DMA_CHANNELS >= 4) +#if (MAX_DMA_CHANNELS >= 4) SH_DMAC_BASE0 + 0x00, /* channel 0 */ SH_DMAC_BASE0 + 0x10, SH_DMAC_BASE0 + 0x20, SH_DMAC_BASE0 + 0x30, #endif -#if (CONFIG_NR_ONCHIP_DMA_CHANNELS >= 6) +#if (MAX_DMA_CHANNELS >= 6) SH_DMAC_BASE0 + 0x50, SH_DMAC_BASE0 + 0x60, #endif -#if (CONFIG_NR_ONCHIP_DMA_CHANNELS >= 8) +#if (MAX_DMA_CHANNELS >= 8) SH_DMAC_BASE1 + 0x00, SH_DMAC_BASE1 + 0x10, #endif -#if (CONFIG_NR_ONCHIP_DMA_CHANNELS >= 12) +#if (MAX_DMA_CHANNELS >= 12) SH_DMAC_BASE1 + 0x20, SH_DMAC_BASE1 + 0x30, SH_DMAC_BASE1 + 0x50, -- cgit v1.2.3 From 7759491274bc5ba7cd72b3b9cc5ec8247b937efb Mon Sep 17 00:00:00 2001 From: Magnus Damm Date: Fri, 13 Mar 2009 15:23:04 +0000 Subject: sh: SuperH Mobile suspend support This patch contains CONFIG_SUSPEND support to the SuperH architecture. If enabled, SuperH Mobile processors will register their suspend callbacks during boot. To suspend, use "echo mem > /sys/power/state". To allow wakeup, make sure "/sys/device/platform/../power/wakeup" contains "enabled". Additional per-device driver patches are most likely needed. Signed-off-by: Magnus Damm Signed-off-by: Paul Mundt --- arch/sh/include/asm/suspend.h | 9 +++++++++ 1 file changed, 9 insertions(+) (limited to 'arch/sh/include/asm') diff --git a/arch/sh/include/asm/suspend.h b/arch/sh/include/asm/suspend.h index 5d6d8aba568..b1b995370e7 100644 --- a/arch/sh/include/asm/suspend.h +++ b/arch/sh/include/asm/suspend.h @@ -1,6 +1,7 @@ #ifndef _ASM_SH_SUSPEND_H #define _ASM_SH_SUSPEND_H +#ifndef __ASSEMBLY__ static inline int arch_prepare_suspend(void) { return 0; } #include @@ -9,5 +10,13 @@ struct swsusp_arch_regs { struct pt_regs user_regs; unsigned long bank1_regs[8]; }; +#endif + +/* flags passed to assembly suspend code */ +#define SUSP_SH_SLEEP (1 << 0) /* Regular sleep mode */ +#define SUSP_SH_STANDBY (1 << 1) /* SH-Mobile Software standby mode */ +#define SUSP_SH_RSTANDBY (1 << 2) /* SH-Mobile R-standby mode */ +#define SUSP_SH_USTANDBY (1 << 3) /* SH-Mobile U-standby mode */ +#define SUSP_SH_SF (1 << 4) /* Enable self-refresh */ #endif /* _ASM_SH_SUSPEND_H */ -- cgit v1.2.3 From 8263a67e169fdf0d06d172acbf6c03ae172a69d4 Mon Sep 17 00:00:00 2001 From: Paul Mundt Date: Tue, 17 Mar 2009 17:49:49 +0900 Subject: sh: Support for extended ASIDs on PTEAEX-capable SH-X3 cores. This adds support for extended ASIDs (up to 16-bits) on newer SH-X3 cores that implement the PTAEX register and respective functionality. Presently only the 65nm SH7786 (90nm only supports legacy 8-bit ASIDs). The main change is in how the PTE is written out when loading the entry in to the TLB, as well as in how the TLB entry is selectively flushed. While SH-X2 extended mode splits out the memory-mapped U and I-TLB data arrays for extra bits, extended ASID mode splits out the address arrays. While we don't use the memory-mapped data array access, the address array accesses are necessary for selective TLB flushes, so these are implemented newly and replace the generic SH-4 implementation. With this, TLB flushes in switch_mm() are almost non-existent on newer parts. Signed-off-by: Paul Mundt --- arch/sh/include/asm/cpu-features.h | 1 + arch/sh/include/asm/mmu_context.h | 15 ++++++++++----- arch/sh/include/asm/mmu_context_32.h | 12 ++++++++++++ 3 files changed, 23 insertions(+), 5 deletions(-) (limited to 'arch/sh/include/asm') diff --git a/arch/sh/include/asm/cpu-features.h b/arch/sh/include/asm/cpu-features.h index 86308aa3973..694abe490ed 100644 --- a/arch/sh/include/asm/cpu-features.h +++ b/arch/sh/include/asm/cpu-features.h @@ -21,5 +21,6 @@ #define CPU_HAS_LLSC 0x0040 /* movli.l/movco.l */ #define CPU_HAS_L2_CACHE 0x0080 /* Secondary cache / URAM */ #define CPU_HAS_OP32 0x0100 /* 32-bit instruction support */ +#define CPU_HAS_PTEAEX 0x0200 /* PTE ASID Extension support */ #endif /* __ASM_SH_CPU_FEATURES_H */ diff --git a/arch/sh/include/asm/mmu_context.h b/arch/sh/include/asm/mmu_context.h index 5d9157bd474..2a9c55f1a83 100644 --- a/arch/sh/include/asm/mmu_context.h +++ b/arch/sh/include/asm/mmu_context.h @@ -19,13 +19,18 @@ * (a) TLB cache version (or round, cycle whatever expression you like) * (b) ASID (Address Space IDentifier) */ +#ifdef CONFIG_CPU_HAS_PTEAEX +#define MMU_CONTEXT_ASID_MASK 0x0000ffff +#else #define MMU_CONTEXT_ASID_MASK 0x000000ff -#define MMU_CONTEXT_VERSION_MASK 0xffffff00 -#define MMU_CONTEXT_FIRST_VERSION 0x00000100 -#define NO_CONTEXT 0UL +#endif -/* ASID is 8-bit value, so it can't be 0x100 */ -#define MMU_NO_ASID 0x100 +#define MMU_CONTEXT_VERSION_MASK (~0UL & ~MMU_CONTEXT_ASID_MASK) +#define MMU_CONTEXT_FIRST_VERSION (MMU_CONTEXT_ASID_MASK + 1) + +/* Impossible ASID value, to differentiate from NO_CONTEXT. */ +#define MMU_NO_ASID MMU_CONTEXT_FIRST_VERSION +#define NO_CONTEXT 0UL #define asid_cache(cpu) (cpu_data[cpu].asid_cache) diff --git a/arch/sh/include/asm/mmu_context_32.h b/arch/sh/include/asm/mmu_context_32.h index f4f9aebd68b..8ef800c549a 100644 --- a/arch/sh/include/asm/mmu_context_32.h +++ b/arch/sh/include/asm/mmu_context_32.h @@ -10,6 +10,17 @@ static inline void destroy_context(struct mm_struct *mm) /* Do nothing */ } +#ifdef CONFIG_CPU_HAS_PTEAEX +static inline void set_asid(unsigned long asid) +{ + __raw_writel(asid, MMU_PTEAEX); +} + +static inline unsigned long get_asid(void) +{ + return __raw_readl(MMU_PTEAEX) & MMU_CONTEXT_ASID_MASK; +} +#else static inline void set_asid(unsigned long asid) { unsigned long __dummy; @@ -33,6 +44,7 @@ static inline unsigned long get_asid(void) asid &= MMU_CONTEXT_ASID_MASK; return asid; } +#endif /* CONFIG_CPU_HAS_PTEAEX */ /* MMU_TTB is used for optimizing the fault handling. */ static inline void set_TTB(pgd_t *pgd) -- cgit v1.2.3 From c20351846efcb755ba849d9fb701fbd9a1ffb7c2 Mon Sep 17 00:00:00 2001 From: Paul Mundt Date: Tue, 17 Mar 2009 21:19:49 +0900 Subject: sh: Flush only the needed range when unmapping a VMA. This follows the ARM change from Aaro Koskinen: When unmapping N pages (e.g. shared memory) the amount of TLB flushes done can be (N*PAGE_SIZE/ZAP_BLOCK_SIZE)*N although it should be N at maximum. With PREEMPT kernel ZAP_BLOCK_SIZE is 8 pages, so there is a noticeable performance penalty when unmapping a large VMA and the system is spending its time in flush_tlb_range(). The problem is that tlb_end_vma() is always flushing the full VMA range. The subrange that needs to be flushed can be calculated by tlb_remove_tlb_entry(). This approach was suggested by Hugh Dickins, and is also used by other arches. The speed increase is roughly 3x for 8M mappings and for larger mappings even more. Bits and peices are taken from the ARM patch as well as the existing arch/um implementation that is quite similar. The end result is a significant reduction in both partial and full TLB flushes initiated through flush_tlb_range(). At the same time, the nommu implementation was broken, had a superfluous cache flush, and subsequently would have triggered a BUG_ON() if a code-path had triggered it. Tidy this up for correctness and provide a nopped-out implementation there. More background on the initial discussion can be found at: http://marc.info/?t=123609820900002&r=1&w=2 http://marc.info/?t=123660375800003&r=1&w=2 Signed-off-by: Paul Mundt --- arch/sh/include/asm/tlb.h | 100 ++++++++++++++++++++++++++++++++++++++++++---- 1 file changed, 92 insertions(+), 8 deletions(-) (limited to 'arch/sh/include/asm') diff --git a/arch/sh/include/asm/tlb.h b/arch/sh/include/asm/tlb.h index 88ff1ae8a6b..9c16f737074 100644 --- a/arch/sh/include/asm/tlb.h +++ b/arch/sh/include/asm/tlb.h @@ -6,22 +6,106 @@ #endif #ifndef __ASSEMBLY__ +#include + +#ifdef CONFIG_MMU +#include +#include + +/* + * TLB handling. This allows us to remove pages from the page + * tables, and efficiently handle the TLB issues. + */ +struct mmu_gather { + struct mm_struct *mm; + unsigned int fullmm; + unsigned long start, end; +}; -#define tlb_start_vma(tlb, vma) \ - flush_cache_range(vma, vma->vm_start, vma->vm_end) +DECLARE_PER_CPU(struct mmu_gather, mmu_gathers); -#define tlb_end_vma(tlb, vma) \ - flush_tlb_range(vma, vma->vm_start, vma->vm_end) +static inline void init_tlb_gather(struct mmu_gather *tlb) +{ + tlb->start = TASK_SIZE; + tlb->end = 0; -#define __tlb_remove_tlb_entry(tlb, pte, address) do { } while (0) + if (tlb->fullmm) { + tlb->start = 0; + tlb->end = TASK_SIZE; + } +} + +static inline struct mmu_gather * +tlb_gather_mmu(struct mm_struct *mm, unsigned int full_mm_flush) +{ + struct mmu_gather *tlb = &get_cpu_var(mmu_gathers); + + tlb->mm = mm; + tlb->fullmm = full_mm_flush; + + init_tlb_gather(tlb); + + return tlb; +} + +static inline void +tlb_finish_mmu(struct mmu_gather *tlb, unsigned long start, unsigned long end) +{ + if (tlb->fullmm) + flush_tlb_mm(tlb->mm); + + /* keep the page table cache within bounds */ + check_pgt_cache(); + + put_cpu_var(mmu_gathers); +} + +static inline void +tlb_remove_tlb_entry(struct mmu_gather *tlb, pte_t *ptep, unsigned long address) +{ + if (tlb->start > address) + tlb->start = address; + if (tlb->end < address + PAGE_SIZE) + tlb->end = address + PAGE_SIZE; +} /* - * Flush whole TLBs for MM + * In the case of tlb vma handling, we can optimise these away in the + * case where we're doing a full MM flush. When we're doing a munmap, + * the vmas are adjusted to only cover the region to be torn down. */ -#define tlb_flush(tlb) flush_tlb_mm((tlb)->mm) +static inline void +tlb_start_vma(struct mmu_gather *tlb, struct vm_area_struct *vma) +{ + if (!tlb->fullmm) + flush_cache_range(vma, vma->vm_start, vma->vm_end); +} + +static inline void +tlb_end_vma(struct mmu_gather *tlb, struct vm_area_struct *vma) +{ + if (!tlb->fullmm && tlb->end) { + flush_tlb_range(vma, tlb->start, tlb->end); + init_tlb_gather(tlb); + } +} + +#define tlb_remove_page(tlb,page) free_page_and_swap_cache(page) +#define pte_free_tlb(tlb, ptep) pte_free((tlb)->mm, ptep) +#define pmd_free_tlb(tlb, pmdp) pmd_free((tlb)->mm, pmdp) +#define pud_free_tlb(tlb, pudp) pud_free((tlb)->mm, pudp) + +#define tlb_migrate_finish(mm) do { } while (0) + +#else /* CONFIG_MMU */ + +#define tlb_start_vma(tlb, vma) do { } while (0) +#define tlb_end_vma(tlb, vma) do { } while (0) +#define __tlb_remove_tlb_entry(tlb, pte, address) do { } while (0) +#define tlb_flush(tlb) do { } while (0) -#include #include +#endif /* CONFIG_MMU */ #endif /* __ASSEMBLY__ */ #endif /* __ASM_SH_TLB_H */ -- cgit v1.2.3 From 3bf509230a626d11cba0e0145f552918092f586d Mon Sep 17 00:00:00 2001 From: Rafael Ignacio Zurita Date: Fri, 20 Mar 2009 02:08:22 +0000 Subject: sh: fix the HD64461 level-triggered interrupts handling Rework the hd64461 demuxer code to fix the HD64461 level-triggered interrupts handling, using handle_level_irq() as needed. Signed-off-by: Rafael Ignacio Zurita Signed-off-by: Paul Mundt --- arch/sh/include/asm/hd64461.h | 1 - 1 file changed, 1 deletion(-) (limited to 'arch/sh/include/asm') diff --git a/arch/sh/include/asm/hd64461.h b/arch/sh/include/asm/hd64461.h index 8c1353baf00..52b4b623827 100644 --- a/arch/sh/include/asm/hd64461.h +++ b/arch/sh/include/asm/hd64461.h @@ -242,7 +242,6 @@ #include /* arch/sh/cchips/hd6446x/hd64461/setup.c */ -int hd64461_irq_demux(int irq); void hd64461_register_irq_demux(int irq, int (*demux) (int irq, void *dev), void *dev); void hd64461_unregister_irq_demux(int irq); -- cgit v1.2.3