sh: wire up clear_user_highpage() for sh4, convert sh7705.

This wires up clear_user_highpage() on SH-4 and subsequently converts the
SH7705 32kB cache mode over to using it. Now that the SH-4 implementation
handles all of the dcache purging directly in the aliasing case, there is
no need to do this in the default clear_page() implementation.

Signed-off-by: Paul Mundt <lethal@linux-sh.org>
diff --git a/arch/sh/include/asm/cacheflush.h b/arch/sh/include/asm/cacheflush.h
index 4c5462d..4e36011 100644
--- a/arch/sh/include/asm/cacheflush.h
+++ b/arch/sh/include/asm/cacheflush.h
@@ -49,7 +49,7 @@
 	flush_dcache_page(page);
 }
 
-#if defined(CONFIG_CPU_SH4) && !defined(CONFIG_CACHE_OFF)
+#if (defined(CONFIG_CPU_SH4) || defined(CONFIG_SH7705_CACHE_32KB)) && !defined(CONFIG_CACHE_OFF)
 extern void copy_to_user_page(struct vm_area_struct *vma,
 	struct page *page, unsigned long vaddr, void *dst, const void *src,
 	unsigned long len);
diff --git a/arch/sh/include/asm/page.h b/arch/sh/include/asm/page.h
index a31ab40..5208b7b 100644
--- a/arch/sh/include/asm/page.h
+++ b/arch/sh/include/asm/page.h
@@ -56,21 +56,25 @@
 	return (addr1 ^ addr2) & shm_align_mask;
 }
 
-extern void clear_page(void *to);
+
+#define clear_page(page)	memset((void *)(page), 0, PAGE_SIZE)
 extern void copy_page(void *to, void *from);
 
+struct page;
+struct vm_area_struct;
+
 #if !defined(CONFIG_CACHE_OFF) && defined(CONFIG_MMU) && \
 	(defined(CONFIG_CPU_SH5) || defined(CONFIG_CPU_SH4) || \
 	 defined(CONFIG_SH7705_CACHE_32KB))
-struct page;
-struct vm_area_struct;
 extern void clear_user_page(void *to, unsigned long address, struct page *page);
 extern void copy_user_page(void *to, void *from, unsigned long address,
 			   struct page *page);
-#if defined(CONFIG_CPU_SH4)
+#if defined(CONFIG_CPU_SH4) || defined(CONFIG_SH7705_CACHE_32KB)
 extern void copy_user_highpage(struct page *to, struct page *from,
 			       unsigned long vaddr, struct vm_area_struct *vma);
 #define __HAVE_ARCH_COPY_USER_HIGHPAGE
+extern void clear_user_highpage(struct page *page, unsigned long vaddr);
+#define clear_user_highpage	clear_user_highpage
 #endif
 #else
 #define clear_user_page(page, vaddr, pg)	clear_page(page)
diff --git a/arch/sh/include/asm/pgtable.h b/arch/sh/include/asm/pgtable.h
index d9f68f9..bef3ab7 100644
--- a/arch/sh/include/asm/pgtable.h
+++ b/arch/sh/include/asm/pgtable.h
@@ -141,7 +141,8 @@
 extern void page_table_range_init(unsigned long start, unsigned long end,
 				  pgd_t *pgd);
 
-#if !defined(CONFIG_CACHE_OFF) && defined(CONFIG_CPU_SH4) && defined(CONFIG_MMU)
+#if !defined(CONFIG_CACHE_OFF) && (defined(CONFIG_CPU_SH4) || \
+    defined(CONFIG_SH7705_CACHE_32KB)) && defined(CONFIG_MMU)
 extern void kmap_coherent_init(void);
 #else
 #define kmap_coherent_init()	do { } while (0)
diff --git a/arch/sh/kernel/sh_ksyms_32.c b/arch/sh/kernel/sh_ksyms_32.c
index cec6108..8dbe26b 100644
--- a/arch/sh/kernel/sh_ksyms_32.c
+++ b/arch/sh/kernel/sh_ksyms_32.c
@@ -101,11 +101,6 @@
 EXPORT_SYMBOL(flush_dcache_page);
 #endif
 
-#if !defined(CONFIG_CACHE_OFF) && defined(CONFIG_MMU) && \
-	(defined(CONFIG_CPU_SH4) || defined(CONFIG_SH7705_CACHE_32KB))
-EXPORT_SYMBOL(clear_user_page);
-#endif
-
 #ifdef CONFIG_MCOUNT
 DECLARE_EXPORT(mcount);
 #endif
