diff options
Diffstat (limited to 'arch/sh')
-rw-r--r-- | arch/sh/Kconfig | 37 | ||||
-rw-r--r-- | arch/sh/boards/Kconfig | 6 | ||||
-rw-r--r-- | arch/sh/boards/mach-highlander/Kconfig | 2 | ||||
-rw-r--r-- | arch/sh/boards/mach-rsk/Kconfig | 2 | ||||
-rw-r--r-- | arch/sh/include/asm/atomic-irq.h | 16 | ||||
-rw-r--r-- | arch/sh/include/asm/bitops-llsc.h | 72 | ||||
-rw-r--r-- | arch/sh/include/asm/cmpxchg-llsc.h | 38 | ||||
-rw-r--r-- | arch/sh/include/asm/gpio.h | 70 | ||||
-rw-r--r-- | arch/sh/include/asm/kprobes.h | 2 | ||||
-rw-r--r-- | arch/sh/include/asm/processor_32.h | 12 | ||||
-rw-r--r-- | arch/sh/include/asm/processor_64.h | 14 | ||||
-rw-r--r-- | arch/sh/include/asm/timer.h | 4 | ||||
-rw-r--r-- | arch/sh/kernel/cpu/sh4a/setup-sh7343.c | 34 | ||||
-rw-r--r-- | arch/sh/kernel/cpu/sh4a/setup-sh7366.c | 34 | ||||
-rw-r--r-- | arch/sh/kernel/cpu/sh4a/setup-sh7722.c | 34 | ||||
-rw-r--r-- | arch/sh/kernel/cpu/sh4a/setup-sh7723.c | 34 | ||||
-rw-r--r-- | arch/sh/kernel/gpio.c | 338 | ||||
-rw-r--r-- | arch/sh/kernel/time_32.c | 71 | ||||
-rw-r--r-- | arch/sh/kernel/timers/timer-mtu2.c | 3 | ||||
-rw-r--r-- | arch/sh/kernel/timers/timer-tmu.c | 20 |
20 files changed, 538 insertions, 305 deletions
diff --git a/arch/sh/Kconfig b/arch/sh/Kconfig index ebabe518e72..78a01d7d37e 100644 --- a/arch/sh/Kconfig +++ b/arch/sh/Kconfig @@ -107,6 +107,9 @@ config SYS_SUPPORTS_NUMA config SYS_SUPPORTS_PCI bool +config SYS_SUPPORTS_CMT + bool + config STACKTRACE_SUPPORT def_bool y @@ -188,6 +191,7 @@ choice config CPU_SUBTYPE_SH7619 bool "Support SH7619 processor" select CPU_SH2 + select SYS_SUPPORTS_CMT # SH-2A Processor Support @@ -200,15 +204,18 @@ config CPU_SUBTYPE_SH7203 bool "Support SH7203 processor" select CPU_SH2A select CPU_HAS_FPU + select SYS_SUPPORTS_CMT config CPU_SUBTYPE_SH7206 bool "Support SH7206 processor" select CPU_SH2A + select SYS_SUPPORTS_CMT config CPU_SUBTYPE_SH7263 bool "Support SH7263 processor" select CPU_SH2A select CPU_HAS_FPU + select SYS_SUPPORTS_CMT config CPU_SUBTYPE_MXG bool "Support MX-G processor" @@ -324,6 +331,7 @@ config CPU_SUBTYPE_SH7723 select CPU_SH4A select CPU_SHX2 select ARCH_SPARSEMEM_ENABLE + select SYS_SUPPORTS_CMT help Select SH7723 if you have an SH-MobileR2 CPU. @@ -362,6 +370,7 @@ config CPU_SUBTYPE_SHX3 config CPU_SUBTYPE_SH7343 bool "Support SH7343 processor" select CPU_SH4AL_DSP + select SYS_SUPPORTS_CMT config CPU_SUBTYPE_SH7722 bool "Support SH7722 processor" @@ -369,6 +378,7 @@ config CPU_SUBTYPE_SH7722 select CPU_SHX2 select ARCH_SPARSEMEM_ENABLE select SYS_SUPPORTS_NUMA + select SYS_SUPPORTS_CMT config CPU_SUBTYPE_SH7366 bool "Support SH7366 processor" @@ -376,6 +386,7 @@ config CPU_SUBTYPE_SH7366 select CPU_SHX2 select ARCH_SPARSEMEM_ENABLE select SYS_SUPPORTS_NUMA + select SYS_SUPPORTS_CMT # SH-5 Processor Support @@ -398,25 +409,34 @@ source "arch/sh/boards/Kconfig" menu "Timer and clock configuration" config SH_TMU - def_bool y - prompt "TMU timer support" + bool "TMU timer support" depends on CPU_SH3 || CPU_SH4 + default y select GENERIC_TIME select GENERIC_CLOCKEVENTS help This enables the use of the TMU as the system timer. config SH_CMT - def_bool y - prompt "CMT timer support" - depends on CPU_SH2 && !CPU_SUBTYPE_MXG + bool "CMT timer support" + depends on SYS_SUPPORTS_CMT && CPU_SH2 + default y help This enables the use of the CMT as the system timer. +# +# Support for the new-style CMT driver. This will replace SH_CMT +# once its other dependencies are merged. +# +config SH_TIMER_CMT + bool "CMT clockevents driver" + depends on SYS_SUPPORTS_CMT && !SH_CMT + select GENERIC_CLOCKEVENTS + config SH_MTU2 - def_bool n - prompt "MTU2 timer support" + bool "MTU2 timer support" depends on CPU_SH2A + default y help This enables the use of the MTU2 as the system timer. @@ -426,7 +446,8 @@ config SH_TIMER_IRQ CPU_SUBTYPE_SH7763 default "86" if CPU_SUBTYPE_SH7619 default "140" if CPU_SUBTYPE_SH7206 - default "142" if CPU_SUBTYPE_SH7203 + default "142" if CPU_SUBTYPE_SH7203 && SH_CMT + default "153" if CPU_SUBTYPE_SH7203 && SH_MTU2 default "238" if CPU_SUBTYPE_MXG default "16" diff --git a/arch/sh/boards/Kconfig b/arch/sh/boards/Kconfig index 861914747e4..c9da37088d2 100644 --- a/arch/sh/boards/Kconfig +++ b/arch/sh/boards/Kconfig @@ -165,7 +165,7 @@ config SH_SH7785LCR_29BIT_PHYSMAPS config SH_MIGOR bool "Migo-R" depends on CPU_SUBTYPE_SH7722 - select GENERIC_GPIO + select ARCH_REQUIRE_GPIOLIB help Select Migo-R if configuring for the SH7722 Migo-R platform by Renesas System Solutions Asia Pte. Ltd. @@ -173,7 +173,7 @@ config SH_MIGOR config SH_AP325RXA bool "AP-325RXA" depends on CPU_SUBTYPE_SH7723 - select GENERIC_GPIO + select ARCH_REQUIRE_GPIOLIB help Renesas "AP-325RXA" support. Compatible with ALGO SYSTEM CO.,LTD. "AP-320A" @@ -240,7 +240,7 @@ config SH_X3PROTO config SH_MAGIC_PANEL_R2 bool "Magic Panel R2" depends on CPU_SUBTYPE_SH7720 - select GENERIC_GPIO + select ARCH_REQUIRE_GPIOLIB help Select Magic Panel R2 if configuring for Magic Panel R2. diff --git a/arch/sh/boards/mach-highlander/Kconfig b/arch/sh/boards/mach-highlander/Kconfig index 08057f62687..def49cc0a7b 100644 --- a/arch/sh/boards/mach-highlander/Kconfig +++ b/arch/sh/boards/mach-highlander/Kconfig @@ -18,7 +18,7 @@ config SH_R7780MP config SH_R7785RP bool "R7785RP board support" depends on CPU_SUBTYPE_SH7785 - select GENERIC_GPIO + select ARCH_REQUIRE_GPIOLIB endchoice diff --git a/arch/sh/boards/mach-rsk/Kconfig b/arch/sh/boards/mach-rsk/Kconfig index bff095dffc0..aeff3b04220 100644 --- a/arch/sh/boards/mach-rsk/Kconfig +++ b/arch/sh/boards/mach-rsk/Kconfig @@ -10,7 +10,7 @@ config SH_RSK7201 config SH_RSK7203 bool "RSK7203" - select GENERIC_GPIO + select ARCH_REQUIRE_GPIOLIB depends on CPU_SUBTYPE_SH7203 endchoice 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); } 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" ); diff --git a/arch/sh/include/asm/gpio.h b/arch/sh/include/asm/gpio.h index 90673658eb1..61f93da2c62 100644 --- a/arch/sh/include/asm/gpio.h +++ b/arch/sh/include/asm/gpio.h @@ -19,8 +19,42 @@ #include <cpu/gpio.h> #endif +#define ARCH_NR_GPIOS 512 +#include <asm-generic/gpio.h> + +#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 char pinmux_flag_t; +typedef unsigned short pinmux_flag_t; #define PINMUX_TYPE_NONE 0 #define PINMUX_TYPE_FUNCTION 1 @@ -34,6 +68,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; @@ -54,7 +93,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; }; @@ -89,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 <asm-generic/gpio.h> - #endif /* __ASM_SH_GPIO_H */ 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 */ 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 */ diff --git a/arch/sh/kernel/cpu/sh4a/setup-sh7343.c b/arch/sh/kernel/cpu/sh4a/setup-sh7343.c index 4ff4dc64520..c1549382c87 100644 --- a/arch/sh/kernel/cpu/sh4a/setup-sh7343.c +++ b/arch/sh/kernel/cpu/sh4a/setup-sh7343.c @@ -12,6 +12,7 @@ #include <linux/serial.h> #include <linux/serial_sci.h> #include <linux/uio_driver.h> +#include <linux/sh_cmt.h> #include <asm/clock.h> static struct resource iic0_resources[] = { @@ -140,6 +141,38 @@ static struct platform_device jpu_device = { .num_resources = ARRAY_SIZE(jpu_resources), }; +static struct sh_cmt_config cmt_platform_data = { + .name = "CMT", + .channel_offset = 0x60, + .timer_bit = 5, + .clk = "cmt0", + .clockevent_rating = 125, + .clocksource_rating = 200, +}; + +static struct resource cmt_resources[] = { + [0] = { + .name = "CMT", + .start = 0x044a0060, + .end = 0x044a006b, + .flags = IORESOURCE_MEM, + }, + [1] = { + .start = 104, + .flags = IORESOURCE_IRQ, + }, +}; + +static struct platform_device cmt_device = { + .name = "sh_cmt", + .id = 0, + .dev = { + .platform_data = &cmt_platform_data, + }, + .resource = cmt_resources, + .num_resources = ARRAY_SIZE(cmt_resources), +}; + static struct plat_sci_port sci_platform_data[] = { { .mapbase = 0xffe00000, @@ -175,6 +208,7 @@ static struct platform_device sci_device = { }; static struct platform_device *sh7343_devices[] __initdata = { + &cmt_device, &iic0_device, &iic1_device, &sci_device, diff --git a/arch/sh/kernel/cpu/sh4a/setup-sh7366.c b/arch/sh/kernel/cpu/sh4a/setup-sh7366.c index 839ae97a7fd..93ecf8ed5c6 100644 --- a/arch/sh/kernel/cpu/sh4a/setup-sh7366.c +++ b/arch/sh/kernel/cpu/sh4a/setup-sh7366.c @@ -14,6 +14,7 @@ #include <linux/serial.h> #include <linux/serial_sci.h> #include <linux/uio_driver.h> +#include <linux/sh_cmt.h> #include <asm/clock.h> static struct resource iic_resources[] = { @@ -147,6 +148,38 @@ static struct platform_device veu1_device = { .num_resources = ARRAY_SIZE(veu1_resources), }; +static struct sh_cmt_config cmt_platform_data = { + .name = "CMT", + .channel_offset = 0x60, + .timer_bit = 5, + .clk = "cmt0", + .clockevent_rating = 125, + .clocksource_rating = 200, +}; + +static struct resource cmt_resources[] = { + [0] = { + .name = "CMT", + .start = 0x044a0060, + .end = 0x044a006b, + .flags = IORESOURCE_MEM, + }, + [1] = { + .start = 104, + .flags = IORESOURCE_IRQ, + }, +}; + +static struct platform_device cmt_device = { + .name = "sh_cmt", + .id = 0, + .dev = { + .platform_data = &cmt_platform_data, + }, + .resource = cmt_resources, + .num_resources = ARRAY_SIZE(cmt_resources), +}; + static struct plat_sci_port sci_platform_data[] = { { .mapbase = 0xffe00000, @@ -167,6 +200,7 @@ static struct platform_device sci_device = { }; static struct platform_device *sh7366_devices[] __initdata = { + &cmt_device, &iic_device, &sci_device, &usb_host_device, diff --git a/arch/sh/kernel/cpu/sh4a/setup-sh7722.c b/arch/sh/kernel/cpu/sh4a/setup-sh7722.c index 5146afc156e..0e5d204bc79 100644 --- a/arch/sh/kernel/cpu/sh4a/setup-sh7722.c +++ b/arch/sh/kernel/cpu/sh4a/setup-sh7722.c @@ -13,6 +13,7 @@ #include <linux/serial_sci.h> #include <linux/mm.h> #include <linux/uio_driver.h> +#include <linux/sh_cmt.h> #include <asm/clock.h> #include <asm/mmzone.h> @@ -176,6 +177,38 @@ static struct platform_device jpu_device = { .num_resources = ARRAY_SIZE(jpu_resources), }; +static struct sh_cmt_config cmt_platform_data = { + .name = "CMT", + .channel_offset = 0x60, + .timer_bit = 5, + .clk = "cmt0", + .clockevent_rating = 125, + .clocksource_rating = 200, +}; + +static struct resource cmt_resources[] = { + [0] = { + .name = "CMT", + .start = 0x044a0060, + .end = 0x044a006b, + .flags = IORESOURCE_MEM, + }, + [1] = { + .start = 104, + .flags = IORESOURCE_IRQ, + }, +}; + +static struct platform_device cmt_device = { + .name = "sh_cmt", + .id = 0, + .dev = { + .platform_data = &cmt_platform_data, + }, + .resource = cmt_resources, + .num_resources = ARRAY_SIZE(cmt_resources), +}; + static struct plat_sci_port sci_platform_data[] = { { .mapbase = 0xffe00000, @@ -209,6 +242,7 @@ static struct platform_device sci_device = { }; static struct platform_device *sh7722_devices[] __initdata = { + &cmt_device, &rtc_device, &usbf_device, &iic_device, diff --git a/arch/sh/kernel/cpu/sh4a/setup-sh7723.c b/arch/sh/kernel/cpu/sh4a/setup-sh7723.c index 849770d780a..5338dacbcfb 100644 --- a/arch/sh/kernel/cpu/sh4a/setup-sh7723.c +++ b/arch/sh/kernel/cpu/sh4a/setup-sh7723.c @@ -13,6 +13,7 @@ #include <linux/mm.h> #include <linux/serial_sci.h> #include <linux/uio_driver.h> +#include <linux/sh_cmt.h> #include <asm/clock.h> #include <asm/mmzone.h> @@ -100,6 +101,38 @@ static struct platform_device veu1_device = { .num_resources = ARRAY_SIZE(veu1_resources), }; +static struct sh_cmt_config cmt_platform_data = { + .name = "CMT", + .channel_offset = 0x60, + .timer_bit = 5, + .clk = "cmt0", + .clockevent_rating = 125, + .clocksource_rating = 200, +}; + +static struct resource cmt_resources[] = { + [0] = { + .name = "CMT", + .start = 0x044a0060, + .end = 0x044a006b, + .flags = IORESOURCE_MEM, + }, + [1] = { + .start = 104, + .flags = IORESOURCE_IRQ, + }, +}; + +static struct platform_device cmt_device = { + .name = "sh_cmt", + .id = 0, + .dev = { + .platform_data = &cmt_platform_data, + }, + .resource = cmt_resources, + .num_resources = ARRAY_SIZE(cmt_resources), +}; + static struct plat_sci_port sci_platform_data[] = { { .mapbase = 0xffe00000, @@ -221,6 +254,7 @@ static struct platform_device iic_device = { }; static struct platform_device *sh7723_devices[] __initdata = { + &cmt_device, &sci_device, &rtc_device, &iic_device, diff --git a/arch/sh/kernel/gpio.c b/arch/sh/kernel/gpio.c index d3716536103..d22e5af699f 100644 --- a/arch/sh/kernel/gpio.c +++ b/arch/sh/kernel/gpio.c @@ -19,36 +19,75 @@ #include <linux/bitops.h> #include <linux/gpio.h> -static struct pinmux_info *registered_gpio; +static int enum_in_range(pinmux_enum_t enum_id, struct pinmux_range *r) +{ + if (enum_id < r->begin) + return 0; -static struct pinmux_info *gpio_controller(unsigned gpio) + if (enum_id > r->end) + return 0; + + return 1; +} + +static unsigned long gpio_read_raw_reg(unsigned long reg, + unsigned long reg_width) { - if (!registered_gpio) - return NULL; + switch (reg_width) { + case 8: + return ctrl_inb(reg); + case 16: + return ctrl_inw(reg); + case 32: + return ctrl_inl(reg); + } - if (gpio < registered_gpio->first_gpio) - return NULL; + BUG(); + return 0; +} - if (gpio > registered_gpio->last_gpio) - return NULL; +static void gpio_write_raw_reg(unsigned long reg, + unsigned long reg_width, + unsigned long data) +{ + switch (reg_width) { + case 8: + ctrl_outb(data, reg); + return; + case 16: + ctrl_outw(data, reg); + return; + case 32: + ctrl_outl(data, reg); + return; + } - return registered_gpio; + BUG(); } -static int enum_in_range(pinmux_enum_t enum_id, struct pinmux_range *r) +static void gpio_write_bit(struct pinmux_data_reg *dr, + unsigned long in_pos, unsigned long value) { - if (enum_id < r->begin) - return 0; + unsigned long pos; - if (enum_id > r->end) - return 0; + pos = dr->reg_width - (in_pos + 1); - return 1; +#ifdef DEBUG + pr_info("write_bit addr = %lx, value = %ld, pos = %ld, " + "r_width = %ld\n", + dr->reg, !!value, pos, dr->reg_width); +#endif + + if (value) + set_bit(pos, &dr->reg_shadow); + else + clear_bit(pos, &dr->reg_shadow); + + gpio_write_raw_reg(dr->reg, dr->reg_width, dr->reg_shadow); } -static int read_write_reg(unsigned long reg, unsigned long reg_width, - unsigned long field_width, unsigned long in_pos, - unsigned long value, int do_write) +static int gpio_read_reg(unsigned long reg, unsigned long reg_width, + unsigned long field_width, unsigned long in_pos) { unsigned long data, mask, pos; @@ -57,52 +96,53 @@ static int read_write_reg(unsigned long reg, unsigned long reg_width, pos = reg_width - ((in_pos + 1) * field_width); #ifdef DEBUG - pr_info("%s, addr = %lx, value = %ld, pos = %ld, " + pr_info("read_reg: addr = %lx, pos = %ld, " "r_width = %ld, f_width = %ld\n", - do_write ? "write" : "read", reg, value, pos, - reg_width, field_width); + reg, pos, reg_width, field_width); #endif - switch (reg_width) { - case 8: - data = ctrl_inb(reg); - break; - case 16: - data = ctrl_inw(reg); - break; - case 32: - data = ctrl_inl(reg); - break; - } + data = gpio_read_raw_reg(reg, reg_width); + return (data >> pos) & mask; +} - if (!do_write) - return (data >> pos) & mask; +static void gpio_write_reg(unsigned long reg, unsigned long reg_width, + unsigned long field_width, unsigned long in_pos, + unsigned long value) +{ + unsigned long mask, pos; - data &= ~(mask << pos); - data |= value << pos; + mask = (1 << field_width) - 1; + pos = reg_width - ((in_pos + 1) * field_width); + +#ifdef DEBUG + pr_info("write_reg addr = %lx, value = %ld, pos = %ld, " + "r_width = %ld, f_width = %ld\n", + reg, value, pos, reg_width, field_width); +#endif + + mask = ~(mask << pos); + value = value << pos; switch (reg_width) { case 8: - ctrl_outb(data, reg); + ctrl_outb((ctrl_inb(reg) & mask) | value, reg); break; case 16: - ctrl_outw(data, reg); + ctrl_outw((ctrl_inw(reg) & mask) | value, reg); break; case 32: - ctrl_outl(data, reg); + ctrl_outl((ctrl_inl(reg) & mask) | value, reg); break; } - return 0; } -static int get_data_reg(struct pinmux_info *gpioc, unsigned gpio, - struct pinmux_data_reg **drp, int *bitp) +static int setup_data_reg(struct pinmux_info *gpioc, unsigned gpio) { - pinmux_enum_t enum_id = gpioc->gpios[gpio].enum_id; + struct pinmux_gpio *gpiop = &gpioc->gpios[gpio]; struct pinmux_data_reg *data_reg; int k, n; - if (!enum_in_range(enum_id, &gpioc->data)) + if (!enum_in_range(gpiop->enum_id, &gpioc->data)) return -1; k = 0; @@ -113,19 +153,58 @@ static int get_data_reg(struct pinmux_info *gpioc, unsigned gpio, break; for (n = 0; n < data_reg->reg_width; n++) { - if (data_reg->enum_ids[n] == enum_id) { - *drp = data_reg; - *bitp = n; + if (data_reg->enum_ids[n] == gpiop->enum_id) { + gpiop->flags &= ~PINMUX_FLAG_DREG; + gpiop->flags |= (k << PINMUX_FLAG_DREG_SHIFT); + gpiop->flags &= ~PINMUX_FLAG_DBIT; + gpiop->flags |= (n << PINMUX_FLAG_DBIT_SHIFT); return 0; - } } k++; } + BUG(); + return -1; } +static void setup_data_regs(struct pinmux_info *gpioc) +{ + struct pinmux_data_reg *drp; + int k; + + for (k = gpioc->first_gpio; k <= gpioc->last_gpio; k++) + setup_data_reg(gpioc, k); + + k = 0; + while (1) { + drp = gpioc->data_regs + k; + + if (!drp->reg_width) + break; + + drp->reg_shadow = gpio_read_raw_reg(drp->reg, drp->reg_width); + k++; + } +} + +static int get_data_reg(struct pinmux_info *gpioc, unsigned gpio, + struct pinmux_data_reg **drp, int *bitp) +{ + struct pinmux_gpio *gpiop = &gpioc->gpios[gpio]; + int k, n; + + if (!enum_in_range(gpiop->enum_id, &gpioc->data)) + return -1; + + k = (gpiop->flags & PINMUX_FLAG_DREG) >> PINMUX_FLAG_DREG_SHIFT; + n = (gpiop->flags & PINMUX_FLAG_DBIT) >> PINMUX_FLAG_DBIT_SHIFT; + *drp = gpioc->data_regs + k; + *bitp = n; + return 0; +} + static int get_config_reg(struct pinmux_info *gpioc, pinmux_enum_t enum_id, struct pinmux_cfg_reg **crp, int *indexp, unsigned long **cntp) @@ -187,9 +266,9 @@ static int get_gpio_enum_id(struct pinmux_info *gpioc, unsigned gpio, return -1; } -static int write_config_reg(struct pinmux_info *gpioc, - struct pinmux_cfg_reg *crp, - int index) +static void write_config_reg(struct pinmux_info *gpioc, + struct pinmux_cfg_reg *crp, + int index) { unsigned long ncomb, pos, value; @@ -197,8 +276,7 @@ static int write_config_reg(struct pinmux_info *gpioc, pos = index / ncomb; value = index % ncomb; - return read_write_reg(crp->reg, crp->reg_width, - crp->field_width, pos, value, 1); + gpio_write_reg(crp->reg, crp->reg_width, crp->field_width, pos, value); } static int check_config_reg(struct pinmux_info *gpioc, @@ -211,8 +289,8 @@ static int check_config_reg(struct pinmux_info *gpioc, pos = index / ncomb; value = index % ncomb; - if (read_write_reg(crp->reg, crp->reg_width, - crp->field_width, pos, 0, 0) == value) + if (gpio_read_reg(crp->reg, crp->reg_width, + crp->field_width, pos) == value) return 0; return -1; @@ -220,8 +298,8 @@ static int check_config_reg(struct pinmux_info *gpioc, enum { GPIO_CFG_DRYRUN, GPIO_CFG_REQ, GPIO_CFG_FREE }; -int pinmux_config_gpio(struct pinmux_info *gpioc, unsigned gpio, - int pinmux_type, int cfg_mode) +static int pinmux_config_gpio(struct pinmux_info *gpioc, unsigned gpio, + int pinmux_type, int cfg_mode) { struct pinmux_cfg_reg *cr = NULL; pinmux_enum_t enum_id; @@ -287,8 +365,7 @@ int pinmux_config_gpio(struct pinmux_info *gpioc, unsigned gpio, break; case GPIO_CFG_REQ: - if (write_config_reg(gpioc, cr, index) != 0) - goto out_err; + write_config_reg(gpioc, cr, index); *cntp = *cntp + 1; break; @@ -305,9 +382,14 @@ int pinmux_config_gpio(struct pinmux_info *gpioc, unsigned gpio, static DEFINE_SPINLOCK(gpio_lock); -int __gpio_request(unsigned gpio) +static struct pinmux_info *chip_to_pinmux(struct gpio_chip *chip) { - struct pinmux_info *gpioc = gpio_controller(gpio); + return container_of(chip, struct pinmux_info, chip); +} + +static int sh_gpio_request(struct gpio_chip *chip, unsigned offset) +{ + struct pinmux_info *gpioc = chip_to_pinmux(chip); struct pinmux_data_reg *dummy; unsigned long flags; int i, ret, pinmux_type; @@ -319,29 +401,30 @@ int __gpio_request(unsigned gpio) spin_lock_irqsave(&gpio_lock, flags); - if ((gpioc->gpios[gpio].flags & PINMUX_FLAG_TYPE) != PINMUX_TYPE_NONE) + if ((gpioc->gpios[offset].flags & PINMUX_FLAG_TYPE) != PINMUX_TYPE_NONE) goto err_unlock; /* setup pin function here if no data is associated with pin */ - if (get_data_reg(gpioc, gpio, &dummy, &i) != 0) + if (get_data_reg(gpioc, offset, &dummy, &i) != 0) pinmux_type = PINMUX_TYPE_FUNCTION; else pinmux_type = PINMUX_TYPE_GPIO; if (pinmux_type == PINMUX_TYPE_FUNCTION) { - if (pinmux_config_gpio(gpioc, gpio, + if (pinmux_config_gpio(gpioc, offset, pinmux_type, GPIO_CFG_DRYRUN) != 0) goto err_unlock; - if (pinmux_config_gpio(gpioc, gpio, + if (pinmux_config_gpio(gpioc, offset, pinmux_type, GPIO_CFG_REQ) != 0) BUG(); } - gpioc->gpios[gpio].flags = pinmux_type; + gpioc->gpios[offset].flags &= ~PINMUX_FLAG_TYPE; + gpioc->gpios[offset].flags |= pinmux_type; ret = 0; err_unlock: @@ -349,11 +432,10 @@ int __gpio_request(unsigned gpio) err_out: return ret; } -EXPORT_SYMBOL(__gpio_request); -void gpio_free(unsigned gpio) +static void sh_gpio_free(struct gpio_chip *chip, unsigned offset) { - struct pinmux_info *gpioc = gpio_controller(gpio); + struct pinmux_info *gpioc = chip_to_pinmux(chip); unsigned long flags; int pinmux_type; @@ -362,20 +444,23 @@ void gpio_free(unsigned gpio) spin_lock_irqsave(&gpio_lock, flags); - pinmux_type = gpioc->gpios[gpio].flags & PINMUX_FLAG_TYPE; - pinmux_config_gpio(gpioc, gpio, pinmux_type, GPIO_CFG_FREE); - gpioc->gpios[gpio].flags = PINMUX_TYPE_NONE; + pinmux_type = gpioc->gpios[offset].flags & PINMUX_FLAG_TYPE; + pinmux_config_gpio(gpioc, offset, pinmux_type, GPIO_CFG_FREE); + gpioc->gpios[offset].flags &= ~PINMUX_FLAG_TYPE; + gpioc->gpios[offset].flags |= PINMUX_TYPE_NONE; spin_unlock_irqrestore(&gpio_lock, flags); } -EXPORT_SYMBOL(gpio_free); static int pinmux_direction(struct pinmux_info *gpioc, unsigned gpio, int new_pinmux_type) { - int ret, pinmux_type; + int pinmux_type; + int ret = -EINVAL; + + if (!gpioc) + goto err_out; - ret = -EINVAL; pinmux_type = gpioc->gpios[gpio].flags & PINMUX_FLAG_TYPE; switch (pinmux_type) { @@ -401,102 +486,99 @@ static int pinmux_direction(struct pinmux_info *gpioc, GPIO_CFG_REQ) != 0) BUG(); - gpioc->gpios[gpio].flags = new_pinmux_type; + gpioc->gpios[gpio].flags &= ~PINMUX_FLAG_TYPE; + gpioc->gpios[gpio].flags |= new_pinmux_type; ret = 0; err_out: return ret; } -int gpio_direction_input(unsigned gpio) +static int sh_gpio_direction_input(struct gpio_chip *chip, unsigned offset) { - struct pinmux_info *gpioc = gpio_controller(gpio); + struct pinmux_info *gpioc = chip_to_pinmux(chip); unsigned long flags; - int ret = -EINVAL; - - if (!gpioc) - goto err_out; + int ret; spin_lock_irqsave(&gpio_lock, flags); - ret = pinmux_direction(gpioc, gpio, PINMUX_TYPE_INPUT); + ret = pinmux_direction(gpioc, offset, PINMUX_TYPE_INPUT); spin_unlock_irqrestore(&gpio_lock, flags); - err_out: + return ret; } -EXPORT_SYMBOL(gpio_direction_input); -static int __gpio_get_set_value(struct pinmux_info *gpioc, - unsigned gpio, int value, - int do_write) +static void sh_gpio_set_value(struct pinmux_info *gpioc, + unsigned gpio, int value) { struct pinmux_data_reg *dr = NULL; int bit = 0; - if (get_data_reg(gpioc, gpio, &dr, &bit) != 0) + if (!gpioc || get_data_reg(gpioc, gpio, &dr, &bit) != 0) BUG(); else - value = read_write_reg(dr->reg, dr->reg_width, - 1, bit, !!value, do_write); - - return value; + gpio_write_bit(dr, bit, value); } -int gpio_direction_output(unsigned gpio, int value) +static int sh_gpio_direction_output(struct gpio_chip *chip, unsigned offset, + int value) { - struct pinmux_info *gpioc = gpio_controller(gpio); + struct pinmux_info *gpioc = chip_to_pinmux(chip); unsigned long flags; - int ret = -EINVAL; - - if (!gpioc) - goto err_out; + int ret; + sh_gpio_set_value(gpioc, offset, value); spin_lock_irqsave(&gpio_lock, flags); - __gpio_get_set_value(gpioc, gpio, value, 1); - ret = pinmux_direction(gpioc, gpio, PINMUX_TYPE_OUTPUT); + ret = pinmux_direction(gpioc, offset, PINMUX_TYPE_OUTPUT); spin_unlock_irqrestore(&gpio_lock, flags); - err_out: + return ret; } -EXPORT_SYMBOL(gpio_direction_output); -int gpio_get_value(unsigned gpio) +static int sh_gpio_get_value(struct pinmux_info *gpioc, unsigned gpio) { - struct pinmux_info *gpioc = gpio_controller(gpio); - unsigned long flags; - int value = 0; + struct pinmux_data_reg *dr = NULL; + int bit = 0; - if (!gpioc) + if (!gpioc || get_data_reg(gpioc, gpio, &dr, &bit) != 0) { BUG(); - else { - spin_lock_irqsave(&gpio_lock, flags); - value = __gpio_get_set_value(gpioc, gpio, 0, 0); - spin_unlock_irqrestore(&gpio_lock, flags); + return 0; } - return value; + return gpio_read_reg(dr->reg, dr->reg_width, 1, bit); } -EXPORT_SYMBOL(gpio_get_value); -void gpio_set_value(unsigned gpio, int value) +static int sh_gpio_get(struct gpio_chip *chip, unsigned offset) { - struct pinmux_info *gpioc = gpio_controller(gpio); - unsigned long flags; + return sh_gpio_get_value(chip_to_pinmux(chip), offset); +} - if (!gpioc) - BUG(); - else { - spin_lock_irqsave(&gpio_lock, flags); - __gpio_get_set_value(gpioc, gpio, value, 1); - spin_unlock_irqrestore(&gpio_lock, flags); - } +static void sh_gpio_set(struct gpio_chip *chip, unsigned offset, int value) +{ + sh_gpio_set_value(chip_to_pinmux(chip), offset, value); } -EXPORT_SYMBOL(gpio_set_value); int register_pinmux(struct pinmux_info *pip) { - registered_gpio = pip; - pr_info("pinmux: %s handling gpio %d -> %d\n", + struct gpio_chip *chip = &pip->chip; + + pr_info("sh pinmux: %s handling gpio %d -> %d\n", pip->name, pip->first_gpio, pip->last_gpio); - return 0; + setup_data_regs(pip); + + chip->request = sh_gpio_request; + chip->free = sh_gpio_free; + chip->direction_input = sh_gpio_direction_input; + chip->get = sh_gpio_get; + chip->direction_output = sh_gpio_direction_output; + chip->set = sh_gpio_set; + + WARN_ON(pip->first_gpio != 0); /* needs testing */ + + chip->label = pip->name; + chip->owner = THIS_MODULE; + chip->base = pip->first_gpio; + chip->ngpio = (pip->last_gpio - pip->first_gpio) + 1; + + return gpiochip_add(chip); } diff --git a/arch/sh/kernel/time_32.c b/arch/sh/kernel/time_32.c index 8457f83242c..c34e1e0f9b0 100644 --- a/arch/sh/kernel/time_32.c +++ b/arch/sh/kernel/time_32.c @@ -41,14 +41,6 @@ static int null_rtc_set_time(const time_t secs) return 0; } -/* - * Null high precision timer functions for systems lacking one. - */ -static cycle_t null_hpt_read(void) -{ - return 0; -} - void (*rtc_sh_get_time)(struct timespec *) = null_rtc_get_time; int (*rtc_sh_set_time)(const time_t) = null_rtc_set_time; @@ -112,7 +104,6 @@ int do_settimeofday(struct timespec *tv) EXPORT_SYMBOL(do_settimeofday); #endif /* !CONFIG_GENERIC_TIME */ -#ifndef CONFIG_GENERIC_CLOCKEVENTS /* last time the RTC clock got updated */ static long last_rtc_update; @@ -156,7 +147,6 @@ void handle_timer_tick(void) update_process_times(user_mode(get_irq_regs())); #endif } -#endif /* !CONFIG_GENERIC_CLOCKEVENTS */ #ifdef CONFIG_PM int timer_suspend(struct sys_device *dev, pm_message_t state) @@ -189,7 +179,12 @@ static struct sysdev_class timer_sysclass = { static int __init timer_init_sysfs(void) { - int ret = sysdev_class_register(&timer_sysclass); + int ret; + + if (!sys_timer) + return 0; + + ret = sysdev_class_register(&timer_sysclass); if (ret != 0) return ret; @@ -200,42 +195,21 @@ device_initcall(timer_init_sysfs); void (*board_time_init)(void); -/* - * Shamelessly based on the MIPS and Sparc64 work. - */ -static unsigned long timer_ticks_per_nsec_quotient __read_mostly; -unsigned long sh_hpt_frequency = 0; - -#define NSEC_PER_CYC_SHIFT 10 - -static struct clocksource clocksource_sh = { +struct clocksource clocksource_sh = { .name = "SuperH", - .rating = 200, - .mask = CLOCKSOURCE_MASK(32), - .read = null_hpt_read, - .shift = 16, - .flags = CLOCK_SOURCE_IS_CONTINUOUS, }; -static void __init init_sh_clocksource(void) -{ - if (!sh_hpt_frequency || clocksource_sh.read == null_hpt_read) - return; - - clocksource_sh.mult = clocksource_hz2mult(sh_hpt_frequency, - clocksource_sh.shift); - - timer_ticks_per_nsec_quotient = - clocksource_hz2mult(sh_hpt_frequency, NSEC_PER_CYC_SHIFT); - - clocksource_register(&clocksource_sh); -} - #ifdef CONFIG_GENERIC_TIME unsigned long long sched_clock(void) { - unsigned long long ticks = clocksource_sh.read(); - return (ticks * timer_ticks_per_nsec_quotient) >> NSEC_PER_CYC_SHIFT; + unsigned long long cycles; + + /* jiffies based sched_clock if no clocksource is installed */ + if (!clocksource_sh.rating) + return (unsigned long long)jiffies * (NSEC_PER_SEC / HZ); + + cycles = clocksource_sh.read(); + return cyc2ns(&clocksource_sh, cycles); } #endif @@ -259,17 +233,8 @@ void __init time_init(void) * initialized for us. */ sys_timer = get_sys_timer(); - printk(KERN_INFO "Using %s for system timer\n", sys_timer->name); - - - if (sys_timer->ops->read) - clocksource_sh.read = sys_timer->ops->read; - - init_sh_clocksource(); - - if (sh_hpt_frequency) - printk("Using %lu.%03lu MHz high precision timer.\n", - ((sh_hpt_frequency + 500) / 1000) / 1000, - ((sh_hpt_frequency + 500) / 1000) % 1000); + if (unlikely(!sys_timer)) + panic("System timer missing.\n"); + printk(KERN_INFO "Using %s for system timer\n", sys_timer->name); } diff --git a/arch/sh/kernel/timers/timer-mtu2.c b/arch/sh/kernel/timers/timer-mtu2.c index c3d237e1d56..9a77ae86b40 100644 --- a/arch/sh/kernel/timers/timer-mtu2.c +++ b/arch/sh/kernel/timers/timer-mtu2.c @@ -35,7 +35,8 @@ #define MTU2_TSR_1 0xfffe4385 #define MTU2_TCNT_1 0xfffe4386 /* 16-bit counter */ -#if defined(CONFIG_CPU_SUBTYPE_SH7201) +#if defined(CONFIG_CPU_SUBTYPE_SH7201) || \ + defined(CONFIG_CPU_SUBTYPE_SH7203) #define MTU2_TGRA_1 0xfffe4388 #else #define MTU2_TGRA_1 0xfffe438a diff --git a/arch/sh/kernel/timers/timer-tmu.c b/arch/sh/kernel/timers/timer-tmu.c index 0db3f951033..2b62f9cff22 100644 --- a/arch/sh/kernel/timers/timer-tmu.c +++ b/arch/sh/kernel/timers/timer-tmu.c @@ -146,7 +146,14 @@ static irqreturn_t tmu_timer_interrupt(int irq, void *dummy) _tmu_clear_status(TMU0); _tmu_set_irq(TMU0,tmu0_clockevent.mode != CLOCK_EVT_MODE_ONESHOT); - evt->event_handler(evt); + switch (tmu0_clockevent.mode) { + case CLOCK_EVT_MODE_ONESHOT: + case CLOCK_EVT_MODE_PERIODIC: + evt->event_handler(evt); + break; + default: + break; + } return IRQ_HANDLED; } @@ -254,7 +261,14 @@ static int tmu_timer_init(void) _tmu_start(TMU1); - sh_hpt_frequency = clk_get_rate(&tmu1_clk); + clocksource_sh.rating = 200; + clocksource_sh.mask = CLOCKSOURCE_MASK(32); + clocksource_sh.read = tmu_timer_read; + clocksource_sh.shift = 10; + clocksource_sh.mult = clocksource_hz2mult(clk_get_rate(&tmu1_clk), + clocksource_sh.shift); + clocksource_sh.flags = CLOCK_SOURCE_IS_CONTINUOUS; + clocksource_register(&clocksource_sh); tmu0_clockevent.mult = div_sc(frequency, NSEC_PER_SEC, tmu0_clockevent.shift); @@ -264,6 +278,7 @@ static int tmu_timer_init(void) clockevent_delta2ns(1, &tmu0_clockevent); tmu0_clockevent.cpumask = cpumask_of(0); + tmu0_clockevent.rating = 100; clockevents_register_device(&tmu0_clockevent); @@ -274,7 +289,6 @@ static struct sys_timer_ops tmu_timer_ops = { .init = tmu_timer_init, .start = tmu_timer_start, .stop = tmu_timer_stop, - .read = tmu_timer_read, }; struct sys_timer tmu_timer = { |