linux/arch/mips/dec/setup.c
Maciej W. Rozycki cf3af0a4d3 MIPS: DEC: Restore bootmem reservation for firmware working memory area
Fix a crash on DEC platforms starting with:

VFS: Mounted root (nfs filesystem) on device 0:11.
Freeing unused PROM memory: 124k freed
BUG: Bad page state in process swapper  pfn:00001
page:(ptrval) refcount:0 mapcount:-128 mapping:00000000 index:0x1 pfn:0x1
flags: 0x0()
raw: 00000000 00000100 00000122 00000000 00000001 00000000 ffffff7f 00000000
page dumped because: nonzero mapcount
Modules linked in:
CPU: 0 PID: 1 Comm: swapper Not tainted 5.9.0-00858-g865c50e1d279 #1
Stack : 8065dc48 0000000b 8065d2b8 9bc27dcc 80645bfc 9bc259a4 806a1b97 80703124
        80710000 8064a900 00000001 80099574 806b116c 1000ec00 9bc27d88 806a6f30
        00000000 00000000 80645bfc 00000000 31232039 80706ba4 2e392e35 8039f348
        2d383538 00000070 0000000a 35363867 00000000 806c2830 80710000 806b0000
        80710000 8064a900 00000001 81000000 00000000 00000000 8035af2c 80700000
        ...
Call Trace:
[<8004bc5c>] show_stack+0x34/0x104
[<8015675c>] bad_page+0xfc/0x128
[<80157714>] free_pcppages_bulk+0x1f4/0x5dc
[<801591cc>] free_unref_page+0xc0/0x130
[<8015cb04>] free_reserved_area+0x144/0x1d8
[<805abd78>] kernel_init+0x20/0x100
[<80046070>] ret_from_kernel_thread+0x14/0x1c
Disabling lock debugging due to kernel taint

caused by an attempt to free bootmem space that as from
commit b93ddc4f91 ("mips: Reserve memory for the kernel image resources")
has not been anymore reserved due to the removal of generic MIPS arch code
that used to reserve all the memory from the beginning of RAM up to the
kernel load address.

This memory does need to be reserved on DEC platforms however as it is
used by REX firmware as working area, as per the TURBOchannel firmware
specification[1]:

Table 2-2  REX Memory Regions
-------------------------------------------------------------------------
        Starting        Ending
Region  Address         Address         Use
-------------------------------------------------------------------------
0       0xa0000000      0xa000ffff      Restart block, exception vectors,
                                        REX stack and bss
1       0xa0010000      0xa0017fff      Keyboard or tty drivers

2       0xa0018000      0xa001f3ff 1)   CRT driver

3       0xa0020000      0xa002ffff      boot, cnfg, init and t objects

4       0xa0020000      0xa002ffff      64KB scratch space
-------------------------------------------------------------------------
1) Note that the last 3 Kbytes of region 2 are reserved for backward
compatibility with previous system software.
-------------------------------------------------------------------------

(this table uses KSEG2 unmapped virtual addresses, which in the MIPS
architecture are offset from physical addresses by a fixed value of
0xa0000000 and therefore the regions referred do correspond to the
beginning of the physical address space) and we call into the firmware
on several occasions throughout the bootstrap process.  It is believed
that pre-REX firmware used with non-TURBOchannel DEC platforms has the
same requirements, as hinted by note #1 cited.

Recreate the discarded reservation then, in DEC platform code, removing
the crash.

References:

[1] "TURBOchannel Firmware Specification", On-line version,
    EK-TCAAD-FS-004, Digital Equipment Corporation, January 1993,
    Chapter 2 "System Module Firmware", p. 2-5

Signed-off-by: Maciej W. Rozycki <macro@linux-mips.org>
Fixes: b93ddc4f91 ("mips: Reserve memory for the kernel image resources")
Cc: stable@vger.kernel.org # v5.2+

Signed-off-by: Thomas Bogendoerfer <tsbogend@alpha.franken.de>
2020-10-14 23:57:57 +02:00

784 lines
24 KiB
C

