635 lines · 16.9 KB · C
RawDownload
/* *	linux/arch/alpha/kernel/sys_sable.c * *	Copyright (C) 1995 David A Rusling *	Copyright (C) 1996 Jay A Estabrook *	Copyright (C) 1998, 1999 Richard Henderson * * Code supporting the Sable, Sable-Gamma, and Lynx systems. */ #include <linux/kernel.h>#include <linux/types.h>#include <linux/mm.h>#include <linux/sched.h>#include <linux/pci.h>#include <linux/init.h> #include <asm/ptrace.h>#include <asm/dma.h>#include <asm/irq.h>#include <asm/mmu_context.h>#include <asm/io.h>#include <asm/pgtable.h>#include <asm/core_t2.h>#include <asm/tlbflush.h> #include "proto.h"#include "irq_impl.h"#include "pci_impl.h"#include "machvec_impl.h" DEFINE_SPINLOCK(sable_lynx_irq_lock); typedef struct irq_swizzle_struct{	char irq_to_mask[64];	char mask_to_irq[64]; 	/* Note mask bit is true for DISABLED irqs.  */	unsigned long shadow_mask; 	void (*update_irq_hw)(unsigned long bit, unsigned long mask);	void (*ack_irq_hw)(unsigned long bit); } irq_swizzle_t; static irq_swizzle_t *sable_lynx_irq_swizzle; static void sable_lynx_init_irq(int nr_of_irqs); #if defined(CONFIG_ALPHA_GENERIC) || defined(CONFIG_ALPHA_SABLE) /***********************************************************************//* *   For SABLE, which is really baroque, we manage 40 IRQ's, but the *   hardware really only supports 24, not via normal ISA PIC, *   but cascaded custom 8259's, etc. *	 0-7  (char at 536) *	 8-15 (char at 53a) *	16-23 (char at 53c) * * Summary Registers (536/53a/53c): * * Bit      Meaning               Kernel IRQ *------------------------------------------ * 0        PCI slot 0			34 * 1        NCR810 (builtin)		33 * 2        TULIP (builtin)		32 * 3        mouse			12 * 4        PCI slot 1			35 * 5        PCI slot 2			36 * 6        keyboard			1 * 7        floppy			6 * 8        COM2			3 * 9        parallel port		7 *10        EISA irq 3			- *11        EISA irq 4			- *12        EISA irq 5			5 *13        EISA irq 6			- *14        EISA irq 7			- *15        COM1			4 *16        EISA irq 9			9 *17        EISA irq 10			10 *18        EISA irq 11			11 *19        EISA irq 12			- *20        EISA irq 13			- *21        EISA irq 14			14 *22        NC				15 *23        IIC				- */ static voidsable_update_irq_hw(unsigned long bit, unsigned long mask){	int port = 0x537; 	if (bit >= 16) {		port = 0x53d;		mask >>= 16;	} else if (bit >= 8) {		port = 0x53b;		mask >>= 8;	} 	outb(mask, port);} static voidsable_ack_irq_hw(unsigned long bit){	int port, val1, val2; 	if (bit >= 16) {		port = 0x53c;		val1 = 0xE0 | (bit - 16);		val2 = 0xE0 | 4;	} else if (bit >= 8) {		port = 0x53a;		val1 = 0xE0 | (bit - 8);		val2 = 0xE0 | 3;	} else {		port = 0x536;		val1 = 0xE0 | (bit - 0);		val2 = 0xE0 | 1;	} 	outb(val1, port);	/* ack the slave */	outb(val2, 0x534);	/* ack the master */} static irq_swizzle_t sable_irq_swizzle = {	{		-1,  6, -1,  8, 15, 12,  7,  9,	/* pseudo PIC  0-7  */		-1, 16, 17, 18,  3, -1, 21, 22,	/* pseudo PIC  8-15 */		-1, -1, -1, -1, -1, -1, -1, -1,	/* pseudo EISA 0-7  */		-1, -1, -1, -1, -1, -1, -1, -1,	/* pseudo EISA 8-15  */		 2,  1,  0,  4,  5, -1, -1, -1,	/* pseudo PCI */		-1, -1, -1, -1, -1, -1, -1, -1,	/*  */		-1, -1, -1, -1, -1, -1, -1, -1,	/*  */		-1, -1, -1, -1, -1, -1, -1, -1 	/*  */	},	{		34, 33, 32, 12, 35, 36,  1,  6,	/* mask 0-7  */		 3,  7, -1, -1,  5, -1, -1,  4,	/* mask 8-15  */		 9, 10, 11, -1, -1, 14, 15, -1,	/* mask 16-23  */		-1, -1, -1, -1, -1, -1, -1, -1,	/*  */		-1, -1, -1, -1, -1, -1, -1, -1,	/*  */		-1, -1, -1, -1, -1, -1, -1, -1,	/*  */		-1, -1, -1, -1, -1, -1, -1, -1,	/*  */		-1, -1, -1, -1, -1, -1, -1, -1	/*  */	},	-1,	sable_update_irq_hw,	sable_ack_irq_hw}; static void __initsable_init_irq(void){	outb(-1, 0x537);	/* slave 0 */	outb(-1, 0x53b);	/* slave 1 */	outb(-1, 0x53d);	/* slave 2 */	outb(0x44, 0x535);	/* enable cascades in master */ 	sable_lynx_irq_swizzle = &sable_irq_swizzle;	sable_lynx_init_irq(40);} /* * PCI Fixup configuration for ALPHA SABLE (2100). * * The device to slot mapping looks like: * * Slot     Device *  0       TULIP *  1       SCSI *  2       PCI-EISA bridge *  3       none *  4       none *  5       none *  6       PCI on board slot 0 *  7       PCI on board slot 1 *  8       PCI on board slot 2 *    * * This two layered interrupt approach means that we allocate IRQ 16 and  * above for PCI interrupts.  The IRQ relates to which bit the interrupt * comes in on.  This makes interrupt processing much easier. *//* * NOTE: the IRQ assignments below are arbitrary, but need to be consistent * with the values in the irq swizzling tables above. */ static int __initsable_map_irq(const struct pci_dev *dev, u8 slot, u8 pin){	static char irq_tab[9][5] __initdata = {		/*INT    INTA   INTB   INTC   INTD */		{ 32+0,  32+0,  32+0,  32+0,  32+0},  /* IdSel 0,  TULIP  */		{ 32+1,  32+1,  32+1,  32+1,  32+1},  /* IdSel 1,  SCSI   */		{   -1,    -1,    -1,    -1,    -1},  /* IdSel 2,  SIO   */		{   -1,    -1,    -1,    -1,    -1},  /* IdSel 3,  none   */		{   -1,    -1,    -1,    -1,    -1},  /* IdSel 4,  none   */		{   -1,    -1,    -1,    -1,    -1},  /* IdSel 5,  none   */		{ 32+2,  32+2,  32+2,  32+2,  32+2},  /* IdSel 6,  slot 0 */		{ 32+3,  32+3,  32+3,  32+3,  32+3},  /* IdSel 7,  slot 1 */		{ 32+4,  32+4,  32+4,  32+4,  32+4}   /* IdSel 8,  slot 2 */	};	long min_idsel = 0, max_idsel = 8, irqs_per_slot = 5;	return COMMON_TABLE_LOOKUP;}#endif /* defined(CONFIG_ALPHA_GENERIC) || defined(CONFIG_ALPHA_SABLE) */ #if defined(CONFIG_ALPHA_GENERIC) || defined(CONFIG_ALPHA_LYNX) /***********************************************************************//* LYNX hardware specifics *//* *   For LYNX, which is also baroque, we manage 64 IRQs, via a custom IC. * * Bit      Meaning               Kernel IRQ *------------------------------------------ * 0         * 1         * 2         * 3        mouse			12 * 4         * 5         * 6        keyboard			1 * 7        floppy			6 * 8        COM2			3 * 9        parallel port		7 *10        EISA irq 3			- *11        EISA irq 4			- *12        EISA irq 5			5 *13        EISA irq 6			- *14        EISA irq 7			- *15        COM1			4 *16        EISA irq 9			9 *17        EISA irq 10			10 *18        EISA irq 11			11 *19        EISA irq 12			- *20         *21        EISA irq 14			14 *22        EISA irq 15			15 *23        IIC				- *24        VGA (builtin)               - *25 *26 *27 *28        NCR810 (builtin)		28 *29 *30 *31 *32        PCI 0 slot 4 A primary bus  32 *33        PCI 0 slot 4 B primary bus  33 *34        PCI 0 slot 4 C primary bus  34 *35        PCI 0 slot 4 D primary bus *36        PCI 0 slot 5 A primary bus *37        PCI 0 slot 5 B primary bus *38        PCI 0 slot 5 C primary bus *39        PCI 0 slot 5 D primary bus *40        PCI 0 slot 6 A primary bus *41        PCI 0 slot 6 B primary bus *42        PCI 0 slot 6 C primary bus *43        PCI 0 slot 6 D primary bus *44        PCI 0 slot 7 A primary bus *45        PCI 0 slot 7 B primary bus *46        PCI 0 slot 7 C primary bus *47        PCI 0 slot 7 D primary bus *48        PCI 0 slot 0 A secondary bus *49        PCI 0 slot 0 B secondary bus *50        PCI 0 slot 0 C secondary bus *51        PCI 0 slot 0 D secondary bus *52        PCI 0 slot 1 A secondary bus *53        PCI 0 slot 1 B secondary bus *54        PCI 0 slot 1 C secondary bus *55        PCI 0 slot 1 D secondary bus *56        PCI 0 slot 2 A secondary bus *57        PCI 0 slot 2 B secondary bus *58        PCI 0 slot 2 C secondary bus *59        PCI 0 slot 2 D secondary bus *60        PCI 0 slot 3 A secondary bus *61        PCI 0 slot 3 B secondary bus *62        PCI 0 slot 3 C secondary bus *63        PCI 0 slot 3 D secondary bus */ static voidlynx_update_irq_hw(unsigned long bit, unsigned long mask){	/*	 * Write the AIR register on the T3/T4 with the	 * address of the IC mask register (offset 0x40)	 */	*(vulp)T2_AIR = 0x40;	mb();	*(vulp)T2_AIR; /* re-read to force write */	mb();	*(vulp)T2_DIR = mask;    	mb();	mb();} static voidlynx_ack_irq_hw(unsigned long bit){	*(vulp)T2_VAR = (u_long) bit;	mb();	mb();} static irq_swizzle_t lynx_irq_swizzle = {	{ /* irq_to_mask */		-1,  6, -1,  8, 15, 12,  7,  9,	/* pseudo PIC  0-7  */		-1, 16, 17, 18,  3, -1, 21, 22,	/* pseudo PIC  8-15 */		-1, -1, -1, -1, -1, -1, -1, -1,	/* pseudo */		-1, -1, -1, -1, 28, -1, -1, -1,	/* pseudo */		32, 33, 34, 35, 36, 37, 38, 39,	/* mask 32-39 */		40, 41, 42, 43, 44, 45, 46, 47,	/* mask 40-47 */		48, 49, 50, 51, 52, 53, 54, 55,	/* mask 48-55 */		56, 57, 58, 59, 60, 61, 62, 63	/* mask 56-63 */	},	{ /* mask_to_irq */		-1, -1, -1, 12, -1, -1,  1,  6,	/* mask 0-7   */		 3,  7, -1, -1,  5, -1, -1,  4,	/* mask 8-15  */		 9, 10, 11, -1, -1, 14, 15, -1,	/* mask 16-23 */		-1, -1, -1, -1, 28, -1, -1, -1,	/* mask 24-31 */		32, 33, 34, 35, 36, 37, 38, 39,	/* mask 32-39 */		40, 41, 42, 43, 44, 45, 46, 47,	/* mask 40-47 */		48, 49, 50, 51, 52, 53, 54, 55,	/* mask 48-55 */		56, 57, 58, 59, 60, 61, 62, 63	/* mask 56-63 */	},	-1,	lynx_update_irq_hw,	lynx_ack_irq_hw}; static void __initlynx_init_irq(void){	sable_lynx_irq_swizzle = &lynx_irq_swizzle;	sable_lynx_init_irq(64);} /* * PCI Fixup configuration for ALPHA LYNX (2100A) * * The device to slot mapping looks like: * * Slot     Device *  0       none *  1       none *  2       PCI-EISA bridge *  3       PCI-PCI bridge *  4       NCR 810 (Demi-Lynx only) *  5       none *  6       PCI on board slot 4 *  7       PCI on board slot 5 *  8       PCI on board slot 6 *  9       PCI on board slot 7 * * And behind the PPB we have: * * 11       PCI on board slot 0 * 12       PCI on board slot 1 * 13       PCI on board slot 2 * 14       PCI on board slot 3 *//* * NOTE: the IRQ assignments below are arbitrary, but need to be consistent * with the values in the irq swizzling tables above. */ static int __initlynx_map_irq(const struct pci_dev *dev, u8 slot, u8 pin){	static char irq_tab[19][5] __initdata = {		/*INT    INTA   INTB   INTC   INTD */		{   -1,    -1,    -1,    -1,    -1},  /* IdSel 13,  PCEB   */		{   -1,    -1,    -1,    -1,    -1},  /* IdSel 14,  PPB    */		{   28,    28,    28,    28,    28},  /* IdSel 15,  NCR demi */		{   -1,    -1,    -1,    -1,    -1},  /* IdSel 16,  none   */		{   32,    32,    33,    34,    35},  /* IdSel 17,  slot 4 */		{   36,    36,    37,    38,    39},  /* IdSel 18,  slot 5 */		{   40,    40,    41,    42,    43},  /* IdSel 19,  slot 6 */		{   44,    44,    45,    46,    47},  /* IdSel 20,  slot 7 */		{   -1,    -1,    -1,    -1,    -1},  /* IdSel 22,  none   */		/* The following are actually behind the PPB. */		{   -1,    -1,    -1,    -1,    -1},  /* IdSel 16   none */		{   28,    28,    28,    28,    28},  /* IdSel 17   NCR lynx */		{   -1,    -1,    -1,    -1,    -1},  /* IdSel 18   none */		{   -1,    -1,    -1,    -1,    -1},  /* IdSel 19   none */		{   -1,    -1,    -1,    -1,    -1},  /* IdSel 20   none */		{   -1,    -1,    -1,    -1,    -1},  /* IdSel 21   none */		{   48,    48,    49,    50,    51},  /* IdSel 22   slot 0 */		{   52,    52,    53,    54,    55},  /* IdSel 23   slot 1 */		{   56,    56,    57,    58,    59},  /* IdSel 24   slot 2 */		{   60,    60,    61,    62,    63}   /* IdSel 25   slot 3 */	};	const long min_idsel = 2, max_idsel = 20, irqs_per_slot = 5;	return COMMON_TABLE_LOOKUP;} static u8 __initlynx_swizzle(struct pci_dev *dev, u8 *pinp){	int slot, pin = *pinp; 	if (dev->bus->number == 0) {		slot = PCI_SLOT(dev->devfn);	}	/* Check for the built-in bridge */	else if (PCI_SLOT(dev->bus->self->devfn) == 3) {		slot = PCI_SLOT(dev->devfn) + 11;	}	else	{		/* Must be a card-based bridge.  */		do {			if (PCI_SLOT(dev->bus->self->devfn) == 3) {				slot = PCI_SLOT(dev->devfn) + 11;				break;			}			pin = pci_swizzle_interrupt_pin(dev, pin); 			/* Move up the chain of bridges.  */			dev = dev->bus->self;			/* Slot of the next bridge.  */			slot = PCI_SLOT(dev->devfn);		} while (dev->bus->self);	}	*pinp = pin;	return slot;} #endif /* defined(CONFIG_ALPHA_GENERIC) || defined(CONFIG_ALPHA_LYNX) */ /***********************************************************************//* GENERIC irq routines */ static inline voidsable_lynx_enable_irq(struct irq_data *d){	unsigned long bit, mask; 	bit = sable_lynx_irq_swizzle->irq_to_mask[d->irq];	spin_lock(&sable_lynx_irq_lock);	mask = sable_lynx_irq_swizzle->shadow_mask &= ~(1UL << bit);	sable_lynx_irq_swizzle->update_irq_hw(bit, mask);	spin_unlock(&sable_lynx_irq_lock);#if 0	printk("%s: mask 0x%lx bit 0x%lx irq 0x%x\n",	       __func__, mask, bit, irq);#endif} static voidsable_lynx_disable_irq(struct irq_data *d){	unsigned long bit, mask; 	bit = sable_lynx_irq_swizzle->irq_to_mask[d->irq];	spin_lock(&sable_lynx_irq_lock);	mask = sable_lynx_irq_swizzle->shadow_mask |= 1UL << bit;	sable_lynx_irq_swizzle->update_irq_hw(bit, mask);	spin_unlock(&sable_lynx_irq_lock);#if 0	printk("%s: mask 0x%lx bit 0x%lx irq 0x%x\n",	       __func__, mask, bit, irq);#endif} static voidsable_lynx_mask_and_ack_irq(struct irq_data *d){	unsigned long bit, mask; 	bit = sable_lynx_irq_swizzle->irq_to_mask[d->irq];	spin_lock(&sable_lynx_irq_lock);	mask = sable_lynx_irq_swizzle->shadow_mask |= 1UL << bit;	sable_lynx_irq_swizzle->update_irq_hw(bit, mask);	sable_lynx_irq_swizzle->ack_irq_hw(bit);	spin_unlock(&sable_lynx_irq_lock);} static struct irq_chip sable_lynx_irq_type = {	.name		= "SABLE/LYNX",	.irq_unmask	= sable_lynx_enable_irq,	.irq_mask	= sable_lynx_disable_irq,	.irq_mask_ack	= sable_lynx_mask_and_ack_irq,}; static void sable_lynx_srm_device_interrupt(unsigned long vector){	/* Note that the vector reported by the SRM PALcode corresponds	   to the interrupt mask bits, but we have to manage via the

Lines 1–500 of 635.