diff options
Diffstat (limited to 'include/asm-arm/arch-ebsa285')
-rw-r--r-- | include/asm-arm/arch-ebsa285/a.out.h | 11 | ||||
-rw-r--r-- | include/asm-arm/arch-ebsa285/dma.h | 16 | ||||
-rw-r--r-- | include/asm-arm/arch-ebsa285/hardware.h | 116 | ||||
-rw-r--r-- | include/asm-arm/arch-ebsa285/io.h | 219 | ||||
-rw-r--r-- | include/asm-arm/arch-ebsa285/irq.h | 252 | ||||
-rw-r--r-- | include/asm-arm/arch-ebsa285/irqs.h | 114 | ||||
-rw-r--r-- | include/asm-arm/arch-ebsa285/keyboard.h | 81 | ||||
-rw-r--r-- | include/asm-arm/arch-ebsa285/memory.h | 74 | ||||
-rw-r--r-- | include/asm-arm/arch-ebsa285/mm-init.h | 5 | ||||
-rw-r--r-- | include/asm-arm/arch-ebsa285/mmu.h | 28 | ||||
-rw-r--r-- | include/asm-arm/arch-ebsa285/oldlatches.h | 9 | ||||
-rw-r--r-- | include/asm-arm/arch-ebsa285/processor.h | 15 | ||||
-rw-r--r-- | include/asm-arm/arch-ebsa285/serial.h | 11 | ||||
-rw-r--r-- | include/asm-arm/arch-ebsa285/system.h | 39 | ||||
-rw-r--r-- | include/asm-arm/arch-ebsa285/time.h | 386 | ||||
-rw-r--r-- | include/asm-arm/arch-ebsa285/timex.h | 6 | ||||
-rw-r--r-- | include/asm-arm/arch-ebsa285/uncompress.h | 5 |
17 files changed, 927 insertions, 460 deletions
diff --git a/include/asm-arm/arch-ebsa285/a.out.h b/include/asm-arm/arch-ebsa285/a.out.h index 2746584c8..71fcffe8e 100644 --- a/include/asm-arm/arch-ebsa285/a.out.h +++ b/include/asm-arm/arch-ebsa285/a.out.h @@ -1,15 +1,16 @@ /* * linux/include/asm-arm/arch-ebsa110/a.out.h * - * Copyright (C) 1996 Russell King + * Copyright (C) 1996-1999 Russell King */ - #ifndef __ASM_ARCH_A_OUT_H #define __ASM_ARCH_A_OUT_H -#ifdef __KERNEL__ -#define STACK_TOP ((current->personality==PER_LINUX_32BIT)? 0xc0000000 : 0x04000000) -#endif +#include <asm/arch/memory.h> + +#define STACK_TOP \ + ((current->personality == PER_LINUX_32BIT) ? \ + TASK_SIZE : 0x04000000) #endif diff --git a/include/asm-arm/arch-ebsa285/dma.h b/include/asm-arm/arch-ebsa285/dma.h index 28c093aec..8b74a7f84 100644 --- a/include/asm-arm/arch-ebsa285/dma.h +++ b/include/asm-arm/arch-ebsa285/dma.h @@ -3,8 +3,8 @@ * * Architecture DMA routines * - * Copyright (C) 1998 Russell King - * Copyright (C) 1998 Philip Blundell + * Copyright (C) 1998,1999 Russell King + * Copyright (C) 1998,1999 Philip Blundell */ #ifndef __ASM_ARCH_DMA_H #define __ASM_ARCH_DMA_H @@ -15,12 +15,16 @@ #define MAX_DMA_ADDRESS 0xffffffff /* - * The 21285 has two internal DMA channels; we call these 0 and 1. + * The 21285 has two internal DMA channels; we call these 8 and 9. * On CATS hardware we have an additional eight ISA dma channels - * numbered 2..9. + * numbered 0..7. */ +#define _ISA_DMA(x) (0+(x)) +#define _DC21285_DMA(x) (8+(x)) + #define MAX_DMA_CHANNELS 10 -#define DMA_ISA_BASE 2 -#define DMA_FLOPPY (DMA_ISA_BASE + 2) + +#define DMA_FLOPPY _ISA_DMA(2) +#define DMA_ISA_CASCADE _ISA_DMA(4) #endif /* _ASM_ARCH_DMA_H */ diff --git a/include/asm-arm/arch-ebsa285/hardware.h b/include/asm-arm/arch-ebsa285/hardware.h index e08c5b823..c989e0f09 100644 --- a/include/asm-arm/arch-ebsa285/hardware.h +++ b/include/asm-arm/arch-ebsa285/hardware.h @@ -1,47 +1,135 @@ /* * linux/include/asm-arm/arch-ebsa285/hardware.h * - * Copyright (C) 1998 Russell King. + * Copyright (C) 1998-1999 Russell King. * * This file contains the hardware definitions of the EBSA-285. */ +#ifndef __ASM_ARCH_HARDWARE_H +#define __ASM_ARCH_HARDWARE_H +#include <linux/config.h> +#include <asm/arch/memory.h> -/* Logical Physical +#ifdef CONFIG_HOST_FOOTBRIDGE +/* Virtual Physical * 0xfff00000 0x40000000 X-Bus - * 0xffe00000 0x7c000000 PCI I/O space + * 0xff000000 0x7c000000 PCI I/O space * * 0xfe000000 0x42000000 CSR * 0xfd000000 0x78000000 Outbound write flush * 0xfc000000 0x79000000 PCI IACK/special space * - * 0xf9000000 0x7a010000 PCI Config type 1 - * 0xf8000000 0x7b010000 PCI Config type 0 + * 0xf9000000 0x7a000000 PCI Config type 1 + * 0xf8000000 0x7b000000 PCI Config type 0 * */ +#define XBUS_SIZE 0x00100000 +#define XBUS_BASE 0xfff00000 -#include <asm/dec21285.h> - -#define IO_BASE 0xe0000000 -#define PCIO_BASE 0xffe00000 -#define PCI_IACK 0xfc000000 +#define PCIO_SIZE 0x00100000 +#define PCIO_BASE 0xff000000 -#define XBUS_LEDS ((volatile unsigned char *)0xfff12000) +#define ARMCSR_SIZE 0x01000000 +#define ARMCSR_BASE 0xfe000000 + +#define WFLUSH_SIZE 0x01000000 +#define WFLUSH_BASE 0xfd000000 + +#define PCIIACK_SIZE 0x01000000 +#define PCIIACK_BASE 0xfc000000 + +#define PCICFG1_SIZE 0x01000000 +#define PCICFG1_BASE 0xf9000000 + +#define PCICFG0_SIZE 0x01000000 +#define PCICFG0_BASE 0xf8000000 + +#define PCIMEM_SIZE 0x18000000 +#define PCIMEM_BASE 0xe0000000 + +#define FLUSH_SIZE 0x00100000 +#define FLUSH_BASE 0xdf000000 + +#define FLASH_SIZE 0x00400000 +#define FLASH_BASE 0xd8000000 + +#elif defined(CONFIG_ARCH_CO285) + +#define PCIMEM_SIZE 0x80000000 +#define PCIMEM_BASE 0x80000000 + +#define FLASH_SIZE 0x01000000 +#define FLASH_BASE 0x7f000000 + +#define FLUSH_SIZE 0x00100000 +#define FLUSH_BASE 0x7e000000 + +#define WFLUSH_SIZE 0x01000000 +#define WFLUSH_BASE 0x7d000000 + +#define ARMCSR_SIZE 0x00100000 +#define ARMCSR_BASE 0x7cf00000 + +#define XBUS_SIZE 0x00020000 +#define XBUS_BASE 0x7cee0000 + +#define PCIO_SIZE 0x00010000 +#define PCIO_BASE 0x7ced0000 + +#else + +#error Add your add-in architecture here + +#endif + +#define XBUS_LEDS ((volatile unsigned char *)(XBUS_BASE + 0x12000)) #define XBUS_LED_AMBER (1 << 0) #define XBUS_LED_GREEN (1 << 1) #define XBUS_LED_RED (1 << 2) #define XBUS_LED_TOGGLE (1 << 8) -#define XBUS_SWITCH ((volatile unsigned char *)0xfff12000) +#define XBUS_SWITCH ((volatile unsigned char *)(XBUS_BASE + 0x12000)) #define XBUS_SWITCH_SWITCH ((*XBUS_SWITCH) & 15) #define XBUS_SWITCH_J17_13 ((*XBUS_SWITCH) & (1 << 4)) #define XBUS_SWITCH_J17_11 ((*XBUS_SWITCH) & (1 << 5)) #define XBUS_SWITCH_J17_9 ((*XBUS_SWITCH) & (1 << 6)) -#define KERNTOPHYS(a) ((unsigned long)(&a)) - #define PARAMS_OFFSET 0x0100 #define PARAMS_BASE (PAGE_OFFSET + PARAMS_OFFSET) #define FLUSH_BASE_PHYS 0x50000000 + +/* PIC irq control */ +#define PIC_LO 0x20 +#define PIC_MASK_LO 0x21 +#define PIC_HI 0xA0 +#define PIC_MASK_HI 0xA1 + +/* GPIO pins */ +#define GPIO_CCLK 0x800 +#define GPIO_DSCLK 0x400 +#define GPIO_E2CLK 0x200 +#define GPIO_IOLOAD 0x100 +#define GPIO_RED_LED 0x080 +#define GPIO_WDTIMER 0x040 +#define GPIO_DATA 0x020 +#define GPIO_IOCLK 0x010 +#define GPIO_DONE 0x008 +#define GPIO_FAN 0x004 +#define GPIO_GREEN_LED 0x002 +#define GPIO_RESET 0x001 + +/* CPLD pins */ +#define CPLD_DSRESET 8 +#define CPLD_UNMUTE 2 + +#ifndef __ASSEMBLY__ +extern void gpio_modify_op(int mask, int set); +extern void gpio_modify_io(int mask, int in); +extern int gpio_read(void); +extern void cpld_modify(int mask, int set); +#endif + +#endif diff --git a/include/asm-arm/arch-ebsa285/io.h b/include/asm-arm/arch-ebsa285/io.h index 1be73879d..b23ee6863 100644 --- a/include/asm-arm/arch-ebsa285/io.h +++ b/include/asm-arm/arch-ebsa285/io.h @@ -16,34 +16,37 @@ * has the constant-optimised IO */ #undef ARCH_IO_DELAY +#define ARCH_READWRITE /* * Dynamic IO functions - let the compiler * optimize the expressions */ -#define DECLARE_DYN_OUT(fnsuffix,instr,typ) \ -extern __inline__ void __out##fnsuffix (unsigned int value, unsigned int port) \ -{ \ - __asm__ __volatile__( \ - "str%?" ##instr## " %0, [%1, %2] @ out"###fnsuffix \ - : \ - : "r" (value), "r" (PCIO_BASE), typ (port)); \ +#define DECLARE_DYN_OUT(fnsuffix,instr,typ) \ +extern __inline__ void \ +__out##fnsuffix (unsigned int value, unsigned int port) \ +{ \ + __asm__ __volatile__( \ + "str%?" ##instr## " %0, [%1, %2] @ out"###fnsuffix \ + : \ + : "r" (value), "r" (PCIO_BASE), typ (port)); \ } -#define DECLARE_DYN_IN(sz,fnsuffix,instr,typ) \ -extern __inline__ unsigned sz __in##fnsuffix (unsigned int port) \ -{ \ - unsigned long value; \ - __asm__ __volatile__( \ - "ldr%?" ##instr## " %0, [%1, %2] @ in"###fnsuffix \ - : "=&r" (value) \ - : "r" (PCIO_BASE), typ (port)); \ - return (unsigned sz)value; \ +#define DECLARE_DYN_IN(sz,fnsuffix,instr,typ) \ +extern __inline__ unsigned sz \ +__in##fnsuffix (unsigned int port) \ +{ \ + unsigned long value; \ + __asm__ __volatile__( \ + "ldr%?" ##instr## " %0, [%1, %2] @ in"###fnsuffix \ + : "=&r" (value) \ + : "r" (PCIO_BASE), typ (port)); \ + return (unsigned sz)value; \ } -extern __inline__ unsigned int __ioaddr (unsigned int port) \ -{ \ - return (unsigned int)(PCIO_BASE + port); \ +extern __inline__ unsigned int __ioaddr (unsigned int port) \ +{ \ + return (unsigned int)(PCIO_BASE + port); \ } #define DECLARE_IO(sz,fnsuffix,instr,typ) \ @@ -64,65 +67,65 @@ DECLARE_IO(long,l,"","Jr") * These have to be macros for the 'J' constraint to work - * +/-4096 immediate operand. */ -#define __outbc(value,port) \ -({ \ - __asm__ __volatile__( \ - "str%?b %0, [%1, %2] @ outbc" \ - : \ - : "r" (value), "r" (PCIO_BASE), "Jr" (port)); \ +#define __outbc(value,port) \ +({ \ + __asm__ __volatile__( \ + "str%?b %0, [%1, %2] @ outbc" \ + : \ + : "r" (value), "r" (PCIO_BASE), "Jr" (port)); \ }) -#define __inbc(port) \ -({ \ - unsigned char result; \ - __asm__ __volatile__( \ - "ldr%?b %0, [%1, %2] @ inbc" \ - : "=r" (result) \ - : "r" (PCIO_BASE), "Jr" (port)); \ - result; \ +#define __inbc(port) \ +({ \ + unsigned char result; \ + __asm__ __volatile__( \ + "ldr%?b %0, [%1, %2] @ inbc" \ + : "=r" (result) \ + : "r" (PCIO_BASE), "Jr" (port)); \ + result; \ }) -#define __outwc(value,port) \ -({ \ - __asm__ __volatile__( \ - "str%?h %0, [%1, %2] @ outwc" \ - : \ - : "r" (value), "r" (PCIO_BASE), "r" (port)); \ +#define __outwc(value,port) \ +({ \ + __asm__ __volatile__( \ + "str%?h %0, [%1, %2] @ outwc" \ + : \ + : "r" (value), "r" (PCIO_BASE), "r" (port)); \ }) -#define __inwc(port) \ -({ \ - unsigned short result; \ - __asm__ __volatile__( \ - "ldr%?h %0, [%1, %2] @ inwc" \ - : "=r" (result) \ - : "r" (PCIO_BASE), "r" (port)); \ - result & 0xffff; \ +#define __inwc(port) \ +({ \ + unsigned short result; \ + __asm__ __volatile__( \ + "ldr%?h %0, [%1, %2] @ inwc" \ + : "=r" (result) \ + : "r" (PCIO_BASE), "r" (port)); \ + result & 0xffff; \ }) -#define __outlc(value,port) \ -({ \ - __asm__ __volatile__( \ - "str%? %0, [%1, %2] @ outlc" \ - : \ - : "r" (value), "r" (PCIO_BASE), "Jr" (port)); \ +#define __outlc(value,port) \ +({ \ + __asm__ __volatile__( \ + "str%? %0, [%1, %2] @ outlc" \ + : \ + : "r" (value), "r" (PCIO_BASE), "Jr" (port)); \ }) -#define __inlc(port) \ -({ \ - unsigned long result; \ - __asm__ __volatile__( \ - "ldr%? %0, [%1, %2] @ inlc" \ - : "=r" (result) \ - : "r" (PCIO_BASE), "Jr" (port)); \ - result; \ +#define __inlc(port) \ +({ \ + unsigned long result; \ + __asm__ __volatile__( \ + "ldr%? %0, [%1, %2] @ inlc" \ + : "=r" (result) \ + : "r" (PCIO_BASE), "Jr" (port)); \ + result; \ }) -#define __ioaddrc(port) \ -({ \ - unsigned long addr; \ - addr = PCIO_BASE + port; \ - addr; \ +#define __ioaddrc(port) \ +({ \ + unsigned long addr; \ + addr = PCIO_BASE + port; \ + addr; \ }) /* @@ -130,20 +133,22 @@ DECLARE_IO(long,l,"","Jr") * * IO address has already been translated to a virtual address */ -#define outb_t(v,p) \ +#define outb_t(v,p) \ (*(volatile unsigned char *)(p) = (v)) -#define inb_t(p) \ +#define inb_t(p) \ (*(volatile unsigned char *)(p)) -#define outl_t(v,p) \ +#define outl_t(v,p) \ (*(volatile unsigned long *)(p) = (v)) -#define inl_t(p) \ +#define inl_t(p) \ (*(volatile unsigned long *)(p)) /* - * ioremap support + * ioremap support - validate a PCI memory address, + * and convert a PCI memory address to a physical + * address for the page tables. */ #define valid_ioaddr(iomem,size) ((iomem) < 0x80000000 && (iomem) + (size) <= 0x80000000) #define io_to_phys(iomem) ((iomem) + DC21285_PCI_MEM) @@ -153,58 +158,48 @@ DECLARE_IO(long,l,"","Jr") * is using read*() and so on with addresses they didn't get from ioremap * this can go away. */ -#define IO_FUDGE_FACTOR 0xe0000000 +#define IO_FUDGE_FACTOR PCIMEM_BASE -extern inline void *ioremap(unsigned long iomem_addr, unsigned long size) -{ - unsigned long phys_addr; - - if (!valid_ioaddr(iomem_addr, size)) - return NULL; - - phys_addr = io_to_phys(iomem_addr & PAGE_MASK); - - return (void *)((unsigned long)__ioremap(phys_addr, size, 0) - - IO_FUDGE_FACTOR); -} +/* + * ioremap takes a PCI memory address, as specified in + * linux/Documentation/IO-mapping.txt + */ +#define ioremap(iomem_addr,size) \ +({ \ + unsigned long _addr = (iomem_addr), _size = (size); \ + void *_ret = NULL; \ + if (valid_ioaddr(_addr, _size)) { \ + _addr = io_to_phys(_addr); \ + _ret = __ioremap(_addr, _size, 0) - IO_FUDGE_FACTOR; \ + } \ + _ret; }) #define ioremap_nocache(iomem_addr,size) ioremap((iomem_addr),(size)) extern void iounmap(void *addr); -/* - * We'd probably be better off with these as macros rather than functions. - * Firstly that would be more efficient and secondly we could do with the - * ability to stop GCC whinging about type conversions. --philb - */ -static inline void writeb(unsigned char b, unsigned int addr) -{ - *(volatile unsigned char *)(IO_FUDGE_FACTOR + (addr)) = b; -} - -static inline unsigned char readb(unsigned int addr) -{ - return *(volatile unsigned char *)(IO_FUDGE_FACTOR + (addr)); +#define DECLARE_PCI_WRITE(typ,fnsuffix) \ +static inline void write##fnsuffix(unsigned typ val, unsigned int addr) \ +{ \ + *(volatile unsigned typ *)(IO_FUDGE_FACTOR + addr) = val; \ } -static inline void writew(unsigned short b, unsigned int addr) -{ - *(volatile unsigned short *)(IO_FUDGE_FACTOR + (addr)) = b; +#define DECLARE_PCI_READ(typ,fnsuffix) \ +static inline unsigned typ read##fnsuffix (unsigned int addr) \ +{ \ + return *(volatile unsigned typ *)(IO_FUDGE_FACTOR + addr); \ } -static inline unsigned short readw(unsigned int addr) -{ - return *(volatile unsigned short *)(IO_FUDGE_FACTOR + (addr)); -} +#define DECLARE_PCI(typ,fnsuffix) \ + DECLARE_PCI_WRITE(typ,fnsuffix) \ + DECLARE_PCI_READ(typ,fnsuffix) -static inline void writel(unsigned long b, unsigned int addr) -{ - *(volatile unsigned long *)(IO_FUDGE_FACTOR + (addr)) = b; -} +DECLARE_PCI(char,b) +DECLARE_PCI(short,w) +DECLARE_PCI(long,l) -static inline unsigned short readl(unsigned int addr) -{ - return *(volatile unsigned long *)(IO_FUDGE_FACTOR + (addr)); -} +#undef DECLARE_PCI +#undef DECLARE_PCI_READ +#undef DECLARE_PCI_WRITE #endif diff --git a/include/asm-arm/arch-ebsa285/irq.h b/include/asm-arm/arch-ebsa285/irq.h index 74bc33c58..ca1a55cdb 100644 --- a/include/asm-arm/arch-ebsa285/irq.h +++ b/include/asm-arm/arch-ebsa285/irq.h @@ -4,136 +4,206 @@ * Copyright (C) 1996-1998 Russell King * * Changelog: - * 22-08-1998 RMK Restructured IRQ routines - * 03-09-1998 PJB Merged CATS support + * 22-Aug-1998 RMK Restructured IRQ routines + * 03-Sep-1998 PJB Merged CATS support + * 20-Jan-1998 RMK Started merge of EBSA286, CATS and NetWinder + * 26-Jan-1999 PJB Don't use IACK on CATS + * 16-Mar-1999 RMK Added autodetect of ISA PICs */ #include <linux/config.h> +#include <asm/hardware.h> +#include <asm/dec21285.h> +#include <asm/irq.h> -static void ebsa285_mask_irq(unsigned int irq) +/* + * Footbridge IRQ translation table + * Converts from our IRQ numbers into FootBridge masks + */ +static int dc21285_irq_mask[] = { + IRQ_MASK_UART_RX, /* 0 */ + IRQ_MASK_UART_TX, /* 1 */ + IRQ_MASK_TIMER1, /* 2 */ + IRQ_MASK_TIMER2, /* 3 */ + IRQ_MASK_TIMER3, /* 4 */ + IRQ_MASK_IN0, /* 5 */ + IRQ_MASK_IN1, /* 6 */ + IRQ_MASK_IN2, /* 7 */ + IRQ_MASK_IN3, /* 8 */ + IRQ_MASK_DOORBELLHOST, /* 9 */ + IRQ_MASK_DMA1, /* 10 */ + IRQ_MASK_DMA2, /* 11 */ + IRQ_MASK_PCI, /* 12 */ + IRQ_MASK_SDRAMPARITY, /* 13 */ + IRQ_MASK_I2OINPOST, /* 14 */ + IRQ_MASK_PCI_ERR /* 15 */ +}; + +static int isa_irq = -1; + +static inline int fixup_irq(unsigned int irq) { - *CSR_IRQ_DISABLE = 1 << irq; +#ifdef CONFIG_HOST_FOOTBRIDGE + if (irq == isa_irq) + irq = *(unsigned char *)PCIIACK_BASE; +#endif + + return irq; } -static void ebsa285_unmask_irq(unsigned int irq) +static void dc21285_mask_irq(unsigned int irq) { - *CSR_IRQ_ENABLE = 1 << irq; + *CSR_IRQ_DISABLE = dc21285_irq_mask[irq & 15]; } -#ifdef CONFIG_CATS +static void dc21285_unmask_irq(unsigned int irq) +{ + *CSR_IRQ_ENABLE = dc21285_irq_mask[irq & 15]; +} -/* - * This contains the irq mask for both 8259A irq controllers, - */ -static unsigned int isa_irq_mask = 0xffff; +static void isa_mask_pic_lo_irq(unsigned int irq) +{ + unsigned int mask = 1 << (irq & 7); + + outb(inb(PIC_MASK_LO) | mask, PIC_MASK_LO); +} -#define cached_21 (isa_irq_mask & 0xff) -#define cached_A1 ((isa_irq_mask >> 8) & 0xff) +static void isa_mask_ack_pic_lo_irq(unsigned int irq) +{ + unsigned int mask = 1 << (irq & 7); -#define update_8259(_irq) \ - if ((_irq) & 8) \ - outb(cached_A1, 0xa1); \ - else \ - outb(cached_21, 0x21); + outb(inb(PIC_MASK_LO) | mask, PIC_MASK_LO); + outb(0x20, PIC_LO); +} -static void isa_interrupt(int irq, void *h, struct pt_regs *regs) +static void isa_unmask_pic_lo_irq(unsigned int irq) { - asmlinkage void do_IRQ(int irq, struct pt_regs * regs); - unsigned int irqbits = inb(0x20) | (inb(0xa0) << 8), irqnr = 0; - irqbits &= ~(1<<2); /* don't try to service the cascade */ - while (irqbits) { - if (irqbits & 1) - do_IRQ(32 + irqnr, regs); - irqbits >>= 1; - irqnr++; - } + unsigned int mask = 1 << (irq & 7); + + outb(inb(PIC_MASK_LO) & ~mask, PIC_MASK_LO); } -static void no_action(int cpl, void *dev_id, struct pt_regs *regs) { } +static void isa_mask_pic_hi_irq(unsigned int irq) +{ + unsigned int mask = 1 << (irq & 7); -static struct irqaction irq_isa = - { isa_interrupt, SA_INTERRUPT, 0, "ISA PIC", NULL, NULL }; -static struct irqaction irq_cascade = - { no_action, 0, 0, "cascade", NULL, NULL }; + outb(inb(PIC_MASK_HI) | mask, PIC_MASK_HI); +} -static void cats_mask_and_ack_isa_irq(unsigned int irq) +static void isa_mask_ack_pic_hi_irq(unsigned int irq) { - isa_irq_mask |= (1 << (irq - 32)); - update_8259(irq); - if (irq & 8) { - inb(0xA1); /* DUMMY */ - outb(cached_A1,0xA1); - outb(0x62,0x20); /* Specific EOI to cascade */ - outb(0x20,0xA0); - } else { - inb(0x21); /* DUMMY */ - outb(cached_21,0x21); - outb(0x20,0x20); - } + unsigned int mask = 1 << (irq & 7); + + outb(inb(PIC_MASK_HI) | mask, PIC_MASK_HI); + outb(0x62, PIC_LO); + outb(0x20, PIC_HI); } -static void cats_mask_isa_irq(unsigned int irq) +static void isa_unmask_pic_hi_irq(unsigned int irq) { - isa_irq_mask |= (1 << (irq - 32)); - update_8259(irq); + unsigned int mask = 1 << (irq & 7); + + outb(inb(PIC_MASK_HI) & ~mask, PIC_MASK_HI); } -static void cats_unmask_isa_irq(unsigned int irq) +static void no_action(int cpl, void *dev_id, struct pt_regs *regs) { - isa_irq_mask &= ~(1 << (irq - 32)); - update_8259(irq); } - -#endif + +static struct irqaction irq_cascade = { no_action, 0, 0, "cascade", NULL, NULL }; static __inline__ void irq_init_irq(void) { int irq; + /* + * setup DC21285 IRQs + */ *CSR_IRQ_DISABLE = -1; *CSR_FIQ_DISABLE = -1; - for (irq = 0; irq < NR_IRQS; irq++) { + for (irq = _DC21285_IRQ(0); irq < _DC21285_IRQ(16); irq++) { irq_desc[irq].valid = 1; irq_desc[irq].probe_ok = 1; -#ifdef CONFIG_CATS - if (machine_is_cats() && IRQ_IS_ISA(irq)) { - irq_desc[irq].mask_ack = cats_mask_and_ack_isa_irq; - irq_desc[irq].mask = cats_mask_isa_irq; - irq_desc[irq].unmask = cats_unmask_isa_irq; + irq_desc[irq].mask_ack = dc21285_mask_irq; + irq_desc[irq].mask = dc21285_mask_irq; + irq_desc[irq].unmask = dc21285_unmask_irq; + } + + /* + * Determine the ISA settings for + * the machine we're running on. + */ + switch (machine_arch_type) { + default: + isa_irq = -1; + break; + + case MACH_TYPE_EBSA285: + /* The following is dependent on which slot + * you plug the Southbridge card into. We + * currently assume that you plug it into + * the right-hand most slot. + */ + isa_irq = IRQ_PCI; + break; + + case MACH_TYPE_CATS: + isa_irq = IRQ_IN2; + break; + + case MACH_TYPE_NETWINDER: + isa_irq = IRQ_IN3; + break; + } + + if (isa_irq != -1) { + /* + * Setup, and then probe for an ISA PIC + */ + outb(0x11, PIC_LO); + outb(_ISA_IRQ(0), PIC_MASK_LO); /* IRQ number */ + outb(0x04, PIC_MASK_LO); /* Slave on Ch2 */ + outb(0x01, PIC_MASK_LO); /* x86 */ + outb(0xf5, PIC_MASK_LO); /* pattern: 11110101 */ + + outb(0x11, PIC_HI); + outb(_ISA_IRQ(8), PIC_MASK_HI); /* IRQ number */ + outb(0x02, PIC_MASK_HI); /* Slave on Ch1 */ + outb(0x01, PIC_MASK_HI); /* x86 */ + outb(0xfa, PIC_MASK_HI); /* pattern: 11111010 */ + +// outb(0x68, PIC_LO); /* enable special mode */ +// outb(0x68, PIC_HI); /* enable special mode */ + outb(0x0b, PIC_LO); + outb(0x0b, PIC_HI); + + if (inb(PIC_MASK_LO) == 0xf5 && inb(PIC_MASK_HI) == 0xfa) { + outb(0xff, PIC_MASK_LO);/* mask all IRQs */ + outb(0xff, PIC_MASK_HI);/* mask all IRQs */ } else -#endif - { - irq_desc[irq].mask_ack = ebsa285_mask_irq; - irq_desc[irq].mask = ebsa285_mask_irq; - irq_desc[irq].unmask = ebsa285_unmask_irq; - } + isa_irq = -1; } -#ifdef CONFIG_CATS - if (machine_is_cats()) { - request_region(0x20, 2, "pic1"); - request_region(0xa0, 2, "pic2"); - - /* set up master 8259 */ - outb(0x11, 0x20); - outb(0, 0x21); - outb(1<<2, 0x21); - outb(0x1, 0x21); - outb(0xff, 0x21); - outb(0x68, 0x20); - outb(0xa, 0x20); - - /* set up slave 8259 */ - outb(0x11, 0xa0); - outb(0, 0xa1); - outb(2, 0xa1); - outb(0x1, 0xa1); - outb(0xff, 0xa1); - outb(0x68, 0xa0); - outb(0xa, 0xa0); - - setup_arm_irq(IRQ_ISA_PIC, &irq_isa); + if (isa_irq != -1) { + for (irq = _ISA_IRQ(0); irq < _ISA_IRQ(8); irq++) { + irq_desc[irq].valid = 1; + irq_desc[irq].probe_ok = 1; + irq_desc[irq].mask_ack = isa_mask_ack_pic_lo_irq; + irq_desc[irq].mask = isa_mask_pic_lo_irq; + irq_desc[irq].unmask = isa_unmask_pic_lo_irq; + } + + for (irq = _ISA_IRQ(8); irq < _ISA_IRQ(16); irq++) { + irq_desc[irq].valid = 1; + irq_desc[irq].probe_ok = 1; + irq_desc[irq].mask_ack = isa_mask_ack_pic_hi_irq; + irq_desc[irq].mask = isa_mask_pic_hi_irq; + irq_desc[irq].unmask = isa_unmask_pic_hi_irq; + } + + request_region(PIC_LO, 2, "pic1"); + request_region(PIC_HI, 2, "pic2"); setup_arm_irq(IRQ_ISA_CASCADE, &irq_cascade); + setup_arm_irq(isa_irq, &irq_cascade); } -#endif } diff --git a/include/asm-arm/arch-ebsa285/irqs.h b/include/asm-arm/arch-ebsa285/irqs.h index 6021bee6e..afb2e379d 100644 --- a/include/asm-arm/arch-ebsa285/irqs.h +++ b/include/asm-arm/arch-ebsa285/irqs.h @@ -3,55 +3,85 @@ * * Copyright (C) 1998 Russell King * Copyright (C) 1998 Phil Blundell + * + * Changelog: + * 20-Jan-1998 RMK Started merge of EBSA286, CATS and NetWinder + * 01-Feb-1999 PJB ISA IRQs start at 0 not 16 */ -#define NR_IRQS 48 +#define NR_IRQS 32 +#define NR_DC21285_IRQS 16 + +#define _ISA_IRQ(x) (0 + (x)) +#define _DC21285_IRQ(x) (16 + (x)) /* * This is a list of all interrupts that the 21285 - * can generate + * can generate and we handle. */ -#define IRQ_RESERVED 0 -#define IRQ_SOFTIRQ 1 -#define IRQ_CONRX 2 -#define IRQ_CONTX 3 -#define IRQ_TIMER1 4 -#define IRQ_TIMER2 5 -#define IRQ_TIMER3 6 -#define IRQ_TIMER4 7 -#define IRQ_IN0 8 -#define IRQ_IN1 9 -#define IRQ_IN2 10 -#define IRQ_IN3 11 -#define IRQ_XCS0 12 -#define IRQ_XCS1 13 -#define IRQ_XCS2 14 -#define IRQ_DOORBELLHOST 15 -#define IRQ_DMA1 16 -#define IRQ_DMA2 17 -#define IRQ_PCI 18 -#define IRQ_BIST 22 -#define IRQ_SERR 23 -#define IRQ_SDRAMPARITY 24 -#define IRQ_I2OINPOST 25 -#define IRQ_DISCARDTIMER 27 -#define IRQ_PCIDATAPARITY 28 -#define IRQ_PCIMASTERABORT 29 -#define IRQ_PCITARGETABORT 30 -#define IRQ_PCIPARITY 31 - -/* IRQs 32-47 are the 16 ISA interrupts on a CATS board. */ -#define IRQ_ISA_PIC IRQ_IN2 -#define IRQ_IS_ISA(_x) (((_x) >= 32) && ((_x) <= 47)) -#define IRQ_ISA(_x) ((_x) + 0x20) -#define IRQ_ISA_CASCADE IRQ_ISA(2) +#define IRQ_CONRX _DC21285_IRQ(0) +#define IRQ_CONTX _DC21285_IRQ(1) +#define IRQ_TIMER1 _DC21285_IRQ(2) +#define IRQ_TIMER2 _DC21285_IRQ(3) +#define IRQ_TIMER3 _DC21285_IRQ(4) +#define IRQ_IN0 _DC21285_IRQ(5) +#define IRQ_IN1 _DC21285_IRQ(6) +#define IRQ_IN2 _DC21285_IRQ(7) +#define IRQ_IN3 _DC21285_IRQ(8) +#define IRQ_DOORBELLHOST _DC21285_IRQ(9) +#define IRQ_DMA1 _DC21285_IRQ(10) +#define IRQ_DMA2 _DC21285_IRQ(11) +#define IRQ_PCI _DC21285_IRQ(12) +#define IRQ_SDRAMPARITY _DC21285_IRQ(13) +#define IRQ_I2OINPOST _DC21285_IRQ(14) +#define IRQ_PCI_ERR _DC21285_IRQ(15) + +#define IRQ_ISA_TIMER _ISA_IRQ(0) +#define IRQ_ISA_KEYBOARD _ISA_IRQ(1) +#define IRQ_ISA_CASCADE _ISA_IRQ(2) +#define IRQ_ISA_UART2 _ISA_IRQ(3) +#define IRQ_ISA_UART _ISA_IRQ(4) +#define IRQ_ISA_FLOPPY _ISA_IRQ(6) +#define IRQ_ISA_PRINTER _ISA_IRQ(7) +#define IRQ_ISA_RTC_ALARM _ISA_IRQ(8) +#define IRQ_ISA_2 _ISA_IRQ(9) +#define IRQ_ISA_PS2MOUSE _ISA_IRQ(12) +#define IRQ_ISA_HARDDISK1 _ISA_IRQ(14) +#define IRQ_ISA_HARDDISK2 _ISA_IRQ(15) + +#define IRQ_MASK_UART_RX (1 << 2) +#define IRQ_MASK_UART_TX (1 << 3) +#define IRQ_MASK_TIMER1 (1 << 4) +#define IRQ_MASK_TIMER2 (1 << 5) +#define IRQ_MASK_TIMER3 (1 << 6) +#define IRQ_MASK_IN0 (1 << 8) +#define IRQ_MASK_IN1 (1 << 9) +#define IRQ_MASK_IN2 (1 << 10) +#define IRQ_MASK_IN3 (1 << 11) +#define IRQ_MASK_DOORBELLHOST (1 << 15) +#define IRQ_MASK_DMA1 (1 << 16) +#define IRQ_MASK_DMA2 (1 << 17) +#define IRQ_MASK_PCI (1 << 18) +#define IRQ_MASK_SDRAMPARITY (1 << 24) +#define IRQ_MASK_I2OINPOST (1 << 25) +#define IRQ_MASK_PCI_ERR ((1 <<23) | (1 << 27) | (1 << 28) | (1 << 29) | (1 << 30) | (1 << 31)) /* - * Now map them to the Linux interrupts + * Netwinder interrupt allocations */ -#define IRQ_TIMER IRQ_TIMER1 -#define IRQ_FLOPPYDISK IRQ_ISA(6) -#define IRQ_HARDDISK IRQ_ISA(14) -#define IRQ_HARDDISK_SECONDARY IRQ_ISA(15) +#define IRQ_NETWINDER_ETHER10 IRQ_IN0 +#define IRQ_NETWINDER_ETHER100 IRQ_IN1 +#define IRQ_NETWINDER_VIDCOMP IRQ_IN2 +#define IRQ_NETWINDER_PS2MOUSE _ISA_IRQ(5) +#define IRQ_NETWINDER_IR _ISA_IRQ(6) +#define IRQ_NETWINDER_BUTTON _ISA_IRQ(10) +#define IRQ_NETWINDER_VGA _ISA_IRQ(11) +#define IRQ_NETWINDER_SOUND _ISA_IRQ(12) + +#undef RTC_IRQ +#define RTC_IRQ IRQ_ISA_RTC_ALARM +#undef AUX_IRQ +#define AUX_IRQ (machine_is_netwinder() ? IRQ_NETWINDER_PS2MOUSE : IRQ_ISA_PS2MOUSE) +#define IRQ_FLOPPYDISK IRQ_ISA_FLOPPY -#define irq_cannonicalize(_i) (((_i) == IRQ_ISA_CASCADE) ? IRQ_ISA(9) : _i) +#define irq_cannonicalize(_i) (((_i) == IRQ_ISA_CASCADE) ? IRQ_ISA_2 : _i) diff --git a/include/asm-arm/arch-ebsa285/keyboard.h b/include/asm-arm/arch-ebsa285/keyboard.h index ad6eb0e5a..dcc7b49f9 100644 --- a/include/asm-arm/arch-ebsa285/keyboard.h +++ b/include/asm-arm/arch-ebsa285/keyboard.h @@ -6,20 +6,13 @@ * (C) 1998 Russell King * (C) 1998 Phil Blundell */ - -#include <linux/config.h> #include <asm/irq.h> #include <asm/system.h> -#define NR_SCANCODES 128 - -#ifdef CONFIG_CATS - -#define KEYBOARD_IRQ IRQ_ISA(1) +extern int have_isa_bridge; extern int pckbd_setkeycode(unsigned int scancode, unsigned int keycode); extern int pckbd_getkeycode(unsigned int scancode); -extern int pckbd_pretranslate(unsigned char scancode, char raw_mode); extern int pckbd_translate(unsigned char scancode, unsigned char *keycode, char raw_mode); extern char pckbd_unexpected_up(unsigned char keycode); @@ -27,46 +20,52 @@ extern void pckbd_leds(unsigned char leds); extern void pckbd_init_hw(void); extern unsigned char pckbd_sysrq_xlate[128]; -#define kbd_setkeycode pckbd_setkeycode -#define kbd_getkeycode pckbd_getkeycode -#define kbd_pretranslate pckbd_pretranslate -#define kbd_translate(sc, kcp, ufp, rm) ({ *ufp = sc & 0200; \ - pckbd_translate(sc & 0x7f, kcp, rm);}) +#define KEYBOARD_IRQ IRQ_ISA_KEYBOARD -#define kbd_unexpected_up pckbd_unexpected_up -#define kbd_leds pckbd_leds -#define kbd_init_hw() \ - do { if (machine_is_cats()) pckbd_init_hw(); } while (0) -#define kbd_sysrq_xlate pckbd_sysrq_xlate -#define kbd_disable_irq() -#define kbd_enable_irq() +#define NR_SCANCODES 128 -#define SYSRQ_KEY 0x54 +#define kbd_setkeycode(sc,kc) \ + ({ \ + int __ret; \ + if (have_isa_bridge) \ + __ret = pckbd_setkeycode(sc,kc);\ + else \ + __ret = -EINVAL; \ + __ret; \ + }) -#else +#define kbd_getkeycode(sc) \ + ({ \ + int __ret; \ + if (have_isa_bridge) \ + __ret = pckbd_getkeycode(sc); \ + else \ + __ret = -EINVAL; \ + __ret; \ + }) -/* Dummy keyboard definitions */ +#define kbd_translate(sc, kcp, rm) \ + ({ \ + pckbd_translate(sc, kcp, rm); \ + }) -#define kbd_setkeycode(sc,kc) (-EINVAL) -#define kbd_getkeycode(sc) (-EINVAL) +#define kbd_unexpected_up pckbd_unexpected_up -/* Prototype: int kbd_pretranslate(scancode, raw_mode) - * Returns : 0 to ignore scancode - */ -#define kbd_pretranslate(sc,rm) (1) +#define kbd_leds(leds) \ + do { \ + if (have_isa_bridge) \ + pckbd_leds(leds); \ + } while (0) + +#define kbd_init_hw() \ + do { \ + if (have_isa_bridge) \ + pckbd_init_hw(); \ + } while (0) + +#define kbd_sysrq_xlate pckbd_sysrq_xlate -/* Prototype: int kbd_translate(scancode, *keycode, *up_flag, raw_mode) - * Returns : 0 to ignore scancode, *keycode set to keycode, *up_flag - * set to 0200 if scancode indicates release - */ -#define kbd_translate(sc, kcp, ufp, rm) (1) -#define kbd_unexpected_up(kc) (0200) -#define kbd_leds(leds) -#define kbd_init_hw() -//#define kbd_sysrq_xlate ps2kbd_sysrq_xlate #define kbd_disable_irq() #define kbd_enable_irq() -#define SYSRQ_KEY 13 - -#endif +#define SYSRQ_KEY 0x54 diff --git a/include/asm-arm/arch-ebsa285/memory.h b/include/asm-arm/arch-ebsa285/memory.h new file mode 100644 index 000000000..a03cea639 --- /dev/null +++ b/include/asm-arm/arch-ebsa285/memory.h @@ -0,0 +1,74 @@ +/* + * linux/include/asm-arm/arch-ebsa285/memory.h + * + * Copyright (c) 1996-1999 Russell King. + * + * Changelog: + * 20-Oct-1996 RMK Created + * 31-Dec-1997 RMK Fixed definitions to reduce warnings. + * 17-May-1998 DAG Added __virt_to_bus and __bus_to_virt functions. + * 21-Nov-1998 RMK Changed __virt_to_bus and __bus_to_virt to macros. + * 21-Mar-1999 RMK Added PAGE_OFFSET for co285 architecture. + * Renamed to memory.h + * Moved PAGE_OFFSET and TASK_SIZE here + */ +#ifndef __ASM_ARCH_MMU_H +#define __ASM_ARCH_MMU_H + +#include <linux/config.h> + +#if defined(CONFIG_HOST_FOOTBRIDGE) + +/* + * Task size: 3GB + */ +#define TASK_SIZE (0xc0000000UL) + +/* + * Page offset: 3GB + */ +#define PAGE_OFFSET (0xc0000000UL) + +#define __virt_to_bus__is_a_macro +#define __virt_to_bus(x) ((x) - 0xe0000000) +#define __bus_to_virt__is_a_macro +#define __bus_to_virt(x) ((x) + 0xe0000000) + +#elif defined(CONFIG_ADDIN_FOOTBRIDGE) + +#if defined(CONFIG_ARCH_CO285) + +/* + * Task size: 1.5GB + */ +#define TASK_SIZE (0x60000000UL) + +/* + * Page offset: 1.5GB + */ +#define PAGE_OFFSET (0x60000000UL) + +#else + +#error Add in your architecture here + +#endif + +#ifndef __ASSEMBLY__ +extern unsigned long __virt_to_bus(unsigned long); +extern unsigned long __bus_to_virt(unsigned long); +#endif + +#endif + +/* + * On Footbridge machines, the dram is contiguous. + * On Host Footbridge, these conversions are constant. + * On an add-in footbridge, these depend on register settings. + */ +#define __virt_to_phys__is_a_macro +#define __virt_to_phys(vpage) ((unsigned long)(vpage) - PAGE_OFFSET) +#define __phys_to_virt__is_a_macro +#define __phys_to_virt(ppage) ((unsigned long)(ppage) + PAGE_OFFSET) + +#endif diff --git a/include/asm-arm/arch-ebsa285/mm-init.h b/include/asm-arm/arch-ebsa285/mm-init.h deleted file mode 100644 index c6937abd0..000000000 --- a/include/asm-arm/arch-ebsa285/mm-init.h +++ /dev/null @@ -1,5 +0,0 @@ -/* - * linux/include/asm-arm/arch-ebsa110/mmap.h - * - * Copyright (C) 1996,1997,1998 Russell King - */ diff --git a/include/asm-arm/arch-ebsa285/mmu.h b/include/asm-arm/arch-ebsa285/mmu.h deleted file mode 100644 index b26aa8f66..000000000 --- a/include/asm-arm/arch-ebsa285/mmu.h +++ /dev/null @@ -1,28 +0,0 @@ -/* - * linux/include/asm-arm/arch-ebsa285/mmu.h - * - * Copyright (c) 1996,1997,1998 Russell King. - * - * Changelog: - * 20-10-1996 RMK Created - * 31-12-1997 RMK Fixed definitions to reduce warnings - * 17-05-1998 DAG Added __virt_to_bus and __bus_to_virt functions. - * 21-11-1998 RMK Changed __virt_to_bus and __bus_to_virt to macros. - */ -#ifndef __ASM_ARCH_MMU_H -#define __ASM_ARCH_MMU_H - -/* - * On ebsa285, the dram is contiguous - */ -#define __virt_to_phys__is_a_macro -#define __virt_to_phys(vpage) ((unsigned long)(vpage) - PAGE_OFFSET) -#define __phys_to_virt__is_a_macro -#define __phys_to_virt(ppage) ((unsigned long)(ppage) + PAGE_OFFSET) - -#define __virt_to_bus__is_a_macro -#define __virt_to_bus(x) ((x) - 0xe0000000) -#define __bus_to_virt__is_a_macro -#define __bus_to_virt(x) ((x) + 0xe0000000) - -#endif diff --git a/include/asm-arm/arch-ebsa285/oldlatches.h b/include/asm-arm/arch-ebsa285/oldlatches.h deleted file mode 100644 index 8ff6ebd67..000000000 --- a/include/asm-arm/arch-ebsa285/oldlatches.h +++ /dev/null @@ -1,9 +0,0 @@ -/* - * Dummy oldlatches.h - * - * Copyright (C) 1996 Russell King - */ - -#ifdef __need_oldlatches -#error "Old latches not present in this (rpc) machine" -#endif diff --git a/include/asm-arm/arch-ebsa285/processor.h b/include/asm-arm/arch-ebsa285/processor.h index e98d1ff33..bd99869af 100644 --- a/include/asm-arm/arch-ebsa285/processor.h +++ b/include/asm-arm/arch-ebsa285/processor.h @@ -1,12 +1,17 @@ /* * linux/include/asm-arm/arch-ebsa110/processor.h * - * Copyright (C) 1996,1997,1998 Russell King + * Copyright (C) 1996-1999 Russell King + * + * Changelog: + * 21-Mar-1999 RMK Added asm/arch/memory.h */ #ifndef __ASM_ARCH_PROCESSOR_H #define __ASM_ARCH_PROCESSOR_H +#include <asm/arch/memory.h> + /* * Bus types */ @@ -15,17 +20,9 @@ #define MCA_bus 0 #define MCA_bus__is_a_macro /* for versions in ksyms.c */ -/* - * User space: 3GB - */ -#define TASK_SIZE (0xc0000000UL) - /* This decides where the kernel will search for a free chunk of vm * space during mmap's. */ #define TASK_UNMAPPED_BASE (TASK_SIZE / 3) -#define INIT_MMAP \ -{ &init_mm, 0, 0, PAGE_SHARED, VM_READ | VM_WRITE | VM_EXEC, NULL, &init_mm.mmap } - #endif diff --git a/include/asm-arm/arch-ebsa285/serial.h b/include/asm-arm/arch-ebsa285/serial.h index c874f9dfa..63a699e66 100644 --- a/include/asm-arm/arch-ebsa285/serial.h +++ b/include/asm-arm/arch-ebsa285/serial.h @@ -10,8 +10,6 @@ #ifndef __ASM_ARCH_SERIAL_H #define __ASM_ARCH_SERIAL_H -#include <linux/config.h> - #include <asm/irq.h> /* @@ -23,13 +21,8 @@ */ #define BASE_BAUD (1843200 / 16) -#ifdef CONFIG_CATS -#define _SER_IRQ0 IRQ_ISA(4) -#define _SER_IRQ1 IRQ_ISA(3) -#else -#define _SER_IRQ0 0 -#define _SER_IRQ1 0 -#endif +#define _SER_IRQ0 IRQ_ISA_UART +#define _SER_IRQ1 IRQ_ISA_UART2 #define STD_COM_FLAGS (ASYNC_BOOT_AUTOCONF | ASYNC_SKIP_TEST) diff --git a/include/asm-arm/arch-ebsa285/system.h b/include/asm-arm/arch-ebsa285/system.h index 40d540dba..a8f94c198 100644 --- a/include/asm-arm/arch-ebsa285/system.h +++ b/include/asm-arm/arch-ebsa285/system.h @@ -3,6 +3,8 @@ * * Copyright (c) 1996,1997,1998 Russell King. */ +#include <asm/dec21285.h> +#include <asm/io.h> #include <asm/hardware.h> #include <asm/leds.h> @@ -16,14 +18,37 @@ extern __inline__ void arch_reset(char mode) mov r0, #0x130 mcr p15, 0, r0, c1, c0 @ MMU off mcr p15, 0, ip, c7, c7 @ flush caches - mov pc, lr"); + mov pc, lr" : : : "cc"); } else { - /* To reboot, we set up the 21285 watchdog and enable it. - * We then wait for it to timeout. - */ - *CSR_TIMER4_LOAD = 0x8000; - *CSR_TIMER4_CNTL = TIMER_CNTL_ENABLE | TIMER_CNTL_AUTORELOAD | TIMER_CNTL_DIV16; - *CSR_SA110_CNTL |= 1 << 13; + if (machine_is_ebsa285() || machine_is_co285()) { + /* To reboot, we set up the 21285 watchdog and + * enable it. We then wait for it to timeout. + */ + *CSR_TIMER4_LOAD = 0x8000; + *CSR_TIMER4_CNTL = TIMER_CNTL_ENABLE | + TIMER_CNTL_AUTORELOAD | + TIMER_CNTL_DIV16; + *CSR_SA110_CNTL |= 1 << 13; + } else if (machine_is_netwinder()) { + /* open up the SuperIO chip + */ + outb(0x87, 0x370); + outb(0x87, 0x370); + + /* aux function group 1 (logical device 7) + */ + outb(0x07, 0x370); + outb(0x07, 0x371); + + /* set GP16 for WD-TIMER output + */ + outb(0xe6, 0x370); + outb(0x00, 0x371); + + /* set a RED LED and toggle WD_TIMER for rebooting + */ + outb(0xc4, 0x338); + } } } diff --git a/include/asm-arm/arch-ebsa285/time.h b/include/asm-arm/arch-ebsa285/time.h index 342e9528f..ed70ecf25 100644 --- a/include/asm-arm/arch-ebsa285/time.h +++ b/include/asm-arm/arch-ebsa285/time.h @@ -10,116 +10,346 @@ * 21-Mar-1998 RMK Created * 27-Aug-1998 PJB CATS support * 28-Dec-1998 APH Made leds optional + * 20-Jan-1999 RMK Started merge of EBSA285, CATS and NetWinder + * 16-Mar-1999 RMK More support for EBSA285-like machines with RTCs in */ -#define RTC_PORT(x) (0x72+(x)) -#define RTC_ALWAYS_BCD 1 +#define RTC_PORT(x) (rtc_base+(x)) +#define RTC_ALWAYS_BCD 0 #include <linux/config.h> +#include <linux/mc146818rtc.h> + +#include <asm/dec21285.h> #include <asm/leds.h> #include <asm/system.h> -#include <linux/mc146818rtc.h> -extern __inline__ unsigned long gettimeoffset (void) +static int rtc_base; +static unsigned long (*gettimeoffset)(void); +static int (*set_rtc_mmss)(unsigned long nowtime); +static long last_rtc_update = 0; /* last time the cmos clock got updated */ + +#ifdef CONFIG_LEDS +static void do_leds(void) +{ + static unsigned int count = 50; + static int last_pid; + + if (current->pid != last_pid) { + last_pid = current->pid; + if (last_pid) + leds_event(led_idle_end); + else + leds_event(led_idle_start); + } + + if (--count == 0) { + count = 50; + leds_event(led_timer); + } +} +#else +#define do_leds() +#endif + +#define mSEC_10_from_14 ((14318180 + 100) / 200) + +static unsigned long isa_gettimeoffset(void) +{ + int count; + + static int count_p = (mSEC_10_from_14/6); /* for the first call after boot */ + static unsigned long jiffies_p = 0; + + /* + * cache volatile jiffies temporarily; we have IRQs turned off. + */ + unsigned long jiffies_t; + + /* timer count may underflow right here */ + outb_p(0x00, 0x43); /* latch the count ASAP */ + + count = inb_p(0x40); /* read the latched count */ + + /* + * We do this guaranteed double memory access instead of a _p + * postfix in the previous port access. Wheee, hackady hack + */ + jiffies_t = jiffies; + + count |= inb_p(0x40) << 8; + + /* Detect timer underflows. If we haven't had a timer tick since + the last time we were called, and time is apparently going + backwards, the counter must have wrapped during this routine. */ + if ((jiffies_t == jiffies_p) && (count > count_p)) + count -= (mSEC_10_from_14/6); + else + jiffies_p = jiffies_t; + + count_p = count; + + count = (((mSEC_10_from_14/6)-1) - count) * tick; + count = (count + (mSEC_10_from_14/6)/2) / (mSEC_10_from_14/6); + + return count; +} + +static void isa_timer_interrupt(int irq, void *dev_id, struct pt_regs *regs) +{ + if (machine_is_netwinder()) + do_leds(); + + do_timer(regs); + + /* If we have an externally synchronized linux clock, then update + * CMOS clock accordingly every ~11 minutes. Set_rtc_mmss() has to be + * called as close as possible to 500 ms before the new second starts. + */ + if ((time_status & STA_UNSYNC) == 0 && + xtime.tv_sec > last_rtc_update + 660 && + xtime.tv_usec > 50000 - (tick >> 1) && + xtime.tv_usec < 50000 + (tick >> 1)) { + if (set_rtc_mmss(xtime.tv_sec) == 0) + last_rtc_update = xtime.tv_sec; + else + last_rtc_update = xtime.tv_sec - 600; /* do it again in 60 s */ + } +} + +static struct irqaction isa_timer_irq = { + isa_timer_interrupt, + 0, + 0, + "timer", + NULL, + NULL +}; + +__initfunc(static unsigned long +get_isa_cmos_time(void)) +{ + unsigned int year, mon, day, hour, min, sec; + int i; + + // check to see if the RTC makes sense..... + if ((CMOS_READ(RTC_VALID) & RTC_VRT) == 0) + return mktime(1970, 1, 1, 0, 0, 0); + + /* The Linux interpretation of the CMOS clock register contents: + * When the Update-In-Progress (UIP) flag goes from 1 to 0, the + * RTC registers show the second which has precisely just started. + * Let's hope other operating systems interpret the RTC the same way. + */ + /* read RTC exactly on falling edge of update flag */ + for (i = 0 ; i < 1000000 ; i++) /* may take up to 1 second... */ + if (CMOS_READ(RTC_FREQ_SELECT) & RTC_UIP) + break; + + for (i = 0 ; i < 1000000 ; i++) /* must try at least 2.228 ms */ + if (!(CMOS_READ(RTC_FREQ_SELECT) & RTC_UIP)) + break; + + do { /* Isn't this overkill ? UIP above should guarantee consistency */ + sec = CMOS_READ(RTC_SECONDS); + min = CMOS_READ(RTC_MINUTES); + hour = CMOS_READ(RTC_HOURS); + day = CMOS_READ(RTC_DAY_OF_MONTH); + mon = CMOS_READ(RTC_MONTH); + year = CMOS_READ(RTC_YEAR); + } while (sec != CMOS_READ(RTC_SECONDS)); + + if (!(CMOS_READ(RTC_CONTROL) & RTC_DM_BINARY) || RTC_ALWAYS_BCD) { + BCD_TO_BIN(sec); + BCD_TO_BIN(min); + BCD_TO_BIN(hour); + BCD_TO_BIN(day); + BCD_TO_BIN(mon); + BCD_TO_BIN(year); + } + if ((year += 1900) < 1970) + year += 100; + return mktime(year, mon, day, hour, min, sec); +} + +static int +set_isa_cmos_time(unsigned long nowtime) +{ + int retval = 0; + int real_seconds, real_minutes, cmos_minutes; + unsigned char save_control, save_freq_select; + + save_control = CMOS_READ(RTC_CONTROL); /* tell the clock it's being set */ + CMOS_WRITE((save_control|RTC_SET), RTC_CONTROL); + + save_freq_select = CMOS_READ(RTC_FREQ_SELECT); /* stop and reset prescaler */ + CMOS_WRITE((save_freq_select|RTC_DIV_RESET2), RTC_FREQ_SELECT); + + cmos_minutes = CMOS_READ(RTC_MINUTES); + if (!(save_control & RTC_DM_BINARY) || RTC_ALWAYS_BCD) + BCD_TO_BIN(cmos_minutes); + + /* + * since we're only adjusting minutes and seconds, + * don't interfere with hour overflow. This avoids + * messing with unknown time zones but requires your + * RTC not to be off by more than 15 minutes + */ + real_seconds = nowtime % 60; + real_minutes = nowtime / 60; + if (((abs(real_minutes - cmos_minutes) + 15)/30) & 1) + real_minutes += 30; /* correct for half hour time zone */ + real_minutes %= 60; + + if (abs(real_minutes - cmos_minutes) < 30) { + if (!(save_control & RTC_DM_BINARY) || RTC_ALWAYS_BCD) { + BIN_TO_BCD(real_seconds); + BIN_TO_BCD(real_minutes); + } + CMOS_WRITE(real_seconds,RTC_SECONDS); + CMOS_WRITE(real_minutes,RTC_MINUTES); + } else + retval = -1; + + /* The following flags have to be released exactly in this order, + * otherwise the DS12887 (popular MC146818A clone with integrated + * battery and quartz) will not reset the oscillator and will not + * update precisely 500 ms later. You won't find this mentioned in + * the Dallas Semiconductor data sheets, but who believes data + * sheets anyway ... -- Markus Kuhn + */ + CMOS_WRITE(save_control, RTC_CONTROL); + CMOS_WRITE(save_freq_select, RTC_FREQ_SELECT); + + return retval; +} + + + +static unsigned long __ebsa285_text timer1_gettimeoffset (void) { unsigned long value = LATCH - *CSR_TIMER1_VALUE; return (tick * value) / LATCH; } -extern __inline__ int reset_timer (void) +static void __ebsa285_text timer1_interrupt(int irq, void *dev_id, struct pt_regs *regs) { *CSR_TIMER1_CLR = 0; -#ifdef CONFIG_LEDS - /* - * Do the LEDs thing on EBSA-285 hardware. + /* Do the LEDs things on non-CATS hardware. */ - if (!machine_is_cats()) { - static unsigned int count = 50; - static int last_pid; - - if (current->pid != last_pid) { - last_pid = current->pid; - if (last_pid) - leds_event(led_idle_end); - else - leds_event(led_idle_start); - } - - if (--count == 0) { - count = 50; - leds_event(led_timer); - } + if (!machine_is_cats()) + do_leds(); + + do_timer(regs); + + /* If we have an externally synchronized linux clock, then update + * CMOS clock accordingly every ~11 minutes. Set_rtc_mmss() has to be + * called as close as possible to 500 ms before the new second starts. + */ + if ((time_status & STA_UNSYNC) == 0 && + xtime.tv_sec > last_rtc_update + 660 && + xtime.tv_usec > 50000 - (tick >> 1) && + xtime.tv_usec < 50000 + (tick >> 1)) { + if (set_rtc_mmss(xtime.tv_sec) == 0) + last_rtc_update = xtime.tv_sec; + else + last_rtc_update = xtime.tv_sec - 600; /* do it again in 60 s */ } -#endif - - return 1; } -/* - * We don't have a RTC to update! - */ -#define update_rtc() +static struct irqaction __ebsa285_data timer1_irq = { + timer1_interrupt, + 0, + 0, + "timer", + NULL, + NULL +}; + +static int +set_dummy_time(unsigned long secs) +{ + return 1; +} /* * Set up timer interrupt, and return the current time in seconds. */ -extern __inline__ unsigned long setup_timer (void) +extern __inline__ void setup_timer(void) { - int year, mon, day, hour, min, sec; + switch(machine_arch_type) { + case MACH_TYPE_CO285: + /* + * Add-in 21285s shouldn't access the RTC + */ + rtc_base = 0; + break; - /* - * Default the date to 1 Jan 1970 0:0:0 - */ - year = 1970; mon = 1; day = 1; - hour = 0; min = 0; sec = 0; + default: + rtc_base = 0x70; + break; + } + + if (rtc_base) { + int reg_d, reg_b; - *CSR_TIMER1_CLR = 0; - *CSR_TIMER1_LOAD = LATCH; - *CSR_TIMER1_CNTL = TIMER_CNTL_ENABLE | TIMER_CNTL_AUTORELOAD | TIMER_CNTL_DIV16; + reg_d = CMOS_READ(RTC_REG_D); - if (machine_is_cats()) - { - int i; /* - * Read the real time from the Dallas chip. (Code borrowed - * from arch/i386/kernel/time.c). + * make sure the divider is set */ - - /* The Linux interpretation of the CMOS clock register contents: - * When the Update-In-Progress (UIP) flag goes from 1 to 0, the - * RTC registers show the second which has precisely just started. - * Let's hope other operating systems interpret the RTC the same way. + CMOS_WRITE(RTC_REF_CLCK_32KHZ, RTC_REG_A); + + /* + * Set control reg B + * (24 hour mode, update enabled) */ + reg_b = CMOS_READ(RTC_REG_B) & 0x7f; + reg_b |= 2; + CMOS_WRITE(reg_b, RTC_REG_B); - /* read RTC exactly on falling edge of update flag */ - for (i = 0 ; i < 1000000 ; i++) /* may take up to 1 second... */ - if (CMOS_READ(RTC_FREQ_SELECT) & RTC_UIP) - break; - for (i = 0 ; i < 1000000 ; i++) /* must try at least 2.228 ms */ - if (!(CMOS_READ(RTC_FREQ_SELECT) & RTC_UIP)) - break; - do { /* Isn't this overkill ? UIP above should guarantee consistency */ - sec = CMOS_READ(RTC_SECONDS); - min = CMOS_READ(RTC_MINUTES); - hour = CMOS_READ(RTC_HOURS); - day = CMOS_READ(RTC_DAY_OF_MONTH); - mon = CMOS_READ(RTC_MONTH); - year = CMOS_READ(RTC_YEAR); - } while (sec != CMOS_READ(RTC_SECONDS)); - if (!(CMOS_READ(RTC_CONTROL) & RTC_DM_BINARY) || RTC_ALWAYS_BCD) - { - BCD_TO_BIN(sec); - BCD_TO_BIN(min); - BCD_TO_BIN(hour); - BCD_TO_BIN(day); - BCD_TO_BIN(mon); - BCD_TO_BIN(year); - } - if ((year += 1900) < 1970) - year += 100; + if ((CMOS_READ(RTC_REG_A) & 0x7f) == RTC_REF_CLCK_32KHZ && + CMOS_READ(RTC_REG_B) == reg_b) { + + /* + * Check the battery + */ + if ((reg_d & 0x80) == 0) + printk(KERN_WARNING "RTC: *** warning: CMOS battery bad\n"); + + xtime.tv_sec = get_isa_cmos_time(); + set_rtc_mmss = set_isa_cmos_time; + } else + rtc_base = 0; } - return mktime(year, mon, day, hour, min, sec); + if (!rtc_base) { + /* + * Default the date to 1 Jan 1970 0:0:0 + */ + xtime.tv_sec = mktime(1970, 1, 1, 0, 0, 0); + set_rtc_mmss = set_dummy_time; + } + + if (machine_is_ebsa285()) { + gettimeoffset = timer1_gettimeoffset; + + *CSR_TIMER1_CLR = 0; + *CSR_TIMER1_LOAD = LATCH; + *CSR_TIMER1_CNTL = TIMER_CNTL_ENABLE | TIMER_CNTL_AUTORELOAD | TIMER_CNTL_DIV16; + + setup_arm_irq(IRQ_TIMER1, &timer1_irq); + } else { + /* enable PIT timer */ + /* set for periodic (4) and LSB/MSB write (0x30) */ + outb(0x34, 0x43); + outb((mSEC_10_from_14/6) & 0xFF, 0x40); + outb((mSEC_10_from_14/6) >> 8, 0x40); + + gettimeoffset = isa_gettimeoffset; + + setup_arm_irq(IRQ_ISA_TIMER, &isa_timer_irq); + } } diff --git a/include/asm-arm/arch-ebsa285/timex.h b/include/asm-arm/arch-ebsa285/timex.h index 0a730a70e..de5bffba8 100644 --- a/include/asm-arm/arch-ebsa285/timex.h +++ b/include/asm-arm/arch-ebsa285/timex.h @@ -7,8 +7,8 @@ */ /* - * On the EBSA, the clock ticks at weird rates. - * This is therefore not used to calculate the - * divisor. + * On EBSA285 boards, the clock runs at 50MHz and is + * divided by a 4-bit prescaler. Other boards use an + * ISA derived timer, and this is unused. */ #define CLOCK_TICK_RATE (50000000 / 16) diff --git a/include/asm-arm/arch-ebsa285/uncompress.h b/include/asm-arm/arch-ebsa285/uncompress.h index 7f655745f..e72e4f362 100644 --- a/include/asm-arm/arch-ebsa285/uncompress.h +++ b/include/asm-arm/arch-ebsa285/uncompress.h @@ -1,9 +1,12 @@ /* - * linux/include/asm-arm/arch-ebsa110/uncompress.h + * linux/include/asm-arm/arch-ebsa285/uncompress.h * * Copyright (C) 1996,1997,1998 Russell King */ +/* + * Note! This could cause problems on the NetWinder + */ #define BASE 0x42000160 static __inline__ void putc(char c) |