sh: P4 ioremap pass-through
authorMagnus Damm <damm@igel.co.jp>
Tue, 25 Nov 2008 12:57:29 +0000 (21:57 +0900)
committerPaul Mundt <lethal@linux-sh.org>
Mon, 22 Dec 2008 09:43:48 +0000 (18:43 +0900)
This patch adds a pass-through case when ioremapping P4 addresses.

Addresses passed to ioremap() should be physical addresses, so the
best option is usually to convert the virtual address to a physical
address before calling ioremap. This will give you a virtual address
in P2 which matches the physical address and this works well for
most internal hardware blocks on the SuperH architecture.

However, some hardware blocks must be accessed through P4. Converting
the P4 address to a physical and then back to a P2 does not work. One
example of this is the sh7722 TMU block, it must be accessed through P4.

Without this patch P4 addresses will be mapped using PTEs which
requires the page allocator to be up and running.

Signed-off-by: Magnus Damm <damm@igel.co.jp>
Signed-off-by: Paul Mundt <lethal@linux-sh.org>
arch/sh/include/asm/addrspace.h
arch/sh/include/asm/io.h
arch/sh/mm/fault_32.c
arch/sh/mm/ioremap_32.c

index 2702d81bfc0db77048cdf1670304e20ed08c39f2..36736c7e93dbd7a7621b9874047e7957294e4397 100644 (file)
 /* Check if an address can be reached in 29 bits */
 #define IS_29BIT(a)    (((unsigned long)(a)) < 0x20000000)
 
+#ifdef CONFIG_SH_STORE_QUEUES
+/*
+ * This is a special case for the SH-4 store queues, as pages for this
+ * space still need to be faulted in before it's possible to flush the
+ * store queue cache for writeout to the remapped region.
+ */
+#define P3_ADDR_MAX            (P4SEG_STORE_QUE + 0x04000000)
+#else
+#define P3_ADDR_MAX            P4SEG
+#endif
+
 #endif /* __KERNEL__ */
 #endif /* __ASM_SH_ADDRSPACE_H */
index 65eaae34e753035209455a1916dc68cc4e7b22d6..61f6dae40534831195c12972091f859ad2d14214 100644 (file)
@@ -260,6 +260,10 @@ __ioremap_mode(unsigned long offset, unsigned long size, unsigned long flags)
 
                return (void __iomem *)P2SEGADDR(offset);
        }
+
+       /* P4 above the store queues are always mapped. */
+       if (unlikely(offset >= P3_ADDR_MAX))
+               return (void __iomem *)P4SEGADDR(offset);
 #endif
 
        return __ioremap(offset, size, flags);
index 898d477e47c171e6930832d950d85f0a3bd9a617..e58726892b5ff5b57c358e075a35d49fa821b8ce 100644 (file)
@@ -265,17 +265,6 @@ static inline int notify_page_fault(struct pt_regs *regs, int trap)
        return ret;
 }
 
-#ifdef CONFIG_SH_STORE_QUEUES
-/*
- * This is a special case for the SH-4 store queues, as pages for this
- * space still need to be faulted in before it's possible to flush the
- * store queue cache for writeout to the remapped region.
- */
-#define P3_ADDR_MAX            (P4SEG_STORE_QUE + 0x04000000)
-#else
-#define P3_ADDR_MAX            P4SEG
-#endif
-
 /*
  * Called with interrupts disabled.
  */
index 882a32ebc6b7c593c303a4d711cce5ae03001222..32946fba123e597046a7316f49150a1b6d3be8ea 100644 (file)
@@ -116,9 +116,10 @@ EXPORT_SYMBOL(__ioremap);
 void __iounmap(void __iomem *addr)
 {
        unsigned long vaddr = (unsigned long __force)addr;
+       unsigned long seg = PXSEG(vaddr);
        struct vm_struct *p;
 
-       if (PXSEG(vaddr) < P3SEG || is_pci_memaddr(vaddr))
+       if (seg < P3SEG || seg >= P3_ADDR_MAX || is_pci_memaddr(vaddr))
                return;
 
 #ifdef CONFIG_32BIT