/*
 *  linux/arch/arm/mach-ebsa110/isamem.c
 *
 *  Copyright (C) 2001 Russell King
 *
 * Perform "ISA" memory and IO accesses.  The EBSA110 has some "peculiarities"
 * in the way it handles accesses to odd IO ports on 16-bit devices.  These
 * devices have their D0-D15 lines connected to the processors D0-D15 lines.
 * Since they expect all byte IO operations to be performed on D0-D7, and the
 * StrongARM expects to transfer the byte to these odd addresses on D8-D15,
 * we must use a trick to get the required behaviour.
 *
 * The trick employed here is to use long word stores to odd address -1.  The
 * glue logic picks this up as a "trick" access, and asserts the LSB of the
 * peripherals address bus, thereby accessing the odd IO port.  Meanwhile, the
 * StrongARM transfers its data on D0-D7 as expected.
 *
 * Things get more interesting on the pass-1 EBSA110 - the PCMCIA controller
 * wiring was screwed in such a way that it had limited memory space access.
 * Luckily, the work-around for this is not too horrible.  See
 * __isamem_convert_addr for the details.
 */
#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/types.h>

#include <asm/io.h>
#include <asm/page.h>

static void __iomem *__isamem_convert_addr(void __iomem *addr)
{
	u32 ret, a = (u32 __force) addr;

	/*
	 * The PCMCIA controller is wired up as follows:
	 *        +---------+---------+---------+---------+---------+---------+
	 * PCMCIA | 2 2 2 2 | 1 1 1 1 | 1 1 1 1 | 1 1     |         |         |
	 *        | 3 2 1 0 | 9 8 7 6 | 5 4 3 2 | 1 0 9 8 | 7 6 5 4 | 3 2 1 0 |
	 *        +---------+---------+---------+---------+---------+---------+
	 *  CPU   | 2 2 2 2 | 2 1 1 1 | 1 1 1 1 | 1 1 1   |         |         |
	 *        | 4 3 2 1 | 0 9 9 8 | 7 6 5 4 | 3 2 0 9 | 8 7 6 5 | 4 3 2 x |
	 *        +---------+---------+---------+---------+---------+---------+
	 *
	 * This means that we can access PCMCIA regions as follows:
	 *	0x*10000 -> 0x*1ffff
	 *	0x*70000 -> 0x*7ffff
	 *	0x*90000 -> 0x*9ffff
	 *	0x*f0000 -> 0x*fffff
	 */
	ret  = (a & 0xf803fe) << 1;
	ret |= (a & 0x03fc00) << 2;

	ret += 0xe8000000;

	if ((a & 0x20000) == (a & 0x40000) >> 1)
		return (void __iomem *)ret;

	BUG();
	return NULL;
}

/*
 * read[bwl] and write[bwl]
 */
u8 __readb(void __iomem *addr)
{
	void __iomem *a = __isamem_convert_addr(addr);
	u32 ret;

	if ((unsigned long)addr & 1)
		ret = __raw_readl(a);
	else
		ret = __raw_readb(a);
	return ret;
}

u16 __readw(void __iomem *addr)
{
	void __iomem *a = __isamem_convert_addr(addr);

	if ((unsigned long)addr & 1)
		BUG();

	return __raw_readw(a);
}

u32 __readl(void __iomem *addr)
{
	void __iomem *a = __isamem_convert_addr(addr);
	u32 ret;

	if ((unsigned long)addr & 3)
		BUG();

	ret = __raw_readw(a);
	ret |= __raw_readw(a + 4) << 16;
	return ret;
}

EXPORT_SYMBOL(__readb);
EXPORT_SYMBOL(__readw);
EXPORT_SYMBOL(__readl);

void __writeb(u8 val, void __iomem *addr)
{
	void __iomem *a = __isamem_convert_addr(addr);

	if ((unsigned long)addr & 1)
		__raw_writel(val, a);
	else
		__raw_writeb(val, a);
}

void __writew(u16 val, void __iomem *addr)
{
	void __iomem *a = __isamem_convert_addr(addr);

	if ((unsigned long)addr & 1)
		BUG();

	__raw_writew(val, a);
}

void __writel(u32 val, void __iomem *addr)
{
	void __iomem *a = __isamem_convert_addr(addr);

	if ((unsigned long)addr & 3)
		BUG();

	__raw_writew(val, a);
	__raw_writew(val >> 16, a + 4);
}

EXPORT_SYMBOL(__writeb);
EXPORT_SYMBOL(__writew);
EXPORT_SYMBOL(__writel);

#define SUPERIO_PORT(p) \
	(((p) >> 3) == (0x3f8 >> 3) || \
	 ((p) >> 3) == (0x2f8 >> 3) || \
	 ((p) >> 3) == (0x378 >> 3))

/*
 * We're addressing an 8 or 16-bit peripheral which tranfers
 * odd addresses on the low ISA byte lane.
 */
u8 __inb8(unsigned int port)
{
	u32 ret;

	/*
	 * The SuperIO registers use sane addressing techniques...
	 */
	if (SUPERIO_PORT(port))
		ret = __raw_readb((void __iomem *)ISAIO_BASE + (port << 2));
	else {
		void __iomem *a = (void __iomem *)ISAIO_BASE + ((port & ~1) << 1);

		/*
		 * Shame nothing else does
		 */
		if (port & 1)
			ret = __raw_readl(a);
		else
			ret = __raw_readb(a);
	}
	return ret;
}

