summaryrefslogtreecommitdiffstats
path: root/arch/mips/sni
diff options
context:
space:
mode:
authorRalf Baechle <ralf@linux-mips.org>1997-04-29 21:13:14 +0000
committer <ralf@linux-mips.org>1997-04-29 21:13:14 +0000
commit19c9bba94152148523ba0f7ef7cffe3d45656b11 (patch)
tree40b1cb534496a7f1ca0f5c314a523c69f1fee464 /arch/mips/sni
parent7206675c40394c78a90e74812bbdbf8cf3cca1be (diff)
Import of Linux/MIPS 2.1.36
Diffstat (limited to 'arch/mips/sni')
-rw-r--r--arch/mips/sni/Makefile2
-rw-r--r--arch/mips/sni/int-handler.S29
-rw-r--r--arch/mips/sni/pci.c126
-rw-r--r--arch/mips/sni/reset.c17
-rw-r--r--arch/mips/sni/setup.c48
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;
}