@@ -114,7 +109,6 @@
 #ifdef CONFIG_IPV6
 EXPORT_SYMBOL(csum_ipv6_magic);
 #endif
-EXPORT_SYMBOL(clear_page);
 EXPORT_SYMBOL(copy_page);
 EXPORT_SYMBOL(__clear_user);
 EXPORT_SYMBOL(_ebss);
diff --git a/arch/sh/lib/clear_page.S b/arch/sh/lib/clear_page.S
index 8342bfb..bee9817 100644
--- a/arch/sh/lib/clear_page.S
+++ b/arch/sh/lib/clear_page.S
@@ -8,52 +8,6 @@
 #include <linux/linkage.h>
 #include <asm/page.h>
 
-/*
- * clear_page
- * @to: P1 address
- *
- * void clear_page(void *to)
- */
-
-/*
- * r0 --- scratch
- * r4 --- to
- * r5 --- to + PAGE_SIZE
- */
-ENTRY(clear_page)
-	mov	r4,r5
-	mov.l	.Llimit,r0
-	add	r0,r5
-	mov	#0,r0
-	!
-1:
-#if defined(CONFIG_CPU_SH4)
-	movca.l	r0,@r4
-	mov	r4,r1
-#else
-	mov.l	r0,@r4
-#endif
-	add	#32,r4
-	mov.l	r0,@-r4
-	mov.l	r0,@-r4
-	mov.l	r0,@-r4
-	mov.l	r0,@-r4
-	mov.l	r0,@-r4
-	mov.l	r0,@-r4
-	mov.l	r0,@-r4
-#if defined(CONFIG_CPU_SH4)
-	ocbwb	@r1
-#endif
-	cmp/eq	r5,r4
-	bf/s	1b
-	 add	#28,r4
-	!
-	rts
-	 nop
-
-	.balign 4
-.Llimit:	.long	(PAGE_SIZE-28)
-
 ENTRY(__clear_user)
 	!
 	mov	#0, r0
diff --git a/arch/sh/mm/Makefile_32 b/arch/sh/mm/Makefile_32
index 986a1e0..5c04bbb 100644
--- a/arch/sh/mm/Makefile_32
+++ b/arch/sh/mm/Makefile_32
@@ -31,7 +31,7 @@
 obj-y				+= $(tlb-y)
 ifndef CONFIG_CACHE_OFF
 obj-$(CONFIG_CPU_SH4)		+= pg-sh4.o
-obj-$(CONFIG_SH7705_CACHE_32KB)	+= pg-sh7705.o
+obj-$(CONFIG_SH7705_CACHE_32KB)	+= pg-sh4.o
 endif
 endif
 
diff --git a/arch/sh/mm/pg-nommu.c b/arch/sh/mm/pg-nommu.c
index 91ed4e6..7e33b48 100644
--- a/arch/sh/mm/pg-nommu.c
+++ b/arch/sh/mm/pg-nommu.c
@@ -1,7 +1,7 @@
 /*
  * arch/sh/mm/pg-nommu.c
  *
- * clear_page()/copy_page() implementation for MMUless SH.
+ * copy_page()/__copy_user()/__clear_user() implementations for MMUless SH.
  *
  * Copyright (C) 2003  Paul Mundt
  *
@@ -20,11 +20,6 @@
 	memcpy(to, from, PAGE_SIZE);
 }
 
-void clear_page(void *to)
-{
-	memset(to, 0, PAGE_SIZE);
-}
-
 __kernel_size_t __copy_user(void *to, const void *from, __kernel_size_t n)
 {
 	memcpy(to, from, n);
diff --git a/arch/sh/mm/pg-sh4.c b/arch/sh/mm/pg-sh4.c
index f3c4b2a..4d93070 100644
--- a/arch/sh/mm/pg-sh4.c
+++ b/arch/sh/mm/pg-sh4.c
@@ -2,7 +2,7 @@
  * arch/sh/mm/pg-sh4.c
  *
  * Copyright (C) 1999, 2000, 2002  Niibe Yutaka
- * Copyright (C) 2002 - 2007  Paul Mundt
+ * Copyright (C) 2002 - 2009  Paul Mundt
  *
  * Released under the terms of the GNU GPL v2.0.
  */
@@ -58,20 +58,6 @@
 	preempt_check_resched();
 }
 