/*
 * We're addressing a 16-bit peripheral which transfers odd
 * addresses on the high ISA byte lane.
 */
u8 __inb16(unsigned int port)
{
	unsigned int offset;

	/*
	 * The SuperIO registers use sane addressing techniques...
	 */
	if (SUPERIO_PORT(port))
		offset = port << 2;
	else
		offset = (port & ~1) << 1 | (port & 1);

	return __raw_readb((void __iomem *)ISAIO_BASE + offset);
}

u16 __inw(unsigned int port)
{
	unsigned int offset;

	/*
	 * The SuperIO registers use sane addressing techniques...
	 */
	if (SUPERIO_PORT(port))
		offset = port << 2;
	else {
		offset = port << 1;
		BUG_ON(port & 1);
	}
	return __raw_readw((void __iomem *)ISAIO_BASE + offset);
}

/*
 * Fake a 32-bit read with two 16-bit reads.  Needed for 3c589.
 */
u32 __inl(unsigned int port)
{
	void __iomem *a;

	if (SUPERIO_PORT(port) || port & 3)
		BUG();

	a = (void __iomem *)ISAIO_BASE + ((port & ~1) << 1);

	return __raw_readw(a) | __raw_readw(a + 4) << 16;
}

EXPORT_SYMBOL(__inb8);
EXPORT_SYMBOL(__inb16);
EXPORT_SYMBOL(__inw);
EXPORT_SYMBOL(__inl);

void __outb8(u8 val, unsigned int port)
{
	/*
	 * The SuperIO registers use sane addressing techniques...
	 */
	if (SUPERIO_PORT(port))
		__raw_writeb(val, (void __iomem *)ISAIO_BASE + (port << 2));
	else {
		void __iomem *a = (void __iomem *)ISAIO_BASE + ((port & ~1) << 1);

		/*
		 * Shame nothing else does
		 */
		if (port & 1)
			__raw_writel(val, a);
		else
			__raw_writeb(val, a);
	}
}

void __outb16(u8 val, unsigned int port)
{
	unsigned int offset;

	/*
	 * The SuperIO registers use sane addressing techniques...
	 */
	if (SUPERIO_PORT(port))
		offset = port << 2;
	else
		offset = (port & ~1) << 1 | (port & 1);

	__raw_writeb(val, (void __iomem *)ISAIO_BASE + offset);
}

void __outw(u16 val, unsigned int port)
{
	unsigned int offset;

	/*
	 * The SuperIO registers use sane addressing techniques...
	 */
	if (SUPERIO_PORT(port))
		offset = port << 2;
	else {
		offset = port << 1;
		BUG_ON(port & 1);
	}
	__raw_writew(val, (void __iomem *)ISAIO_BASE + offset);
}

void __outl(u32 val, unsigned int port)
{
	BUG();
}

EXPORT_SYMBOL(__outb8);
EXPORT_SYMBOL(__outb16);
EXPORT_SYMBOL(__outw);
EXPORT_SYMBOL(__outl);

void outsb(unsigned int port, const void *from, int len)
{
	u32 off;

	if (SUPERIO_PORT(port))
		off = port << 2;
	else {
		off = (port & ~1) << 1;
		if (port & 1)
			BUG();
	}

	__raw_writesb((void __iomem *)ISAIO_BASE + off, from, len);
}

void insb(unsigned int port, void *from, int len)
{
	u32 off;

	if (SUPERIO_PORT(port))
		off = port << 2;
	else {
		off = (port & ~1) << 1;
		if (port & 1)
			BUG();
	}

	__raw_readsb((void __iomem *)ISAIO_BASE + off, from, len);
}

EXPORT_SYMBOL(outsb);
EXPORT_SYMBOL(insb);

void outsw(unsigned int port, const void *from, int len)
{
	u32 off;

	if (SUPERIO_PORT(port))
		off = port << 2;
	else {
		off = (port & ~1) << 1;
		if (port & 1)
			BUG();
	}

	__raw_writesw((void __iomem *)ISAIO_BASE + off, from, len);
}

void insw(unsigned int port, void *from, int len)
{
	u32 off;

	if (SUPERIO_PORT(port))
		off = port << 2;
	else {
		off = (port & ~1) << 1;
		if (port & 1)
			BUG();
	}

	__raw_readsw((void __iomem *)ISAIO_BASE + off, from, len);
}

EXPORT_SYMBOL(outsw);
EXPORT_SYMBOL(insw);

/*
 * We implement these as 16-bit insw/outsw, mainly for
 * 3c589 cards.
 */
void outsl(unsigned int port, const void *from, int len)
{
	u32 off = port << 1;

	if (SUPERIO_PORT(port) || port & 3)
		BUG();

	__raw_writesw((void __iomem *)ISAIO_BASE + off, from, len << 1);
}

void insl(unsigned int port, void *from, int len)
{
	u32 off = port << 1;

	if (SUPERIO_PORT(port) || port & 3)
		BUG();

	__raw_readsw((void __iomem *)ISAIO_BASE + off, from, len << 1);
}

EXPORT_SYMBOL(outsl);
EXPORT_SYMBOL(insl);
