From 70f784ec1ddacf8e17da2663f842efac029da796 Mon Sep 17 00:00:00 2001 From: Magnus Damm Date: Thu, 7 Feb 2008 00:38:24 +0900 Subject: sh: migor board support This patch adds basic support for the Migo-R board. Only simple stuff provided by the cpu specific sh7722 code is in place now, like serial console port, timers and usb gadget. There is also partial support for the smc91c111 ethernet controller - unfortunately some driver header file also needs patching (not included here) to make the driver get IRQ sense information from the platform data. Signed-off-by: Magnus Damm Signed-off-by: Paul Mundt --- arch/sh/Kconfig | 7 +++++++ 1 file changed, 7 insertions(+) (limited to 'arch/sh/Kconfig') diff --git a/arch/sh/Kconfig b/arch/sh/Kconfig index d87d4bf8880..8398cf105a0 100644 --- a/arch/sh/Kconfig +++ b/arch/sh/Kconfig @@ -473,6 +473,13 @@ config SH_HIGHLANDER depends on CPU_SUBTYPE_SH7780 || CPU_SUBTYPE_SH7785 select SYS_SUPPORTS_PCI +config SH_MIGOR + bool "Migo-R" + depends on CPU_SUBTYPE_SH7722 + help + Select Migo-R if configuring for the SH7722 Migo-R platform + by Renesas System Solutions Asia Pte. Ltd. + config SH_EDOSK7705 bool "EDOSK7705" depends on CPU_SUBTYPE_SH7705 -- cgit v1.2.3-70-g09d2 From e7cc9a7340b8ec018caa9eb1d035fdaef1f2fc51 Mon Sep 17 00:00:00 2001 From: Magnus Damm Date: Thu, 7 Feb 2008 20:18:21 +0900 Subject: sh: trapped io support V2 The idea is that we want to get rid of the in/out/readb/writeb callbacks from the machvec and replace that with simple inline read and write operations to memory. Fast and simple for most hardware devices (think pci). Some devices require special treatment though - like 16-bit only CF devices - so we need to have some method to hook in callbacks. This patch makes it possible to add a per-device trap generating filter. This way we can get maximum performance of sane hardware - which doesn't need this filter - and crappy hardware works but gets punished by a performance hit. V2 changes things around a bit and replaces io access callbacks with a simple minimum_bus_width value. In the future we can add stride as well. Signed-off-by: Magnus Damm Signed-off-by: Paul Mundt --- arch/sh/Kconfig | 3 + arch/sh/kernel/Makefile_32 | 1 + arch/sh/kernel/Makefile_64 | 1 + arch/sh/kernel/io.c | 8 +- arch/sh/kernel/io_generic.c | 24 ++-- arch/sh/kernel/io_trapped.c | 269 ++++++++++++++++++++++++++++++++++++++++++++ arch/sh/kernel/traps_32.c | 59 ++++++---- arch/sh/mm/fault_32.c | 3 + include/asm-sh/io.h | 10 ++ include/asm-sh/io_trapped.h | 58 ++++++++++ include/asm-sh/system.h | 5 + include/asm-sh/system_32.h | 3 + 12 files changed, 406 insertions(+), 38 deletions(-) create mode 100644 arch/sh/kernel/io_trapped.c create mode 100644 include/asm-sh/io_trapped.h (limited to 'arch/sh/Kconfig') diff --git a/arch/sh/Kconfig b/arch/sh/Kconfig index 8398cf105a0..f61bf17db39 100644 --- a/arch/sh/Kconfig +++ b/arch/sh/Kconfig @@ -93,6 +93,9 @@ config ARCH_NO_VIRT_TO_BUS config ARCH_SUPPORTS_AOUT def_bool y +config IO_TRAPPED + bool + source "init/Kconfig" menu "System type" diff --git a/arch/sh/kernel/Makefile_32 b/arch/sh/kernel/Makefile_32 index c8928983105..62bf373266f 100644 --- a/arch/sh/kernel/Makefile_32 +++ b/arch/sh/kernel/Makefile_32 @@ -22,5 +22,6 @@ obj-$(CONFIG_CRASH_DUMP) += crash_dump.o obj-$(CONFIG_PM) += pm.o obj-$(CONFIG_STACKTRACE) += stacktrace.o obj-$(CONFIG_BINFMT_ELF) += dump_task.o +obj-$(CONFIG_IO_TRAPPED) += io_trapped.o EXTRA_CFLAGS += -Werror diff --git a/arch/sh/kernel/Makefile_64 b/arch/sh/kernel/Makefile_64 index 1ef21cc087f..e01283d49cb 100644 --- a/arch/sh/kernel/Makefile_64 +++ b/arch/sh/kernel/Makefile_64 @@ -18,5 +18,6 @@ obj-$(CONFIG_CRASH_DUMP) += crash_dump.o obj-$(CONFIG_PM) += pm.o obj-$(CONFIG_STACKTRACE) += stacktrace.o obj-$(CONFIG_BINFMT_ELF) += dump_task.o +obj-$(CONFIG_IO_TRAPPED) += io_trapped.o EXTRA_CFLAGS += -Werror diff --git a/arch/sh/kernel/io.c b/arch/sh/kernel/io.c index 71c9fde2fd9..2b899122990 100644 --- a/arch/sh/kernel/io.c +++ b/arch/sh/kernel/io.c @@ -63,7 +63,13 @@ EXPORT_SYMBOL(memset_io); void __iomem *ioport_map(unsigned long port, unsigned int nr) { - return sh_mv.mv_ioport_map(port, nr); + void __iomem *ret; + + ret = __ioport_map_trapped(port, nr); + if (ret) + return ret; + + return __ioport_map(port, nr); } EXPORT_SYMBOL(ioport_map); diff --git a/arch/sh/kernel/io_generic.c b/arch/sh/kernel/io_generic.c index 771ea423044..db769449f5a 100644 --- a/arch/sh/kernel/io_generic.c +++ b/arch/sh/kernel/io_generic.c @@ -33,17 +33,17 @@ static inline void delay(void) u8 generic_inb(unsigned long port) { - return ctrl_inb((unsigned long __force)ioport_map(port, 1)); + return ctrl_inb((unsigned long __force)__ioport_map(port, 1)); } u16 generic_inw(unsigned long port) { - return ctrl_inw((unsigned long __force)ioport_map(port, 2)); + return ctrl_inw((unsigned long __force)__ioport_map(port, 2)); } u32 generic_inl(unsigned long port) { - return ctrl_inl((unsigned long __force)ioport_map(port, 4)); + return ctrl_inl((unsigned long __force)__ioport_map(port, 4)); } u8 generic_inb_p(unsigned long port) @@ -81,7 +81,7 @@ void generic_insb(unsigned long port, void *dst, unsigned long count) volatile u8 *port_addr; u8 *buf = dst; - port_addr = (volatile u8 *)ioport_map(port, 1); + port_addr = (volatile u8 *)__ioport_map(port, 1); while (count--) *buf++ = *port_addr; } @@ -91,7 +91,7 @@ void generic_insw(unsigned long port, void *dst, unsigned long count) volatile u16 *port_addr; u16 *buf = dst; - port_addr = (volatile u16 *)ioport_map(port, 2); + port_addr = (volatile u16 *)__ioport_map(port, 2); while (count--) *buf++ = *port_addr; @@ -103,7 +103,7 @@ void generic_insl(unsigned long port, void *dst, unsigned long count) volatile u32 *port_addr; u32 *buf = dst; - port_addr = (volatile u32 *)ioport_map(port, 4); + port_addr = (volatile u32 *)__ioport_map(port, 4); while (count--) *buf++ = *port_addr; @@ -112,17 +112,17 @@ void generic_insl(unsigned long port, void *dst, unsigned long count) void generic_outb(u8 b, unsigned long port) { - ctrl_outb(b, (unsigned long __force)ioport_map(port, 1)); + ctrl_outb(b, (unsigned long __force)__ioport_map(port, 1)); } void generic_outw(u16 b, unsigned long port) { - ctrl_outw(b, (unsigned long __force)ioport_map(port, 2)); + ctrl_outw(b, (unsigned long __force)__ioport_map(port, 2)); } void generic_outl(u32 b, unsigned long port) { - ctrl_outl(b, (unsigned long __force)ioport_map(port, 4)); + ctrl_outl(b, (unsigned long __force)__ioport_map(port, 4)); } void generic_outb_p(u8 b, unsigned long port) @@ -153,7 +153,7 @@ void generic_outsb(unsigned long port, const void *src, unsigned long count) volatile u8 *port_addr; const u8 *buf = src; - port_addr = (volatile u8 __force *)ioport_map(port, 1); + port_addr = (volatile u8 __force *)__ioport_map(port, 1); while (count--) *port_addr = *buf++; @@ -164,7 +164,7 @@ void generic_outsw(unsigned long port, const void *src, unsigned long count) volatile u16 *port_addr; const u16 *buf = src; - port_addr = (volatile u16 __force *)ioport_map(port, 2); + port_addr = (volatile u16 __force *)__ioport_map(port, 2); while (count--) *port_addr = *buf++; @@ -177,7 +177,7 @@ void generic_outsl(unsigned long port, const void *src, unsigned long count) volatile u32 *port_addr; const u32 *buf = src; - port_addr = (volatile u32 __force *)ioport_map(port, 4); + port_addr = (volatile u32 __force *)__ioport_map(port, 4); while (count--) *port_addr = *buf++; diff --git a/arch/sh/kernel/io_trapped.c b/arch/sh/kernel/io_trapped.c new file mode 100644 index 00000000000..0bfdc9a34e1 --- /dev/null +++ b/arch/sh/kernel/io_trapped.c @@ -0,0 +1,269 @@ +/* + * Trapped io support + * + * Copyright (C) 2008 Magnus Damm + * + * Intercept io operations by trapping. + * + * 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. + */ +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define TRAPPED_PAGES_MAX 16 +#define MAX(a, b) (((a) >= (b)) ? (a) : (b)) + +#ifdef CONFIG_HAS_IOPORT +LIST_HEAD(trapped_io); +#endif +#ifdef CONFIG_HAS_IOMEM +LIST_HEAD(trapped_mem); +#endif +static DEFINE_SPINLOCK(trapped_lock); + +int __init register_trapped_io(struct trapped_io *tiop) +{ + struct resource *res; + unsigned long len = 0, flags = 0; + struct page *pages[TRAPPED_PAGES_MAX]; + int k, n; + + /* structure must be page aligned */ + if ((unsigned long)tiop & (PAGE_SIZE - 1)) + goto bad; + + for (k = 0; k < tiop->num_resources; k++) { + res = tiop->resource + k; + len += roundup((res->end - res->start) + 1, PAGE_SIZE); + flags |= res->flags; + } + + /* support IORESOURCE_IO _or_ MEM, not both */ + if (hweight_long(flags) != 1) + goto bad; + + n = len >> PAGE_SHIFT; + + if (n >= TRAPPED_PAGES_MAX) + goto bad; + + for (k = 0; k < n; k++) + pages[k] = virt_to_page(tiop); + + tiop->virt_base = vmap(pages, n, VM_MAP, PAGE_NONE); + if (!tiop->virt_base) + goto bad; + + len = 0; + for (k = 0; k < tiop->num_resources; k++) { + res = tiop->resource + k; + pr_info("trapped io 0x%08lx overrides %s 0x%08lx\n", + (unsigned long)(tiop->virt_base + len), + res->flags & IORESOURCE_IO ? "io" : "mmio", + (unsigned long)res->start); + len += roundup((res->end - res->start) + 1, PAGE_SIZE); + } + + tiop->magic = IO_TRAPPED_MAGIC; + INIT_LIST_HEAD(&tiop->list); + spin_lock_irq(&trapped_lock); + if (flags & IORESOURCE_IO) + list_add(&tiop->list, &trapped_io); + if (flags & IORESOURCE_MEM) + list_add(&tiop->list, &trapped_mem); + spin_unlock_irq(&trapped_lock); + + return 0; + bad: + pr_warning("unable to install trapped io filter\n"); + return -1; +} + +void __iomem *match_trapped_io_handler(struct list_head *list, + unsigned long offset, + unsigned long size) +{ + unsigned long voffs; + struct trapped_io *tiop; + struct resource *res; + int k, len; + + spin_lock_irq(&trapped_lock); + list_for_each_entry(tiop, list, list) { + voffs = 0; + for (k = 0; k < tiop->num_resources; k++) { + res = tiop->resource + k; + if (res->start == offset) { + spin_unlock_irq(&trapped_lock); + return tiop->virt_base + voffs; + } + + len = (res->end - res->start) + 1; + voffs += roundup(len, PAGE_SIZE); + } + } + spin_unlock_irq(&trapped_lock); + return NULL; +} + +static struct trapped_io *lookup_tiop(unsigned long address) +{ + pgd_t *pgd_k; + pud_t *pud_k; + pmd_t *pmd_k; + pte_t *pte_k; + pte_t entry; + + pgd_k = swapper_pg_dir + pgd_index(address); + if (!pgd_present(*pgd_k)) + return NULL; + + pud_k = pud_offset(pgd_k, address); + if (!pud_present(*pud_k)) + return NULL; + + pmd_k = pmd_offset(pud_k, address); + if (!pmd_present(*pmd_k)) + return NULL; + + pte_k = pte_offset_kernel(pmd_k, address); + entry = *pte_k; + + return pfn_to_kaddr(pte_pfn(entry)); +} + +static unsigned long lookup_address(struct trapped_io *tiop, + unsigned long address) +{ + struct resource *res; + unsigned long vaddr = (unsigned long)tiop->virt_base; + unsigned long len; + int k; + + for (k = 0; k < tiop->num_resources; k++) { + res = tiop->resource + k; + len = roundup((res->end - res->start) + 1, PAGE_SIZE); + if (address < (vaddr + len)) + return res->start + (address - vaddr); + vaddr += len; + } + return 0; +} + +static unsigned long long copy_word(unsigned long src_addr, int src_len, + unsigned long dst_addr, int dst_len) +{ + unsigned long long tmp = 0; + + switch (src_len) { + case 1: + tmp = ctrl_inb(src_addr); + break; + case 2: + tmp = ctrl_inw(src_addr); + break; + case 4: + tmp = ctrl_inl(src_addr); + break; + case 8: + tmp = ctrl_inq(src_addr); + break; + } + + switch (dst_len) { + case 1: + ctrl_outb(tmp, dst_addr); + break; + case 2: + ctrl_outw(tmp, dst_addr); + break; + case 4: + ctrl_outl(tmp, dst_addr); + break; + case 8: + ctrl_outq(tmp, dst_addr); + break; + } + + return tmp; +} + +static unsigned long from_device(void *dst, const void *src, unsigned long cnt) +{ + struct trapped_io *tiop; + unsigned long src_addr = (unsigned long)src; + unsigned long long tmp; + + pr_debug("trapped io read 0x%08lx (%ld)\n", src_addr, cnt); + tiop = lookup_tiop(src_addr); + WARN_ON(!tiop || (tiop->magic != IO_TRAPPED_MAGIC)); + + src_addr = lookup_address(tiop, src_addr); + if (!src_addr) + return cnt; + + tmp = copy_word(src_addr, MAX(cnt, (tiop->minimum_bus_width / 8)), + (unsigned long)dst, cnt); + + pr_debug("trapped io read 0x%08lx -> 0x%08llx\n", src_addr, tmp); + return 0; +} + +static unsigned long to_device(void *dst, const void *src, unsigned long cnt) +{ + struct trapped_io *tiop; + unsigned long dst_addr = (unsigned long)dst; + unsigned long long tmp; + + pr_debug("trapped io write 0x%08lx (%ld)\n", dst_addr, cnt); + tiop = lookup_tiop(dst_addr); + WARN_ON(!tiop || (tiop->magic != IO_TRAPPED_MAGIC)); + + dst_addr = lookup_address(tiop, dst_addr); + if (!dst_addr) + return cnt; + + tmp = copy_word((unsigned long)src, cnt, + dst_addr, MAX(cnt, (tiop->minimum_bus_width / 8))); + + pr_debug("trapped io write 0x%08lx -> 0x%08llx\n", dst_addr, tmp); + return 0; +} + +static struct mem_access trapped_io_access = { + from_device, + to_device, +}; + +int handle_trapped_io(struct pt_regs *regs, unsigned long address) +{ + mm_segment_t oldfs; + opcode_t instruction; + int tmp; + + if (!lookup_tiop(address)) + return 0; + + WARN_ON(user_mode(regs)); + + oldfs = get_fs(); + set_fs(KERNEL_DS); + if (copy_from_user(&instruction, (void *)(regs->pc), + sizeof(instruction))) { + set_fs(oldfs); + return 0; + } + + tmp = handle_unaligned_access(instruction, regs, &trapped_io_access); + set_fs(oldfs); + return tmp == 0; +} diff --git a/arch/sh/kernel/traps_32.c b/arch/sh/kernel/traps_32.c index 25b1b8672cf..baa4fa368dc 100644 --- a/arch/sh/kernel/traps_32.c +++ b/arch/sh/kernel/traps_32.c @@ -172,6 +172,11 @@ static inline void sign_extend(unsigned int count, unsigned char *dst) #endif } +static struct mem_access user_mem_access = { + copy_from_user, + copy_to_user, +}; + /* * handle an instruction that does an unaligned memory access by emulating the * desired behaviour @@ -179,7 +184,8 @@ static inline void sign_extend(unsigned int count, unsigned char *dst) * (if that instruction is in a branch delay slot) * - return 0 if emulation okay, -EFAULT on existential error */ -static int handle_unaligned_ins(opcode_t instruction, struct pt_regs *regs) +static int handle_unaligned_ins(opcode_t instruction, struct pt_regs *regs, + struct mem_access *ma) { int ret, index, count; unsigned long *rm, *rn; @@ -206,7 +212,7 @@ static int handle_unaligned_ins(opcode_t instruction, struct pt_regs *regs) #if !defined(__LITTLE_ENDIAN__) dst += 4-count; #endif - if (copy_from_user(dst, src, count)) + if (ma->from(dst, src, count)) goto fetch_fault; sign_extend(count, dst); @@ -219,7 +225,7 @@ static int handle_unaligned_ins(opcode_t instruction, struct pt_regs *regs) dst = (unsigned char*) *rn; dst += regs->regs[0]; - if (copy_to_user(dst, src, count)) + if (ma->to(dst, src, count)) goto fetch_fault; } ret = 0; @@ -230,7 +236,7 @@ static int handle_unaligned_ins(opcode_t instruction, struct pt_regs *regs) dst = (unsigned char*) *rn; dst += (instruction&0x000F)<<2; - if (copy_to_user(dst,src,4)) + if (ma->to(dst, src, 4)) goto fetch_fault; ret = 0; break; @@ -243,7 +249,7 @@ static int handle_unaligned_ins(opcode_t instruction, struct pt_regs *regs) #if !defined(__LITTLE_ENDIAN__) src += 4-count; #endif - if (copy_to_user(dst, src, count)) + if (ma->to(dst, src, count)) goto fetch_fault; ret = 0; break; @@ -254,7 +260,7 @@ static int handle_unaligned_ins(opcode_t instruction, struct pt_regs *regs) dst = (unsigned char*) rn; *(unsigned long*)dst = 0; - if (copy_from_user(dst,src,4)) + if (ma->from(dst, src, 4)) goto fetch_fault; ret = 0; break; @@ -269,7 +275,7 @@ static int handle_unaligned_ins(opcode_t instruction, struct pt_regs *regs) #if !defined(__LITTLE_ENDIAN__) dst += 4-count; #endif - if (copy_from_user(dst, src, count)) + if (ma->from(dst, src, count)) goto fetch_fault; sign_extend(count, dst); ret = 0; @@ -285,7 +291,7 @@ static int handle_unaligned_ins(opcode_t instruction, struct pt_regs *regs) dst = (unsigned char*) *rm; /* called Rn in the spec */ dst += (instruction&0x000F)<<1; - if (copy_to_user(dst, src, 2)) + if (ma->to(dst, src, 2)) goto fetch_fault; ret = 0; break; @@ -299,7 +305,7 @@ static int handle_unaligned_ins(opcode_t instruction, struct pt_regs *regs) #if !defined(__LITTLE_ENDIAN__) dst += 2; #endif - if (copy_from_user(dst, src, 2)) + if (ma->from(dst, src, 2)) goto fetch_fault; sign_extend(2, dst); ret = 0; @@ -320,8 +326,9 @@ static int handle_unaligned_ins(opcode_t instruction, struct pt_regs *regs) * emulate the instruction in the delay slot * - fetches the instruction from PC+2 */ -static inline int handle_unaligned_delayslot(struct pt_regs *regs, - opcode_t old_instruction) +static inline int handle_delayslot(struct pt_regs *regs, + opcode_t old_instruction, + struct mem_access *ma) { opcode_t instruction; void *addr = (void *)(regs->pc + instruction_size(old_instruction)); @@ -336,7 +343,7 @@ static inline int handle_unaligned_delayslot(struct pt_regs *regs, regs, 0); } - return handle_unaligned_ins(instruction, regs); + return handle_unaligned_ins(instruction, regs, ma); } /* @@ -362,7 +369,8 @@ static inline int handle_unaligned_delayslot(struct pt_regs *regs, static int handle_unaligned_notify_count = 10; -static int handle_unaligned_access(opcode_t instruction, struct pt_regs *regs) +int handle_unaligned_access(opcode_t instruction, struct pt_regs *regs, + struct mem_access *ma) { u_int rm; int ret, index; @@ -385,19 +393,19 @@ static int handle_unaligned_access(opcode_t instruction, struct pt_regs *regs) case 0x0000: if (instruction==0x000B) { /* rts */ - ret = handle_unaligned_delayslot(regs, instruction); + ret = handle_delayslot(regs, instruction, ma); if (ret==0) regs->pc = regs->pr; } else if ((instruction&0x00FF)==0x0023) { /* braf @Rm */ - ret = handle_unaligned_delayslot(regs, instruction); + ret = handle_delayslot(regs, instruction, ma); if (ret==0) regs->pc += rm + 4; } else if ((instruction&0x00FF)==0x0003) { /* bsrf @Rm */ - ret = handle_unaligned_delayslot(regs, instruction); + ret = handle_delayslot(regs, instruction, ma); if (ret==0) { regs->pr = regs->pc + 4; regs->pc += rm + 4; @@ -418,13 +426,13 @@ static int handle_unaligned_access(opcode_t instruction, struct pt_regs *regs) case 0x4000: if ((instruction&0x00FF)==0x002B) { /* jmp @Rm */ - ret = handle_unaligned_delayslot(regs, instruction); + ret = handle_delayslot(regs, instruction, ma); if (ret==0) regs->pc = rm; } else if ((instruction&0x00FF)==0x000B) { /* jsr @Rm */ - ret = handle_unaligned_delayslot(regs, instruction); + ret = handle_delayslot(regs, instruction, ma); if (ret==0) { regs->pr = regs->pc + 4; regs->pc = rm; @@ -451,7 +459,7 @@ static int handle_unaligned_access(opcode_t instruction, struct pt_regs *regs) case 0x0B00: /* bf lab - no delayslot*/ break; case 0x0F00: /* bf/s lab */ - ret = handle_unaligned_delayslot(regs, instruction); + ret = handle_delayslot(regs, instruction, ma); if (ret==0) { #if defined(CONFIG_CPU_SH4) || defined(CONFIG_SH7705_CACHE_32KB) if ((regs->sr & 0x00000001) != 0) @@ -464,7 +472,7 @@ static int handle_unaligned_access(opcode_t instruction, struct pt_regs *regs) case 0x0900: /* bt lab - no delayslot */ break; case 0x0D00: /* bt/s lab */ - ret = handle_unaligned_delayslot(regs, instruction); + ret = handle_delayslot(regs, instruction, ma); if (ret==0) { #if defined(CONFIG_CPU_SH4) || defined(CONFIG_SH7705_CACHE_32KB) if ((regs->sr & 0x00000001) == 0) @@ -478,13 +486,13 @@ static int handle_unaligned_access(opcode_t instruction, struct pt_regs *regs) break; case 0xA000: /* bra label */ - ret = handle_unaligned_delayslot(regs, instruction); + ret = handle_delayslot(regs, instruction, ma); if (ret==0) regs->pc += SH_PC_12BIT_OFFSET(instruction); break; case 0xB000: /* bsr label */ - ret = handle_unaligned_delayslot(regs, instruction); + ret = handle_delayslot(regs, instruction, ma); if (ret==0) { regs->pr = regs->pc + 4; regs->pc += SH_PC_12BIT_OFFSET(instruction); @@ -495,7 +503,7 @@ static int handle_unaligned_access(opcode_t instruction, struct pt_regs *regs) /* handle non-delay-slot instruction */ simple: - ret = handle_unaligned_ins(instruction, regs); + ret = handle_unaligned_ins(instruction, regs, ma); if (ret==0) regs->pc += instruction_size(instruction); return ret; @@ -558,7 +566,8 @@ asmlinkage void do_address_error(struct pt_regs *regs, goto uspace_segv; } - tmp = handle_unaligned_access(instruction, regs); + tmp = handle_unaligned_access(instruction, regs, + &user_mem_access); set_fs(oldfs); if (tmp==0) @@ -587,7 +596,7 @@ uspace_segv: die("insn faulting in do_address_error", regs, 0); } - handle_unaligned_access(instruction, regs); + handle_unaligned_access(instruction, regs, &user_mem_access); set_fs(oldfs); } } diff --git a/arch/sh/mm/fault_32.c b/arch/sh/mm/fault_32.c index 33b43d20e9f..4ef0a1f1a9a 100644 --- a/arch/sh/mm/fault_32.c +++ b/arch/sh/mm/fault_32.c @@ -15,6 +15,7 @@ #include #include #include +#include #include #include #include @@ -163,6 +164,8 @@ no_context: if (fixup_exception(regs)) return; + if (handle_trapped_io(regs, address)) + return; /* * Oops. The kernel tried to access some bad page. We'll have to * terminate things with extreme prejudice. diff --git a/include/asm-sh/io.h b/include/asm-sh/io.h index 94900c08951..3d2b114f9d5 100644 --- a/include/asm-sh/io.h +++ b/include/asm-sh/io.h @@ -38,6 +38,7 @@ */ #define __IO_PREFIX generic #include +#include #define maybebadio(port) \ printk(KERN_ERR "bad PC-like io %s:%u for port 0x%lx at 0x%08x\n", \ @@ -207,6 +208,8 @@ static inline void __set_io_port_base(unsigned long pbase) generic_io_base = pbase; } +#define __ioport_map(p, n) sh_mv.mv_ioport_map((p), (n)) + /* We really want to try and get these to memcpy etc */ extern void memcpy_fromio(void *, volatile void __iomem *, unsigned long); extern void memcpy_toio(volatile void __iomem *, const void *, unsigned long); @@ -309,7 +312,14 @@ __ioremap_mode(unsigned long offset, unsigned long size, unsigned long flags) { #ifdef CONFIG_SUPERH32 unsigned long last_addr = offset + size - 1; +#endif + void __iomem *ret; + ret = __ioremap_trapped(offset, size); + if (ret) + return ret; + +#ifdef CONFIG_SUPERH32 /* * 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/include/asm-sh/io_trapped.h b/include/asm-sh/io_trapped.h new file mode 100644 index 00000000000..f1251d4f0ba --- /dev/null +++ b/include/asm-sh/io_trapped.h @@ -0,0 +1,58 @@ +#ifndef __ASM_SH_IO_TRAPPED_H +#define __ASM_SH_IO_TRAPPED_H + +#include +#include +#include + +#define IO_TRAPPED_MAGIC 0xfeedbeef + +struct trapped_io { + unsigned int magic; + struct resource *resource; + unsigned int num_resources; + unsigned int minimum_bus_width; + struct list_head list; + void __iomem *virt_base; +} __aligned(PAGE_SIZE); + +#ifdef CONFIG_IO_TRAPPED +int register_trapped_io(struct trapped_io *tiop); +int handle_trapped_io(struct pt_regs *regs, unsigned long address); + +void __iomem *match_trapped_io_handler(struct list_head *list, + unsigned long offset, + unsigned long size); + +#ifdef CONFIG_HAS_IOMEM +extern struct list_head trapped_mem; + +static inline void __iomem * +__ioremap_trapped(unsigned long offset, unsigned long size) +{ + return match_trapped_io_handler(&trapped_mem, offset, size); +} +#else +#define __ioremap_trapped(offset, size) NULL +#endif + +#ifdef CONFIG_HAS_IOPORT +extern struct list_head trapped_io; + +static inline void __iomem * +__ioport_map_trapped(unsigned long offset, unsigned long size) +{ + return match_trapped_io_handler(&trapped_io, offset, size); +} +#else +#define __ioport_map_trapped(offset, size) NULL +#endif + +#else +#define register_trapped_io(tiop) (-1) +#define handle_trapped_io(tiop, address) 0 +#define __ioremap_trapped(offset, size) NULL +#define __ioport_map_trapped(offset, size) NULL +#endif + +#endif /* __ASM_SH_IO_TRAPPED_H */ diff --git a/include/asm-sh/system.h b/include/asm-sh/system.h index 772cd1a0a67..5145aa2a0ce 100644 --- a/include/asm-sh/system.h +++ b/include/asm-sh/system.h @@ -182,6 +182,11 @@ BUILD_TRAP_HANDLER(fpu_state_restore); #define arch_align_stack(x) (x) +struct mem_access { + unsigned long (*from)(void *dst, const void *src, unsigned long cnt); + unsigned long (*to)(void *dst, const void *src, unsigned long cnt); +}; + #ifdef CONFIG_SUPERH32 # include "system_32.h" #else diff --git a/include/asm-sh/system_32.h b/include/asm-sh/system_32.h index 7ff08d956ba..f11bcf0855e 100644 --- a/include/asm-sh/system_32.h +++ b/include/asm-sh/system_32.h @@ -96,4 +96,7 @@ do { \ : "=&r" (__dummy)); \ } while (0) +int handle_unaligned_access(opcode_t instruction, struct pt_regs *regs, + struct mem_access *ma); + #endif /* __ASM_SH_SYSTEM_32_H */ -- cgit v1.2.3-70-g09d2 From 2d952b4b8c94ed8576b4221dad9654c5d98275d0 Mon Sep 17 00:00:00 2001 From: Magnus Damm Date: Thu, 7 Feb 2008 20:21:10 +0900 Subject: sh: trapped io support for r2d V2 This patch converts the CF device on r2d boards from machvec readb/writeb to trapped io. Signed-off-by: Magnus Damm Signed-off-by: Paul Mundt --- arch/sh/Kconfig | 1 + arch/sh/boards/renesas/rts7751r2d/setup.c | 45 ++++++++++--------------------- include/asm-sh/rts7751r2d.h | 3 --- 3 files changed, 15 insertions(+), 34 deletions(-) (limited to 'arch/sh/Kconfig') diff --git a/arch/sh/Kconfig b/arch/sh/Kconfig index f61bf17db39..0d288fe8702 100644 --- a/arch/sh/Kconfig +++ b/arch/sh/Kconfig @@ -459,6 +459,7 @@ config SH_RTS7751R2D bool "RTS7751R2D" depends on CPU_SUBTYPE_SH7751R select SYS_SUPPORTS_PCI + select IO_TRAPPED help Select RTS7751R2D if configuring for a Renesas Technology Sales SH-Graphics board. diff --git a/arch/sh/boards/renesas/rts7751r2d/setup.c b/arch/sh/boards/renesas/rts7751r2d/setup.c index a0ef81b7de3..f21ee49ef3a 100644 --- a/arch/sh/boards/renesas/rts7751r2d/setup.c +++ b/arch/sh/boards/renesas/rts7751r2d/setup.c @@ -21,6 +21,7 @@ #include #include #include +#include #include static struct resource cf_ide_resources[] = { @@ -214,13 +215,25 @@ static struct platform_device *rts7751r2d_devices[] __initdata = { &uart_device, &sm501_device, #endif - &cf_ide_device, &heartbeat_device, &spi_sh_sci_device, }; +/* + * The CF is connected with a 16-bit bus where 8-bit operations are + * unsupported. The linux ata driver is however using 8-bit operations, so + * insert a trapped io filter to convert 8-bit operations into 16-bit. + */ +static struct trapped_io cf_trapped_io = { + .resource = cf_ide_resources, + .num_resources = 2, + .minimum_bus_width = 16, +}; + static int __init rts7751r2d_devices_setup(void) { + if (register_trapped_io(&cf_trapped_io) == 0) + platform_device_register(&cf_ide_device); spi_register_board_info(spi_bus, ARRAY_SIZE(spi_bus)); return platform_add_devices(rts7751r2d_devices, ARRAY_SIZE(rts7751r2d_devices)); @@ -232,34 +245,6 @@ static void rts7751r2d_power_off(void) ctrl_outw(0x0001, PA_POWOFF); } -static inline unsigned char is_ide_ioaddr(unsigned long addr) -{ - return ((cf_ide_resources[0].start <= addr && - addr <= cf_ide_resources[0].end) || - (cf_ide_resources[1].start <= addr && - addr <= cf_ide_resources[1].end)); -} - -void rts7751r2d_writeb(u8 b, void __iomem *addr) -{ - unsigned long tmp = (unsigned long __force)addr; - - if (is_ide_ioaddr(tmp)) - ctrl_outw((u16)b, tmp); - else - ctrl_outb(b, tmp); -} - -u8 rts7751r2d_readb(void __iomem *addr) -{ - unsigned long tmp = (unsigned long __force)addr; - - if (is_ide_ioaddr(tmp)) - return ctrl_inw(tmp) & 0xff; - else - return ctrl_inb(tmp); -} - /* * Initialize the board */ @@ -310,6 +295,4 @@ static struct sh_machine_vector mv_rts7751r2d __initmv = { .mv_setup = rts7751r2d_setup, .mv_init_irq = init_rts7751r2d_IRQ, .mv_irq_demux = rts7751r2d_irq_demux, - .mv_writeb = rts7751r2d_writeb, - .mv_readb = rts7751r2d_readb, }; diff --git a/include/asm-sh/rts7751r2d.h b/include/asm-sh/rts7751r2d.h index 83b9c111f17..0a800157b82 100644 --- a/include/asm-sh/rts7751r2d.h +++ b/include/asm-sh/rts7751r2d.h @@ -67,7 +67,4 @@ void init_rts7751r2d_IRQ(void); int rts7751r2d_irq_demux(int); -#define __IO_PREFIX rts7751r2d -#include - #endif /* __ASM_SH_RENESAS_RTS7751R2D */ -- cgit v1.2.3-70-g09d2 From c1a34e4c547a7e6185078bf5e65a3ca0e1081df2 Mon Sep 17 00:00:00 2001 From: Magnus Damm Date: Thu, 7 Feb 2008 20:23:53 +0900 Subject: sh: trapped io support for highlander V2 This patch converts the highlander CF device from good old machvec readb/writeb to the new shiny trapped io. Signed-off-by: Magnus Damm Signed-off-by: Paul Mundt --- arch/sh/Kconfig | 1 + arch/sh/boards/renesas/r7780rp/setup.c | 47 ++++++++++++---------------------- include/asm-sh/r7780rp.h | 3 --- 3 files changed, 17 insertions(+), 34 deletions(-) (limited to 'arch/sh/Kconfig') diff --git a/arch/sh/Kconfig b/arch/sh/Kconfig index 0d288fe8702..3297b87a40d 100644 --- a/arch/sh/Kconfig +++ b/arch/sh/Kconfig @@ -476,6 +476,7 @@ config SH_HIGHLANDER bool "Highlander" depends on CPU_SUBTYPE_SH7780 || CPU_SUBTYPE_SH7785 select SYS_SUPPORTS_PCI + select IO_TRAPPED config SH_MIGOR bool "Migo-R" diff --git a/arch/sh/boards/renesas/r7780rp/setup.c b/arch/sh/boards/renesas/r7780rp/setup.c index f7a8d5c9d51..2f68bea7890 100644 --- a/arch/sh/boards/renesas/r7780rp/setup.c +++ b/arch/sh/boards/renesas/r7780rp/setup.c @@ -23,6 +23,7 @@ #include #include #include +#include static struct resource r8a66597_usb_host_resources[] = { [0] = { @@ -181,13 +182,27 @@ static struct platform_device *r7780rp_devices[] __initdata = { &m66592_usb_peripheral_device, &heartbeat_device, #ifndef CONFIG_SH_R7780RP - &cf_ide_device, &ax88796_device, #endif }; +/* + * The CF is connected using a 16-bit bus where 8-bit operations are + * unsupported. The linux ata driver is however using 8-bit operations, so + * insert a trapped io filter to convert 8-bit operations into 16-bit. + */ +static struct trapped_io cf_trapped_io = { + .resource = cf_ide_resources, + .num_resources = 2, + .minimum_bus_width = 16, +}; + static int __init r7780rp_devices_setup(void) { +#ifndef CONFIG_SH_R7780RP + if (register_trapped_io(&cf_trapped_io) == 0) + platform_device_register(&cf_ide_device); +#endif return platform_add_devices(r7780rp_devices, ARRAY_SIZE(r7780rp_devices)); } @@ -226,34 +241,6 @@ static void r7780rp_power_off(void) ctrl_outw(0x0001, PA_POFF); } -static inline unsigned char is_ide_ioaddr(unsigned long addr) -{ - return ((cf_ide_resources[0].start <= addr && - addr <= cf_ide_resources[0].end) || - (cf_ide_resources[1].start <= addr && - addr <= cf_ide_resources[1].end)); -} - -void highlander_writeb(u8 b, void __iomem *addr) -{ - unsigned long tmp = (unsigned long __force)addr; - - if (is_ide_ioaddr(tmp)) - ctrl_outw((u16)b, tmp); - else - ctrl_outb(b, tmp); -} - -u8 highlander_readb(void __iomem *addr) -{ - unsigned long tmp = (unsigned long __force)addr; - - if (is_ide_ioaddr(tmp)) - return ctrl_inw(tmp) & 0xff; - else - return ctrl_inb(tmp); -} - /* * Initialize the board */ @@ -338,6 +325,4 @@ static struct sh_machine_vector mv_highlander __initmv = { .mv_setup = highlander_setup, .mv_init_irq = highlander_init_irq, .mv_irq_demux = highlander_irq_demux, - .mv_readb = highlander_readb, - .mv_writeb = highlander_writeb, }; diff --git a/include/asm-sh/r7780rp.h b/include/asm-sh/r7780rp.h index bdecea0840a..1770460a461 100644 --- a/include/asm-sh/r7780rp.h +++ b/include/asm-sh/r7780rp.h @@ -195,7 +195,4 @@ unsigned char *highlander_init_irq_r7780mp(void); unsigned char *highlander_init_irq_r7780rp(void); unsigned char *highlander_init_irq_r7785rp(void); -#define __IO_PREFIX r7780rp -#include - #endif /* __ASM_SH_RENESAS_R7780RP */ -- cgit v1.2.3-70-g09d2 From 9109a30e5a548b39463b5a777943cf103da507af Mon Sep 17 00:00:00 2001 From: Magnus Damm Date: Fri, 8 Feb 2008 17:31:24 +0900 Subject: sh: add support for sh7366 processor This patch adds sh7366 cpu supports. Just the most basic things like interrupt controller, clocks and serial port are included at this point. Signed-off-by: Magnus Damm Signed-off-by: Paul Mundt --- arch/sh/Kconfig | 7 ++ arch/sh/Kconfig.debug | 2 +- arch/sh/kernel/cpu/sh4/probe.c | 6 ++ arch/sh/kernel/cpu/sh4a/Makefile | 2 + arch/sh/kernel/cpu/sh4a/clock-sh7722.c | 10 +- arch/sh/kernel/cpu/sh4a/setup-sh7366.c | 177 +++++++++++++++++++++++++++++++++ arch/sh/kernel/setup.c | 2 +- drivers/serial/sh-sci.c | 2 +- drivers/serial/sh-sci.h | 8 +- include/asm-sh/cpu-sh4/freq.h | 4 +- include/asm-sh/processor.h | 2 +- 11 files changed, 215 insertions(+), 7 deletions(-) create mode 100644 arch/sh/kernel/cpu/sh4a/setup-sh7366.c (limited to 'arch/sh/Kconfig') diff --git a/arch/sh/Kconfig b/arch/sh/Kconfig index 3297b87a40d..b3400b5ad5c 100644 --- a/arch/sh/Kconfig +++ b/arch/sh/Kconfig @@ -315,6 +315,13 @@ config CPU_SUBTYPE_SH7722 select ARCH_SPARSEMEM_ENABLE select SYS_SUPPORTS_NUMA +config CPU_SUBTYPE_SH7366 + bool "Support SH7366 processor" + select CPU_SH4AL_DSP + select CPU_SHX2 + select ARCH_SPARSEMEM_ENABLE + select SYS_SUPPORTS_NUMA + # SH-5 Processor Support config CPU_SUBTYPE_SH5_101 diff --git a/arch/sh/Kconfig.debug b/arch/sh/Kconfig.debug index ccfa0b23d36..93722d099e7 100644 --- a/arch/sh/Kconfig.debug +++ b/arch/sh/Kconfig.debug @@ -30,7 +30,7 @@ config EARLY_SCIF_CONSOLE_PORT hex depends on EARLY_SCIF_CONSOLE default "0xffe00000" if CPU_SUBTYPE_SH7780 || CPU_SUBTYPE_SH7763 - default "0xffe00000" if CPU_SUBTYPE_SH7722 + default "0xffe00000" if CPU_SUBTYPE_SH7722 || CPU_SUBTYPE_SH7366 default "0xffea0000" if CPU_SUBTYPE_SH7785 default "0xfffe8000" if CPU_SUBTYPE_SH7203 default "0xfffe9800" if CPU_SUBTYPE_SH7206 || CPU_SUBTYPE_SH7263 diff --git a/arch/sh/kernel/cpu/sh4/probe.c b/arch/sh/kernel/cpu/sh4/probe.c index 89b454b1f0f..9e89984c4f1 100644 --- a/arch/sh/kernel/cpu/sh4/probe.c +++ b/arch/sh/kernel/cpu/sh4/probe.c @@ -132,6 +132,12 @@ int __init detect_cpu_and_cache_system(void) boot_cpu_data.dcache.ways = 4; boot_cpu_data.flags |= CPU_HAS_LLSC; } + else if (prr == 0x70) { + boot_cpu_data.type = CPU_SH7366; + boot_cpu_data.icache.ways = 4; + boot_cpu_data.dcache.ways = 4; + boot_cpu_data.flags |= CPU_HAS_LLSC; + } break; case 0x4000: /* 1st cut */ case 0x4001: /* 2nd cut */ diff --git a/arch/sh/kernel/cpu/sh4a/Makefile b/arch/sh/kernel/cpu/sh4a/Makefile index 08ac6387bf1..5d890ac8e79 100644 --- a/arch/sh/kernel/cpu/sh4a/Makefile +++ b/arch/sh/kernel/cpu/sh4a/Makefile @@ -9,6 +9,7 @@ obj-$(CONFIG_CPU_SUBTYPE_SH7780) += setup-sh7780.o obj-$(CONFIG_CPU_SUBTYPE_SH7785) += setup-sh7785.o obj-$(CONFIG_CPU_SUBTYPE_SH7343) += setup-sh7343.o obj-$(CONFIG_CPU_SUBTYPE_SH7722) += setup-sh7722.o +obj-$(CONFIG_CPU_SUBTYPE_SH7366) += setup-sh7366.o obj-$(CONFIG_CPU_SUBTYPE_SHX3) += setup-shx3.o # SMP setup @@ -21,6 +22,7 @@ clock-$(CONFIG_CPU_SUBTYPE_SH7780) := clock-sh7780.o clock-$(CONFIG_CPU_SUBTYPE_SH7785) := clock-sh7785.o clock-$(CONFIG_CPU_SUBTYPE_SH7343) := clock-sh7343.o clock-$(CONFIG_CPU_SUBTYPE_SH7722) := clock-sh7722.o +clock-$(CONFIG_CPU_SUBTYPE_SH7366) := clock-sh7722.o clock-$(CONFIG_CPU_SUBTYPE_SHX3) := clock-shx3.o obj-y += $(clock-y) diff --git a/arch/sh/kernel/cpu/sh4a/clock-sh7722.c b/arch/sh/kernel/cpu/sh4a/clock-sh7722.c index a0fd8bb21f7..299138ebe16 100644 --- a/arch/sh/kernel/cpu/sh4a/clock-sh7722.c +++ b/arch/sh/kernel/cpu/sh4a/clock-sh7722.c @@ -1,7 +1,7 @@ /* * arch/sh/kernel/cpu/sh4a/clock-sh7722.c * - * SH7722 support for the clock framework + * SH7722 & SH7366 support for the clock framework * * Copyright (c) 2006-2007 Nomad Global Solutions Inc * Based on code for sh7343 by Paul Mundt @@ -417,15 +417,19 @@ static int sh7722_siu_which(struct clk *clk) return 0; if (!strcmp(clk->name, "siu_b_clk")) return 1; +#if defined(CONFIG_CPU_SUBTYPE_SH7722) if (!strcmp(clk->name, "irda_clk")) return 2; +#endif return -EINVAL; } static unsigned long sh7722_siu_regs[] = { [0] = SCLKACR, [1] = SCLKBCR, +#if defined(CONFIG_CPU_SUBTYPE_SH7722) [2] = IrDACLKCR, +#endif }; static int sh7722_siu_start_stop(struct clk *clk, int enable) @@ -571,10 +575,12 @@ static struct clk sh7722_siu_b_clock = { .ops = &sh7722_siu_clk_ops, }; +#if defined(CONFIG_CPU_SUBTYPE_SH7722) static struct clk sh7722_irda_clock = { .name = "irda_clk", .ops = &sh7722_siu_clk_ops, }; +#endif static struct clk sh7722_video_clock = { .name = "video_clk", @@ -588,7 +594,9 @@ static struct clk *sh7722_clocks[] = { &sh7722_sdram_clock, &sh7722_siu_a_clock, &sh7722_siu_b_clock, +#if defined(CONFIG_CPU_SUBTYPE_SH7722) &sh7722_irda_clock, +#endif &sh7722_video_clock, }; diff --git a/arch/sh/kernel/cpu/sh4a/setup-sh7366.c b/arch/sh/kernel/cpu/sh4a/setup-sh7366.c new file mode 100644 index 00000000000..967e8b69a2f --- /dev/null +++ b/arch/sh/kernel/cpu/sh4a/setup-sh7366.c @@ -0,0 +1,177 @@ +/* + * SH7366 Setup + * + * Copyright (C) 2008 Renesas Solutions + * + * Based on linux/arch/sh/kernel/cpu/sh4a/setup-sh7722.c + * + * 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. + */ +#include +#include +#include +#include + +static struct plat_sci_port sci_platform_data[] = { + { + .mapbase = 0xffe00000, + .flags = UPF_BOOT_AUTOCONF, + .type = PORT_SCIF, + .irqs = { 80, 80, 80, 80 }, + }, { + .flags = 0, + } +}; + +static struct platform_device sci_device = { + .name = "sh-sci", + .id = -1, + .dev = { + .platform_data = sci_platform_data, + }, +}; + +static struct platform_device *sh7366_devices[] __initdata = { + &sci_device, +}; + +static int __init sh7366_devices_setup(void) +{ + return platform_add_devices(sh7366_devices, + ARRAY_SIZE(sh7366_devices)); +} +__initcall(sh7366_devices_setup); + +enum { + UNUSED=0, + + /* interrupt sources */ + IRQ0, IRQ1, IRQ2, IRQ3, IRQ4, IRQ5, IRQ6, IRQ7, + ICB, + DMAC0, DMAC1, DMAC2, DMAC3, + VIO_CEUI, VIO_BEUI, VIO_VEUI, VOU, + MFI, VPU, USB, + MMC_MMC1I, MMC_MMC2I, MMC_MMC3I, + DMAC4, DMAC5, DMAC_DADERR, + SCIF, SCIFA1, SCIFA2, + DENC, MSIOF, + FLCTL_FLSTEI, FLCTL_FLENDI, FLCTL_FLTREQ0I, FLCTL_FLTREQ1I, + I2C_ALI, I2C_TACKI, I2C_WAITI, I2C_DTEI, + SDHI0, SDHI1, SDHI2, SDHI3, + CMT, TSIF, SIU, + TMU0, TMU1, TMU2, + VEU2, LCDC, + + /* interrupt groups */ + + DMAC0123, VIOVOU, MMC, DMAC45, FLCTL, I2C, SDHI, +}; + +static struct intc_vect vectors[] __initdata = { + INTC_VECT(IRQ0, 0x600), INTC_VECT(IRQ1, 0x620), + INTC_VECT(IRQ2, 0x640), INTC_VECT(IRQ3, 0x660), + INTC_VECT(IRQ4, 0x680), INTC_VECT(IRQ5, 0x6a0), + INTC_VECT(IRQ6, 0x6c0), INTC_VECT(IRQ7, 0x6e0), + INTC_VECT(ICB, 0x700), + INTC_VECT(DMAC0, 0x800), INTC_VECT(DMAC1, 0x820), + INTC_VECT(DMAC2, 0x840), INTC_VECT(DMAC3, 0x860), + INTC_VECT(VIO_CEUI, 0x880), INTC_VECT(VIO_BEUI, 0x8a0), + INTC_VECT(VIO_VEUI, 0x8c0), INTC_VECT(VOU, 0x8e0), + INTC_VECT(MFI, 0x900), INTC_VECT(VPU, 0x980), INTC_VECT(USB, 0xa20), + INTC_VECT(MMC_MMC1I, 0xb00), INTC_VECT(MMC_MMC2I, 0xb20), + INTC_VECT(MMC_MMC3I, 0xb40), + INTC_VECT(DMAC4, 0xb80), INTC_VECT(DMAC5, 0xba0), + INTC_VECT(DMAC_DADERR, 0xbc0), + INTC_VECT(SCIF, 0xc00), INTC_VECT(SCIFA1, 0xc20), + INTC_VECT(SCIFA2, 0xc40), + INTC_VECT(DENC, 0xc60), INTC_VECT(MSIOF, 0xc80), + INTC_VECT(FLCTL_FLSTEI, 0xd80), INTC_VECT(FLCTL_FLENDI, 0xda0), + INTC_VECT(FLCTL_FLTREQ0I, 0xdc0), INTC_VECT(FLCTL_FLTREQ1I, 0xde0), + INTC_VECT(I2C_ALI, 0xe00), INTC_VECT(I2C_TACKI, 0xe20), + INTC_VECT(I2C_WAITI, 0xe40), INTC_VECT(I2C_DTEI, 0xe60), + INTC_VECT(SDHI0, 0xe80), INTC_VECT(SDHI1, 0xea0), + INTC_VECT(SDHI2, 0xec0), INTC_VECT(SDHI3, 0xee0), + INTC_VECT(CMT, 0xf00), INTC_VECT(TSIF, 0xf20), + INTC_VECT(SIU, 0xf80), + INTC_VECT(TMU0, 0x400), INTC_VECT(TMU1, 0x420), + INTC_VECT(TMU2, 0x440), + INTC_VECT(VEU2, 0x580), INTC_VECT(LCDC, 0x580), +}; + +static struct intc_group groups[] __initdata = { + INTC_GROUP(DMAC0123, DMAC0, DMAC1, DMAC2, DMAC3), + INTC_GROUP(VIOVOU, VIO_CEUI, VIO_BEUI, VIO_VEUI, VOU), + INTC_GROUP(MMC, MMC_MMC1I, MMC_MMC2I, MMC_MMC3I), + INTC_GROUP(DMAC45, DMAC4, DMAC5, DMAC_DADERR), + INTC_GROUP(FLCTL, FLCTL_FLSTEI, FLCTL_FLENDI, + FLCTL_FLTREQ0I, FLCTL_FLTREQ1I), + INTC_GROUP(I2C, I2C_ALI, I2C_TACKI, I2C_WAITI, I2C_DTEI), + INTC_GROUP(SDHI, SDHI0, SDHI1, SDHI2, SDHI3), +}; + +static struct intc_mask_reg mask_registers[] __initdata = { + { 0xa4080080, 0xa40800c0, 8, /* IMR0 / IMCR0 */ + { } }, + { 0xa4080084, 0xa40800c4, 8, /* IMR1 / IMCR1 */ + { VOU, VIO_VEUI, VIO_BEUI, VIO_CEUI, DMAC3, DMAC2, DMAC1, DMAC0 } }, + { 0xa4080088, 0xa40800c8, 8, /* IMR2 / IMCR2 */ + { 0, 0, 0, VPU, 0, 0, 0, MFI } }, + { 0xa408008c, 0xa40800cc, 8, /* IMR3 / IMCR3 */ + { 0, 0, 0, ICB } }, + { 0xa4080090, 0xa40800d0, 8, /* IMR4 / IMCR4 */ + { 0, TMU2, TMU1, TMU0, VEU2, 0, 0, LCDC } }, + { 0xa4080094, 0xa40800d4, 8, /* IMR5 / IMCR5 */ + { 0, DMAC_DADERR, DMAC5, DMAC4, DENC, SCIFA2, SCIFA1, SCIF } }, + { 0xa4080098, 0xa40800d8, 8, /* IMR6 / IMCR6 */ + { 0, 0, 0, 0, 0, 0, 0, MSIOF } }, + { 0xa408009c, 0xa40800dc, 8, /* IMR7 / IMCR7 */ + { I2C_DTEI, I2C_WAITI, I2C_TACKI, I2C_ALI, + FLCTL_FLTREQ1I, FLCTL_FLTREQ0I, FLCTL_FLENDI, FLCTL_FLSTEI } }, + { 0xa40800a0, 0xa40800e0, 8, /* IMR8 / IMCR8 */ + { SDHI3, SDHI2, SDHI1, SDHI0, 0, 0, 0, SIU } }, + { 0xa40800a4, 0xa40800e4, 8, /* IMR9 / IMCR9 */ + { 0, 0, 0, CMT, 0, USB, } }, + { 0xa40800a8, 0xa40800e8, 8, /* IMR10 / IMCR10 */ + { 0, MMC_MMC3I, MMC_MMC2I, MMC_MMC1I } }, + { 0xa40800ac, 0xa40800ec, 8, /* IMR11 / IMCR11 */ + { 0, 0, 0, 0, 0, 0, 0, TSIF } }, + { 0xa4140044, 0xa4140064, 8, /* INTMSK00 / INTMSKCLR00 */ + { IRQ0, IRQ1, IRQ2, IRQ3, IRQ4, IRQ5, IRQ6, IRQ7 } }, +}; + +static struct intc_prio_reg prio_registers[] __initdata = { + { 0xa4080000, 0, 16, 4, /* IPRA */ { TMU0, TMU1, TMU2 } }, + { 0xa4080004, 0, 16, 4, /* IPRB */ { VEU2, LCDC, ICB } }, + { 0xa4080008, 0, 16, 4, /* IPRC */ { } }, + { 0xa408000c, 0, 16, 4, /* IPRD */ { } }, + { 0xa4080010, 0, 16, 4, /* IPRE */ { DMAC0123, VIOVOU, MFI, VPU } }, + { 0xa4080014, 0, 16, 4, /* IPRF */ { 0, DMAC45, USB, CMT } }, + { 0xa4080018, 0, 16, 4, /* IPRG */ { SCIF, SCIFA1, SCIFA2, DENC } }, + { 0xa408001c, 0, 16, 4, /* IPRH */ { MSIOF, 0, FLCTL, I2C } }, + { 0xa4080020, 0, 16, 4, /* IPRI */ { 0, 0, TSIF, } }, + { 0xa4080024, 0, 16, 4, /* IPRJ */ { 0, 0, SIU } }, + { 0xa4080028, 0, 16, 4, /* IPRK */ { 0, MMC, 0, SDHI } }, + { 0xa408002c, 0, 16, 4, /* IPRL */ { } }, + { 0xa4140010, 0, 32, 4, /* INTPRI00 */ + { IRQ0, IRQ1, IRQ2, IRQ3, IRQ4, IRQ5, IRQ6, IRQ7 } }, +}; + +static struct intc_sense_reg sense_registers[] __initdata = { + { 0xa414001c, 16, 2, /* ICR1 */ + { IRQ0, IRQ1, IRQ2, IRQ3, IRQ4, IRQ5, IRQ6, IRQ7 } }, +}; + +static DECLARE_INTC_DESC(intc_desc, "sh7366", vectors, groups, + mask_registers, prio_registers, sense_registers); + +void __init plat_irq_setup(void) +{ + register_intc_controller(&intc_desc); +} + +void __init plat_mem_setup(void) +{ + /* TODO: Register Node 1 */ +} diff --git a/arch/sh/kernel/setup.c b/arch/sh/kernel/setup.c index 18a5baf2cba..ff4f54a47c0 100644 --- a/arch/sh/kernel/setup.c +++ b/arch/sh/kernel/setup.c @@ -333,7 +333,7 @@ static const char *cpu_name[] = { [CPU_SH7343] = "SH7343", [CPU_SH7785] = "SH7785", [CPU_SH7722] = "SH7722", [CPU_SHX3] = "SH-X3", [CPU_SH5_101] = "SH5-101", [CPU_SH5_103] = "SH5-103", - [CPU_SH_NONE] = "Unknown" + [CPU_SH7366] = "SH7366", [CPU_SH_NONE] = "Unknown" }; const char *get_cpu_subtype(struct sh_cpuinfo *c) diff --git a/drivers/serial/sh-sci.c b/drivers/serial/sh-sci.c index ddf63914453..9ce12cb2ceb 100644 --- a/drivers/serial/sh-sci.c +++ b/drivers/serial/sh-sci.c @@ -393,7 +393,7 @@ static void sci_init_pins_scif(struct uart_port *port, unsigned int cflag) if (cflag & CRTSCTS) { fcr_val |= SCFCR_MCE; } else { -#ifdef CONFIG_CPU_SUBTYPE_SH7343 +#if defined(CONFIG_CPU_SUBTYPE_SH7343) || defined(CONFIG_CPU_SUBTYPE_SH7366) /* Nothing */ #elif defined(CONFIG_CPU_SUBTYPE_SH7763) || \ defined(CONFIG_CPU_SUBTYPE_SH7780) || \ diff --git a/drivers/serial/sh-sci.h b/drivers/serial/sh-sci.h index f5764ebcfe0..57aaa09811e 100644 --- a/drivers/serial/sh-sci.h +++ b/drivers/serial/sh-sci.h @@ -97,6 +97,12 @@ # define SCSCR_INIT(port) 0x0038 /* TIE=0,RIE=0,TE=1,RE=1,REIE=1 */ # define SCIF_ONLY # define PORT_PSCR 0xA405011E +#elif defined(CONFIG_CPU_SUBTYPE_SH7366) +# define SCPDR0 0xA405013E /* 16 bit SCIF0 PSDR */ +# define SCSPTR0 SCPDR0 +# define SCIF_ORER 0x0001 /* overrun error bit */ +# define SCSCR_INIT(port) 0x0038 /* TIE=0,RIE=0,TE=1,RE=1,REIE=1 */ +# define SCIF_ONLY #elif defined(CONFIG_CPU_SUBTYPE_SH4_202) # define SCSPTR2 0xffe80020 /* 16 bit SCIF */ # define SCIF_ORER 0x0001 /* overrun error bit */ @@ -577,7 +583,7 @@ static inline int sci_rxd_in(struct uart_port *port) return ctrl_inw(SCSPTR3) & 0x0001 ? 1 : 0; /* SCIF */ return 1; } -#elif defined(CONFIG_CPU_SUBTYPE_SH7722) +#elif defined(CONFIG_CPU_SUBTYPE_SH7722) || defined(CONFIG_CPU_SUBTYPE_SH7366) static inline int sci_rxd_in(struct uart_port *port) { if (port->mapbase == 0xffe00000) diff --git a/include/asm-sh/cpu-sh4/freq.h b/include/asm-sh/cpu-sh4/freq.h index 1ac10b9a078..ec028c64921 100644 --- a/include/asm-sh/cpu-sh4/freq.h +++ b/include/asm-sh/cpu-sh4/freq.h @@ -10,12 +10,14 @@ #ifndef __ASM_CPU_SH4_FREQ_H #define __ASM_CPU_SH4_FREQ_H -#if defined(CONFIG_CPU_SUBTYPE_SH7722) +#if defined(CONFIG_CPU_SUBTYPE_SH7722) || defined(CONFIG_CPU_SUBTYPE_SH7366) #define FRQCR 0xa4150000 #define VCLKCR 0xa4150004 #define SCLKACR 0xa4150008 #define SCLKBCR 0xa415000c +#if defined(CONFIG_CPU_SUBTYPE_SH7722) #define IrDACLKCR 0xa4150010 +#endif #elif defined(CONFIG_CPU_SUBTYPE_SH7763) || \ defined(CONFIG_CPU_SUBTYPE_SH7780) #define FRQCR 0xffc80000 diff --git a/include/asm-sh/processor.h b/include/asm-sh/processor.h index c9b14161f73..19fe47c1ca1 100644 --- a/include/asm-sh/processor.h +++ b/include/asm-sh/processor.h @@ -33,7 +33,7 @@ enum cpu_type { CPU_SH7763, CPU_SH7770, CPU_SH7780, CPU_SH7781, CPU_SH7785, CPU_SHX3, /* SH4AL-DSP types */ - CPU_SH7343, CPU_SH7722, + CPU_SH7343, CPU_SH7722, CPU_SH7366, /* SH-5 types */ CPU_SH5_101, CPU_SH5_103, -- cgit v1.2.3-70-g09d2