/*
 *  linux/arch/m68k/mm/cache.c
 *
 *  Instruction cache handling
 *
 *  Copyright (C) 1995  Hamish Macdonald
 */

#include <linux/module.h>
#include <asm/pgalloc.h>
#include <asm/traps.h>


static unsigned long virt_to_phys_slow(unsigned long vaddr)
{
	if (CPU_IS_060) {
		unsigned long paddr;

		/* The PLPAR instruction causes an access error if the translation
		 * is not possible. To catch this we use the same exception mechanism
		 * as for user space accesses in <asm/uaccess.h>. */
		asm volatile (".chip 68060\n"
			      "1: plpar (%0)\n"
			      ".chip 68k\n"
			      "2:\n"
			      ".section .fixup,\"ax\"\n"
			      "   .even\n"
			      "3: sub.l %0,%0\n"
			      "   jra 2b\n"
			      ".previous\n"
			      ".section __ex_table,\"a\"\n"
			      "   .align 4\n"
			      "   .long 1b,3b\n"
			      ".previous"
			      : "=a" (paddr)
			      : "0" (vaddr));
		return paddr;
	} else if (CPU_IS_040) {
		unsigned long mmusr;

		asm volatile (".chip 68040\n\t"
			      "ptestr (%1)\n\t"
			      "movec %%mmusr, %0\n\t"
			      ".chip 68k"
			      : "=r" (mmusr)
			      : "a" (vaddr));

		if (mmusr & MMU_R_040)
			return (mmusr & PAGE_MASK) | (vaddr & ~PAGE_MASK);
	} else {
		unsigned short mmusr;
		unsigned long *descaddr;

		asm volatile ("ptestr %3,%2@,#7,%0\n\t"
			      "pmove %%psr,%1@"
			      : "=a&" (descaddr)
			      : "a" (&mmusr), "a" (vaddr), "d" (get_fs().seg));
		if (mmusr & (MMU_I|MMU_B|MMU_L))
			return 0;
		descaddr = phys_to_virt((unsigned long)descaddr);
		switch (mmusr & MMU_NUM) {
		case 1:
			return (*descaddr & 0xfe000000) | (vaddr & 0x01ffffff);
		case 2:
			return (*descaddr & 0xfffc0000) | (vaddr & 0x0003ffff);
		case 3:
			return (*descaddr & PAGE_MASK) | (vaddr & ~PAGE_MASK);
		}
	}
	return 0;
}

/* Push n pages at kernel virtual address and clear the icache */
/* RZ: use cpush %bc instead of cpush %dc, cinv %ic */
void flush_icache_range(unsigned long address, unsigned long endaddr)
{
	if (CPU_IS_COLDFIRE) {
		unsigned long start, end;
		start = address & ICACHE_SET_MASK;
		end = endaddr & ICACHE_SET_MASK;
		if (start > end) {
			flush_cf_icache(0, end);
			end = ICACHE_MAX_ADDR;
		}
		flush_cf_icache(start, end);
	} else if (CPU_IS_040_OR_060) {
		address &= PAGE_MASK;

		do {
			asm volatile ("nop\n\t"
				      ".chip 68040\n\t"
				      "cpushp %%bc,(%0)\n\t"
				      ".chip 68k"
				      : : "a" (virt_to_phys_slow(address)));
			address += PAGE_SIZE;
		} while (address < endaddr);
	} else {
		unsigned long tmp;
		asm volatile ("movec %%cacr,%0\n\t"
			      "orw %1,%0\n\t"
			      "movec %0,%%cacr"
			      : "=&d" (tmp)
			      : "di" (FLUSH_I));
	}
}
EXPORT_SYMBOL(flush_icache_range);

void flush_icache_user_range(struct vm_area_struct *vma, struct page *page,
			     unsigned long addr, int len)
{
	if (CPU_IS_COLDFIRE) {
		unsigned long start, end;
		start = addr & ICACHE_SET_MASK;
		end = (addr + len) & ICACHE_SET_MASK;
		if (start > end) {
			flush_cf_icache(0, end);
			end = ICACHE_MAX_ADDR;
		}
		flush_cf_icache(start, end);

	} else if (CPU_IS_040_OR_060) {
		asm volatile ("nop\n\t"
			      ".chip 68040\n\t"
			      "cpushp %%bc,(%0)\n\t"
			      ".chip 68k"
			      : : "a" (page_to_phys(page)));
	} else {
		unsigned long tmp;
		asm volatile ("movec %%cacr,%0\n\t"
			      "orw %1,%0\n\t"
			      "movec %0,%%cacr"
			      : "=&d" (tmp)
			      : "di" (FLUSH_I));
	}
}

