1b2441318SGreg Kroah-Hartman // SPDX-License-Identifier: GPL-2.0
21da177e4SLinus Torvalds /*
31da177e4SLinus Torvalds * linux/arch/alpha/kernel/core_mcpcia.c
41da177e4SLinus Torvalds *
51da177e4SLinus Torvalds * Based on code written by David A Rusling (david.rusling@reo.mts.dec.com).
61da177e4SLinus Torvalds *
71da177e4SLinus Torvalds * Code common to all MCbus-PCI Adaptor core logic chipsets
81da177e4SLinus Torvalds */
91da177e4SLinus Torvalds
101da177e4SLinus Torvalds #define __EXTERN_INLINE inline
111da177e4SLinus Torvalds #include <asm/io.h>
121da177e4SLinus Torvalds #include <asm/core_mcpcia.h>
131da177e4SLinus Torvalds #undef __EXTERN_INLINE
141da177e4SLinus Torvalds
151da177e4SLinus Torvalds #include <linux/types.h>
161da177e4SLinus Torvalds #include <linux/pci.h>
171da177e4SLinus Torvalds #include <linux/sched.h>
181da177e4SLinus Torvalds #include <linux/init.h>
191da177e4SLinus Torvalds #include <linux/delay.h>
201da177e4SLinus Torvalds
211da177e4SLinus Torvalds #include <asm/ptrace.h>
221da177e4SLinus Torvalds
231da177e4SLinus Torvalds #include "proto.h"
241da177e4SLinus Torvalds #include "pci_impl.h"
251da177e4SLinus Torvalds
261da177e4SLinus Torvalds /*
271da177e4SLinus Torvalds * NOTE: Herein lie back-to-back mb instructions. They are magic.
281da177e4SLinus Torvalds * One plausible explanation is that the i/o controller does not properly
291da177e4SLinus Torvalds * handle the system transaction. Another involves timing. Ho hum.
301da177e4SLinus Torvalds */
311da177e4SLinus Torvalds
321da177e4SLinus Torvalds /*
331da177e4SLinus Torvalds * BIOS32-style PCI interface:
341da177e4SLinus Torvalds */
351da177e4SLinus Torvalds
361da177e4SLinus Torvalds #define DEBUG_CFG 0
371da177e4SLinus Torvalds
381da177e4SLinus Torvalds #if DEBUG_CFG
391da177e4SLinus Torvalds # define DBG_CFG(args) printk args
401da177e4SLinus Torvalds #else
411da177e4SLinus Torvalds # define DBG_CFG(args)
421da177e4SLinus Torvalds #endif
431da177e4SLinus Torvalds
441da177e4SLinus Torvalds /*
451da177e4SLinus Torvalds * Given a bus, device, and function number, compute resulting
461da177e4SLinus Torvalds * configuration space address and setup the MCPCIA_HAXR2 register
471da177e4SLinus Torvalds * accordingly. It is therefore not safe to have concurrent
481da177e4SLinus Torvalds * invocations to configuration space access routines, but there
491da177e4SLinus Torvalds * really shouldn't be any need for this.
501da177e4SLinus Torvalds *
511da177e4SLinus Torvalds * Type 0:
521da177e4SLinus Torvalds *
531da177e4SLinus Torvalds * 3 3|3 3 2 2|2 2 2 2|2 2 2 2|1 1 1 1|1 1 1 1|1 1
541da177e4SLinus Torvalds * 3 2|1 0 9 8|7 6 5 4|3 2 1 0|9 8 7 6|5 4 3 2|1 0 9 8|7 6 5 4|3 2 1 0
551da177e4SLinus Torvalds * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
561da177e4SLinus Torvalds * | | |D|D|D|D|D|D|D|D|D|D|D|D|D|D|D|D|D|D|D|D|D|F|F|F|R|R|R|R|R|R|0|0|
571da177e4SLinus Torvalds * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
581da177e4SLinus Torvalds *
591da177e4SLinus Torvalds * 31:11 Device select bit.
601da177e4SLinus Torvalds * 10:8 Function number
611da177e4SLinus Torvalds * 7:2 Register number
621da177e4SLinus Torvalds *
631da177e4SLinus Torvalds * Type 1:
641da177e4SLinus Torvalds *
651da177e4SLinus Torvalds * 3 3|3 3 2 2|2 2 2 2|2 2 2 2|1 1 1 1|1 1 1 1|1 1
661da177e4SLinus Torvalds * 3 2|1 0 9 8|7 6 5 4|3 2 1 0|9 8 7 6|5 4 3 2|1 0 9 8|7 6 5 4|3 2 1 0
671da177e4SLinus Torvalds * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
681da177e4SLinus Torvalds * | | | | | | | | | | |B|B|B|B|B|B|B|B|D|D|D|D|D|F|F|F|R|R|R|R|R|R|0|1|
691da177e4SLinus Torvalds * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
701da177e4SLinus Torvalds *
711da177e4SLinus Torvalds * 31:24 reserved
721da177e4SLinus Torvalds * 23:16 bus number (8 bits = 128 possible buses)
731da177e4SLinus Torvalds * 15:11 Device number (5 bits)
741da177e4SLinus Torvalds * 10:8 function number
751da177e4SLinus Torvalds * 7:2 register number
761da177e4SLinus Torvalds *
771da177e4SLinus Torvalds * Notes:
781da177e4SLinus Torvalds * The function number selects which function of a multi-function device
791da177e4SLinus Torvalds * (e.g., SCSI and Ethernet).
801da177e4SLinus Torvalds *
811da177e4SLinus Torvalds * The register selects a DWORD (32 bit) register offset. Hence it
821da177e4SLinus Torvalds * doesn't get shifted by 2 bits as we want to "drop" the bottom two
831da177e4SLinus Torvalds * bits.
841da177e4SLinus Torvalds */
851da177e4SLinus Torvalds
861da177e4SLinus Torvalds static unsigned int
conf_read(unsigned long addr,unsigned char type1,struct pci_controller * hose)871da177e4SLinus Torvalds conf_read(unsigned long addr, unsigned char type1,
881da177e4SLinus Torvalds struct pci_controller *hose)
891da177e4SLinus Torvalds {
901da177e4SLinus Torvalds unsigned long flags;
911da177e4SLinus Torvalds unsigned long mid = MCPCIA_HOSE2MID(hose->index);
92280da4e4SRichard Henderson unsigned int stat0, value, cpu;
931da177e4SLinus Torvalds
941da177e4SLinus Torvalds cpu = smp_processor_id();
951da177e4SLinus Torvalds
961da177e4SLinus Torvalds local_irq_save(flags);
971da177e4SLinus Torvalds
981da177e4SLinus Torvalds DBG_CFG(("conf_read(addr=0x%lx, type1=%d, hose=%d)\n",
991da177e4SLinus Torvalds addr, type1, mid));
1001da177e4SLinus Torvalds
1011da177e4SLinus Torvalds /* Reset status register to avoid losing errors. */
1021da177e4SLinus Torvalds stat0 = *(vuip)MCPCIA_CAP_ERR(mid);
1031da177e4SLinus Torvalds *(vuip)MCPCIA_CAP_ERR(mid) = stat0;
1041da177e4SLinus Torvalds mb();
105280da4e4SRichard Henderson *(vuip)MCPCIA_CAP_ERR(mid);
1061da177e4SLinus Torvalds DBG_CFG(("conf_read: MCPCIA_CAP_ERR(%d) was 0x%x\n", mid, stat0));
1071da177e4SLinus Torvalds
1081da177e4SLinus Torvalds mb();
1091da177e4SLinus Torvalds draina();
1101da177e4SLinus Torvalds mcheck_expected(cpu) = 1;
1111da177e4SLinus Torvalds mcheck_taken(cpu) = 0;
1121da177e4SLinus Torvalds mcheck_extra(cpu) = mid;
1131da177e4SLinus Torvalds mb();
1141da177e4SLinus Torvalds
1151da177e4SLinus Torvalds /* Access configuration space. */
1161da177e4SLinus Torvalds value = *((vuip)addr);
1171da177e4SLinus Torvalds mb();
1181da177e4SLinus Torvalds mb(); /* magic */
1191da177e4SLinus Torvalds
1201da177e4SLinus Torvalds if (mcheck_taken(cpu)) {
1211da177e4SLinus Torvalds mcheck_taken(cpu) = 0;
1221da177e4SLinus Torvalds value = 0xffffffffU;
1231da177e4SLinus Torvalds mb();
1241da177e4SLinus Torvalds }
1251da177e4SLinus Torvalds mcheck_expected(cpu) = 0;
1261da177e4SLinus Torvalds mb();
1271da177e4SLinus Torvalds
1281da177e4SLinus Torvalds DBG_CFG(("conf_read(): finished\n"));
1291da177e4SLinus Torvalds
1301da177e4SLinus Torvalds local_irq_restore(flags);
1311da177e4SLinus Torvalds return value;
1321da177e4SLinus Torvalds }
1331da177e4SLinus Torvalds
1341da177e4SLinus Torvalds static void
conf_write(unsigned long addr,unsigned int value,unsigned char type1,struct pci_controller * hose)1351da177e4SLinus Torvalds conf_write(unsigned long addr, unsigned int value, unsigned char type1,
1361da177e4SLinus Torvalds struct pci_controller *hose)
1371da177e4SLinus Torvalds {
1381da177e4SLinus Torvalds unsigned long flags;
1391da177e4SLinus Torvalds unsigned long mid = MCPCIA_HOSE2MID(hose->index);
140280da4e4SRichard Henderson unsigned int stat0, cpu;
1411da177e4SLinus Torvalds
1421da177e4SLinus Torvalds cpu = smp_processor_id();
1431da177e4SLinus Torvalds
1441da177e4SLinus Torvalds local_irq_save(flags); /* avoid getting hit by machine check */
1451da177e4SLinus Torvalds
1461da177e4SLinus Torvalds /* Reset status register to avoid losing errors. */
1471da177e4SLinus Torvalds stat0 = *(vuip)MCPCIA_CAP_ERR(mid);
1481da177e4SLinus Torvalds *(vuip)MCPCIA_CAP_ERR(mid) = stat0; mb();
149280da4e4SRichard Henderson *(vuip)MCPCIA_CAP_ERR(mid);
1501da177e4SLinus Torvalds DBG_CFG(("conf_write: MCPCIA CAP_ERR(%d) was 0x%x\n", mid, stat0));
1511da177e4SLinus Torvalds
1521da177e4SLinus Torvalds draina();
1531da177e4SLinus Torvalds mcheck_expected(cpu) = 1;
1541da177e4SLinus Torvalds mcheck_extra(cpu) = mid;
1551da177e4SLinus Torvalds mb();
1561da177e4SLinus Torvalds
1571da177e4SLinus Torvalds /* Access configuration space. */
1581da177e4SLinus Torvalds *((vuip)addr) = value;
1591da177e4SLinus Torvalds mb();
1601da177e4SLinus Torvalds mb(); /* magic */
161280da4e4SRichard Henderson *(vuip)MCPCIA_CAP_ERR(mid); /* read to force the write */
1621da177e4SLinus Torvalds mcheck_expected(cpu) = 0;
1631da177e4SLinus Torvalds mb();
1641da177e4SLinus Torvalds
1651da177e4SLinus Torvalds DBG_CFG(("conf_write(): finished\n"));
1661da177e4SLinus Torvalds local_irq_restore(flags);
1671da177e4SLinus Torvalds }
1681da177e4SLinus Torvalds
1691da177e4SLinus Torvalds static int
mk_conf_addr(struct pci_bus * pbus,unsigned int devfn,int where,struct pci_controller * hose,unsigned long * pci_addr,unsigned char * type1)1701da177e4SLinus Torvalds mk_conf_addr(struct pci_bus *pbus, unsigned int devfn, int where,
1711da177e4SLinus Torvalds struct pci_controller *hose, unsigned long *pci_addr,
1721da177e4SLinus Torvalds unsigned char *type1)
1731da177e4SLinus Torvalds {
1741da177e4SLinus Torvalds u8 bus = pbus->number;
1751da177e4SLinus Torvalds unsigned long addr;
1761da177e4SLinus Torvalds
1771da177e4SLinus Torvalds DBG_CFG(("mk_conf_addr(bus=%d,devfn=0x%x,hose=%d,where=0x%x,"
1781da177e4SLinus Torvalds " pci_addr=0x%p, type1=0x%p)\n",
1791da177e4SLinus Torvalds bus, devfn, hose->index, where, pci_addr, type1));
1801da177e4SLinus Torvalds
1811da177e4SLinus Torvalds /* Type 1 configuration cycle for *ALL* busses. */
1821da177e4SLinus Torvalds *type1 = 1;
1831da177e4SLinus Torvalds
1841da177e4SLinus Torvalds if (!pbus->parent) /* No parent means peer PCI bus. */
1851da177e4SLinus Torvalds bus = 0;
1861da177e4SLinus Torvalds addr = (bus << 16) | (devfn << 8) | (where);
1871da177e4SLinus Torvalds addr <<= 5; /* swizzle for SPARSE */
1881da177e4SLinus Torvalds addr |= hose->config_space_base;
1891da177e4SLinus Torvalds
1901da177e4SLinus Torvalds *pci_addr = addr;
1911da177e4SLinus Torvalds DBG_CFG(("mk_conf_addr: returning pci_addr 0x%lx\n", addr));
1921da177e4SLinus Torvalds return 0;
1931da177e4SLinus Torvalds }
1941da177e4SLinus Torvalds
1951da177e4SLinus Torvalds static int
mcpcia_read_config(struct pci_bus * bus,unsigned int devfn,int where,int size,u32 * value)1961da177e4SLinus Torvalds mcpcia_read_config(struct pci_bus *bus, unsigned int devfn, int where,
1971da177e4SLinus Torvalds int size, u32 *value)
1981da177e4SLinus Torvalds {
1991da177e4SLinus Torvalds struct pci_controller *hose = bus->sysdata;
2001da177e4SLinus Torvalds unsigned long addr, w;
2011da177e4SLinus Torvalds unsigned char type1;
2021da177e4SLinus Torvalds
2031da177e4SLinus Torvalds if (mk_conf_addr(bus, devfn, where, hose, &addr, &type1))
2041da177e4SLinus Torvalds return PCIBIOS_DEVICE_NOT_FOUND;
2051da177e4SLinus Torvalds
2061da177e4SLinus Torvalds addr |= (size - 1) * 8;
2071da177e4SLinus Torvalds w = conf_read(addr, type1, hose);
2081da177e4SLinus Torvalds switch (size) {
2091da177e4SLinus Torvalds case 1:
2101da177e4SLinus Torvalds *value = __kernel_extbl(w, where & 3);
2111da177e4SLinus Torvalds break;
2121da177e4SLinus Torvalds case 2:
2131da177e4SLinus Torvalds *value = __kernel_extwl(w, where & 3);
2141da177e4SLinus Torvalds break;
2151da177e4SLinus Torvalds case 4:
2161da177e4SLinus Torvalds *value = w;
2171da177e4SLinus Torvalds break;
2181da177e4SLinus Torvalds }
2191da177e4SLinus Torvalds return PCIBIOS_SUCCESSFUL;
2201da177e4SLinus Torvalds }
2211da177e4SLinus Torvalds
2221da177e4SLinus Torvalds static int
mcpcia_write_config(struct pci_bus * bus,unsigned int devfn,int where,int size,u32 value)2231da177e4SLinus Torvalds mcpcia_write_config(struct pci_bus *bus, unsigned int devfn, int where,
2241da177e4SLinus Torvalds int size, u32 value)
2251da177e4SLinus Torvalds {
2261da177e4SLinus Torvalds struct pci_controller *hose = bus->sysdata;
2271da177e4SLinus Torvalds unsigned long addr;
2281da177e4SLinus Torvalds unsigned char type1;
2291da177e4SLinus Torvalds
2301da177e4SLinus Torvalds if (mk_conf_addr(bus, devfn, where, hose, &addr, &type1))
2311da177e4SLinus Torvalds return PCIBIOS_DEVICE_NOT_FOUND;
2321da177e4SLinus Torvalds
2331da177e4SLinus Torvalds addr |= (size - 1) * 8;
2341da177e4SLinus Torvalds value = __kernel_insql(value, where & 3);
2351da177e4SLinus Torvalds conf_write(addr, value, type1, hose);
2361da177e4SLinus Torvalds return PCIBIOS_SUCCESSFUL;
2371da177e4SLinus Torvalds }
2381da177e4SLinus Torvalds
2391da177e4SLinus Torvalds struct pci_ops mcpcia_pci_ops =
2401da177e4SLinus Torvalds {
2411da177e4SLinus Torvalds .read = mcpcia_read_config,
2421da177e4SLinus Torvalds .write = mcpcia_write_config,
2431da177e4SLinus Torvalds };
2441da177e4SLinus Torvalds
2451da177e4SLinus Torvalds void
mcpcia_pci_tbi(struct pci_controller * hose,dma_addr_t start,dma_addr_t end)2461da177e4SLinus Torvalds mcpcia_pci_tbi(struct pci_controller *hose, dma_addr_t start, dma_addr_t end)
2471da177e4SLinus Torvalds {
2481da177e4SLinus Torvalds wmb();
2491da177e4SLinus Torvalds *(vuip)MCPCIA_SG_TBIA(MCPCIA_HOSE2MID(hose->index)) = 0;
2501da177e4SLinus Torvalds mb();
2511da177e4SLinus Torvalds }
2521da177e4SLinus Torvalds
2531da177e4SLinus Torvalds static int __init
mcpcia_probe_hose(int h)2541da177e4SLinus Torvalds mcpcia_probe_hose(int h)
2551da177e4SLinus Torvalds {
2561da177e4SLinus Torvalds int cpu = smp_processor_id();
2571da177e4SLinus Torvalds int mid = MCPCIA_HOSE2MID(h);
2581da177e4SLinus Torvalds unsigned int pci_rev;
2591da177e4SLinus Torvalds
2601da177e4SLinus Torvalds /* Gotta be REAL careful. If hose is absent, we get an mcheck. */
2611da177e4SLinus Torvalds
2621da177e4SLinus Torvalds mb();
2631da177e4SLinus Torvalds mb();
2641da177e4SLinus Torvalds draina();
2651da177e4SLinus Torvalds wrmces(7);
2661da177e4SLinus Torvalds
2671da177e4SLinus Torvalds mcheck_expected(cpu) = 2; /* indicates probing */
2681da177e4SLinus Torvalds mcheck_taken(cpu) = 0;
2691da177e4SLinus Torvalds mcheck_extra(cpu) = mid;
2701da177e4SLinus Torvalds mb();
2711da177e4SLinus Torvalds
2721da177e4SLinus Torvalds /* Access the bus revision word. */
2731da177e4SLinus Torvalds pci_rev = *(vuip)MCPCIA_REV(mid);
2741da177e4SLinus Torvalds
2751da177e4SLinus Torvalds mb();
2761da177e4SLinus Torvalds mb(); /* magic */
2771da177e4SLinus Torvalds if (mcheck_taken(cpu)) {
2781da177e4SLinus Torvalds mcheck_taken(cpu) = 0;
2791da177e4SLinus Torvalds pci_rev = 0xffffffff;
2801da177e4SLinus Torvalds mb();
2811da177e4SLinus Torvalds }
2821da177e4SLinus Torvalds mcheck_expected(cpu) = 0;
2831da177e4SLinus Torvalds mb();
2841da177e4SLinus Torvalds
2851da177e4SLinus Torvalds return (pci_rev >> 16) == PCI_CLASS_BRIDGE_HOST;
2861da177e4SLinus Torvalds }
2871da177e4SLinus Torvalds
2881da177e4SLinus Torvalds static void __init
mcpcia_new_hose(int h)2891da177e4SLinus Torvalds mcpcia_new_hose(int h)
2901da177e4SLinus Torvalds {
2911da177e4SLinus Torvalds struct pci_controller *hose;
2921da177e4SLinus Torvalds struct resource *io, *mem, *hae_mem;
2931da177e4SLinus Torvalds int mid = MCPCIA_HOSE2MID(h);
2941da177e4SLinus Torvalds
2951da177e4SLinus Torvalds hose = alloc_pci_controller();
2961da177e4SLinus Torvalds if (h == 0)
2971da177e4SLinus Torvalds pci_isa_hose = hose;
2981da177e4SLinus Torvalds io = alloc_resource();
2991da177e4SLinus Torvalds mem = alloc_resource();
3001da177e4SLinus Torvalds hae_mem = alloc_resource();
3011da177e4SLinus Torvalds
3021da177e4SLinus Torvalds hose->io_space = io;
3031da177e4SLinus Torvalds hose->mem_space = hae_mem;
3041da177e4SLinus Torvalds hose->sparse_mem_base = MCPCIA_SPARSE(mid) - IDENT_ADDR;
3051da177e4SLinus Torvalds hose->dense_mem_base = MCPCIA_DENSE(mid) - IDENT_ADDR;
3061da177e4SLinus Torvalds hose->sparse_io_base = MCPCIA_IO(mid) - IDENT_ADDR;
3071da177e4SLinus Torvalds hose->dense_io_base = 0;
3081da177e4SLinus Torvalds hose->config_space_base = MCPCIA_CONF(mid);
3091da177e4SLinus Torvalds hose->index = h;
3101da177e4SLinus Torvalds
3111da177e4SLinus Torvalds io->start = MCPCIA_IO(mid) - MCPCIA_IO_BIAS;
3121da177e4SLinus Torvalds io->end = io->start + 0xffff;
3131da177e4SLinus Torvalds io->name = pci_io_names[h];
3141da177e4SLinus Torvalds io->flags = IORESOURCE_IO;
3151da177e4SLinus Torvalds
3161da177e4SLinus Torvalds mem->start = MCPCIA_DENSE(mid) - MCPCIA_MEM_BIAS;
3171da177e4SLinus Torvalds mem->end = mem->start + 0xffffffff;
3181da177e4SLinus Torvalds mem->name = pci_mem_names[h];
3191da177e4SLinus Torvalds mem->flags = IORESOURCE_MEM;
3201da177e4SLinus Torvalds
3211da177e4SLinus Torvalds hae_mem->start = mem->start;
3221da177e4SLinus Torvalds hae_mem->end = mem->start + MCPCIA_MEM_MASK;
3231da177e4SLinus Torvalds hae_mem->name = pci_hae0_name;
3241da177e4SLinus Torvalds hae_mem->flags = IORESOURCE_MEM;
3251da177e4SLinus Torvalds
3261da177e4SLinus Torvalds if (request_resource(&ioport_resource, io) < 0)
3271da177e4SLinus Torvalds printk(KERN_ERR "Failed to request IO on hose %d\n", h);
3281da177e4SLinus Torvalds if (request_resource(&iomem_resource, mem) < 0)
3291da177e4SLinus Torvalds printk(KERN_ERR "Failed to request MEM on hose %d\n", h);
3301da177e4SLinus Torvalds if (request_resource(mem, hae_mem) < 0)
3311da177e4SLinus Torvalds printk(KERN_ERR "Failed to request HAE_MEM on hose %d\n", h);
3321da177e4SLinus Torvalds }
3331da177e4SLinus Torvalds
3341da177e4SLinus Torvalds static void
mcpcia_pci_clr_err(int mid)3351da177e4SLinus Torvalds mcpcia_pci_clr_err(int mid)
3361da177e4SLinus Torvalds {
3371da177e4SLinus Torvalds *(vuip)MCPCIA_CAP_ERR(mid);
3381da177e4SLinus Torvalds *(vuip)MCPCIA_CAP_ERR(mid) = 0xffffffff; /* Clear them all. */
3391da177e4SLinus Torvalds mb();
3401da177e4SLinus Torvalds *(vuip)MCPCIA_CAP_ERR(mid); /* Re-read for force write. */
3411da177e4SLinus Torvalds }
3421da177e4SLinus Torvalds
3431da177e4SLinus Torvalds static void __init
mcpcia_startup_hose(struct pci_controller * hose)3441da177e4SLinus Torvalds mcpcia_startup_hose(struct pci_controller *hose)
3451da177e4SLinus Torvalds {
3461da177e4SLinus Torvalds int mid = MCPCIA_HOSE2MID(hose->index);
3471da177e4SLinus Torvalds unsigned int tmp;
3481da177e4SLinus Torvalds
3491da177e4SLinus Torvalds mcpcia_pci_clr_err(mid);
3501da177e4SLinus Torvalds
3511da177e4SLinus Torvalds /*
3521da177e4SLinus Torvalds * Set up error reporting.
3531da177e4SLinus Torvalds */
3541da177e4SLinus Torvalds tmp = *(vuip)MCPCIA_CAP_ERR(mid);
3551da177e4SLinus Torvalds tmp |= 0x0006; /* master/target abort */
3561da177e4SLinus Torvalds *(vuip)MCPCIA_CAP_ERR(mid) = tmp;
3571da177e4SLinus Torvalds mb();
3581da177e4SLinus Torvalds tmp = *(vuip)MCPCIA_CAP_ERR(mid);
3591da177e4SLinus Torvalds
3601da177e4SLinus Torvalds /*
3611da177e4SLinus Torvalds * Set up the PCI->physical memory translation windows.
3621da177e4SLinus Torvalds *
3631da177e4SLinus Torvalds * Window 0 is scatter-gather 8MB at 8MB (for isa)
3641da177e4SLinus Torvalds * Window 1 is scatter-gather (up to) 1GB at 1GB (for pci)
3651da177e4SLinus Torvalds * Window 2 is direct access 2GB at 2GB
3661da177e4SLinus Torvalds */
3677e1c4e27SMike Rapoport hose->sg_isa = iommu_arena_new(hose, 0x00800000, 0x00800000,
3687e1c4e27SMike Rapoport SMP_CACHE_BYTES);
3691da177e4SLinus Torvalds hose->sg_pci = iommu_arena_new(hose, 0x40000000,
3707e1c4e27SMike Rapoport size_for_memory(0x40000000),
3717e1c4e27SMike Rapoport SMP_CACHE_BYTES);
3721da177e4SLinus Torvalds
3731da177e4SLinus Torvalds __direct_map_base = 0x80000000;
3741da177e4SLinus Torvalds __direct_map_size = 0x80000000;
3751da177e4SLinus Torvalds
3761da177e4SLinus Torvalds *(vuip)MCPCIA_W0_BASE(mid) = hose->sg_isa->dma_base | 3;
3771da177e4SLinus Torvalds *(vuip)MCPCIA_W0_MASK(mid) = (hose->sg_isa->size - 1) & 0xfff00000;
3781da177e4SLinus Torvalds *(vuip)MCPCIA_T0_BASE(mid) = virt_to_phys(hose->sg_isa->ptes) >> 8;
3791da177e4SLinus Torvalds
3801da177e4SLinus Torvalds *(vuip)MCPCIA_W1_BASE(mid) = hose->sg_pci->dma_base | 3;
3811da177e4SLinus Torvalds *(vuip)MCPCIA_W1_MASK(mid) = (hose->sg_pci->size - 1) & 0xfff00000;
3821da177e4SLinus Torvalds *(vuip)MCPCIA_T1_BASE(mid) = virt_to_phys(hose->sg_pci->ptes) >> 8;
3831da177e4SLinus Torvalds
3841da177e4SLinus Torvalds *(vuip)MCPCIA_W2_BASE(mid) = __direct_map_base | 1;
3851da177e4SLinus Torvalds *(vuip)MCPCIA_W2_MASK(mid) = (__direct_map_size - 1) & 0xfff00000;
3861da177e4SLinus Torvalds *(vuip)MCPCIA_T2_BASE(mid) = 0;
3871da177e4SLinus Torvalds
3881da177e4SLinus Torvalds *(vuip)MCPCIA_W3_BASE(mid) = 0x0;
3891da177e4SLinus Torvalds
3901da177e4SLinus Torvalds mcpcia_pci_tbi(hose, 0, -1);
3911da177e4SLinus Torvalds
3921da177e4SLinus Torvalds *(vuip)MCPCIA_HBASE(mid) = 0x0;
3931da177e4SLinus Torvalds mb();
3941da177e4SLinus Torvalds
3951da177e4SLinus Torvalds *(vuip)MCPCIA_HAE_MEM(mid) = 0U;
3961da177e4SLinus Torvalds mb();
3971da177e4SLinus Torvalds *(vuip)MCPCIA_HAE_MEM(mid); /* read it back. */
3981da177e4SLinus Torvalds *(vuip)MCPCIA_HAE_IO(mid) = 0;
3991da177e4SLinus Torvalds mb();
4001da177e4SLinus Torvalds *(vuip)MCPCIA_HAE_IO(mid); /* read it back. */
4011da177e4SLinus Torvalds }
4021da177e4SLinus Torvalds
4031da177e4SLinus Torvalds void __init
mcpcia_init_arch(void)4041da177e4SLinus Torvalds mcpcia_init_arch(void)
4051da177e4SLinus Torvalds {
4061da177e4SLinus Torvalds /* With multiple PCI busses, we play with I/O as physical addrs. */
4071da177e4SLinus Torvalds ioport_resource.end = ~0UL;
4081da177e4SLinus Torvalds
4091da177e4SLinus Torvalds /* Allocate hose 0. That's the one that all the ISA junk hangs
4101da177e4SLinus Torvalds off of, from which we'll be registering stuff here in a bit.
4111da177e4SLinus Torvalds Other hose detection is done in mcpcia_init_hoses, which is
4121da177e4SLinus Torvalds called from init_IRQ. */
4131da177e4SLinus Torvalds
4141da177e4SLinus Torvalds mcpcia_new_hose(0);
4151da177e4SLinus Torvalds }
4161da177e4SLinus Torvalds
4171da177e4SLinus Torvalds /* This is called from init_IRQ, since we cannot take interrupts
4181da177e4SLinus Torvalds before then. Which means we cannot do this in init_arch. */
4191da177e4SLinus Torvalds
4201da177e4SLinus Torvalds void __init
mcpcia_init_hoses(void)4211da177e4SLinus Torvalds mcpcia_init_hoses(void)
4221da177e4SLinus Torvalds {
4231da177e4SLinus Torvalds struct pci_controller *hose;
4241da177e4SLinus Torvalds int hose_count;
4251da177e4SLinus Torvalds int h;
4261da177e4SLinus Torvalds
4271da177e4SLinus Torvalds /* First, find how many hoses we have. */
4281da177e4SLinus Torvalds hose_count = 0;
4291da177e4SLinus Torvalds for (h = 0; h < MCPCIA_MAX_HOSES; ++h) {
4301da177e4SLinus Torvalds if (mcpcia_probe_hose(h)) {
4311da177e4SLinus Torvalds if (h != 0)
4321da177e4SLinus Torvalds mcpcia_new_hose(h);
4331da177e4SLinus Torvalds hose_count++;
4341da177e4SLinus Torvalds }
4351da177e4SLinus Torvalds }
4361da177e4SLinus Torvalds
4371da177e4SLinus Torvalds printk("mcpcia_init_hoses: found %d hoses\n", hose_count);
4381da177e4SLinus Torvalds
4391da177e4SLinus Torvalds /* Now do init for each hose. */
4401da177e4SLinus Torvalds for (hose = hose_head; hose; hose = hose->next)
4411da177e4SLinus Torvalds mcpcia_startup_hose(hose);
4421da177e4SLinus Torvalds }
4431da177e4SLinus Torvalds
4441da177e4SLinus Torvalds static void
mcpcia_print_uncorrectable(struct el_MCPCIA_uncorrected_frame_mcheck * logout)4451da177e4SLinus Torvalds mcpcia_print_uncorrectable(struct el_MCPCIA_uncorrected_frame_mcheck *logout)
4461da177e4SLinus Torvalds {
4471da177e4SLinus Torvalds struct el_common_EV5_uncorrectable_mcheck *frame;
4481da177e4SLinus Torvalds int i;
4491da177e4SLinus Torvalds
4501da177e4SLinus Torvalds frame = &logout->procdata;
4511da177e4SLinus Torvalds
4521da177e4SLinus Torvalds /* Print PAL fields */
4531da177e4SLinus Torvalds for (i = 0; i < 24; i += 2) {
4541da177e4SLinus Torvalds printk(" paltmp[%d-%d] = %16lx %16lx\n",
4551da177e4SLinus Torvalds i, i+1, frame->paltemp[i], frame->paltemp[i+1]);
4561da177e4SLinus Torvalds }
4571da177e4SLinus Torvalds for (i = 0; i < 8; i += 2) {
4581da177e4SLinus Torvalds printk(" shadow[%d-%d] = %16lx %16lx\n",
4591da177e4SLinus Torvalds i, i+1, frame->shadow[i],
4601da177e4SLinus Torvalds frame->shadow[i+1]);
4611da177e4SLinus Torvalds }
4621da177e4SLinus Torvalds printk(" Addr of excepting instruction = %16lx\n",
4631da177e4SLinus Torvalds frame->exc_addr);
4641da177e4SLinus Torvalds printk(" Summary of arithmetic traps = %16lx\n",
4651da177e4SLinus Torvalds frame->exc_sum);
4661da177e4SLinus Torvalds printk(" Exception mask = %16lx\n",
4671da177e4SLinus Torvalds frame->exc_mask);
4681da177e4SLinus Torvalds printk(" Base address for PALcode = %16lx\n",
4691da177e4SLinus Torvalds frame->pal_base);
4701da177e4SLinus Torvalds printk(" Interrupt Status Reg = %16lx\n",
4711da177e4SLinus Torvalds frame->isr);
4721da177e4SLinus Torvalds printk(" CURRENT SETUP OF EV5 IBOX = %16lx\n",
4731da177e4SLinus Torvalds frame->icsr);
4741da177e4SLinus Torvalds printk(" I-CACHE Reg %s parity error = %16lx\n",
4751da177e4SLinus Torvalds (frame->ic_perr_stat & 0x800L) ?
4761da177e4SLinus Torvalds "Data" : "Tag",
4771da177e4SLinus Torvalds frame->ic_perr_stat);
4781da177e4SLinus Torvalds printk(" D-CACHE error Reg = %16lx\n",
4791da177e4SLinus Torvalds frame->dc_perr_stat);
4801da177e4SLinus Torvalds if (frame->dc_perr_stat & 0x2) {
4811da177e4SLinus Torvalds switch (frame->dc_perr_stat & 0x03c) {
4821da177e4SLinus Torvalds case 8:
4831da177e4SLinus Torvalds printk(" Data error in bank 1\n");
4841da177e4SLinus Torvalds break;
4851da177e4SLinus Torvalds case 4:
4861da177e4SLinus Torvalds printk(" Data error in bank 0\n");
4871da177e4SLinus Torvalds break;
4881da177e4SLinus Torvalds case 20:
4891da177e4SLinus Torvalds printk(" Tag error in bank 1\n");
4901da177e4SLinus Torvalds break;
4911da177e4SLinus Torvalds case 10:
4921da177e4SLinus Torvalds printk(" Tag error in bank 0\n");
4931da177e4SLinus Torvalds break;
4941da177e4SLinus Torvalds }
4951da177e4SLinus Torvalds }
4961da177e4SLinus Torvalds printk(" Effective VA = %16lx\n",
4971da177e4SLinus Torvalds frame->va);
4981da177e4SLinus Torvalds printk(" Reason for D-stream = %16lx\n",
4991da177e4SLinus Torvalds frame->mm_stat);
5001da177e4SLinus Torvalds printk(" EV5 SCache address = %16lx\n",
5011da177e4SLinus Torvalds frame->sc_addr);
5021da177e4SLinus Torvalds printk(" EV5 SCache TAG/Data parity = %16lx\n",
5031da177e4SLinus Torvalds frame->sc_stat);
5041da177e4SLinus Torvalds printk(" EV5 BC_TAG_ADDR = %16lx\n",
5051da177e4SLinus Torvalds frame->bc_tag_addr);
5061da177e4SLinus Torvalds printk(" EV5 EI_ADDR: Phys addr of Xfer = %16lx\n",
5071da177e4SLinus Torvalds frame->ei_addr);
5081da177e4SLinus Torvalds printk(" Fill Syndrome = %16lx\n",
5091da177e4SLinus Torvalds frame->fill_syndrome);
5101da177e4SLinus Torvalds printk(" EI_STAT reg = %16lx\n",
5111da177e4SLinus Torvalds frame->ei_stat);
5121da177e4SLinus Torvalds printk(" LD_LOCK = %16lx\n",
5131da177e4SLinus Torvalds frame->ld_lock);
5141da177e4SLinus Torvalds }
5151da177e4SLinus Torvalds
5161da177e4SLinus Torvalds static void
mcpcia_print_system_area(unsigned long la_ptr)5171da177e4SLinus Torvalds mcpcia_print_system_area(unsigned long la_ptr)
5181da177e4SLinus Torvalds {
5191da177e4SLinus Torvalds struct el_common *frame;
5201da177e4SLinus Torvalds struct pci_controller *hose;
5211da177e4SLinus Torvalds
5221da177e4SLinus Torvalds struct IOD_subpacket {
5231da177e4SLinus Torvalds unsigned long base;
5241da177e4SLinus Torvalds unsigned int whoami;
5251da177e4SLinus Torvalds unsigned int rsvd1;
5261da177e4SLinus Torvalds unsigned int pci_rev;
5271da177e4SLinus Torvalds unsigned int cap_ctrl;
5281da177e4SLinus Torvalds unsigned int hae_mem;
5291da177e4SLinus Torvalds unsigned int hae_io;
5301da177e4SLinus Torvalds unsigned int int_ctl;
5311da177e4SLinus Torvalds unsigned int int_reg;
5321da177e4SLinus Torvalds unsigned int int_mask0;
5331da177e4SLinus Torvalds unsigned int int_mask1;
5341da177e4SLinus Torvalds unsigned int mc_err0;
5351da177e4SLinus Torvalds unsigned int mc_err1;
5361da177e4SLinus Torvalds unsigned int cap_err;
5371da177e4SLinus Torvalds unsigned int rsvd2;
5381da177e4SLinus Torvalds unsigned int pci_err1;
5391da177e4SLinus Torvalds unsigned int mdpa_stat;
5401da177e4SLinus Torvalds unsigned int mdpa_syn;
5411da177e4SLinus Torvalds unsigned int mdpb_stat;
5421da177e4SLinus Torvalds unsigned int mdpb_syn;
5431da177e4SLinus Torvalds unsigned int rsvd3;
5441da177e4SLinus Torvalds unsigned int rsvd4;
5451da177e4SLinus Torvalds unsigned int rsvd5;
5461da177e4SLinus Torvalds } *iodpp;
5471da177e4SLinus Torvalds
5481da177e4SLinus Torvalds frame = (struct el_common *)la_ptr;
5491da177e4SLinus Torvalds iodpp = (struct IOD_subpacket *) (la_ptr + frame->sys_offset);
5501da177e4SLinus Torvalds
5511da177e4SLinus Torvalds for (hose = hose_head; hose; hose = hose->next, iodpp++) {
5521da177e4SLinus Torvalds
5531da177e4SLinus Torvalds printk("IOD %d Register Subpacket - Bridge Base Address %16lx\n",
5541da177e4SLinus Torvalds hose->index, iodpp->base);
5551da177e4SLinus Torvalds printk(" WHOAMI = %8x\n", iodpp->whoami);
5561da177e4SLinus Torvalds printk(" PCI_REV = %8x\n", iodpp->pci_rev);
5571da177e4SLinus Torvalds printk(" CAP_CTRL = %8x\n", iodpp->cap_ctrl);
5581da177e4SLinus Torvalds printk(" HAE_MEM = %8x\n", iodpp->hae_mem);
5591da177e4SLinus Torvalds printk(" HAE_IO = %8x\n", iodpp->hae_io);
5601da177e4SLinus Torvalds printk(" INT_CTL = %8x\n", iodpp->int_ctl);
5611da177e4SLinus Torvalds printk(" INT_REG = %8x\n", iodpp->int_reg);
5621da177e4SLinus Torvalds printk(" INT_MASK0 = %8x\n", iodpp->int_mask0);
5631da177e4SLinus Torvalds printk(" INT_MASK1 = %8x\n", iodpp->int_mask1);
5641da177e4SLinus Torvalds printk(" MC_ERR0 = %8x\n", iodpp->mc_err0);
5651da177e4SLinus Torvalds printk(" MC_ERR1 = %8x\n", iodpp->mc_err1);
5661da177e4SLinus Torvalds printk(" CAP_ERR = %8x\n", iodpp->cap_err);
5671da177e4SLinus Torvalds printk(" PCI_ERR1 = %8x\n", iodpp->pci_err1);
5681da177e4SLinus Torvalds printk(" MDPA_STAT = %8x\n", iodpp->mdpa_stat);
5691da177e4SLinus Torvalds printk(" MDPA_SYN = %8x\n", iodpp->mdpa_syn);
5701da177e4SLinus Torvalds printk(" MDPB_STAT = %8x\n", iodpp->mdpb_stat);
5711da177e4SLinus Torvalds printk(" MDPB_SYN = %8x\n", iodpp->mdpb_syn);
5721da177e4SLinus Torvalds }
5731da177e4SLinus Torvalds }
5741da177e4SLinus Torvalds
5751da177e4SLinus Torvalds void
mcpcia_machine_check(unsigned long vector,unsigned long la_ptr)5764fa1970aSAl Viro mcpcia_machine_check(unsigned long vector, unsigned long la_ptr)
5771da177e4SLinus Torvalds {
5781da177e4SLinus Torvalds struct el_MCPCIA_uncorrected_frame_mcheck *mchk_logout;
5791da177e4SLinus Torvalds unsigned int cpu = smp_processor_id();
5801da177e4SLinus Torvalds int expected;
5811da177e4SLinus Torvalds
5821da177e4SLinus Torvalds mchk_logout = (struct el_MCPCIA_uncorrected_frame_mcheck *)la_ptr;
5831da177e4SLinus Torvalds expected = mcheck_expected(cpu);
5841da177e4SLinus Torvalds
5851da177e4SLinus Torvalds mb();
5861da177e4SLinus Torvalds mb(); /* magic */
5871da177e4SLinus Torvalds draina();
5881da177e4SLinus Torvalds
5891da177e4SLinus Torvalds switch (expected) {
5901da177e4SLinus Torvalds case 0:
5911da177e4SLinus Torvalds {
5921da177e4SLinus Torvalds /* FIXME: how do we figure out which hose the
5931da177e4SLinus Torvalds error was on? */
5941da177e4SLinus Torvalds struct pci_controller *hose;
5951da177e4SLinus Torvalds for (hose = hose_head; hose; hose = hose->next)
5961da177e4SLinus Torvalds mcpcia_pci_clr_err(MCPCIA_HOSE2MID(hose->index));
5971da177e4SLinus Torvalds break;
5981da177e4SLinus Torvalds }
5991da177e4SLinus Torvalds case 1:
6001da177e4SLinus Torvalds mcpcia_pci_clr_err(mcheck_extra(cpu));
6011da177e4SLinus Torvalds break;
6021da177e4SLinus Torvalds default:
6031da177e4SLinus Torvalds /* Otherwise, we're being called from mcpcia_probe_hose
6041da177e4SLinus Torvalds and there's no hose clear an error from. */
6051da177e4SLinus Torvalds break;
6061da177e4SLinus Torvalds }
6071da177e4SLinus Torvalds
6081da177e4SLinus Torvalds wrmces(0x7);
6091da177e4SLinus Torvalds mb();
6101da177e4SLinus Torvalds
6114fa1970aSAl Viro process_mcheck_info(vector, la_ptr, "MCPCIA", expected != 0);
6121da177e4SLinus Torvalds if (!expected && vector != 0x620 && vector != 0x630) {
6131da177e4SLinus Torvalds mcpcia_print_uncorrectable(mchk_logout);
6141da177e4SLinus Torvalds mcpcia_print_system_area(la_ptr);
6151da177e4SLinus Torvalds }
6161da177e4SLinus Torvalds }
617