/*
* System-specific setup, especially interrupts.
*
* 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.
*
* Copyright (C) 1998 Harald Koerfgen
* Copyright (C) 2000, 2001, 2002, 2003, 2005, 2020 Maciej W. Rozycki
*/
#include <linux/console.h>
#include <linux/export.h>
#include <linux/init.h>
#include <linux/interrupt.h>
#include <linux/ioport.h>
#include <linux/irq.h>
#include <linux/irqnr.h>
#include <linux/memblock.h>
#include <linux/param.h>
#include <linux/percpu-defs.h>
#include <linux/sched.h>
#include <linux/spinlock.h>
#include <linux/types.h>
#include <linux/pm.h>
#include <asm/addrspace.h>
#include <asm/bootinfo.h>
#include <asm/cpu.h>
#include <asm/cpu-features.h>
#include <asm/cpu-type.h>
#include <asm/irq.h>
#include <asm/irq_cpu.h>
#include <asm/mipsregs.h>
#include <asm/page.h>
#include <asm/reboot.h>
#include <asm/sections.h>
#include <asm/time.h>
#include <asm/traps.h>
#include <asm/wbflush.h>
#include <asm/dec/interrupts.h>
#include <asm/dec/ioasic.h>
#include <asm/dec/ioasic_addrs.h>
#include <asm/dec/ioasic_ints.h>
#include <asm/dec/kn01.h>
#include <asm/dec/kn02.h>
#include <asm/dec/kn02ba.h>
#include <asm/dec/kn02ca.h>
#include <asm/dec/kn03.h>
#include <asm/dec/kn230.h>
#include <asm/dec/system.h>
extern void dec_machine_restart(char *command);
extern void dec_machine_halt(void);
extern void dec_machine_power_off(void);
extern irqreturn_t dec_intr_halt(int irq, void *dev_id);
unsigned long dec_kn_slot_base, dec_kn_slot_size;
EXPORT_SYMBOL(dec_kn_slot_base);
EXPORT_SYMBOL(dec_kn_slot_size);
int dec_tc_bus;
DEFINE_SPINLOCK(ioasic_ssr_lock);
EXPORT_SYMBOL(ioasic_ssr_lock);
volatile u32 *ioasic_base;
EXPORT_SYMBOL(ioasic_base);
/*
* IRQ routing and priority tables. Priorites are set as follows:
*
* KN01 KN230 KN02 KN02-BA KN02-CA KN03
*
* MEMORY CPU CPU CPU ASIC CPU CPU
* RTC CPU CPU CPU ASIC CPU CPU
* DMA - - - ASIC ASIC ASIC
* SERIAL0 CPU CPU CSR ASIC ASIC ASIC
* SERIAL1 - - - ASIC - ASIC
* SCSI CPU CPU CSR ASIC ASIC ASIC
* ETHERNET CPU * CSR ASIC ASIC ASIC
* other - - - ASIC - -
* TC2 - - CSR CPU ASIC ASIC
* TC1 - - CSR CPU ASIC ASIC
* TC0 - - CSR CPU ASIC ASIC
* other - CPU - CPU ASIC ASIC
* other - - - - CPU CPU
*
* * -- shared with SCSI
*/
int dec_interrupt[DEC_NR_INTS] = {
[0 ... DEC_NR_INTS - 1] = -1
};
EXPORT_SYMBOL(dec_interrupt);
int_ptr cpu_mask_nr_tbl[DEC_MAX_CPU_INTS][2] = {
{ { .i = ~0 }, { .p = dec_intr_unimplemented } },
};
int_ptr asic_mask_nr_tbl[DEC_MAX_ASIC_INTS][2] = {
{ { .i = ~0 }, { .p = asic_intr_unimplemented } },
};
int cpu_fpu_mask = DEC_CPU_IRQ_MASK(DEC_CPU_INR_FPU);
int *fpu_kstat_irq;
static irq_handler_t busirq_handler;
static unsigned int busirq_flags = IRQF_NO_THREAD;
/*
* Bus error (DBE/IBE exceptions and bus interrupts) handling setup.
*/
static void __init dec_be_init(void)
{
switch (mips_machtype) {
case MACH_DS23100: /* DS2100/DS3100 Pmin/Pmax */
board_be_handler = dec_kn01_be_handler;
busirq_handler = dec_kn01_be_interrupt;
busirq_flags |= IRQF_SHARED;
dec_kn01_be_init();
break;
case MACH_DS5000_1XX: /* DS5000/1xx 3min */
case MACH_DS5000_XX: /* DS5000/xx Maxine */
board_be_handler = dec_kn02xa_be_handler;
busirq_handler = dec_kn02xa_be_interrupt;
dec_kn02xa_be_init();
break;
case MACH_DS5000_200: /* DS5000/200 3max */
case MACH_DS5000_2X0: /* DS5000/240 3max+ */
case MACH_DS5900: /* DS5900 bigmax */
board_be_handler = dec_ecc_be_handler;
busirq_handler = dec_ecc_be_interrupt;
dec_ecc_be_init();
break;
}
}
void __init plat_mem_setup(void)
{
board_be_init = dec_be_init;
wbflush_setup();
_machine_restart = dec_machine_restart;
_machine_halt = dec_machine_halt;
pm_power_off = dec_machine_power_off;
ioport_resource.start = ~0UL;
ioport_resource.end = 0UL;
/* Stay away from the firmware working memory area for now. */
memblock_reserve(PHYS_OFFSET, __pa_symbol(&_text) - PHYS_OFFSET);
}
/*
* Machine-specific initialisation for KN01, aka DS2100 (aka Pmin)
* or DS3100 (aka Pmax).
*/
static int kn01_interrupt[DEC_NR_INTS] __initdata = {
[DEC_IRQ_CASCADE] = -1,
[DEC_IRQ_AB_RECV] = -1,
[DEC_IRQ_AB_XMIT] = -1,
[DEC_IRQ_DZ11] = DEC_CPU_IRQ_NR(KN01_CPU_INR_DZ11),
[DEC_IRQ_ASC] = -1,
[DEC_IRQ_FLOPPY] = -1,
[DEC_IRQ_FPU] = DEC_CPU_IRQ_NR(DEC_CPU_INR_FPU),
[DEC_IRQ_HALT] = -1,
[DEC_IRQ_ISDN] = -1,
[DEC_IRQ_LANCE] = DEC_CPU_IRQ_NR(KN01_CPU_INR_LANCE),
[DEC_IRQ_BUS] = DEC_CPU_IRQ_NR(KN01_CPU_INR_BUS),
[DEC_IRQ_PSU] = -1,
[DEC_IRQ_RTC] = DEC_CPU_IRQ_NR(KN01_CPU_INR_RTC),
[DEC_IRQ_SCC0] = -1,
[DEC_IRQ_SCC1] = -1,
[DEC_IRQ_SII] = DEC_CPU_IRQ_NR(KN01_CPU_INR_SII),
[DEC_IRQ_TC0] = -1,
[DEC_IRQ_TC1] = -1,
[DEC_IRQ_TC2] = -1,
[DEC_IRQ_TIMER] = -1,
[DEC_IRQ_VIDEO] = DEC_CPU_IRQ_NR(KN01_CPU_INR_VIDEO),
[DEC_IRQ_ASC_MERR] = -1,
[DEC_IRQ_ASC_ERR] = -1,
[DEC_IRQ_ASC_DMA] = -1,
[DEC_IRQ_FLOPPY_ERR] = -1,
[DEC_IRQ_ISDN_ERR] = -1,
[DEC_IRQ_ISDN_RXDMA] = -1,
[DEC_IRQ_ISDN_TXDMA] = -1,
[DEC_IRQ_LANCE_MERR] = -1,
[DEC_IRQ_SCC0A_RXERR] = -1,
[DEC_IRQ_SCC0A_RXDMA] = -1,
[DEC_IRQ_SCC0A_TXERR] = -1,
[DEC_IRQ_SCC0A_TXDMA] = -1,
[DEC_IRQ_AB_RXERR] = -1,
[DEC_IRQ_AB_RXDMA] = -1,
[DEC_IRQ_AB_TXERR] = -1,
[DEC_IRQ_AB_TXDMA] = -1,
[DEC_IRQ_SCC1A_RXERR] = -1,
[DEC_IRQ_SCC1A_RXDMA] = -1,
[DEC_IRQ_SCC1A_TXERR] = -1,
[DEC_IRQ_SCC1A_TXDMA] = -1,
};
static int_ptr kn01_cpu_mask_nr_tbl[][2] __initdata = {
{ { .i = DEC_CPU_IRQ_MASK(KN01_CPU_INR_BUS) },
{ .i = DEC_CPU_IRQ_NR(KN01_CPU_INR_BUS) } },
{ { .i = DEC_CPU_IRQ_MASK(KN01_CPU_INR_RTC) },
{ .i = DEC_CPU_IRQ_NR(KN01_CPU_INR_RTC) } },
{ { .i = DEC_CPU_IRQ_MASK(KN01_CPU_INR_DZ11) },
{ .i = DEC_CPU_IRQ_NR(KN01_CPU_INR_DZ11) } },
{ { .i = DEC_CPU_IRQ_MASK(KN01_CPU_INR_SII) },
{ .i = DEC_CPU_IRQ_NR(KN01_CPU_INR_SII) } },
{ { .i = DEC_CPU_IRQ_MASK(KN01_CPU_INR_LANCE) },
{ .i = DEC_CPU_IRQ_NR(KN01_CPU_INR_LANCE) } },
{ { .i = DEC_CPU_IRQ_ALL },
{ .p = cpu_all_int } },
};
static void __init dec_init_kn01(void)
{
/* IRQ routing. */
memcpy(&dec_interrupt, &kn01_interrupt,
sizeof(kn01_interrupt));
/* CPU IRQ priorities. */
memcpy(&cpu_mask_nr_tbl, &kn01_cpu_mask_nr_tbl,
sizeof(kn01_cpu_mask_nr_tbl));
mips_cpu_irq_init();
} /* dec_init_kn01 */
/*
* Machine-specific initialisation for KN230, aka DS5100, aka MIPSmate.
*/
static int kn230_interrupt[DEC_NR_INTS] __initdata = {
[DEC_IRQ_CASCADE] = -1,
[DEC_IRQ_AB_RECV] = -1,
[DEC_IRQ_AB_XMIT] = -1,
[DEC_IRQ_DZ11] = DEC_CPU_IRQ_NR(KN230_CPU_INR_DZ11),
[DEC_IRQ_ASC] = -1,
[DEC_IRQ_FLOPPY] = -1,
[DEC_IRQ_FPU] = DEC_CPU_IRQ_NR(DEC_CPU_INR_FPU),
[DEC_IRQ_HALT] = DEC_CPU_IRQ_NR(KN230_CPU_INR_HALT),
[DEC_IRQ_ISDN] = -1,
[DEC_IRQ_LANCE] = DEC_CPU_IRQ_NR(KN230_CPU_INR_LANCE),
[DEC_IRQ_BUS] = DEC_CPU_IRQ_NR(KN230_CPU_INR_BUS),
[DEC_IRQ_PSU] = -1,
[DEC_IRQ_RTC] = DEC_CPU_IRQ_NR(KN230_CPU_INR_RTC),
[DEC_IRQ_SCC0] = -1,
[DEC_IRQ_SCC1] = -1,
[DEC_IRQ_SII] = DEC_CPU_IRQ_NR(KN230_CPU_INR_SII),
[DEC_IRQ_TC0] = -1,
[DEC_IRQ_TC1] = -1,
[DEC_IRQ_TC2] = -1,
[DEC_IRQ_TIMER] = -1,
[DEC_IRQ_VIDEO] = -1,
[DEC_IRQ_ASC_MERR] = -1,
[DEC_IRQ_ASC_ERR] = -1,
[DEC_IRQ_ASC_DMA] = -1,
[DEC_IRQ_FLOPPY_ERR] = -1,
[DEC_IRQ_ISDN_ERR] = -1,
[DEC_IRQ_ISDN_RXDMA] = -1,
[DEC_IRQ_ISDN_TXDMA] = -1,
[DEC_IRQ_LANCE_MERR] = -1,
[DEC_IRQ_SCC0A_RXERR] = -1,
[DEC_IRQ_SCC0A_RXDMA] = -1,
[DEC_IRQ_SCC0A_TXERR] = -1,
[DEC_IRQ_SCC0A_TXDMA] = -1,
[DEC_IRQ_AB_RXERR] = -1,
[DEC_IRQ_AB_RXDMA] = -1,
[DEC_IRQ_AB_TXERR] = -1,
[DEC_IRQ_AB_TXDMA] = -1,
[DEC_IRQ_SCC1A_RXERR] = -1,
[DEC_IRQ_SCC1A_RXDMA] = -1,
[DEC_IRQ_SCC1A_TXERR] = -1,
[DEC_IRQ_SCC1A_TXDMA] = -1,
};
static int_ptr kn230_cpu_mask_nr_tbl[][2] __initdata = {
{ { .i = DEC_CPU_IRQ_MASK(KN230_CPU_INR_BUS) },
{ .i = DEC_CPU_IRQ_NR(KN230_CPU_INR_BUS) } },
{ { .i = DEC_CPU_IRQ_MASK(KN230_CPU_INR_RTC) },
{ .i = DEC_CPU_IRQ_NR(KN230_CPU_INR_RTC) } },
{ { .i = DEC_CPU_IRQ_MASK(KN230_CPU_INR_DZ11) },
{ .i = DEC_CPU_IRQ_NR(KN230_CPU_INR_DZ11) } },
{ { .i = DEC_CPU_IRQ_MASK(KN230_CPU_INR_SII) },
{ .i = DEC_CPU_IRQ_NR(KN230_CPU_INR_SII) } },
{ { .i = DEC_CPU_IRQ_ALL },
{ .p = cpu_all_int } },
};
static void __init dec_init_kn230(void)
{
/* IRQ routing. */
memcpy(&dec_interrupt, &kn230_interrupt,
sizeof(kn230_interrupt));
/* CPU IRQ priorities. */
memcpy(&cpu_mask_nr_tbl, &kn230_cpu_mask_nr_tbl,
sizeof(kn230_cpu_mask_nr_tbl));
mips_cpu_irq_init();
} /* dec_init_kn230 */
/*
* Machine-specific initialisation for KN02, aka DS5000/200, aka 3max.
*/
static int kn02_interrupt[DEC_NR_INTS] __initdata = {
[DEC_IRQ_CASCADE] = DEC_CPU_IRQ_NR(KN02_CPU_INR_CASCADE),
[DEC_IRQ_AB_RECV] = -1,
[DEC_IRQ_AB_XMIT] = -1,
[DEC_IRQ_DZ11] = KN02_IRQ_NR(KN02_CSR_INR_DZ11),
[DEC_IRQ_ASC] = KN02_IRQ_NR(KN02_CSR_INR_ASC),
[DEC_IRQ_FLOPPY] = -1,
[DEC_IRQ_FPU] = DEC_CPU_IRQ_NR(DEC_CPU_INR_FPU),
[DEC_IRQ_HALT] = -1,
[DEC_IRQ_ISDN] = -1,
[DEC_IRQ_LANCE] = KN02_IRQ_NR(KN02_CSR_INR_LANCE),
[DEC_IRQ_BUS] = DEC_CPU_IRQ_NR(KN02_CPU_INR_BUS),
[DEC_IRQ_PSU] = -1,
[DEC_IRQ_RTC] = DEC_CPU_IRQ_NR(KN02_CPU_INR_RTC),
[DEC_IRQ_SCC0] = -1,
[DEC_IRQ_SCC1] = -1,
[DEC_IRQ_SII] = -1,
[DEC_IRQ_TC0] = KN02_IRQ_NR(KN02_CSR_INR_TC0),
[DEC_IRQ_TC1] = KN02_IRQ_NR(KN02_CSR_INR_TC1),
[DEC_IRQ_TC2] = KN02_IRQ_NR(KN02_CSR_INR_TC2),
[DEC_IRQ_TIMER] = -1,
[DEC_IRQ_VIDEO] = -1,
[DEC_IRQ_ASC_MERR] = -1,
[DEC_IRQ_ASC_ERR] = -1,
[DEC_IRQ_ASC_DMA] = -1,
[DEC_IRQ_FLOPPY_ERR] = -1,
[DEC_IRQ_ISDN_ERR] = -1,
[DEC_IRQ_ISDN_RXDMA] = -1,
[DEC_IRQ_ISDN_TXDMA] = -1,
[DEC_IRQ_LANCE_MERR] = -1,
[DEC_IRQ_SCC0A_RXERR] = -1,
[DEC_IRQ_SCC0A_RXDMA] = -1,
[DEC_IRQ_SCC0A_TXERR] = -1,
[DEC_IRQ_SCC0A_TXDMA] = -1,
[DEC_IRQ_AB_RXERR] = -1,
[DEC_IRQ_AB_RXDMA] = -1,
[DEC_IRQ_AB_TXERR] = -1,
[DEC_IRQ_AB_TXDMA] = -1,
[DEC_IRQ_SCC1A_RXERR] = -1,
[DEC_IRQ_SCC1A_RXDMA] = -1,
[DEC_IRQ_SCC1A_TXERR] = -1,
[DEC_IRQ_SCC1A_TXDMA] = -1,
};
static int_ptr kn02_cpu_mask_nr_tbl[][2] __initdata = {
{ { .i = DEC_CPU_IRQ_MASK(KN02_CPU_INR_BUS) },
{ .i = DEC_CPU_IRQ_NR(KN02_CPU_INR_BUS) } },
{ { .i = DEC_CPU_IRQ_MASK(KN02_CPU_INR_RTC) },
{ .i = DEC_CPU_IRQ_NR(KN02_CPU_INR_RTC) } },
{ { .i = DEC_CPU_IRQ_MASK(KN02_CPU_INR_CASCADE) },
{ .p = kn02_io_int } },
{ { .i = DEC_CPU_IRQ_ALL },
{ .p = cpu_all_int } },
};
static int_ptr kn02_asic_mask_nr_tbl[][2] __initdata = {
{ { .i = KN02_IRQ_MASK(KN02_CSR_INR_DZ11) },
{ .i = KN02_IRQ_NR(KN02_CSR_INR_DZ11) } },
{ { .i = KN02_IRQ_MASK(KN02_CSR_INR_ASC) },
{ .i = KN02_IRQ_NR(KN02_CSR_INR_ASC) } },
{ { .i = KN02_IRQ_MASK(KN02_CSR_INR_LANCE) },
{ .i = KN02_IRQ_NR(KN02_CSR_INR_LANCE) } },
{ { .i = KN02_IRQ_MASK(KN02_CSR_INR_TC2) },
{ .i = KN02_IRQ_NR(KN02_CSR_INR_TC2) } },
{ { .i = KN02_IRQ_MASK(KN02_CSR_INR_TC1) },
{ .i = KN02_IRQ_NR(KN02_CSR_INR_TC1) } },
{ { .i = KN02_IRQ_MASK(KN02_CSR_INR_TC0) },
{ .i = KN02_IRQ_NR(KN02_CSR_INR_TC0) } },
{ { .i = KN02_IRQ_ALL },
{ .p = kn02_all_int } },
};
static void __init dec_init_kn02(void)
{
/* IRQ routing. */
memcpy(&dec_interrupt, &kn02_interrupt,
sizeof(kn02_interrupt));
/* CPU IRQ priorities. */
memcpy(&cpu_mask_nr_tbl, &kn02_cpu_mask_nr_tbl,
sizeof(kn02_cpu_mask_nr_tbl));
/* KN02 CSR IRQ priorities. */
memcpy(&asic_mask_nr_tbl, &kn02_asic_mask_nr_tbl,
sizeof(kn02_asic_mask_nr_tbl));
mips_cpu_irq_init();
init_kn02_irqs(KN02_IRQ_BASE);
} /* dec_init_kn02 */
/*
* Machine-specific initialisation for KN02-BA, aka DS5000/1xx
* (xx = 20, 25, 33), aka 3min. Also applies to KN04(-BA), aka
* DS5000/150, aka 4min.
*/
static int kn02ba_interrupt[DEC_NR_INTS] __initdata = {
[DEC_IRQ_CASCADE] = DEC_CPU_IRQ_NR(KN02BA_CPU_INR_CASCADE),
[DEC_IRQ_AB_RECV] = -1,
[DEC_IRQ_AB_XMIT] = -1,
[DEC_IRQ_DZ11] = -1,
[DEC_IRQ_ASC] = IO_IRQ_NR(KN02BA_IO_INR_ASC),
[DEC_IRQ_FLOPPY] = -1,
[DEC_IRQ_FPU] = DEC_CPU_IRQ_NR(DEC_CPU_INR_FPU),
[DEC_IRQ_HALT] = DEC_CPU_IRQ_NR(KN02BA_CPU_INR_HALT),
[DEC_IRQ_ISDN] = -1,
[DEC_IRQ_LANCE] = IO_IRQ_NR(KN02BA_IO_INR_LANCE),
[DEC_IRQ_BUS] = IO_IRQ_NR(KN02BA_IO_INR_BUS),
[DEC_IRQ_PSU] = IO_IRQ_NR(KN02BA_IO_INR_PSU),
[DEC_IRQ_RTC] = IO_IRQ_NR(KN02BA_IO_INR_RTC),
[DEC_IRQ_SCC0] = IO_IRQ_NR(KN02BA_IO_INR_SCC0),
[DEC_IRQ_SCC1] = IO_IRQ_NR(KN02BA_IO_INR_SCC1),
[DEC_IRQ_SII] = -1,
[DEC_IRQ_TC0] = DEC_CPU_IRQ_NR(KN02BA_CPU_INR_TC0),
[DEC_IRQ_TC1] = DEC_CPU_IRQ_NR(KN02BA_CPU_INR_TC1),
[DEC_IRQ_TC2] = DEC_CPU_IRQ_NR(KN02BA_CPU_INR_TC2),
[DEC_IRQ_TIMER] = -1,
[DEC_IRQ_VIDEO] = -1,
[DEC_IRQ_ASC_MERR] = IO_IRQ_NR(IO_INR_ASC_MERR),
[DEC_IRQ_ASC_ERR] = IO_IRQ_NR(IO_INR_ASC_ERR),
[DEC_IRQ_ASC_DMA] = IO_IRQ_NR(IO_INR_ASC_DMA),
[DEC_IRQ_FLOPPY_ERR] = -1,
[DEC_IRQ_ISDN_ERR] = -1,
[DEC_IRQ_ISDN_RXDMA] = -1,
[DEC_IRQ_ISDN_TXDMA] = -1,
[DEC_IRQ_LANCE_MERR] = IO_IRQ_NR(IO_INR_LANCE_MERR),
[DEC_IRQ_SCC0A_RXERR] = IO_IRQ_NR(IO_INR_SCC0A_RXERR),
[DEC_IRQ_SCC0A_RXDMA] = IO_IRQ_NR(IO_INR_SCC0A_RXDMA),
[DEC_IRQ_SCC0A_TXERR] = IO_IRQ_NR(IO_INR_SCC0A_TXERR),
[DEC_IRQ_SCC0A_TXDMA] = IO_IRQ_NR(IO_INR_SCC0A_TXDMA),
[DEC_IRQ_AB_RXERR] = -1,
[DEC_IRQ_AB_RXDMA] = -1,
[DEC_IRQ_AB_TXERR] = -1,
[DEC_IRQ_AB_TXDMA] = -1,
[DEC_IRQ_SCC1A_RXERR] = IO_IRQ_NR(IO_INR_SCC1A_RXERR),
[DEC_IRQ_SCC1A_RXDMA] = IO_IRQ_NR(IO_INR_SCC1A_RXDMA),
[DEC_IRQ_SCC1A_TXERR] = IO_IRQ_NR(IO_INR_SCC1A_TXERR),
[DEC_IRQ_SCC1A_TXDMA] = IO_IRQ_NR(IO_INR_SCC1A_TXDMA),
};
static int_ptr kn02ba_cpu_mask_nr_tbl[][2] __initdata = {
{ { .i = DEC_CPU_IRQ_MASK(KN02BA_CPU_INR_CASCADE) },
{ .p = kn02xa_io_int } },
{ { .i = DEC_CPU_IRQ_MASK(KN02BA_CPU_INR_TC2) },
{ .i = DEC_CPU_IRQ_NR(KN02BA_CPU_INR_TC2) } },
{ { .i = DEC_CPU_IRQ_MASK(KN02BA_CPU_INR_TC1) },
{ .i = DEC_CPU_IRQ_NR(KN02BA_CPU_INR_TC1) } },
{ { .i = DEC_CPU_IRQ_MASK(KN02BA_CPU_INR_TC0) },
{ .i = DEC_CPU_IRQ_NR(KN02BA_CPU_INR_TC0) } },
{ { .i = DEC_CPU_IRQ_ALL },
{ .p = cpu_all_int } },
};
static int_ptr kn02ba_asic_mask_nr_tbl[][2] __initdata = {
{ { .i = IO_IRQ_MASK(KN02BA_IO_INR_BUS) },
{ .i = IO_IRQ_NR(KN02BA_IO_INR_BUS) } },
{ { .i = IO_IRQ_MASK(KN02BA_IO_INR_RTC) },
{ .i = IO_IRQ_NR(KN02BA_IO_INR_RTC) } },
{ { .i = IO_IRQ_DMA },
{ .p = asic_dma_int } },
{ { .i = IO_IRQ_MASK(KN02BA_IO_INR_SCC0) },
{ .i = IO_IRQ_NR(KN02BA_IO_INR_SCC0) } },
{ { .i = IO_IRQ_MASK(KN02BA_IO_INR_SCC1) },
{ .i = IO_IRQ_NR(KN02BA_IO_INR_SCC1) } },
{ { .i = IO_IRQ_MASK(KN02BA_IO_INR_ASC) },
{ .i = IO_IRQ_NR(KN02BA_IO_INR_ASC) } },
{ { .i = IO_IRQ_MASK(KN02BA_IO_INR_LANCE) },
{ .i = IO_IRQ_NR(KN02BA_IO_INR_LANCE) } },
{ { .i = IO_IRQ_ALL },
{ .p = asic_all_int } },
};
static void __init dec_init_kn02ba(void)
{
/* IRQ routing. */
memcpy(&dec_interrupt, &kn02ba_interrupt,
sizeof(kn02ba_interrupt));
/* CPU IRQ priorities. */
memcpy(&cpu_mask_nr_tbl, &kn02ba_cpu_mask_nr_tbl,
sizeof(kn02ba_cpu_mask_nr_tbl));
/* I/O ASIC IRQ priorities. */
memcpy(&asic_mask_nr_tbl, &kn02ba_asic_mask_nr_tbl,
sizeof(kn02ba_asic_mask_nr_tbl));
mips_cpu_irq_init();
init_ioasic_irqs(IO_IRQ_BASE);
} /* dec_init_kn02ba */
/*
* Machine-specific initialisation for KN02-CA, aka DS5000/xx,
* (xx = 20, 25, 33), aka MAXine. Also applies to KN04(-CA), aka
* DS5000/50, aka 4MAXine.
*/
static int kn02ca_interrupt[DEC_NR_INTS] __initdata = {
[DEC_IRQ_CASCADE] = DEC_CPU_IRQ_NR(KN02CA_CPU_INR_CASCADE),
[DEC_IRQ_AB_RECV] = IO_IRQ_NR(KN02CA_IO_INR_AB_RECV),
[DEC_IRQ_AB_XMIT] = IO_IRQ_NR(KN02CA_IO_INR_AB_XMIT),
[DEC_IRQ_DZ11] = -1,
[DEC_IRQ_ASC] = IO_IRQ_NR(KN02CA_IO_INR_ASC),
[DEC_IRQ_FLOPPY] = IO_IRQ_NR(KN02CA_IO_INR_FLOPPY),
[DEC_IRQ_FPU] = DEC_CPU_IRQ_NR(DEC_CPU_INR_FPU),
[DEC_IRQ_HALT] = DEC_CPU_IRQ_NR(KN02CA_CPU_INR_HALT),
[DEC_IRQ_ISDN] = IO_IRQ_NR(KN02CA_IO_INR_ISDN),
[DEC_IRQ_LANCE] = IO_IRQ_NR(KN02CA_IO_INR_LANCE),
[DEC_IRQ_BUS] = DEC_CPU_IRQ_NR(KN02CA_CPU_INR_BUS),
[DEC_IRQ_PSU] = -1,
[DEC_IRQ_RTC] = DEC_CPU_IRQ_NR(KN02CA_CPU_INR_RTC),
[DEC_IRQ_SCC0] = IO_IRQ_NR(KN02CA_IO_INR_SCC0),
[DEC_IRQ_SCC1] = -1,
[DEC_IRQ_SII] = -1,
[DEC_IRQ_TC0] = IO_IRQ_NR(KN02CA_IO_INR_TC0),
[DEC_IRQ_TC1] = IO_IRQ_NR(KN02CA_IO_INR_TC1),
[DEC_IRQ_TC2] = -1,
[DEC_IRQ_TIMER] = DEC_CPU_IRQ_NR(KN02CA_CPU_INR_TIMER),
[DEC_IRQ_VIDEO] = IO_IRQ_NR(KN02CA_IO_INR_VIDEO),
[DEC_IRQ_ASC_MERR] = IO_IRQ_NR(IO_INR_ASC_MERR),
[DEC_IRQ_ASC_ERR] = IO_IRQ_NR(IO_INR_ASC_ERR),
[DEC_IRQ_ASC_DMA] = IO_IRQ_NR(IO_INR_ASC_DMA),
[DEC_IRQ_FLOPPY_ERR] = IO_IRQ_NR(IO_INR_FLOPPY_ERR),
[DEC_IRQ_ISDN_ERR] = IO_IRQ_NR(IO_INR_ISDN_ERR),
[DEC_IRQ_ISDN_RXDMA] = IO_IRQ_NR(IO_INR_ISDN_RXDMA),
[DEC_IRQ_ISDN_TXDMA] = IO_IRQ_NR(IO_INR_ISDN_TXDMA),
[DEC_IRQ_LANCE_MERR] = IO_IRQ_NR(IO_INR_LANCE_MERR),
[DEC_IRQ_SCC0A_RXERR] = IO_IRQ_NR(IO_INR_SCC0A_RXERR),
[DEC_IRQ_SCC0A_RXDMA] = IO_IRQ_NR(IO_INR_SCC0A_RXDMA),
[DEC_IRQ_SCC0A_TXERR] = IO_IRQ_NR(IO_INR_SCC0A_TXERR),
[DEC_IRQ_SCC0A_TXDMA] = IO_IRQ_NR(IO_INR_SCC0A_TXDMA),
[DEC_IRQ_AB_RXERR] = IO_IRQ_NR(IO_INR_AB_RXERR),
[DEC_IRQ_AB_RXDMA] = IO_IRQ_NR(IO_INR_AB_RXDMA),
[DEC_IRQ_AB_TXERR] = IO_IRQ_NR(IO_INR_AB_TXERR),
[DEC_IRQ_AB_TXDMA] = IO_IRQ_NR(IO_INR_AB_TXDMA),
[DEC_IRQ_SCC1A_RXERR] = -1,
[DEC_IRQ_SCC1A_RXDMA] = -1,
[DEC_IRQ_SCC1A_TXERR] = -1,
[DEC_IRQ_SCC1A_TXDMA] = -1,
};
static int_ptr kn02ca_cpu_mask_nr_tbl[][2] __initdata = {
{ { .i = DEC_CPU_IRQ_MASK(KN02CA_CPU_INR_BUS) },
{ .i = DEC_CPU_IRQ_NR(KN02CA_CPU_INR_BUS) } },
{ { .i = DEC_CPU_IRQ_MASK(KN02CA_CPU_INR_RTC) },
{ .i = DEC_CPU_IRQ_NR(KN02CA_CPU_INR_RTC) } },
{ { .i = DEC_CPU_IRQ_MASK(KN02CA_CPU_INR_CASCADE) },
{ .p = kn02xa_io_int } },
{ { .i = DEC_CPU_IRQ_ALL },
{ .p = cpu_all_int } },
};
static int_ptr kn02ca_asic_mask_nr_tbl[][2] __initdata = {
{ { .i = IO_IRQ_DMA },
{ .p = asic_dma_int } },
{ { .i = IO_IRQ_MASK(KN02CA_IO_INR_SCC0) },
{ .i = IO_IRQ_NR(KN02CA_IO_INR_SCC0) } },
{ { .i = IO_IRQ_MASK(KN02CA_IO_INR_ASC) },
{ .i = IO_IRQ_NR(KN02CA_IO_INR_ASC) } },
{ { .i = IO_IRQ_MASK(KN02CA_IO_INR_LANCE) },
{ .i = IO_IRQ_NR(KN02CA_IO_INR_LANCE) } },
{ { .i = IO_IRQ_MASK(KN02CA_IO_INR_TC1) },
{ .i = IO_IRQ_NR(KN02CA_IO_INR_TC1) } },
{ { .i = IO_IRQ_MASK(KN02CA_IO_INR_TC0) },
{ .i = IO_IRQ_NR(KN02CA_IO_INR_TC0) } },
{ { .i = IO_IRQ_ALL },
{ .p = asic_all_int } },
};
static void __init dec_init_kn02ca(void)
{
/* IRQ routing. */
memcpy(&dec_interrupt, &kn02ca_interrupt,
sizeof(kn02ca_interrupt));
/* CPU IRQ priorities. */
memcpy(&cpu_mask_nr_tbl, &kn02ca_cpu_mask_nr_tbl,
sizeof(kn02ca_cpu_mask_nr_tbl));
/* I/O ASIC IRQ priorities. */
memcpy(&asic_mask_nr_tbl, &kn02ca_asic_mask_nr_tbl,
sizeof(kn02ca_asic_mask_nr_tbl));
mips_cpu_irq_init();
init_ioasic_irqs(IO_IRQ_BASE);
} /* dec_init_kn02ca */
/*
* Machine-specific initialisation for KN03, aka DS5000/240,
* aka 3max+ and DS5900, aka BIGmax. Also applies to KN05, aka
* DS5000/260, aka 4max+ and DS5900/260.
*/
static int kn03_interrupt[DEC_NR_INTS] __initdata = {
[DEC_IRQ_CASCADE] = DEC_CPU_IRQ_NR(KN03_CPU_INR_CASCADE),
[DEC_IRQ_AB_RECV] = -1,
[DEC_IRQ_AB_XMIT] = -1,
[DEC_IRQ_DZ11] = -1,
[DEC_IRQ_ASC] = IO_IRQ_NR(KN03_IO_INR_ASC),
[DEC_IRQ_FLOPPY] = -1,
[DEC_IRQ_FPU] = DEC_CPU_IRQ_NR(DEC_CPU_INR_FPU),
[DEC_IRQ_HALT] = DEC_CPU_IRQ_NR(KN03_CPU_INR_HALT),
[DEC_IRQ_ISDN] = -1,
[DEC_IRQ_LANCE] = IO_IRQ_NR(KN03_IO_INR_LANCE),
[DEC_IRQ_BUS] = DEC_CPU_IRQ_NR(KN03_CPU_INR_BUS),
[DEC_IRQ_PSU] = IO_IRQ_NR(KN03_IO_INR_PSU),
[DEC_IRQ_RTC] = DEC_CPU_IRQ_NR(KN03_CPU_INR_RTC),
[DEC_IRQ_SCC0] = IO_IRQ_NR(KN03_IO_INR_SCC0),
[DEC_IRQ_SCC1] = IO_IRQ_NR(KN03_IO_INR_SCC1),
[DEC_IRQ_SII] = -1,
[DEC_IRQ_TC0] = IO_IRQ_NR(KN03_IO_INR_TC0),
[DEC_IRQ_TC1] = IO_IRQ_NR(KN03_IO_INR_TC1),
[DEC_IRQ_TC2] = IO_IRQ_NR(KN03_IO_INR_TC2),
[DEC_IRQ_TIMER] = -1,
[DEC_IRQ_VIDEO] = -1,
[DEC_IRQ_ASC_MERR] = IO_IRQ_NR(IO_INR_ASC_MERR),
[DEC_IRQ_ASC_ERR] = IO_IRQ_NR(IO_INR_ASC_ERR),
[DEC_IRQ_ASC_DMA] = IO_IRQ_NR(IO_INR_ASC_DMA),
[DEC_IRQ_FLOPPY_ERR] = -1,
[DEC_IRQ_ISDN_ERR] = -1,
[DEC_IRQ_ISDN_RXDMA] = -1,
[DEC_IRQ_ISDN_TXDMA] = -1,
[DEC_IRQ_LANCE_MERR] = IO_IRQ_NR(IO_INR_LANCE_MERR),
[DEC_IRQ_SCC0A_RXERR] = IO_IRQ_NR(IO_INR_SCC0A_RXERR),
[DEC_IRQ_SCC0A_RXDMA] = IO_IRQ_NR(IO_INR_SCC0A_RXDMA),
[DEC_IRQ_SCC0A_TXERR] = IO_IRQ_NR(IO_INR_SCC0A_TXERR),
[DEC_IRQ_SCC0A_TXDMA] = IO_IRQ_NR(IO_INR_SCC0A_TXDMA),
[DEC_IRQ_AB_RXERR] = -1,
[DEC_IRQ_AB_RXDMA] = -1,
[DEC_IRQ_AB_TXERR] = -1,
[DEC_IRQ_AB_TXDMA] = -1,
[DEC_IRQ_SCC1A_RXERR] = IO_IRQ_NR(IO_INR_SCC1A_RXERR),
[DEC_IRQ_SCC1A_RXDMA] = IO_IRQ_NR(IO_INR_SCC1A_RXDMA),
[DEC_IRQ_SCC1A_TXERR] = IO_IRQ_NR(IO_INR_SCC1A_TXERR),
[DEC_IRQ_SCC1A_TXDMA] = IO_IRQ_NR(IO_INR_SCC1A_TXDMA),
};
static int_ptr kn03_cpu_mask_nr_tbl[][2] __initdata = {
{ { .i = DEC_CPU_IRQ_MASK(KN03_CPU_INR_BUS) },
{ .i = DEC_CPU_IRQ_NR(KN03_CPU_INR_BUS) } },
{ { .i = DEC_CPU_IRQ_MASK(KN03_CPU_INR_RTC) },
{ .i = DEC_CPU_IRQ_NR(KN03_CPU_INR_RTC) } },
{ { .i = DEC_CPU_IRQ_MASK(KN03_CPU_INR_CASCADE) },
{ .p = kn03_io_int } },
{ { .i = DEC_CPU_IRQ_ALL },
{ .p = cpu_all_int } },
};
static int_ptr kn03_asic_mask_nr_tbl[][2] __initdata = {
{ { .i = IO_IRQ_DMA },
{ .p = asic_dma_int } },
{ { .i = IO_IRQ_MASK(KN03_IO_INR_SCC0) },
{ .i = IO_IRQ_NR(KN03_IO_INR_SCC0) } },
{ { .i = IO_IRQ_MASK(KN03_IO_INR_SCC1) },
{ .i = IO_IRQ_NR(KN03_IO_INR_SCC1) } },
{ { .i = IO_IRQ_MASK(KN03_IO_INR_ASC) },
{ .i = IO_IRQ_NR(KN03_IO_INR_ASC) } },
{ { .i = IO_IRQ_MASK(KN03_IO_INR_LANCE) },
{ .i = IO_IRQ_NR(KN03_IO_INR_LANCE) } },
{ { .i = IO_IRQ_MASK(KN03_IO_INR_TC2) },
{ .i = IO_IRQ_NR(KN03_IO_INR_TC2) } },
{ { .i = IO_IRQ_MASK(KN03_IO_INR_TC1) },
{ .i = IO_IRQ_NR(KN03_IO_INR_TC1) } },
{ { .i = IO_IRQ_MASK(KN03_IO_INR_TC0) },
{ .i = IO_IRQ_NR(KN03_IO_INR_TC0) } },
{ { .i = IO_IRQ_ALL },
{ .p = asic_all_int } },
};
static void __init dec_init_kn03(void)
{
/* IRQ routing. */
memcpy(&dec_interrupt, &kn03_interrupt,
sizeof(kn03_interrupt));
/* CPU IRQ priorities. */
memcpy(&cpu_mask_nr_tbl, &kn03_cpu_mask_nr_tbl,
sizeof(kn03_cpu_mask_nr_tbl));
/* I/O ASIC IRQ priorities. */
memcpy(&asic_mask_nr_tbl, &kn03_asic_mask_nr_tbl,
sizeof(kn03_asic_mask_nr_tbl));
mips_cpu_irq_init();
init_ioasic_irqs(IO_IRQ_BASE);
} /* dec_init_kn03 */
void __init arch_init_irq(void)
{
switch (mips_machtype) {
case MACH_DS23100: /* DS2100/DS3100 Pmin/Pmax */
dec_init_kn01();
break;
case MACH_DS5100: /* DS5100 MIPSmate */
dec_init_kn230();
break;
case MACH_DS5000_200: /* DS5000/200 3max */
dec_init_kn02();
break;
case MACH_DS5000_1XX: /* DS5000/1xx 3min */
dec_init_kn02ba();
break;
case MACH_DS5000_2X0: /* DS5000/240 3max+ */
case MACH_DS5900: /* DS5900 bigmax */
dec_init_kn03();
break;
case MACH_DS5000_XX: /* Personal DS5000/xx */
dec_init_kn02ca();
break;
case MACH_DS5800: /* DS5800 Isis */
panic("Don't know how to set this up!");
break;
case MACH_DS5400: /* DS5400 MIPSfair */
panic("Don't know how to set this up!");
break;
case MACH_DS5500: /* DS5500 MIPSfair-2 */
panic("Don't know how to set this up!");
break;
}
/* Free the FPU interrupt if the exception is present. */
if (!cpu_has_nofpuex) {
cpu_fpu_mask = 0;
dec_interrupt[DEC_IRQ_FPU] = -1;
}
/* Free the halt interrupt unused on R4k systems. */
if (current_cpu_type() == CPU_R4000SC ||
current_cpu_type() == CPU_R4400SC)
dec_interrupt[DEC_IRQ_HALT] = -1;
/* Register board interrupts: FPU and cascade. */
if (dec_interrupt[DEC_IRQ_FPU] >= 0 && cpu_has_fpu) {
struct irq_desc *desc_fpu;
int irq_fpu;
irq_fpu = dec_interrupt[DEC_IRQ_FPU];
if (request_irq(irq_fpu, no_action, IRQF_NO_THREAD, "fpu",
NULL))
pr_err("Failed to register fpu interrupt\n");
desc_fpu = irq_to_desc(irq_fpu);
fpu_kstat_irq = this_cpu_ptr(desc_fpu->kstat_irqs);
}
if (dec_interrupt[DEC_IRQ_CASCADE] >= 0) {
if (request_irq(dec_interrupt[DEC_IRQ_CASCADE], no_action,
IRQF_NO_THREAD, "cascade", NULL))
pr_err("Failed to register cascade interrupt\n");
}
/* Register the bus error interrupt. */
if (dec_interrupt[DEC_IRQ_BUS] >= 0 && busirq_handler) {
if (request_irq(dec_interrupt[DEC_IRQ_BUS], busirq_handler,
busirq_flags, "bus error", busirq_handler))
pr_err("Failed to register bus error interrupt\n");
}
/* Register the HALT interrupt. */
if (dec_interrupt[DEC_IRQ_HALT] >= 0) {
if (request_irq(dec_interrupt[DEC_IRQ_HALT], dec_intr_halt,
IRQF_NO_THREAD, "halt", NULL))
pr_err("Failed to register halt interrupt\n");
}
}
asmlinkage unsigned int dec_irq_dispatch(unsigned int irq)
{
do_IRQ(irq);
return 0;
}