diff options
author | Ralf Baechle <ralf@linux-mips.org> | 1997-04-29 21:13:14 +0000 |
---|---|---|
committer | <ralf@linux-mips.org> | 1997-04-29 21:13:14 +0000 |
commit | 19c9bba94152148523ba0f7ef7cffe3d45656b11 (patch) | |
tree | 40b1cb534496a7f1ca0f5c314a523c69f1fee464 /arch/mips/sni | |
parent | 7206675c40394c78a90e74812bbdbf8cf3cca1be (diff) |
Import of Linux/MIPS 2.1.36
Diffstat (limited to 'arch/mips/sni')
-rw-r--r-- | arch/mips/sni/Makefile | 2 | ||||
-rw-r--r-- | arch/mips/sni/int-handler.S | 29 | ||||
-rw-r--r-- | arch/mips/sni/pci.c | 126 | ||||
-rw-r--r-- | arch/mips/sni/reset.c | 17 | ||||
-rw-r--r-- | arch/mips/sni/setup.c | 48 |
5 files changed, 199 insertions, 23 deletions
diff --git a/arch/mips/sni/Makefile b/arch/mips/sni/Makefile index 3821d7b62..f0bc3e600 100644 --- a/arch/mips/sni/Makefile +++ b/arch/mips/sni/Makefile @@ -13,7 +13,7 @@ all: sni.o O_TARGET := sni.o -O_OBJS := hw-access.o int-handler.o reset.o setup.o +O_OBJS := hw-access.o int-handler.o pci.o reset.o setup.o int-handler.o: int-handler.S diff --git a/arch/mips/sni/int-handler.S b/arch/mips/sni/int-handler.S index c01c34c9d..f60c82251 100644 --- a/arch/mips/sni/int-handler.S +++ b/arch/mips/sni/int-handler.S @@ -2,10 +2,6 @@ * SNI RM200 PCI specific interrupt handler code. * * Copyright (C) 1994, 1995, 1996 by Ralf Baechle - * - * This is a verbose copy of the Tyne/rPC44 interrupt handler. We - * don't share the code because the SNI machine has some extra interrupt - * features that want to be supported. */ #include <asm/asm.h> #include <linux/config.h> @@ -15,7 +11,6 @@ #include <asm/sni.h> #include <asm/stackframe.h> - .text .set noreorder .set noat .align 5 @@ -23,6 +18,9 @@ SAVE_ALL REG_S sp,PT_OR2(sp) CLI + /* + * Asume we received an interrupt from the PCI ASIC. + */ .set at lui s0,%hi(SNI_PORT_BASE) li a0,0x0f @@ -42,8 +40,6 @@ or t0,s1 sb t0,%lo(cache_21)(s4) sb t0,%lo(SNI_PORT_BASE+0x21)(s0) - lui s3,%hi(intr_count) - lw s7,%lo(intr_count)(s3) li t2,0x20 sb t2,%lo(SNI_PORT_BASE+0x20)(s0) /* @@ -53,10 +49,8 @@ sll t2,a0,PTRLOG addu t3,t2 LONG_L t3,(t3) - addiu t0,s7,1 jalr t3 - sw t0,%lo(intr_count)(s3) - sw s7,%lo(intr_count)(s3) + nop # delay slot /* * Unblock first pic */ @@ -89,8 +83,6 @@ poll_second: li a0,0x0f sb t3,%lo(SNI_PORT_BASE+0xa1)(s0) li t3,0x20 sb t3,%lo(SNI_PORT_BASE+0xa0)(s0) - lui s3,%hi(intr_count) - lw s7,%lo(intr_count)(s3) sb t3,%lo(SNI_PORT_BASE+0x20)(s0) /* * Now call the real handler @@ -100,10 +92,8 @@ poll_second: li a0,0x0f sll t2,a0,PTRLOG addu t3,t2 LONG_L t3,(t3) - addiu t0,s7,1 jalr t3 - sw t0,%lo(intr_count)(s3) # delay slot - sw s7,%lo(intr_count)(s3) + nop # delay slot /* * Unblock second pic */ @@ -119,8 +109,9 @@ poll_second: li a0,0x0f /* * FIXME: This is definatly wrong but I'll have to do it this way * 'till I get more hardware info. + * XXX: Apparently the Lance is attached to interrupt #5. */ -#ifdef CONFIG_LANCE32 +#ifdef CONFIG_PCNET32 /* * FIXME: detect this address @@ -146,8 +137,9 @@ poll_second: li a0,0x0f ori t0,0x041f xori t0,0x041e mtc0 t0,CP0_STATUS + li a0,PCIMT_IRQ_ETHERNET jal do_IRQ - li a0,10 # delay slot + move a1,sp # delay slot sh s0,LANCE_BASE+LANCE_ADDR mfc0 t0,CP0_STATUS ori t0,0x0401 @@ -156,11 +148,12 @@ poll_second: li a0,0x0f j ret_from_sys_call nop # delay slot -#endif /* CONFIG_LANCE32 */ +#endif /* CONFIG_PCNET32 */ /* * FIXME: This is definatly wrong but I'll have to do it this way * 'till I get more hardware info. + * XXX: Apparently the NCR is attached to interrupt #2. */ #ifdef CONFIG_SCSI_NCR53C8XX diff --git a/arch/mips/sni/pci.c b/arch/mips/sni/pci.c new file mode 100644 index 000000000..06edb268f --- /dev/null +++ b/arch/mips/sni/pci.c @@ -0,0 +1,126 @@ +/* + * 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. + * + * SNI specific PCI support for RM200/RM300. + */ +#include <linux/config.h> +#include <linux/bios32.h> +#include <linux/pci.h> +#include <linux/types.h> +#include <asm/byteorder.h> +#include <asm/pci.h> +#include <asm/sni.h> + +#ifdef CONFIG_PCI + +extern inline u32 mkaddr(unsigned char bus, unsigned char dev_fn, + unsigned char where) +{ + return (((bus & 0xff) << 0x10) | + ((dev_fn & 0xff) << 0x08) | + ((where & 0xfc))); +} + +static unsigned long sni_rm200_pcibios_fixup (unsigned long memory_start, + unsigned long memory_end) +{ + /* I guess it's ok to do exactly nothing. */ + return memory_start; +} + +static int sni_rm200_pcibios_read_config_byte (unsigned char bus, + unsigned char dev_fn, + unsigned char where, + unsigned char *val) +{ + u32 res; + + *(volatile u32 *)PCIMT_CONFIG_ADDRESS = mkaddr(bus, dev_fn, where); + res = *(volatile u32 *)PCIMT_CONFIG_DATA; + res = le32_to_cpu(res); + *val = res; + + return PCIBIOS_SUCCESSFUL; +} + +static int sni_rm200_pcibios_read_config_word (unsigned char bus, + unsigned char dev_fn, + unsigned char where, + unsigned short *val) +{ + u32 res; + + if (where & 1) + return PCIBIOS_BAD_REGISTER_NUMBER; + *(volatile u32 *)PCIMT_CONFIG_ADDRESS = mkaddr(bus, dev_fn, where); + res = *(volatile u32 *)PCIMT_CONFIG_DATA; + res = le32_to_cpu(res); + *val = res; + + return PCIBIOS_SUCCESSFUL; +} + +static int sni_rm200_pcibios_read_config_dword (unsigned char bus, + unsigned char dev_fn, + unsigned char where, + unsigned int *val) +{ + u32 res; + + if (where & 3) + return PCIBIOS_BAD_REGISTER_NUMBER; + *(volatile u32 *)PCIMT_CONFIG_ADDRESS = mkaddr(bus, dev_fn, where); + res = *(volatile u32 *)PCIMT_CONFIG_DATA; + res = le32_to_cpu(res); + *val = res; + + return PCIBIOS_SUCCESSFUL; +} + +static int sni_rm200_pcibios_write_config_byte (unsigned char bus, + unsigned char dev_fn, + unsigned char where, + unsigned char val) +{ + /* To do */ + return PCIBIOS_SUCCESSFUL; +} + +static int sni_rm200_pcibios_write_config_word (unsigned char bus, + unsigned char dev_fn, + unsigned char where, + unsigned short val) +{ + /* To do */ + return PCIBIOS_SUCCESSFUL; +} + +static int sni_rm200_pcibios_write_config_dword (unsigned char bus, + unsigned char dev_fn, + unsigned char where, + unsigned int val) +{ + if (where & 3) + return PCIBIOS_BAD_REGISTER_NUMBER; + *(volatile u32 *)PCIMT_CONFIG_ADDRESS = mkaddr(bus, dev_fn, where); + *(volatile u32 *)PCIMT_CONFIG_DATA = le32_to_cpu(val); + + return PCIBIOS_SUCCESSFUL; +} + +unsigned long sni_rm200_pcibios_init(unsigned long memory_start, unsigned long memory_end) +{ + _pcibios_fixup = sni_rm200_pcibios_fixup; + _pcibios_read_config_byte = sni_rm200_pcibios_read_config_byte; + _pcibios_read_config_word = sni_rm200_pcibios_read_config_word; + _pcibios_read_config_dword = sni_rm200_pcibios_read_config_dword; + _pcibios_write_config_byte = sni_rm200_pcibios_write_config_byte; + _pcibios_write_config_word = sni_rm200_pcibios_write_config_word; + _pcibios_write_config_dword = sni_rm200_pcibios_write_config_dword; + + return memory_start; +} + +#endif /* CONFIG_PCI */ diff --git a/arch/mips/sni/reset.c b/arch/mips/sni/reset.c index 9dd017a7c..3052d41fa 100644 --- a/arch/mips/sni/reset.c +++ b/arch/mips/sni/reset.c @@ -4,7 +4,9 @@ * Reset a SNI machine. */ #include <asm/io.h> +#include <asm/reboot.h> #include <asm/system.h> +#include <asm/sni.h> /* * This routine reboots the machine by asking the keyboard @@ -21,11 +23,13 @@ kb_wait(void) break; } -void -sni_hard_reset_now(void) +/* XXX This ends up at the ARC firmware prompt ... */ +void sni_machine_restart(char *command) { int i, j; + /* This does a normal via the keyboard controller like a PC. + We can do that easier ... */ sti(); for (;;) { for (i=0; i<100; i++) { @@ -36,3 +40,12 @@ sni_hard_reset_now(void) } } } + +void sni_machine_halt(void) +{ +} + +void sni_machine_power_off(void) +{ + *(volatile unsigned char *)PCIMT_CSWCSM = 0xfd; +} diff --git a/arch/mips/sni/setup.c b/arch/mips/sni/setup.c index ca958ca2a..1a7a1387d 100644 --- a/arch/mips/sni/setup.c +++ b/arch/mips/sni/setup.c @@ -12,12 +12,15 @@ #include <linux/sched.h> #include <linux/interrupt.h> #include <linux/timex.h> +#include <linux/pci.h> #include <asm/bootinfo.h> #include <asm/io.h> #include <asm/irq.h> #include <asm/processor.h> +#include <asm/reboot.h> #include <asm/sni.h> #include <asm/vector.h> +#include <asm/pci.h> /* * Initial irq handlers. @@ -32,7 +35,10 @@ static struct irqaction irq2 = { no_action, 0, 0, "cascade", NULL, NULL}; extern asmlinkage void sni_rm200_pci_handle_int(void); extern asmlinkage void sni_fd_cacheflush(const void *addr, size_t size); extern struct feature sni_rm200_pci_feature; -extern void sni_hard_reset_now(void); + +extern void sni_machine_restart(char *command); +extern void sni_machine_halt(void); +extern void sni_machine_power_off(void); static void sni_irq_setup(void) @@ -61,7 +67,31 @@ static void sni_rm200_pci_time_init(struct irqaction *irq) } unsigned char aux_device_present; +unsigned long sni_rm200_pcibios_init (unsigned long memory_start, + unsigned long memory_end); + +/* + * A bit more gossip about the iron we're running on ... + */ +static inline void sni_pcimt_detect(void) +{ + char boardtype[80]; + unsigned char csmsr; + char *p = boardtype; + int asic; + + csmsr = *(volatile unsigned char *)PCIMT_CSMSR; + p += sprintf(p, "%s PCI", (csmsr & 0x80) ? "RM200" : "RM300"); + if ((csmsr & 0x80) == 0) + p += sprintf(p, ", board revision %s", + (csmsr & 0x20) ? "D" : "C"); + asic = csmsr & 0x80; + asic = (csmsr & 0x08) ? asic : !asic; + p += sprintf(p, ", ASIC PCI Rev %s", asic ? "1.0" : "1.1"); + printk("%s.\n", boardtype); +} + void sni_rm200_pci_setup(void) { @@ -91,6 +121,8 @@ sni_rm200_pci_setup(void) } } + sni_pcimt_detect(); + irq_setup = sni_irq_setup; fd_cacheflush = sni_fd_cacheflush; // Will go away feature = &sni_rm200_pci_feature; @@ -98,12 +130,24 @@ sni_rm200_pci_setup(void) isa_slot_offset = 0xb0000000; request_region(0x00,0x20,"dma1"); request_region(0x40,0x20,"timer"); + /* XXX FIXME: CONFIG_RTC */ request_region(0x70,0x10,"rtc"); + request_region(0x80,0x10,"dma page reg"); + request_region(0xc0,0x20,"dma2"); board_time_init = sni_rm200_pci_time_init; - hard_reset_now = sni_hard_reset_now; + _machine_restart = sni_machine_restart; + _machine_halt = sni_machine_halt; + _machine_power_off = sni_machine_power_off; if (mips_machtype == MACH_SNI_RM200_PCI) EISA_bus = 1; aux_device_present = 0xaa; + + /* + * Some cluefull person has placed the PCI config data directly in + * the I/O port space ... + */ + request_region(0xcfc,0x04,"PCI config data"); + _pcibios_init = sni_rm200_pcibios_init; } |