From d5a309c22a5c4e51c53c13cfaab19ca4a0adc13b Mon Sep 17 00:00:00 2001 From: Russell King Date: Tue, 29 Jun 2004 17:02:46 +0100 Subject: [PATCH] [ARM] EBSA110 I/O and decompressor fixes. This fixes the buggy decompressor assembly, and fixes PCMCIA IO to use the correct byte lane when accessing certain PCMCIA cards. --- arch/arm/Makefile | 7 ++ arch/arm/mach-ebsa110/io.c | 99 ++++++++++++++++++++--- include/asm-arm/arch-ebsa110/io.h | 54 +++++++++---- include/asm-arm/arch-ebsa110/uncompress.h | 4 +- 4 files changed, 134 insertions(+), 30 deletions(-) diff --git a/arch/arm/Makefile b/arch/arm/Makefile index d8a4d37287cbc..dca3b45fb39b3 100644 --- a/arch/arm/Makefile +++ b/arch/arm/Makefile @@ -94,6 +94,13 @@ textaddr-$(CONFIG_ARCH_FORTUNET) := 0xc0008000 machine-$(CONFIG_ARCH_LH7A40X) := lh7a40x machine-$(CONFIG_ARCH_VERSATILE_PB) := versatile +ifeq ($(CONFIG_ARCH_EBSA110),y) +# This is what happens if you forget the IOCS16 line. +# PCMCIA cards stop working. +CFLAGS_3c589_cs.o :=-DISA_SIXTEEN_BIT_PERIPHERAL +export CFLAGS_3c589_cs.o +endif + TEXTADDR := $(textaddr-y) ifeq ($(incdir-y),) incdir-y := $(machine-y) diff --git a/arch/arm/mach-ebsa110/io.c b/arch/arm/mach-ebsa110/io.c index 6556818e4e6a3..9205e65fe5996 100644 --- a/arch/arm/mach-ebsa110/io.c +++ b/arch/arm/mach-ebsa110/io.c @@ -139,7 +139,11 @@ EXPORT_SYMBOL(__writel); ((p) >> 3) == (0x2f8 >> 3) || \ ((p) >> 3) == (0x378 >> 3)) -u8 __inb(int port) +/* + * 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; @@ -162,7 +166,31 @@ u8 __inb(int port) return ret; } -u16 __inw(int port) +/* + * We're addressing a 16-bit peripheral which transfers odd + * addresses on the high ISA byte lane. + */ +u8 __inb16(unsigned int port) +{ + u32 ret; + + /* + * The SuperIO registers use sane addressing techniques... + */ + if (SUPERIO_PORT(port)) + ret = __raw_readb(ISAIO_BASE + (port << 2)); + else { + u32 a = ISAIO_BASE + ((port & ~1) << 1); + + /* + * Shame nothing else does + */ + ret = __raw_readb(a + (port & 1)); + } + return ret; +} + +u16 __inw(unsigned int port) { u32 ret; @@ -185,17 +213,27 @@ u16 __inw(int port) return ret; } -u32 __inl(int port) +/* + * Fake a 32-bit read with two 16-bit reads. Needed for 3c589. + */ +u32 __inl(unsigned int port) { - BUG(); - return 0; + u32 a; + + if (SUPERIO_PORT(port) || port & 3) + BUG(); + + a = ISAIO_BASE + (port << 1); + + return __raw_readw(a) | __raw_readw(a + 4) << 16; } -EXPORT_SYMBOL(__inb); +EXPORT_SYMBOL(__inb8); +EXPORT_SYMBOL(__inb16); EXPORT_SYMBOL(__inw); EXPORT_SYMBOL(__inl); -void __outb(u8 val, int port) +void __outb8(u8 val, unsigned int port) { /* * The SuperIO registers use sane addressing techniques... @@ -215,7 +253,24 @@ void __outb(u8 val, int port) } } -void __outw(u16 val, int port) +void __outb16(u8 val, unsigned int port) +{ + /* + * The SuperIO registers use sane addressing techniques... + */ + if (SUPERIO_PORT(port)) + __raw_writeb(val, ISAIO_BASE + (port << 2)); + else { + u32 a = ISAIO_BASE + ((port & ~1) << 1); + + /* + * Shame nothing else does + */ + __raw_writeb(val, a + (port & 1)); + } +} + +void __outw(u16 val, unsigned int port) { u32 off; @@ -225,7 +280,7 @@ void __outw(u16 val, int port) if (SUPERIO_PORT(port)) off = port << 2; else { - off = (port & ~1) << 1; + off = port << 1; if (port & 1) BUG(); @@ -233,12 +288,13 @@ void __outw(u16 val, int port) __raw_writew(val, ISAIO_BASE + off); } -void __outl(u32 val, int port) +void __outl(u32 val, unsigned int port) { BUG(); } -EXPORT_SYMBOL(__outb); +EXPORT_SYMBOL(__outb8); +EXPORT_SYMBOL(__outb16); EXPORT_SYMBOL(__outw); EXPORT_SYMBOL(__outl); @@ -315,12 +371,29 @@ void insw(unsigned int port, void *from, int 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) { - panic("outsl not supported on this architecture"); + u32 off = port << 1; + + if (SUPERIO_PORT(port) || port & 3) + BUG(); + + __raw_writesw(ISAIO_BASE + off, from, len << 1); } void insl(unsigned int port, void *from, int len) { - panic("insl not supported on this architecture"); + u32 off = port << 1; + + if (SUPERIO_PORT(port) || port & 3) + BUG(); + + __raw_readsw(ISAIO_BASE + off, from, len << 1); } + +EXPORT_SYMBOL(outsl); +EXPORT_SYMBOL(insl); diff --git a/include/asm-arm/arch-ebsa110/io.h b/include/asm-arm/arch-ebsa110/io.h index 52030abe9cdda..e2c242ff0eb81 100644 --- a/include/asm-arm/arch-ebsa110/io.h +++ b/include/asm-arm/arch-ebsa110/io.h @@ -15,26 +15,44 @@ #define IO_SPACE_LIMIT 0xffff -u8 __inb(int port); -u16 __inw(int port); -u32 __inl(int port); +u8 __inb8(unsigned int port); +void __outb8(u8 val, unsigned int port); -#define inb(p) __inb(p) -#define inw(p) __inw(p) -#define inl(p) __inl(p) +u8 __inb16(unsigned int port); +void __outb16(u8 val, unsigned int port); -void __outb(u8 val, int port); -void __outw(u16 val, int port); -void __outl(u32 val, int port); +u16 __inw(unsigned int port); +void __outw(u16 val, unsigned int port); -#define outb(v,p) __outb(v,p) -#define outw(v,p) __outw(v,p) -#define outl(v,p) __outl(v,p) +u32 __inl(unsigned int port); +void __outl(u32 val, unsigned int port); u8 __readb(void *addr); u16 __readw(void *addr); u32 __readl(void *addr); +void __writeb(u8 val, void *addr); +void __writew(u16 val, void *addr); +void __writel(u32 val, void *addr); + +/* + * Argh, someone forgot the IOCS16 line. We therefore have to handle + * the byte stearing by selecting the correct byte IO functions here. + */ +#ifdef ISA_SIXTEEN_BIT_PERIPHERAL +#define inb(p) __inb16(p) +#define outb(v,p) __outb16(v,p) +#else +#define inb(p) __inb8(p) +#define outb(v,p) __outb8(v,p) +#endif + +#define inw(p) __inw(p) +#define outw(v,p) __outw(v,p) + +#define inl(p) __inl(p) +#define outl(v,p) __outl(v,p) + #define readb(b) __readb(b) #define readw(b) __readw(b) #define readl(b) __readl(b) @@ -42,10 +60,6 @@ u32 __readl(void *addr); #define readw_relaxed(addr) readw(addr) #define readl_relaxed(addr) readl(addr) -void __writeb(u8 val, void *addr); -void __writew(u16 val, void *addr); -void __writel(u32 val, void *addr); - #define writeb(v,b) __writeb(v,b) #define writew(v,b) __writew(v,b) #define writel(v,b) __writel(v,b) @@ -53,4 +67,12 @@ void __writel(u32 val, void *addr); #define __arch_ioremap(cookie,sz,c,a) ((void *)(cookie)) #define __arch_iounmap(cookie) do { } while (0) +extern void insb(unsigned int port, void *buf, int sz); +extern void insw(unsigned int port, void *buf, int sz); +extern void insl(unsigned int port, void *buf, int sz); + +extern void outsb(unsigned int port, const void *buf, int sz); +extern void outsw(unsigned int port, const void *buf, int sz); +extern void outsl(unsigned int port, const void *buf, int sz); + #endif diff --git a/include/asm-arm/arch-ebsa110/uncompress.h b/include/asm-arm/arch-ebsa110/uncompress.h index 8396e9a3dc0b3..1d7d841efc6e9 100644 --- a/include/asm-arm/arch-ebsa110/uncompress.h +++ b/include/asm-arm/arch-ebsa110/uncompress.h @@ -13,6 +13,7 @@ */ static void puts(const char *s) { + unsigned long tmp1, tmp2; __asm__ __volatile__( "ldrb %0, [%2], #1\n" " teq %0, #0\n" @@ -32,7 +33,8 @@ static void puts(const char *s) " and %1, %1, #0x60\n" " teq %1, #0x60\n" " bne 3b" - : : "r" (0), "r" (0), "r" (s), "r" (0xf0000be0) : "cc"); + : "=&r" (tmp1), "=&r" (tmp2) + : "r" (s), "r" (0xf0000be0) : "cc"); } /* -- 2.53.0