diff options
author | Ralf Baechle <ralf@linux-mips.org> | 1999-10-09 00:00:47 +0000 |
---|---|---|
committer | Ralf Baechle <ralf@linux-mips.org> | 1999-10-09 00:00:47 +0000 |
commit | d6434e1042f3b0a6dfe1b1f615af369486f9b1fa (patch) | |
tree | e2be02f33984c48ec019c654051d27964e42c441 /arch/alpha/kernel/core_apecs.c | |
parent | 609d1e803baf519487233b765eb487f9ec227a18 (diff) |
Merge with 2.3.19.
Diffstat (limited to 'arch/alpha/kernel/core_apecs.c')
-rw-r--r-- | arch/alpha/kernel/core_apecs.c | 325 |
1 files changed, 115 insertions, 210 deletions
diff --git a/arch/alpha/kernel/core_apecs.c b/arch/alpha/kernel/core_apecs.c index fa23a4cf6..46378b762 100644 --- a/arch/alpha/kernel/core_apecs.c +++ b/arch/alpha/kernel/core_apecs.c @@ -1,22 +1,24 @@ /* * linux/arch/alpha/kernel/core_apecs.c * - * Code common to all APECS core logic chips. - * * Rewritten for Apecs from the lca.c from: * * Written by David Mosberger (davidm@cs.arizona.edu) with some code * taken from Dave Rusling's (david.rusling@reo.mts.dec.com) 32-bit * bios code. + * + * Code common to all APECS core logic chips. */ + #include <linux/kernel.h> -#include <linux/config.h> #include <linux/types.h> #include <linux/pci.h> #include <linux/init.h> #include <asm/system.h> #include <asm/ptrace.h> +#include <asm/smp.h> +#include <asm/pci.h> #define __EXTERN_INLINE inline #include <asm/io.h> @@ -24,6 +26,7 @@ #undef __EXTERN_INLINE #include "proto.h" +#include "pci_impl.h" /* * NOTE: Herein lie back-to-back mb instructions. They are magic. @@ -35,19 +38,16 @@ * BIOS32-style PCI interface: */ -#ifdef DEBUG -# define DBG(args) printk args +#define DEBUG_CONFIG 0 + +#if DEBUG_CONFIG +# define DBGC(args) printk args #else -# define DBG(args) +# define DBGC(args) #endif #define vuip volatile unsigned int * -volatile unsigned int apecs_mcheck_expected = 0; -volatile unsigned int apecs_mcheck_taken = 0; -static unsigned int apecs_jd, apecs_jd1, apecs_jd2; - - /* * Given a bus, device, and function number, compute resulting * configuration space address and setup the APECS_HAXR2 register @@ -91,14 +91,16 @@ static unsigned int apecs_jd, apecs_jd1, apecs_jd2; */ static int -mk_conf_addr(u8 bus, u8 device_fn, u8 where, unsigned long *pci_addr, +mk_conf_addr(struct pci_dev *dev, int where, unsigned long *pci_addr, unsigned char *type1) { unsigned long addr; + u8 bus = dev->bus->number; + u8 device_fn = dev->devfn; - DBG(("mk_conf_addr(bus=%d ,device_fn=0x%x, where=0x%x," - " pci_addr=0x%p, type1=0x%p)\n", - bus, device_fn, where, pci_addr, type1)); + DBGC(("mk_conf_addr(bus=%d ,device_fn=0x%x, where=0x%x," + " pci_addr=0x%p, type1=0x%p)\n", + bus, device_fn, where, pci_addr, type1)); if (bus == 0) { int device = device_fn >> 3; @@ -106,8 +108,8 @@ mk_conf_addr(u8 bus, u8 device_fn, u8 where, unsigned long *pci_addr, /* type 0 configuration cycle: */ if (device > 20) { - DBG(("mk_conf_addr: device (%d) > 20, returning -1\n", - device)); + DBGC(("mk_conf_addr: device (%d) > 20, returning -1\n", + device)); return -1; } @@ -119,7 +121,7 @@ mk_conf_addr(u8 bus, u8 device_fn, u8 where, unsigned long *pci_addr, addr = (bus << 16) | (device_fn << 8) | (where); } *pci_addr = addr; - DBG(("mk_conf_addr: returning pci_addr 0x%lx\n", addr)); + DBGC(("mk_conf_addr: returning pci_addr 0x%lx\n", addr)); return 0; } @@ -132,25 +134,25 @@ conf_read(unsigned long addr, unsigned char type1) __save_and_cli(flags); /* avoid getting hit by machine check */ - DBG(("conf_read(addr=0x%lx, type1=%d)\n", addr, type1)); + DBGC(("conf_read(addr=0x%lx, type1=%d)\n", addr, type1)); /* Reset status register to avoid losing errors. */ stat0 = *(vuip)APECS_IOC_DCSR; *(vuip)APECS_IOC_DCSR = stat0; mb(); - DBG(("conf_read: APECS DCSR was 0x%x\n", stat0)); + DBGC(("conf_read: APECS DCSR was 0x%x\n", stat0)); /* If Type1 access, must set HAE #2. */ if (type1) { haxr2 = *(vuip)APECS_IOC_HAXR2; mb(); *(vuip)APECS_IOC_HAXR2 = haxr2 | 1; - DBG(("conf_read: TYPE1 access\n")); + DBGC(("conf_read: TYPE1 access\n")); } draina(); - apecs_mcheck_expected = 1; - apecs_mcheck_taken = 0; + mcheck_expected(0) = 1; + mcheck_taken(0) = 0; mb(); /* Access configuration space. */ @@ -159,12 +161,12 @@ conf_read(unsigned long addr, unsigned char type1) asm volatile("ldl %0,%1; mb; mb" : "=r"(value) : "m"(*(vuip)addr) : "$9", "$10", "$11", "$12", "$13", "$14", "memory"); - if (apecs_mcheck_taken) { - apecs_mcheck_taken = 0; + if (mcheck_taken(0)) { + mcheck_taken(0) = 0; value = 0xffffffffU; mb(); } - apecs_mcheck_expected = 0; + mcheck_expected(0) = 0; mb(); #if 1 @@ -178,7 +180,7 @@ conf_read(unsigned long addr, unsigned char type1) /* Now look for any errors. */ stat0 = *(vuip)APECS_IOC_DCSR; - DBG(("conf_read: APECS DCSR after read 0x%x\n", stat0)); + DBGC(("conf_read: APECS DCSR after read 0x%x\n", stat0)); /* Is any error bit set? */ if (stat0 & 0xffe0U) { @@ -214,7 +216,6 @@ conf_write(unsigned long addr, unsigned int value, unsigned char type1) __save_and_cli(flags); /* avoid getting hit by machine check */ - /* Reset status register to avoid losing errors. */ stat0 = *(vuip)APECS_IOC_DCSR; *(vuip)APECS_IOC_DCSR = stat0; @@ -228,14 +229,14 @@ conf_write(unsigned long addr, unsigned int value, unsigned char type1) } draina(); - apecs_mcheck_expected = 1; + mcheck_expected(0) = 1; mb(); /* Access configuration space. */ *(vuip)addr = value; mb(); mb(); /* magic */ - apecs_mcheck_expected = 0; + mcheck_expected(0) = 0; mb(); #if 1 @@ -272,162 +273,106 @@ conf_write(unsigned long addr, unsigned int value, unsigned char type1) __restore_flags(flags); } -int -apecs_hose_read_config_byte (u8 bus, u8 device_fn, u8 where, u8 *value, - struct linux_hose_info *hose) +static int +apecs_read_config_byte(struct pci_dev *dev, int where, u8 *value) { - unsigned long addr = APECS_CONF; - unsigned long pci_addr; + unsigned long addr, pci_addr; unsigned char type1; - if (mk_conf_addr(bus, device_fn, where, &pci_addr, &type1)) + if (mk_conf_addr(dev, where, &pci_addr, &type1)) return PCIBIOS_DEVICE_NOT_FOUND; - addr |= (pci_addr << 5) + 0x00; - + addr = (pci_addr << 5) + 0x00 + APECS_CONF; *value = conf_read(addr, type1) >> ((where & 3) * 8); - return PCIBIOS_SUCCESSFUL; } -int -apecs_hose_read_config_word (u8 bus, u8 device_fn, u8 where, u16 *value, - struct linux_hose_info *hose) +static int +apecs_read_config_word(struct pci_dev *dev, int where, u16 *value) { - unsigned long addr = APECS_CONF; - unsigned long pci_addr; + unsigned long addr, pci_addr; unsigned char type1; - if (mk_conf_addr(bus, device_fn, where, &pci_addr, &type1)) + if (mk_conf_addr(dev, where, &pci_addr, &type1)) return PCIBIOS_DEVICE_NOT_FOUND; - addr |= (pci_addr << 5) + 0x08; - + addr = (pci_addr << 5) + 0x08 + APECS_CONF; *value = conf_read(addr, type1) >> ((where & 3) * 8); return PCIBIOS_SUCCESSFUL; } -int -apecs_hose_read_config_dword (u8 bus, u8 device_fn, u8 where, u32 *value, - struct linux_hose_info *hose) +static int +apecs_read_config_dword(struct pci_dev *dev, int where, u32 *value) { - unsigned long addr = APECS_CONF; - unsigned long pci_addr; + unsigned long addr, pci_addr; unsigned char type1; - if (mk_conf_addr(bus, device_fn, where, &pci_addr, &type1)) + if (mk_conf_addr(dev, where, &pci_addr, &type1)) return PCIBIOS_DEVICE_NOT_FOUND; - addr |= (pci_addr << 5) + 0x18; + addr = (pci_addr << 5) + 0x18 + APECS_CONF; *value = conf_read(addr, type1); return PCIBIOS_SUCCESSFUL; } -int -apecs_hose_write_config_byte (u8 bus, u8 device_fn, u8 where, u8 value, - struct linux_hose_info *hose) +static int +apecs_write_config(struct pci_dev *dev, int where, u32 value, long mask) { - unsigned long addr = APECS_CONF; - unsigned long pci_addr; + unsigned long addr, pci_addr; unsigned char type1; - if (mk_conf_addr(bus, device_fn, where, &pci_addr, &type1)) + if (mk_conf_addr(dev, where, &pci_addr, &type1)) return PCIBIOS_DEVICE_NOT_FOUND; - addr |= (pci_addr << 5) + 0x00; + addr = (pci_addr << 5) + mask + APECS_CONF; conf_write(addr, value << ((where & 3) * 8), type1); return PCIBIOS_SUCCESSFUL; } -int -apecs_hose_write_config_word (u8 bus, u8 device_fn, u8 where, u16 value, - struct linux_hose_info *hose) +static int +apecs_write_config_byte(struct pci_dev *dev, int where, u8 value) { - unsigned long addr = APECS_CONF; - unsigned long pci_addr; - unsigned char type1; - - if (mk_conf_addr(bus, device_fn, where, &pci_addr, &type1)) - return PCIBIOS_DEVICE_NOT_FOUND; - - addr |= (pci_addr << 5) + 0x08; - conf_write(addr, value << ((where & 3) * 8), type1); - return PCIBIOS_SUCCESSFUL; + return apecs_write_config(dev, where, value, 0x00); } -int -apecs_hose_write_config_dword (u8 bus, u8 device_fn, u8 where, u32 value, - struct linux_hose_info *hose) +static int +apecs_write_config_word(struct pci_dev *dev, int where, u16 value) { - unsigned long addr = APECS_CONF; - unsigned long pci_addr; - unsigned char type1; - - if (mk_conf_addr(bus, device_fn, where, &pci_addr, &type1)) - return PCIBIOS_DEVICE_NOT_FOUND; + return apecs_write_config(dev, where, value, 0x08); +} - addr |= (pci_addr << 5) + 0x18; - conf_write(addr, value << ((where & 3) * 8), type1); - return PCIBIOS_SUCCESSFUL; +static int +apecs_write_config_dword(struct pci_dev *dev, int where, u32 value) +{ + return apecs_write_config(dev, where, value, 0x18); } +struct pci_ops apecs_pci_ops = +{ + read_byte: apecs_read_config_byte, + read_word: apecs_read_config_word, + read_dword: apecs_read_config_dword, + write_byte: apecs_write_config_byte, + write_word: apecs_write_config_word, + write_dword: apecs_write_config_dword +}; + void __init apecs_init_arch(unsigned long *mem_start, unsigned long *mem_end) { - switch (alpha_use_srm_setup) - { - default: -#if defined(CONFIG_ALPHA_GENERIC) || defined(CONFIG_ALPHA_SRM_SETUP) - /* Check window 1 for enabled and mapped to 0. */ - if ((*(vuip)APECS_IOC_PB1R & (1U<<19)) - && (*(vuip)APECS_IOC_TB1R == 0)) { - APECS_DMA_WIN_BASE = *(vuip)APECS_IOC_PB1R & 0xfff00000U; - APECS_DMA_WIN_SIZE = *(vuip)APECS_IOC_PM1R & 0xfff00000U; - APECS_DMA_WIN_SIZE += 0x00100000U; -#if 1 - printk("apecs_init: using Window 1 settings\n"); - printk("apecs_init: PB1R 0x%x PM1R 0x%x TB1R 0x%x\n", - *(vuip)APECS_IOC_PB1R, - *(vuip)APECS_IOC_PM1R, - *(vuip)APECS_IOC_TB1R); -#endif - break; - } + struct pci_controler *hose; - /* Check window 2 for enabled and mapped to 0. */ - if ((*(vuip)APECS_IOC_PB2R & (1U<<19)) - && (*(vuip)APECS_IOC_TB2R == 0)) { - APECS_DMA_WIN_BASE = *(vuip)APECS_IOC_PB2R & 0xfff00000U; - APECS_DMA_WIN_SIZE = *(vuip)APECS_IOC_PM2R & 0xfff00000U; - APECS_DMA_WIN_SIZE += 0x00100000U; -#if 1 - printk("apecs_init: using Window 2 settings\n"); - printk("apecs_init: PB2R 0x%x PM2R 0x%x TB2R 0x%x\n", - *(vuip)APECS_IOC_PB2R, - *(vuip)APECS_IOC_PM2R, - *(vuip)APECS_IOC_TB2R); -#endif - break; - } - - /* Otherwise, we must use our defaults. */ - APECS_DMA_WIN_BASE = APECS_DMA_WIN_BASE_DEFAULT; - APECS_DMA_WIN_SIZE = APECS_DMA_WIN_SIZE_DEFAULT; -#endif - case 0: - /* - * Set up the PCI->physical memory translation windows. - * For now, window 2 is disabled. In the future, we may - * want to use it to do scatter/gather DMA. Window 1 - * goes at 1 GB and is 1 GB large. - */ - *(vuip)APECS_IOC_PB2R = 0U; /* disable window 2 */ - - *(vuip)APECS_IOC_PB1R = 1U<<19 | (APECS_DMA_WIN_BASE_DEFAULT & 0xfff00000U); - *(vuip)APECS_IOC_PM1R = (APECS_DMA_WIN_SIZE_DEFAULT - 1) & 0xfff00000U; - *(vuip)APECS_IOC_TB1R = 0; - break; - } + /* + * Set up the PCI->physical memory translation windows. + * For now, window 2 is disabled. In the future, we may + * want to use it to do scatter/gather DMA. Window 1 + * goes at 1 GB and is 1 GB large. + */ + *(vuip)APECS_IOC_PB1R = 1UL << 19 | (APECS_DMA_WIN_BASE & 0xfff00000U); + *(vuip)APECS_IOC_PM1R = (APECS_DMA_WIN_SIZE - 1) & 0xfff00000U; + *(vuip)APECS_IOC_TB1R = 0; + + *(vuip)APECS_IOC_PB2R = 0U; /* disable window 2 */ /* * Finally, clear the HAXR2 register, which gets used @@ -435,23 +380,35 @@ apecs_init_arch(unsigned long *mem_start, unsigned long *mem_end) * we want to use it, and we do not want to depend on * what ARC or SRM might have left behind... */ - *(vuip)APECS_IOC_HAXR2 = 0; mb(); + *(vuip)APECS_IOC_HAXR2 = 0; + mb(); + + /* + * Create our single hose. + */ + + hose = alloc_pci_controler(mem_start); + hose->io_space = &ioport_resource; + hose->mem_space = &iomem_resource; + hose->config_space = APECS_CONF; + hose->index = 0; } -int +void apecs_pci_clr_err(void) { - apecs_jd = *(vuip)APECS_IOC_DCSR; - if (apecs_jd & 0xffe0L) { - apecs_jd1 = *(vuip)APECS_IOC_SEAR; - *(vuip)APECS_IOC_DCSR = apecs_jd | 0xffe1L; - apecs_jd = *(vuip)APECS_IOC_DCSR; + unsigned int jd; + + jd = *(vuip)APECS_IOC_DCSR; + if (jd & 0xffe0L) { + *(vuip)APECS_IOC_SEAR; + *(vuip)APECS_IOC_DCSR = jd | 0xffe1L; mb(); + *(vuip)APECS_IOC_DCSR; } *(vuip)APECS_IOC_TBIA = (unsigned int)APECS_IOC_TBIA; - apecs_jd2 = *(vuip)APECS_IOC_TBIA; mb(); - return 0; + *(vuip)APECS_IOC_TBIA; } void @@ -461,8 +418,6 @@ apecs_machine_check(unsigned long vector, unsigned long la_ptr, struct el_common *mchk_header; struct el_apecs_procdata *mchk_procdata; struct el_apecs_sysdata_mcheck *mchk_sysdata; - unsigned long *ptr; - int i; mchk_header = (struct el_common *)la_ptr; @@ -473,66 +428,16 @@ apecs_machine_check(unsigned long vector, unsigned long la_ptr, mchk_sysdata = (struct el_apecs_sysdata_mcheck *) (la_ptr + mchk_header->sys_offset); -#ifdef DEBUG - printk("apecs_machine_check: vector=0x%lx la_ptr=0x%lx\n", - vector, la_ptr); - printk(" pc=0x%lx size=0x%x procoffset=0x%x sysoffset 0x%x\n", - regs->pc, mchk_header->size, mchk_header->proc_offset, - mchk_header->sys_offset); - printk("apecs_machine_check: expected %d DCSR 0x%lx PEAR 0x%lx\n", - apecs_mcheck_expected, mchk_sysdata->epic_dcsr, - mchk_sysdata->epic_pear); - ptr = (unsigned long *)la_ptr; - for (i = 0; i < mchk_header->size / sizeof(long); i += 2) { - printk(" +%lx %lx %lx\n", i*sizeof(long), ptr[i], ptr[i+1]); - } -#endif - /* - * Check if machine check is due to a badaddr() and if so, - * ignore the machine check. - */ + /* Clear the error before any reporting. */ + mb(); + mb(); /* magic */ + draina(); + apecs_pci_clr_err(); + wrmces(0x7); /* reset machine check pending flag */ + mb(); - if (apecs_mcheck_expected - && (mchk_sysdata->epic_dcsr & 0x0c00UL)) { - apecs_mcheck_expected = 0; - apecs_mcheck_taken = 1; - mb(); - mb(); /* magic */ - apecs_pci_clr_err(); - wrmces(0x7); - mb(); - draina(); - DBG(("apecs_machine_check: EXPECTED\n")); - } - else if (vector == 0x620 || vector == 0x630) { - /* Disable correctable from now on. */ - wrmces(0x1f); - mb(); - draina(); - printk("apecs_machine_check: HW correctable (0x%lx)\n", - vector); - } - else { - printk(KERN_CRIT "APECS machine check:\n"); - printk(KERN_CRIT " vector=0x%lx la_ptr=0x%lx\n", - vector, la_ptr); - printk(KERN_CRIT - " pc=0x%lx size=0x%x procoffset=0x%x sysoffset 0x%x\n", - regs->pc, mchk_header->size, mchk_header->proc_offset, - mchk_header->sys_offset); - printk(KERN_CRIT " expected %d DCSR 0x%lx PEAR 0x%lx\n", - apecs_mcheck_expected, mchk_sysdata->epic_dcsr, - mchk_sysdata->epic_pear); - - ptr = (unsigned long *)la_ptr; - for (i = 0; i < mchk_header->size / sizeof(long); i += 2) { - printk(KERN_CRIT " +%lx %lx %lx\n", - i*sizeof(long), ptr[i], ptr[i+1]); - } -#if 0 - /* doesn't work with MILO */ - show_regs(regs); -#endif - } + process_mcheck_info(vector, la_ptr, regs, "APECS", + (mcheck_expected(0) + && (mchk_sysdata->epic_dcsr & 0x0c00UL))); } |