From a0ab36689a36e583b6e736f1c99ac8c9aebdad59 Mon Sep 17 00:00:00 2001 From: Paul Mundt Date: Wed, 13 Jan 2010 18:31:48 +0900 Subject: sh: fixed PMB mode refactoring. This introduces some much overdue chainsawing of the fixed PMB support. fixed PMB was introduced initially to work around the fact that dynamic PMB mode was relatively broken, though they were never intended to converge. The main areas where there are differences are whether the system is booted in 29-bit mode or 32-bit mode, and whether legacy mappings are to be preserved. Any system booting in true 32-bit mode will not care about legacy mappings, so these are roughly decoupled. Regardless of the entry point, PMB and 32BIT are directly related as far as the kernel is concerned, so we also switch back to having one select the other. With legacy mappings iterated through and applied in the initialization path it's now possible to finally merge the two implementations and permit dynamic remapping overtop of remaining entries regardless of whether boot mappings are crafted by hand or inherited from the boot loader. Signed-off-by: Paul Mundt --- arch/sh/include/asm/io.h | 27 ++++++++++++++++++--------- 1 file changed, 18 insertions(+), 9 deletions(-) (limited to 'arch/sh/include/asm/io.h') diff --git a/arch/sh/include/asm/io.h b/arch/sh/include/asm/io.h index 026dd659a640..f4314d8b05b8 100644 --- a/arch/sh/include/asm/io.h +++ b/arch/sh/include/asm/io.h @@ -244,18 +244,11 @@ __ioremap(unsigned long offset, unsigned long size, unsigned long flags) } static inline void __iomem * -__ioremap_mode(unsigned long offset, unsigned long size, unsigned long flags) +__ioremap_29bit(unsigned long offset, unsigned long size, unsigned long flags) { -#if defined(CONFIG_SUPERH32) && !defined(CONFIG_PMB_FIXED) && !defined(CONFIG_PMB) +#ifdef CONFIG_29BIT unsigned long last_addr = offset + size - 1; -#endif - void __iomem *ret; - ret = __ioremap_trapped(offset, size); - if (ret) - return ret; - -#if defined(CONFIG_SUPERH32) && !defined(CONFIG_PMB_FIXED) && !defined(CONFIG_PMB) /* * For P1 and P2 space this is trivial, as everything is already * mapped. Uncached access for P1 addresses are done through P2. @@ -274,6 +267,22 @@ __ioremap_mode(unsigned long offset, unsigned long size, unsigned long flags) return (void __iomem *)P4SEGADDR(offset); #endif + return NULL; +} + +static inline void __iomem * +__ioremap_mode(unsigned long offset, unsigned long size, unsigned long flags) +{ + void __iomem *ret; + + ret = __ioremap_trapped(offset, size); + if (ret) + return ret; + + ret = __ioremap_29bit(offset, size, flags); + if (ret) + return ret; + return __ioremap(offset, size, flags); } #else -- cgit v1.2.3 From 4d35b93a66e9b87df20784fcf130d2e8760be53f Mon Sep 17 00:00:00 2001 From: Matt Fleming Date: Thu, 5 Nov 2009 07:54:17 +0000 Subject: sh: Add fixed ioremap support Some devices need to be ioremap'd and accessed very early in the boot process. It is not possible to use the standard ioremap() function in this case because that requires kmalloc()'ing some virtual address space and kmalloc() may not be available so early in boot. This patch provides fixmap mappings that allow physical address ranges to be remapped into the kernel address space during the early boot stages. Signed-off-by: Matt Fleming --- arch/sh/include/asm/fixmap.h | 8 +++ arch/sh/include/asm/io.h | 6 ++ arch/sh/kernel/setup.c | 7 ++- arch/sh/mm/Kconfig | 4 ++ arch/sh/mm/Makefile | 1 + arch/sh/mm/ioremap_fixed.c | 144 +++++++++++++++++++++++++++++++++++++++++++ 6 files changed, 167 insertions(+), 3 deletions(-) create mode 100644 arch/sh/mm/ioremap_fixed.c (limited to 'arch/sh/include/asm/io.h') diff --git a/arch/sh/include/asm/fixmap.h b/arch/sh/include/asm/fixmap.h index 1566d3361ca4..38a1de866873 100644 --- a/arch/sh/include/asm/fixmap.h +++ b/arch/sh/include/asm/fixmap.h @@ -60,6 +60,14 @@ enum fixed_addresses { FIX_KMAP_BEGIN, /* reserved pte's for temporary kernel mappings */ FIX_KMAP_END = FIX_KMAP_BEGIN+(KM_TYPE_NR*NR_CPUS)-1, #endif + /* + * FIX_IOREMAP entries are useful for mapping physical address + * space before ioremap() is useable, e.g. really early in boot + * before kmalloc() is working. + */ +#define FIX_N_IOREMAPS 32 + FIX_IOREMAP_BEGIN, + FIX_IOREMAP_END = FIX_IOREMAP_BEGIN + FIX_N_IOREMAPS, __end_of_fixed_addresses }; diff --git a/arch/sh/include/asm/io.h b/arch/sh/include/asm/io.h index f4314d8b05b8..bee5965e0a82 100644 --- a/arch/sh/include/asm/io.h +++ b/arch/sh/include/asm/io.h @@ -237,6 +237,12 @@ void __iomem *__ioremap_caller(unsigned long offset, unsigned long size, unsigned long flags, void *caller); void __iounmap(void __iomem *addr); +#ifdef CONFIG_IOREMAP_FIXED +extern void __iomem *ioremap_fixed(resource_size_t, unsigned long, pgprot_t); +extern void iounmap_fixed(void __iomem *); +extern void ioremap_fixed_init(void); +#endif + static inline void __iomem * __ioremap(unsigned long offset, unsigned long size, unsigned long flags) { diff --git a/arch/sh/kernel/setup.c b/arch/sh/kernel/setup.c index f79ebe32a24a..e187750dd319 100644 --- a/arch/sh/kernel/setup.c +++ b/arch/sh/kernel/setup.c @@ -449,14 +449,15 @@ void __init setup_arch(char **cmdline_p) #ifdef CONFIG_DUMMY_CONSOLE conswitchp = &dummy_con; #endif + paging_init(); + pmb_init(); + + ioremap_fixed_init(); /* Perform the machine specific initialisation */ if (likely(sh_mv.mv_setup)) sh_mv.mv_setup(cmdline_p); - paging_init(); - pmb_init(); - #ifdef CONFIG_SMP plat_smp_setup(); #endif diff --git a/arch/sh/mm/Kconfig b/arch/sh/mm/Kconfig index 7a4ebc8cbadd..b89075256b70 100644 --- a/arch/sh/mm/Kconfig +++ b/arch/sh/mm/Kconfig @@ -169,6 +169,10 @@ config ARCH_MEMORY_PROBE def_bool y depends on MEMORY_HOTPLUG +config IOREMAP_FIXED + def_bool y + depends on X2TLB || SUPERH64 + choice prompt "Kernel page size" default PAGE_SIZE_4KB diff --git a/arch/sh/mm/Makefile b/arch/sh/mm/Makefile index edde8bdd681d..89ba56c20ade 100644 --- a/arch/sh/mm/Makefile +++ b/arch/sh/mm/Makefile @@ -35,6 +35,7 @@ endif obj-$(CONFIG_HUGETLB_PAGE) += hugetlbpage.o obj-$(CONFIG_PMB) += pmb.o obj-$(CONFIG_NUMA) += numa.o +obj-$(CONFIG_IOREMAP_FIXED) += ioremap_fixed.o # Special flags for fault_64.o. This puts restrictions on the number of # caller-save registers that the compiler can target when building this file. diff --git a/arch/sh/mm/ioremap_fixed.c b/arch/sh/mm/ioremap_fixed.c new file mode 100644 index 000000000000..3a9d3d88fe8d --- /dev/null +++ b/arch/sh/mm/ioremap_fixed.c @@ -0,0 +1,144 @@ +/* + * Re-map IO memory to kernel address space so that we can access it. + * + * These functions should only be used when it is necessary to map a + * physical address space into the kernel address space before ioremap() + * can be used, e.g. early in boot before paging_init(). + * + * Copyright (C) 2009 Matt Fleming + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +struct ioremap_map { + void __iomem *addr; + unsigned long size; + unsigned long fixmap_addr; +}; + +static struct ioremap_map ioremap_maps[FIX_N_IOREMAPS]; + +void __init ioremap_fixed_init(void) +{ + struct ioremap_map *map; + int i; + + for (i = 0; i < FIX_N_IOREMAPS; i++) { + map = &ioremap_maps[i]; + map->fixmap_addr = __fix_to_virt(FIX_IOREMAP_BEGIN + i); + } +} + +void __init __iomem * +ioremap_fixed(resource_size_t phys_addr, unsigned long size, pgprot_t prot) +{ + enum fixed_addresses idx0, idx; + resource_size_t last_addr; + struct ioremap_map *map; + unsigned long offset; + unsigned int nrpages; + int i, slot; + + slot = -1; + for (i = 0; i < FIX_N_IOREMAPS; i++) { + map = &ioremap_maps[i]; + if (!map->addr) { + map->size = size; + slot = i; + break; + } + } + + if (slot < 0) + return NULL; + + /* Don't allow wraparound or zero size */ + last_addr = phys_addr + size - 1; + if (!size || last_addr < phys_addr) + return NULL; + + /* + * Fixmap mappings have to be page-aligned + */ + offset = phys_addr & ~PAGE_MASK; + phys_addr &= PAGE_MASK; + size = PAGE_ALIGN(last_addr + 1) - phys_addr; + + /* + * Mappings have to fit in the FIX_IOREMAP area. + */ + nrpages = size >> PAGE_SHIFT; + if (nrpages > FIX_N_IOREMAPS) + return NULL; + + /* + * Ok, go for it.. + */ + idx0 = FIX_IOREMAP_BEGIN + slot; + idx = idx0; + while (nrpages > 0) { + pgprot_val(prot) |= _PAGE_WIRED; + __set_fixmap(idx, phys_addr, prot); + phys_addr += PAGE_SIZE; + idx++; + --nrpages; + } + + map->addr = (void __iomem *)(offset + map->fixmap_addr); + return map->addr; +} + +void __init iounmap_fixed(void __iomem *addr) +{ + enum fixed_addresses idx; + unsigned long virt_addr; + struct ioremap_map *map; + unsigned long offset; + unsigned int nrpages; + int i, slot; + pgprot_t prot; + + slot = -1; + for (i = 0; i < FIX_N_IOREMAPS; i++) { + map = &ioremap_maps[i]; + if (map->addr == addr) { + slot = i; + break; + } + } + + if (slot < 0) + return; + + virt_addr = (unsigned long)addr; + + offset = virt_addr & ~PAGE_MASK; + nrpages = PAGE_ALIGN(offset + map->size - 1) >> PAGE_SHIFT; + + pgprot_val(prot) = _PAGE_WIRED; + + idx = FIX_IOREMAP_BEGIN + slot + nrpages; + while (nrpages > 0) { + __clear_fixmap(idx, prot); + --idx; + --nrpages; + } + + map->size = 0; + map->addr = NULL; +} -- cgit v1.2.3 From edf711b66f2a8a9629aa253ad8b3a5a03b5d7af5 Mon Sep 17 00:00:00 2001 From: Paul Mundt Date: Mon, 18 Jan 2010 21:20:13 +0900 Subject: sh: Fixup the IOREMAP_FIXED=n build. Presently the fixed ioremap API is only defined when CONFIG_IOREMAP_FIXED is set. As we want to call in to it unconditionally, provide a stubbed out interface. Signed-off-by: Paul Mundt --- arch/sh/include/asm/io.h | 9 +++++++++ 1 file changed, 9 insertions(+) (limited to 'arch/sh/include/asm/io.h') diff --git a/arch/sh/include/asm/io.h b/arch/sh/include/asm/io.h index bee5965e0a82..9aa9438c66c3 100644 --- a/arch/sh/include/asm/io.h +++ b/arch/sh/include/asm/io.h @@ -241,6 +241,15 @@ void __iounmap(void __iomem *addr); extern void __iomem *ioremap_fixed(resource_size_t, unsigned long, pgprot_t); extern void iounmap_fixed(void __iomem *); extern void ioremap_fixed_init(void); +#else +static inline void __iomem * +ioremap_fixed(resource_size t phys_addr, unsigned long size, pgprot_t prot) +{ + BUG(); +} + +static inline void ioremap_fixed_init(void) { } +static inline void iounmap_fixed(void __iomem *addr) { } #endif static inline void __iomem * -- cgit v1.2.3 From 4f744affc345f8b158615e0cdd01d1f4985837c3 Mon Sep 17 00:00:00 2001 From: Paul Mundt Date: Mon, 18 Jan 2010 21:30:29 +0900 Subject: sh: Make iounmap_fixed() return success/failure for iounmap() path. This converts iounmap_fixed() to return success/error if it handled the unmap request or not. At the same time, drop the __init label, as this can be called in to later. Signed-off-by: Paul Mundt --- arch/sh/include/asm/io.h | 5 +++-- arch/sh/mm/ioremap_fixed.c | 9 +++++++-- 2 files changed, 10 insertions(+), 4 deletions(-) (limited to 'arch/sh/include/asm/io.h') diff --git a/arch/sh/include/asm/io.h b/arch/sh/include/asm/io.h index 9aa9438c66c3..6a0dd8c1e0a9 100644 --- a/arch/sh/include/asm/io.h +++ b/arch/sh/include/asm/io.h @@ -22,6 +22,7 @@ * for old compat code for I/O offseting to SuperIOs, all of which are * better handled through the machvec ioport mapping routines these days. */ +#include #include #include #include @@ -239,7 +240,7 @@ void __iounmap(void __iomem *addr); #ifdef CONFIG_IOREMAP_FIXED extern void __iomem *ioremap_fixed(resource_size_t, unsigned long, pgprot_t); -extern void iounmap_fixed(void __iomem *); +extern int iounmap_fixed(void __iomem *); extern void ioremap_fixed_init(void); #else static inline void __iomem * @@ -249,7 +250,7 @@ ioremap_fixed(resource_size t phys_addr, unsigned long size, pgprot_t prot) } static inline void ioremap_fixed_init(void) { } -static inline void iounmap_fixed(void __iomem *addr) { } +static inline int iounmap_fixed(void __iomem *addr) { return -EINVAL; } #endif static inline void __iomem * diff --git a/arch/sh/mm/ioremap_fixed.c b/arch/sh/mm/ioremap_fixed.c index 3a9d3d88fe8d..425f6c6bf250 100644 --- a/arch/sh/mm/ioremap_fixed.c +++ b/arch/sh/mm/ioremap_fixed.c @@ -103,7 +103,7 @@ ioremap_fixed(resource_size_t phys_addr, unsigned long size, pgprot_t prot) return map->addr; } -void __init iounmap_fixed(void __iomem *addr) +int iounmap_fixed(void __iomem *addr) { enum fixed_addresses idx; unsigned long virt_addr; @@ -122,8 +122,11 @@ void __init iounmap_fixed(void __iomem *addr) } } + /* + * If we don't match, it's not for us. + */ if (slot < 0) - return; + return -EINVAL; virt_addr = (unsigned long)addr; @@ -141,4 +144,6 @@ void __init iounmap_fixed(void __iomem *addr) map->size = 0; map->addr = NULL; + + return 0; } -- cgit v1.2.3 From d57d64080ddc0ff13fcffc898b6251074a482ba1 Mon Sep 17 00:00:00 2001 From: Paul Mundt Date: Tue, 19 Jan 2010 13:34:38 +0900 Subject: sh: Prevent 64-bit pgprot clobbering across ioremap implementations. Presently 'flags' gets passed around a lot between the various ioremap helpers and implementations, which is only 32-bits. In the X2TLB case we use 64-bit pgprots which presently results in the upper 32bits being chopped off (which handily include our read/write/exec permissions). As such, we convert everything internally to using pgprot_t directly and simply convert over with pgprot_val() where needed. With this in place, transparent fixmap utilization for early ioremap works as expected. Signed-off-by: Paul Mundt --- arch/sh/boards/board-sh7785lcr.c | 6 ++--- arch/sh/boards/mach-landisk/setup.c | 2 +- arch/sh/boards/mach-lboxre2/setup.c | 2 +- arch/sh/boards/mach-sh03/setup.c | 2 +- arch/sh/include/asm/io.h | 53 ++++++++++++++++++++++--------------- arch/sh/mm/ioremap.c | 9 +++---- 6 files changed, 41 insertions(+), 33 deletions(-) (limited to 'arch/sh/include/asm/io.h') diff --git a/arch/sh/boards/board-sh7785lcr.c b/arch/sh/boards/board-sh7785lcr.c index 511de38d2046..fe7e686c94ac 100644 --- a/arch/sh/boards/board-sh7785lcr.c +++ b/arch/sh/boards/board-sh7785lcr.c @@ -21,6 +21,7 @@ #include #include #include +#include #include #include #include @@ -332,15 +333,14 @@ static void __init sh7785lcr_setup(char **cmdline_p) pm_power_off = sh7785lcr_power_off; /* sm501 DRAM configuration */ - sm501_reg = ioremap_fixed(SM107_REG_ADDR, SM501_DRAM_CONTROL, - PAGE_KERNEL); + sm501_reg = ioremap_nocache(SM107_REG_ADDR, SM501_DRAM_CONTROL); if (!sm501_reg) { printk(KERN_ERR "%s: ioremap error.\n", __func__); return; } writel(0x000307c2, sm501_reg + SM501_DRAM_CONTROL); - iounmap_fixed(sm501_reg); + iounmap(sm501_reg); } /* Return the board specific boot mode pin configuration */ diff --git a/arch/sh/boards/mach-landisk/setup.c b/arch/sh/boards/mach-landisk/setup.c index db22ea2e6d49..59816355d199 100644 --- a/arch/sh/boards/mach-landisk/setup.c +++ b/arch/sh/boards/mach-landisk/setup.c @@ -63,7 +63,7 @@ static int __init landisk_devices_setup(void) /* open I/O area window */ paddrbase = virt_to_phys((void *)PA_AREA5_IO); prot = PAGE_KERNEL_PCC(1, _PAGE_PCC_IO16); - cf_ide_base = p3_ioremap(paddrbase, PAGE_SIZE, prot.pgprot); + cf_ide_base = p3_ioremap(paddrbase, PAGE_SIZE, prot); if (!cf_ide_base) { printk("allocate_cf_area : can't open CF I/O window!\n"); return -ENOMEM; diff --git a/arch/sh/boards/mach-lboxre2/setup.c b/arch/sh/boards/mach-lboxre2/setup.c index 2b0b5818e1e4..408dd5df7d45 100644 --- a/arch/sh/boards/mach-lboxre2/setup.c +++ b/arch/sh/boards/mach-lboxre2/setup.c @@ -57,7 +57,7 @@ static int __init lboxre2_devices_setup(void) paddrbase = virt_to_phys((void*)PA_AREA5_IO); psize = PAGE_SIZE; prot = PAGE_KERNEL_PCC( 1 , _PAGE_PCC_IO16); - cf0_io_base = (u32)p3_ioremap(paddrbase, psize, prot.pgprot); + cf0_io_base = (u32)p3_ioremap(paddrbase, psize, prot); if (!cf0_io_base) { printk(KERN_ERR "%s : can't open CF I/O window!\n" , __func__ ); return -ENOMEM; diff --git a/arch/sh/boards/mach-sh03/setup.c b/arch/sh/boards/mach-sh03/setup.c index 74cfb4b8b03d..f14ba0fa950b 100644 --- a/arch/sh/boards/mach-sh03/setup.c +++ b/arch/sh/boards/mach-sh03/setup.c @@ -82,7 +82,7 @@ static int __init sh03_devices_setup(void) /* open I/O area window */ paddrbase = virt_to_phys((void *)PA_AREA5_IO); prot = PAGE_KERNEL_PCC(1, _PAGE_PCC_IO16); - cf_ide_base = p3_ioremap(paddrbase, PAGE_SIZE, prot.pgprot); + cf_ide_base = p3_ioremap(paddrbase, PAGE_SIZE, prot); if (!cf_ide_base) { printk("allocate_cf_area : can't open CF I/O window!\n"); return -ENOMEM; diff --git a/arch/sh/include/asm/io.h b/arch/sh/include/asm/io.h index 6a0dd8c1e0a9..13696dfccc16 100644 --- a/arch/sh/include/asm/io.h +++ b/arch/sh/include/asm/io.h @@ -235,7 +235,7 @@ unsigned long long poke_real_address_q(unsigned long long addr, */ #ifdef CONFIG_MMU void __iomem *__ioremap_caller(unsigned long offset, unsigned long size, - unsigned long flags, void *caller); + pgprot_t prot, void *caller); void __iounmap(void __iomem *addr); #ifdef CONFIG_IOREMAP_FIXED @@ -254,13 +254,13 @@ static inline int iounmap_fixed(void __iomem *addr) { return -EINVAL; } #endif static inline void __iomem * -__ioremap(unsigned long offset, unsigned long size, unsigned long flags) +__ioremap(unsigned long offset, unsigned long size, pgprot_t prot) { - return __ioremap_caller(offset, size, flags, __builtin_return_address(0)); + return __ioremap_caller(offset, size, prot, __builtin_return_address(0)); } static inline void __iomem * -__ioremap_29bit(unsigned long offset, unsigned long size, unsigned long flags) +__ioremap_29bit(unsigned long offset, unsigned long size, pgprot_t prot) { #ifdef CONFIG_29BIT unsigned long last_addr = offset + size - 1; @@ -272,7 +272,7 @@ __ioremap_29bit(unsigned long offset, unsigned long size, unsigned long flags) * mapping must be done by the PMB or by using page tables. */ if (likely(PXSEG(offset) < P3SEG && PXSEG(last_addr) < P3SEG)) { - if (unlikely(flags & _PAGE_CACHABLE)) + if (unlikely(pgprot_val(prot) & _PAGE_CACHABLE)) return (void __iomem *)P1SEGADDR(offset); return (void __iomem *)P2SEGADDR(offset); @@ -287,7 +287,7 @@ __ioremap_29bit(unsigned long offset, unsigned long size, unsigned long flags) } static inline void __iomem * -__ioremap_mode(unsigned long offset, unsigned long size, unsigned long flags) +__ioremap_mode(unsigned long offset, unsigned long size, pgprot_t prot) { void __iomem *ret; @@ -295,30 +295,39 @@ __ioremap_mode(unsigned long offset, unsigned long size, unsigned long flags) if (ret) return ret; - ret = __ioremap_29bit(offset, size, flags); + ret = __ioremap_29bit(offset, size, prot); if (ret) return ret; - return __ioremap(offset, size, flags); + return __ioremap(offset, size, prot); } #else -#define __ioremap(offset, size, flags) ((void __iomem *)(offset)) -#define __ioremap_mode(offset, size, flags) ((void __iomem *)(offset)) +#define __ioremap(offset, size, prot) ((void __iomem *)(offset)) +#define __ioremap_mode(offset, size, prot) ((void __iomem *)(offset)) #define __iounmap(addr) do { } while (0) #endif /* CONFIG_MMU */ -#define ioremap(offset, size) \ - __ioremap_mode((offset), (size), 0) -#define ioremap_nocache(offset, size) \ - __ioremap_mode((offset), (size), 0) -#define ioremap_cache(offset, size) \ - __ioremap_mode((offset), (size), _PAGE_CACHABLE) -#define p3_ioremap(offset, size, flags) \ - __ioremap((offset), (size), (flags)) -#define ioremap_prot(offset, size, flags) \ - __ioremap_mode((offset), (size), (flags)) -#define iounmap(addr) \ - __iounmap((addr)) +static inline void __iomem * +ioremap(unsigned long offset, unsigned long size) +{ + return __ioremap_mode(offset, size, PAGE_KERNEL_NOCACHE); +} + +static inline void __iomem * +ioremap_cache(unsigned long offset, unsigned long size) +{ + return __ioremap_mode(offset, size, PAGE_KERNEL); +} + +static inline void __iomem * +ioremap_prot(resource_size_t offset, unsigned long size, unsigned long flags) +{ + return __ioremap_mode(offset, size, __pgprot(flags)); +} + +#define ioremap_nocache ioremap +#define p3_ioremap __ioremap +#define iounmap __iounmap #define maybebadio(port) \ printk(KERN_ERR "bad PC-like io %s:%u for port 0x%lx at 0x%08x\n", \ diff --git a/arch/sh/mm/ioremap.c b/arch/sh/mm/ioremap.c index a130b2278e92..85b420d00622 100644 --- a/arch/sh/mm/ioremap.c +++ b/arch/sh/mm/ioremap.c @@ -35,11 +35,10 @@ */ void __iomem * __init_refok __ioremap_caller(unsigned long phys_addr, unsigned long size, - unsigned long flags, void *caller) + pgprot_t pgprot, void *caller) { struct vm_struct *area; unsigned long offset, last_addr, addr, orig_addr; - pgprot_t pgprot; /* Don't allow wraparound or zero size */ last_addr = phys_addr + size - 1; @@ -69,7 +68,7 @@ __ioremap_caller(unsigned long phys_addr, unsigned long size, * If we can't yet use the regular approach, go the fixmap route. */ if (!mem_init_done) - return ioremap_fixed(phys_addr, size, __pgprot(flags)); + return ioremap_fixed(phys_addr, size, pgprot); /* * Ok, go for it.. @@ -91,8 +90,9 @@ __ioremap_caller(unsigned long phys_addr, unsigned long size, * PMB entries are all pre-faulted. */ if (unlikely(phys_addr >= P1SEG)) { - unsigned long mapped = pmb_remap(addr, phys_addr, size, flags); + unsigned long mapped; + mapped = pmb_remap(addr, phys_addr, size, pgprot_val(pgprot)); if (likely(mapped)) { addr += mapped; phys_addr += mapped; @@ -101,7 +101,6 @@ __ioremap_caller(unsigned long phys_addr, unsigned long size, } #endif - pgprot = __pgprot(pgprot_val(PAGE_KERNEL_NOCACHE) | flags); if (likely(size)) if (ioremap_page_range(addr, addr + size, phys_addr, pgprot)) { vunmap((void *)orig_addr); -- cgit v1.2.3 From acf2c9685fb8295cb62a623d7358a1cfde8b07ea Mon Sep 17 00:00:00 2001 From: Paul Mundt Date: Tue, 19 Jan 2010 13:49:19 +0900 Subject: sh: Kill off duplicate address alignment in ioremap_fixed(). This is already taken care of in the top-level ioremap, and now that no one should be calling ioremap_fixed() directly we can simply throw the mapping displacement in as an additional argument. Signed-off-by: Paul Mundt --- arch/sh/include/asm/io.h | 6 ++++-- arch/sh/mm/ioremap.c | 2 +- arch/sh/mm/ioremap_fixed.c | 22 +++------------------- 3 files changed, 8 insertions(+), 22 deletions(-) (limited to 'arch/sh/include/asm/io.h') diff --git a/arch/sh/include/asm/io.h b/arch/sh/include/asm/io.h index 13696dfccc16..70269813cef1 100644 --- a/arch/sh/include/asm/io.h +++ b/arch/sh/include/asm/io.h @@ -239,12 +239,14 @@ void __iomem *__ioremap_caller(unsigned long offset, unsigned long size, void __iounmap(void __iomem *addr); #ifdef CONFIG_IOREMAP_FIXED -extern void __iomem *ioremap_fixed(resource_size_t, unsigned long, pgprot_t); +extern void __iomem *ioremap_fixed(resource_size_t, unsigned long, + unsigned long, pgprot_t); extern int iounmap_fixed(void __iomem *); extern void ioremap_fixed_init(void); #else static inline void __iomem * -ioremap_fixed(resource_size t phys_addr, unsigned long size, pgprot_t prot) +ioremap_fixed(resource_size t phys_addr, unsigned long offset, + unsigned long size, pgprot_t prot) { BUG(); } diff --git a/arch/sh/mm/ioremap.c b/arch/sh/mm/ioremap.c index 85b420d00622..bb03308e8408 100644 --- a/arch/sh/mm/ioremap.c +++ b/arch/sh/mm/ioremap.c @@ -68,7 +68,7 @@ __ioremap_caller(unsigned long phys_addr, unsigned long size, * If we can't yet use the regular approach, go the fixmap route. */ if (!mem_init_done) - return ioremap_fixed(phys_addr, size, pgprot); + return ioremap_fixed(phys_addr, offset, size, pgprot); /* * Ok, go for it.. diff --git a/arch/sh/mm/ioremap_fixed.c b/arch/sh/mm/ioremap_fixed.c index 425f6c6bf250..551b513e8fce 100644 --- a/arch/sh/mm/ioremap_fixed.c +++ b/arch/sh/mm/ioremap_fixed.c @@ -45,12 +45,11 @@ void __init ioremap_fixed_init(void) } void __init __iomem * -ioremap_fixed(resource_size_t phys_addr, unsigned long size, pgprot_t prot) +ioremap_fixed(resource_size_t phys_addr, unsigned long offset, + unsigned long size, pgprot_t prot) { enum fixed_addresses idx0, idx; - resource_size_t last_addr; struct ioremap_map *map; - unsigned long offset; unsigned int nrpages; int i, slot; @@ -67,18 +66,6 @@ ioremap_fixed(resource_size_t phys_addr, unsigned long size, pgprot_t prot) if (slot < 0) return NULL; - /* Don't allow wraparound or zero size */ - last_addr = phys_addr + size - 1; - if (!size || last_addr < phys_addr) - return NULL; - - /* - * Fixmap mappings have to be page-aligned - */ - offset = phys_addr & ~PAGE_MASK; - phys_addr &= PAGE_MASK; - size = PAGE_ALIGN(last_addr + 1) - phys_addr; - /* * Mappings have to fit in the FIX_IOREMAP area. */ @@ -111,7 +98,6 @@ int iounmap_fixed(void __iomem *addr) unsigned long offset; unsigned int nrpages; int i, slot; - pgprot_t prot; slot = -1; for (i = 0; i < FIX_N_IOREMAPS; i++) { @@ -133,11 +119,9 @@ int iounmap_fixed(void __iomem *addr) offset = virt_addr & ~PAGE_MASK; nrpages = PAGE_ALIGN(offset + map->size - 1) >> PAGE_SHIFT; - pgprot_val(prot) = _PAGE_WIRED; - idx = FIX_IOREMAP_BEGIN + slot + nrpages; while (nrpages > 0) { - __clear_fixmap(idx, prot); + __clear_fixmap(idx, __pgprot(_PAGE_WIRED)); --idx; --nrpages; } -- cgit v1.2.3 From f33609344acfdde1c1acedf6de3efe6b80af93a6 Mon Sep 17 00:00:00 2001 From: Paul Mundt Date: Tue, 19 Jan 2010 13:55:41 +0900 Subject: sh: Convert p3_ioremap() users to ioremap_prot(). This kills off the ancient p3_ioremap(), converting over to the more generic ioremap_prot() instead. Signed-off-by: Paul Mundt --- arch/sh/boards/mach-landisk/setup.c | 2 +- arch/sh/boards/mach-lboxre2/setup.c | 4 ++-- arch/sh/boards/mach-sh03/setup.c | 2 +- arch/sh/include/asm/io.h | 1 - 4 files changed, 4 insertions(+), 5 deletions(-) (limited to 'arch/sh/include/asm/io.h') diff --git a/arch/sh/boards/mach-landisk/setup.c b/arch/sh/boards/mach-landisk/setup.c index 59816355d199..2d09d4d34f87 100644 --- a/arch/sh/boards/mach-landisk/setup.c +++ b/arch/sh/boards/mach-landisk/setup.c @@ -63,7 +63,7 @@ static int __init landisk_devices_setup(void) /* open I/O area window */ paddrbase = virt_to_phys((void *)PA_AREA5_IO); prot = PAGE_KERNEL_PCC(1, _PAGE_PCC_IO16); - cf_ide_base = p3_ioremap(paddrbase, PAGE_SIZE, prot); + cf_ide_base = ioremap_prot(paddrbase, PAGE_SIZE, pgprot_val(prot)); if (!cf_ide_base) { printk("allocate_cf_area : can't open CF I/O window!\n"); return -ENOMEM; diff --git a/arch/sh/boards/mach-lboxre2/setup.c b/arch/sh/boards/mach-lboxre2/setup.c index 408dd5df7d45..79b4e0d77b71 100644 --- a/arch/sh/boards/mach-lboxre2/setup.c +++ b/arch/sh/boards/mach-lboxre2/setup.c @@ -56,8 +56,8 @@ static int __init lboxre2_devices_setup(void) /* open I/O area window */ paddrbase = virt_to_phys((void*)PA_AREA5_IO); psize = PAGE_SIZE; - prot = PAGE_KERNEL_PCC( 1 , _PAGE_PCC_IO16); - cf0_io_base = (u32)p3_ioremap(paddrbase, psize, prot); + prot = PAGE_KERNEL_PCC(1, _PAGE_PCC_IO16); + cf0_io_base = (u32)ioremap_prot(paddrbase, psize, pgprot_val(prot)); if (!cf0_io_base) { printk(KERN_ERR "%s : can't open CF I/O window!\n" , __func__ ); return -ENOMEM; diff --git a/arch/sh/boards/mach-sh03/setup.c b/arch/sh/boards/mach-sh03/setup.c index f14ba0fa950b..af4a0c012a96 100644 --- a/arch/sh/boards/mach-sh03/setup.c +++ b/arch/sh/boards/mach-sh03/setup.c @@ -82,7 +82,7 @@ static int __init sh03_devices_setup(void) /* open I/O area window */ paddrbase = virt_to_phys((void *)PA_AREA5_IO); prot = PAGE_KERNEL_PCC(1, _PAGE_PCC_IO16); - cf_ide_base = p3_ioremap(paddrbase, PAGE_SIZE, prot); + cf_ide_base = ioremap_prot(paddrbase, PAGE_SIZE, pgprot_val(prot)); if (!cf_ide_base) { printk("allocate_cf_area : can't open CF I/O window!\n"); return -ENOMEM; diff --git a/arch/sh/include/asm/io.h b/arch/sh/include/asm/io.h index 70269813cef1..c32a55601d01 100644 --- a/arch/sh/include/asm/io.h +++ b/arch/sh/include/asm/io.h @@ -328,7 +328,6 @@ ioremap_prot(resource_size_t offset, unsigned long size, unsigned long flags) } #define ioremap_nocache ioremap -#define p3_ioremap __ioremap #define iounmap __iounmap #define maybebadio(port) \ -- cgit v1.2.3 From 6d63e73d520b690e4378cef3003eb5f01f7d128c Mon Sep 17 00:00:00 2001 From: Paul Mundt Date: Tue, 19 Jan 2010 14:00:14 +0900 Subject: sh: Limit ioremap_prot() to 32bit pgprot parts. Presently ioremap_prot() uses an unsigned long to pass the pgprot value around. This results in the upper half of the pgprot being chomped when using 64-bit pgprots on a 32-bit ABI (X2TLB and SH-5). As the only users of ioremap_prot() are presently legacy parts, this doesn't cause too much of an issue. In the future when the interface is converted to use pgprot_t directly this can be re-enabled for the other parts, too. Signed-off-by: Paul Mundt --- arch/sh/Kconfig | 2 +- arch/sh/include/asm/io.h | 2 ++ 2 files changed, 3 insertions(+), 1 deletion(-) (limited to 'arch/sh/include/asm/io.h') diff --git a/arch/sh/Kconfig b/arch/sh/Kconfig index 5ac0115c9e20..8d0eabbf7460 100644 --- a/arch/sh/Kconfig +++ b/arch/sh/Kconfig @@ -13,7 +13,6 @@ config SUPERH select HAVE_LMB select HAVE_OPROFILE select HAVE_GENERIC_DMA_COHERENT - select HAVE_IOREMAP_PROT if MMU select HAVE_ARCH_TRACEHOOK select HAVE_DMA_API_DEBUG select HAVE_DMA_ATTRS @@ -36,6 +35,7 @@ config SUPERH32 def_bool ARCH = "sh" select HAVE_KPROBES select HAVE_KRETPROBES + select HAVE_IOREMAP_PROT if MMU && !X2TLB select HAVE_FUNCTION_TRACER select HAVE_FTRACE_MCOUNT_RECORD select HAVE_DYNAMIC_FTRACE diff --git a/arch/sh/include/asm/io.h b/arch/sh/include/asm/io.h index c32a55601d01..4bad72a1b39e 100644 --- a/arch/sh/include/asm/io.h +++ b/arch/sh/include/asm/io.h @@ -321,11 +321,13 @@ ioremap_cache(unsigned long offset, unsigned long size) return __ioremap_mode(offset, size, PAGE_KERNEL); } +#ifdef CONFIG_HAVE_IOREMAP_PROT static inline void __iomem * ioremap_prot(resource_size_t offset, unsigned long size, unsigned long flags) { return __ioremap_mode(offset, size, __pgprot(flags)); } +#endif #define ioremap_nocache ioremap #define iounmap __iounmap -- cgit v1.2.3 From 70911b861bfbba1851cbb3497635030f34703c7a Mon Sep 17 00:00:00 2001 From: Paul Mundt Date: Wed, 20 Jan 2010 02:45:05 +0900 Subject: sh: Shut up noisy IOREMAP_FIXED=n build. The ioremap_fixed() stub neglected to provide a return value, resulting in a fairly noisy build. Signed-off-by: Paul Mundt --- arch/sh/include/asm/io.h | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'arch/sh/include/asm/io.h') diff --git a/arch/sh/include/asm/io.h b/arch/sh/include/asm/io.h index 4bad72a1b39e..e4f563f472eb 100644 --- a/arch/sh/include/asm/io.h +++ b/arch/sh/include/asm/io.h @@ -245,10 +245,11 @@ extern int iounmap_fixed(void __iomem *); extern void ioremap_fixed_init(void); #else static inline void __iomem * -ioremap_fixed(resource_size t phys_addr, unsigned long offset, +ioremap_fixed(resource_size_t phys_addr, unsigned long offset, unsigned long size, pgprot_t prot) { BUG(); + return NULL; } static inline void ioremap_fixed_init(void) { } -- cgit v1.2.3 From 485773f3e401fca31c112c1ff24797e42ff87afd Mon Sep 17 00:00:00 2001 From: Paul Mundt Date: Tue, 26 Jan 2010 13:02:10 +0900 Subject: sh: flag ctrl_in/outX as __deprecated. These routines are unsuitable for cross-platform use and no new code should be using them, flag them as deprecated in order to give drivers sufficient time to migrate over. Signed-off-by: Paul Mundt --- arch/sh/include/asm/io.h | 55 +++++++++++++++++++++++++++++++++++++++--------- 1 file changed, 45 insertions(+), 10 deletions(-) (limited to 'arch/sh/include/asm/io.h') diff --git a/arch/sh/include/asm/io.h b/arch/sh/include/asm/io.h index e4f563f472eb..98c62fa168c2 100644 --- a/arch/sh/include/asm/io.h +++ b/arch/sh/include/asm/io.h @@ -80,16 +80,51 @@ #define writel(v,a) ({ __raw_writel((v),(a)); mb(); }) #define writeq(v,a) ({ __raw_writeq((v),(a)); mb(); }) -/* SuperH on-chip I/O functions */ -#define ctrl_inb __raw_readb -#define ctrl_inw __raw_readw -#define ctrl_inl __raw_readl -#define ctrl_inq __raw_readq - -#define ctrl_outb __raw_writeb -#define ctrl_outw __raw_writew -#define ctrl_outl __raw_writel -#define ctrl_outq __raw_writeq +/* + * Legacy SuperH on-chip I/O functions + * + * These are all deprecated, all new (and especially cross-platform) code + * should be using the __raw_xxx() routines directly. + */ +static inline u8 __deprecated ctrl_inb(unsigned long addr) +{ + return __raw_readb(addr); +} + +static inline u16 __deprecated ctrl_inw(unsigned long addr) +{ + return __raw_readw(addr); +} + +static inline u32 __deprecated ctrl_inl(unsigned long addr) +{ + return __raw_readl(addr); +} + +static inline u64 __deprecated ctrl_inq(unsigned long addr) +{ + return __raw_readq(addr); +} + +static inline void __deprecated ctrl_outb(u8 v, unsigned long addr) +{ + __raw_writeb(v, addr); +} + +static inline void __deprecated ctrl_outw(u16 v, unsigned long addr) +{ + __raw_writew(v, addr); +} + +static inline void __deprecated ctrl_outl(u32 v, unsigned long addr) +{ + __raw_writel(v, addr); +} + +static inline void __deprecated ctrl_outq(u64 v, unsigned long addr) +{ + __raw_writeq(v, addr); +} extern unsigned long generic_io_base; -- cgit v1.2.3 From d627a2ebd1a303aa4ac1962c553d1e8738735d01 Mon Sep 17 00:00:00 2001 From: Paul Mundt Date: Thu, 28 Jan 2010 18:17:29 +0900 Subject: sh: Fix up the ioremap_fixed() build for nommu. arch/sh/kernel/setup.c:455: error: implicit declaration of function 'ioremap_fixed_init' Signed-off-by: Paul Mundt --- arch/sh/include/asm/io.h | 36 ++++++++++++++++++------------------ 1 file changed, 18 insertions(+), 18 deletions(-) (limited to 'arch/sh/include/asm/io.h') diff --git a/arch/sh/include/asm/io.h b/arch/sh/include/asm/io.h index 98c62fa168c2..bd5fafa23eb4 100644 --- a/arch/sh/include/asm/io.h +++ b/arch/sh/include/asm/io.h @@ -273,24 +273,6 @@ void __iomem *__ioremap_caller(unsigned long offset, unsigned long size, pgprot_t prot, void *caller); void __iounmap(void __iomem *addr); -#ifdef CONFIG_IOREMAP_FIXED -extern void __iomem *ioremap_fixed(resource_size_t, unsigned long, - unsigned long, pgprot_t); -extern int iounmap_fixed(void __iomem *); -extern void ioremap_fixed_init(void); -#else -static inline void __iomem * -ioremap_fixed(resource_size_t phys_addr, unsigned long offset, - unsigned long size, pgprot_t prot) -{ - BUG(); - return NULL; -} - -static inline void ioremap_fixed_init(void) { } -static inline int iounmap_fixed(void __iomem *addr) { return -EINVAL; } -#endif - static inline void __iomem * __ioremap(unsigned long offset, unsigned long size, pgprot_t prot) { @@ -365,6 +347,24 @@ ioremap_prot(resource_size_t offset, unsigned long size, unsigned long flags) } #endif +#ifdef CONFIG_IOREMAP_FIXED +extern void __iomem *ioremap_fixed(resource_size_t, unsigned long, + unsigned long, pgprot_t); +extern int iounmap_fixed(void __iomem *); +extern void ioremap_fixed_init(void); +#else +static inline void __iomem * +ioremap_fixed(resource_size_t phys_addr, unsigned long offset, + unsigned long size, pgprot_t prot) +{ + BUG(); + return NULL; +} + +static inline void ioremap_fixed_init(void) { } +static inline int iounmap_fixed(void __iomem *addr) { return -EINVAL; } +#endif + #define ioremap_nocache ioremap #define iounmap __iounmap -- cgit v1.2.3 From b8f7918f332873a79e4c820e90e7a245ce4d3042 Mon Sep 17 00:00:00 2001 From: Paul Mundt Date: Thu, 18 Feb 2010 13:23:30 +0900 Subject: sh: Provide uncached I/O helpers. There are lots of registers that can only be updated from the uncached mapping, so we add some helpers for those cases in order to make it easier to ensure that we only make the jump when it's absolutely necessary. Signed-off-by: Paul Mundt --- arch/sh/include/asm/io.h | 22 ++++++++++++++++++++++ 1 file changed, 22 insertions(+) (limited to 'arch/sh/include/asm/io.h') diff --git a/arch/sh/include/asm/io.h b/arch/sh/include/asm/io.h index bd5fafa23eb4..7dab7b23a5ec 100644 --- a/arch/sh/include/asm/io.h +++ b/arch/sh/include/asm/io.h @@ -133,6 +133,28 @@ static inline void ctrl_delay(void) __raw_readw(generic_io_base); } +#define __BUILD_UNCACHED_IO(bwlq, type) \ +static inline type read##bwlq##_uncached(unsigned long addr) \ +{ \ + type ret; \ + jump_to_uncached(); \ + ret = __raw_read##bwlq(addr); \ + back_to_cached(); \ + return ret; \ +} \ + \ +static inline void write##bwlq##_uncached(type v, unsigned long addr) \ +{ \ + jump_to_uncached(); \ + __raw_write##bwlq(v, addr); \ + back_to_cached(); \ +} + +__BUILD_UNCACHED_IO(b, u8) +__BUILD_UNCACHED_IO(w, u16) +__BUILD_UNCACHED_IO(l, u32) +__BUILD_UNCACHED_IO(q, u64) + #define __BUILD_MEMORY_STRING(bwlq, type) \ \ static inline void __raw_writes##bwlq(volatile void __iomem *mem, \ -- cgit v1.2.3