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