-/*
- * clear_user_page
- * @to: P1 address
- * @address: U0 address to be mapped
- * @page: page (virt_to_page(to))
- */
-void clear_user_page(void *to, unsigned long address, struct page *page)
-{
-	clear_page(to);
-
-	if (pages_do_alias((unsigned long)to, address & PAGE_MASK))
-		__flush_wback_region(to, PAGE_SIZE);
-}
-
 void copy_to_user_page(struct vm_area_struct *vma, struct page *page,
 		       unsigned long vaddr, void *dst, const void *src,
 		       unsigned long len)
@@ -128,3 +114,16 @@
 	smp_wmb();
 }
 EXPORT_SYMBOL(copy_user_highpage);
+
+void clear_user_highpage(struct page *page, unsigned long vaddr)
+{
+	void *kaddr = kmap_atomic(page, KM_USER0);
+
+	clear_page(kaddr);
+
+	if (pages_do_alias((unsigned long)kaddr, vaddr & PAGE_MASK))
+		__flush_wback_region(kaddr, PAGE_SIZE);
+
+	kunmap_atomic(kaddr, KM_USER0);
+}
+EXPORT_SYMBOL(clear_user_highpage);
diff --git a/arch/sh/mm/pg-sh7705.c b/arch/sh/mm/pg-sh7705.c
deleted file mode 100644
index 684891b..0000000
--- a/arch/sh/mm/pg-sh7705.c
+++ /dev/null
@@ -1,102 +0,0 @@
-/*
- * arch/sh/mm/pg-sh7705.c
- *
- * Copyright (C) 1999, 2000  Niibe Yutaka
- * Copyright (C) 2004  Alex Song
- *
- * 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 <linux/init.h>
-#include <linux/mman.h>
-#include <linux/mm.h>
-#include <linux/threads.h>
-#include <linux/fs.h>
-#include <asm/addrspace.h>
-#include <asm/page.h>
-#include <asm/pgtable.h>
-#include <asm/processor.h>
-#include <asm/cache.h>
-#include <asm/io.h>
-#include <asm/uaccess.h>
-#include <asm/pgalloc.h>
-#include <asm/mmu_context.h>
-#include <asm/cacheflush.h>
-
-static void __flush_purge_virtual_region(void *p1, void *virt, int size)
-{
-	unsigned long v;
-	unsigned long begin, end;
-	unsigned long p1_begin;
-
-
-	begin = L1_CACHE_ALIGN((unsigned long)virt);
-	end = L1_CACHE_ALIGN((unsigned long)virt + size);
-
-	p1_begin = (unsigned long)p1 & ~(L1_CACHE_BYTES - 1);
-
-	/* do this the slow way as we may not have TLB entries
-	 * for virt yet. */
-	for (v = begin; v < end; v += L1_CACHE_BYTES) {
-		unsigned long p;
-	        unsigned long ways, addr;
-
-		p = __pa(p1_begin);
-
-	        ways = current_cpu_data.dcache.ways;
-		addr = CACHE_OC_ADDRESS_ARRAY;
-
-		do {
-			unsigned long data;
-
-			addr |= (v & current_cpu_data.dcache.entry_mask);
-
-			data = ctrl_inl(addr);
-			if ((data & CACHE_PHYSADDR_MASK) ==
-			       (p & CACHE_PHYSADDR_MASK)) {
-				data &= ~(SH_CACHE_UPDATED|SH_CACHE_VALID);
-				ctrl_outl(data, addr);
-			}
-
-			addr += current_cpu_data.dcache.way_incr;
-		} while (--ways);
-
-		p1_begin += L1_CACHE_BYTES;
-	}
-}
-
-/*
- * clear_user_page
- * @to: P1 address
- * @address: U0 address to be mapped
- */
-void clear_user_page(void *to, unsigned long address, struct page *pg)
-{
-	if (pages_do_alias(address, (unsigned long)to))
-		__flush_purge_virtual_region(to,
-					     (void *)(address & 0xfffff000),
-					     PAGE_SIZE);
-
-	clear_page(to);
-	__flush_wback_region(to, PAGE_SIZE);
-}
-
-/*
- * copy_user_page
- * @to: P1 address
- * @from: P1 address
- * @address: U0 address to be mapped
- */
-void copy_user_page(void *to, void *from, unsigned long address, struct page *pg)
-{
-	if (pages_do_alias(address, (unsigned long)to))
-		__flush_purge_virtual_region(to,
-					     (void *)(address & 0xfffff000),
-					     PAGE_SIZE);
-
-	copy_page(to, from);
-	__flush_wback_region(to, PAGE_SIZE);
-}