11da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/*
21da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds**
31da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds**  PCI Lower Bus Adapter (LBA) manager
41da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds**
51da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds**	(c) Copyright 1999,2000 Grant Grundler
61da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds**	(c) Copyright 1999,2000 Hewlett-Packard Company
71da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds**
81da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds**	This program is free software; you can redistribute it and/or modify
91da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds**	it under the terms of the GNU General Public License as published by
101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds**      the Free Software Foundation; either version 2 of the License, or
111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds**      (at your option) any later version.
121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds**
131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds**
141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds** This module primarily provides access to PCI bus (config/IOport
151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds** spaces) on platforms with an SBA/LBA chipset. A/B/C/J/L/N-class
161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds** with 4 digit model numbers - eg C3000 (and A400...sigh).
171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds**
181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds** LBA driver isn't as simple as the Dino driver because:
191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds**   (a) this chip has substantial bug fixes between revisions
201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds**       (Only one Dino bug has a software workaround :^(  )
211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds**   (b) has more options which we don't (yet) support (DMA hints, OLARD)
221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds**   (c) IRQ support lives in the I/O SAPIC driver (not with PCI driver)
231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds**   (d) play nicely with both PAT and "Legacy" PA-RISC firmware (PDC).
241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds**       (dino only deals with "Legacy" PDC)
251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds**
261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds** LBA driver passes the I/O SAPIC HPA to the I/O SAPIC driver.
271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds** (I/O SAPIC is integratd in the LBA chip).
281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds**
291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds** FIXME: Add support to SBA and LBA drivers for DMA hint sets
301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds** FIXME: Add support for PCI card hot-plug (OLARD).
311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds*/
321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/delay.h>
341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/types.h>
351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/kernel.h>
361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/spinlock.h>
371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/init.h>		/* for __init and __devinit */
381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/pci.h>
391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/ioport.h>
401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/slab.h>
411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <asm/byteorder.h>
431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <asm/pdc.h>
441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <asm/pdcpat.h>
451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <asm/page.h>
461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
471790cf9111f61d360d861901b97eba4de3b5414cKyle McMartin#include <asm/ropes.h>
481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <asm/hardware.h>	/* for register_parisc_driver() stuff */
491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <asm/parisc-device.h>
501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <asm/io.h>		/* read/write stuff */
511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#undef DEBUG_LBA	/* general stuff */
531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#undef DEBUG_LBA_PORT	/* debug I/O Port access */
541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#undef DEBUG_LBA_CFG	/* debug Config Space Access (ie PCI Bus walk) */
551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#undef DEBUG_LBA_PAT	/* debug PCI Resource Mgt code - PDC PAT only */
561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#undef FBB_SUPPORT	/* Fast Back-Back xfers - NOT READY YET */
581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#ifdef DEBUG_LBA
611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define DBG(x...)	printk(x)
621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#else
631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define DBG(x...)
641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#endif
651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#ifdef DEBUG_LBA_PORT
671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define DBG_PORT(x...)	printk(x)
681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#else
691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define DBG_PORT(x...)
701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#endif
711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#ifdef DEBUG_LBA_CFG
731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define DBG_CFG(x...)	printk(x)
741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#else
751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define DBG_CFG(x...)
761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#endif
771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#ifdef DEBUG_LBA_PAT
791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define DBG_PAT(x...)	printk(x)
801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#else
811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define DBG_PAT(x...)
821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#endif
831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/*
861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds** Config accessor functions only pass in the 8-bit bus number and not
871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds** the 8-bit "PCI Segment" number. Each LBA will be assigned a PCI bus
881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds** number based on what firmware wrote into the scratch register.
891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds**
901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds** The "secondary" bus number is set to this before calling
911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds** pci_register_ops(). If any PPB's are present, the scan will
921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds** discover them and update the "secondary" and "subordinate"
931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds** fields in the pci_bus structure.
941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds**
951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds** Changes in the configuration *may* result in a different
961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds** bus number for each LBA depending on what firmware does.
971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds*/
981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define MODULE_NAME "LBA"
1001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* non-postable I/O port space, densely packed */
1021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define LBA_PORT_BASE	(PCI_F_EXTEND | 0xfee00000UL)
1038039de10aae3cd4cf0ef0ccebd58aff0e8810df2Helge Dellerstatic void __iomem *astro_iop_base __read_mostly;
1041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic u32 lba_t32;
1061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* lba flags */
1081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define LBA_FLAG_SKIP_PROBE	0x10
1091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define LBA_SKIP_PROBE(d) ((d)->flags & LBA_FLAG_SKIP_PROBE)
1111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* Looks nice and keeps the compiler happy */
1141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define LBA_DEV(d) ((struct lba_device *) (d))
1151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/*
1181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds** Only allow 8 subsidiary busses per LBA
1191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds** Problem is the PCI bus numbering is globally shared.
1201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds*/
1211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define LBA_MAX_NUM_BUSES 8
1221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/************************************
1241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * LBA register read and write support
1251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *
1261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * BE WARNED: register writes are posted.
1271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *  (ie follow writes which must reach HW with a read)
1281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */
1291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define READ_U8(addr)  __raw_readb(addr)
1301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define READ_U16(addr) __raw_readw(addr)
1311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define READ_U32(addr) __raw_readl(addr)
1321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define WRITE_U8(value, addr)  __raw_writeb(value, addr)
1331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define WRITE_U16(value, addr) __raw_writew(value, addr)
1341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define WRITE_U32(value, addr) __raw_writel(value, addr)
1351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define READ_REG8(addr)  readb(addr)
1371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define READ_REG16(addr) readw(addr)
1381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define READ_REG32(addr) readl(addr)
1391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define READ_REG64(addr) readq(addr)
1401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define WRITE_REG8(value, addr)  writeb(value, addr)
1411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define WRITE_REG16(value, addr) writew(value, addr)
1421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define WRITE_REG32(value, addr) writel(value, addr)
1431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define LBA_CFG_TOK(bus,dfn) ((u32) ((bus)<<16 | (dfn)<<8))
1461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define LBA_CFG_BUS(tok)  ((u8) ((tok)>>16))
1471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define LBA_CFG_DEV(tok)  ((u8) ((tok)>>11) & 0x1f)
1481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define LBA_CFG_FUNC(tok) ((u8) ((tok)>>8 ) & 0x7)
1491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/*
1521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds** Extract LBA (Rope) number from HPA
1531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds** REVISIT: 16 ropes for Stretch/Ike?
1541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds*/
1551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define ROPES_PER_IOC	8
1561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define LBA_NUM(x)    ((((unsigned long) x) >> 13) & (ROPES_PER_IOC-1))
1571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic void
1601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldslba_dump_res(struct resource *r, int d)
1611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
1621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	int i;
1631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (NULL == r)
1651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		return;
1661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	printk(KERN_DEBUG "(%p)", r->parent);
1681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	for (i = d; i ; --i) printk(" ");
169645d11d4baa56c6830daac46a92d63b7093cbc09Matthew Wilcox	printk(KERN_DEBUG "%p [%lx,%lx]/%lx\n", r,
170645d11d4baa56c6830daac46a92d63b7093cbc09Matthew Wilcox		(long)r->start, (long)r->end, r->flags);
1711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	lba_dump_res(r->child, d+2);
1721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	lba_dump_res(r->sibling, d);
1731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
1741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/*
1771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds** LBA rev 2.0, 2.1, 2.2, and 3.0 bus walks require a complex
1781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds** workaround for cfg cycles:
1791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds**	-- preserve  LBA state
1801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds**	-- prevent any DMA from occurring
1811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds**	-- turn on smart mode
1821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds**	-- probe with config writes before doing config reads
1831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds**	-- check ERROR_STATUS
1841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds**	-- clear ERROR_STATUS
1851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds**	-- restore LBA state
1861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds**
1871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds** The workaround is only used for device discovery.
1881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds*/
1891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int lba_device_present(u8 bus, u8 dfn, struct lba_device *d)
1911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
1921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	u8 first_bus = d->hba.hba_bus->secondary;
1931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	u8 last_sub_bus = d->hba.hba_bus->subordinate;
1941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if ((bus < first_bus) ||
1961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	    (bus > last_sub_bus) ||
1971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	    ((bus - first_bus) >= LBA_MAX_NUM_BUSES)) {
1981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		return 0;
1991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
2001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
2011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	return 1;
2021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
2031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
2041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
2051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
2061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define LBA_CFG_SETUP(d, tok) {				\
2071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds    /* Save contents of error config register.  */			\
2081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds    error_config = READ_REG32(d->hba.base_addr + LBA_ERROR_CONFIG);		\
2091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds\
2101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds    /* Save contents of status control register.  */			\
2111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds    status_control = READ_REG32(d->hba.base_addr + LBA_STAT_CTL);		\
2121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds\
2131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds    /* For LBA rev 2.0, 2.1, 2.2, and 3.0, we must disable DMA		\
2141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds    ** arbitration for full bus walks.					\
2151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds    */									\
2161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	/* Save contents of arb mask register. */			\
2171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	arb_mask = READ_REG32(d->hba.base_addr + LBA_ARB_MASK);		\
2181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds\
2191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	/*								\
2201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	 * Turn off all device arbitration bits (i.e. everything	\
2211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	 * except arbitration enable bit).				\
2221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	 */								\
2231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	WRITE_REG32(0x1, d->hba.base_addr + LBA_ARB_MASK);		\
2241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds\
2251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds    /*									\
2261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds     * Set the smart mode bit so that master aborts don't cause		\
2271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds     * LBA to go into PCI fatal mode (required).			\
2281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds     */									\
2291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds    WRITE_REG32(error_config | LBA_SMART_MODE, d->hba.base_addr + LBA_ERROR_CONFIG);	\
2301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
2311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
2321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
2331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define LBA_CFG_PROBE(d, tok) {				\
2341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds    /*									\
2351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds     * Setup Vendor ID write and read back the address register		\
2361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds     * to make sure that LBA is the bus master.				\
2371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds     */									\
2381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds    WRITE_REG32(tok | PCI_VENDOR_ID, (d)->hba.base_addr + LBA_PCI_CFG_ADDR);\
2391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds    /*									\
2401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds     * Read address register to ensure that LBA is the bus master,	\
2411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds     * which implies that DMA traffic has stopped when DMA arb is off.	\
2421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds     */									\
2431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds    lba_t32 = READ_REG32((d)->hba.base_addr + LBA_PCI_CFG_ADDR);	\
2441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds    /*									\
2451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds     * Generate a cfg write cycle (will have no affect on		\
2461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds     * Vendor ID register since read-only).				\
2471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds     */									\
2481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds    WRITE_REG32(~0, (d)->hba.base_addr + LBA_PCI_CFG_DATA);		\
2491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds    /*									\
2501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds     * Make sure write has completed before proceeding further,		\
2511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds     * i.e. before setting clear enable.				\
2521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds     */									\
2531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds    lba_t32 = READ_REG32((d)->hba.base_addr + LBA_PCI_CFG_ADDR);	\
2541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
2551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
2561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
2571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/*
2581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * HPREVISIT:
2591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *   -- Can't tell if config cycle got the error.
2601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *
2611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *		OV bit is broken until rev 4.0, so can't use OV bit and
2621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *		LBA_ERROR_LOG_ADDR to tell if error belongs to config cycle.
2631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *
2641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *		As of rev 4.0, no longer need the error check.
2651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *
2661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *   -- Even if we could tell, we still want to return -1
2671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *	for **ANY** error (not just master abort).
2681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *
2691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *   -- Only clear non-fatal errors (we don't want to bring
2701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *	LBA out of pci-fatal mode).
2711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *
2721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *		Actually, there is still a race in which
2731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *		we could be clearing a fatal error.  We will
2741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *		live with this during our initial bus walk
2751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *		until rev 4.0 (no driver activity during
2761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *		initial bus walk).  The initial bus walk
2771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *		has race conditions concerning the use of
2781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *		smart mode as well.
2791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */
2801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
2811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define LBA_MASTER_ABORT_ERROR 0xc
2821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define LBA_FATAL_ERROR 0x10
2831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
2841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define LBA_CFG_MASTER_ABORT_CHECK(d, base, tok, error) {		\
2851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds    u32 error_status = 0;						\
2861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds    /*									\
2871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds     * Set clear enable (CE) bit. Unset by HW when new			\
2881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds     * errors are logged -- LBA HW ERS section 14.3.3).		\
2891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds     */									\
2901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds    WRITE_REG32(status_control | CLEAR_ERRLOG_ENABLE, base + LBA_STAT_CTL); \
2911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds    error_status = READ_REG32(base + LBA_ERROR_STATUS);		\
2921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds    if ((error_status & 0x1f) != 0) {					\
2931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	/*								\
2941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	 * Fail the config read request.				\
2951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	 */								\
2961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	error = 1;							\
2971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if ((error_status & LBA_FATAL_ERROR) == 0) {			\
2981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	    /*								\
2991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	     * Clear error status (if fatal bit not set) by setting	\
3001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	     * clear error log bit (CL).				\
3011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	     */								\
3021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	    WRITE_REG32(status_control | CLEAR_ERRLOG, base + LBA_STAT_CTL); \
3031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}								\
3041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds    }									\
3051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
3061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
3071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define LBA_CFG_TR4_ADDR_SETUP(d, addr)					\
3081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	WRITE_REG32(((addr) & ~3), (d)->hba.base_addr + LBA_PCI_CFG_ADDR);
3091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
3101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define LBA_CFG_ADDR_SETUP(d, addr) {					\
3111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds    WRITE_REG32(((addr) & ~3), (d)->hba.base_addr + LBA_PCI_CFG_ADDR);	\
3121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds    /*									\
3131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds     * Read address register to ensure that LBA is the bus master,	\
3141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds     * which implies that DMA traffic has stopped when DMA arb is off.	\
3151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds     */									\
3161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds    lba_t32 = READ_REG32((d)->hba.base_addr + LBA_PCI_CFG_ADDR);	\
3171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
3181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
3191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
3201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define LBA_CFG_RESTORE(d, base) {					\
3211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds    /*									\
3221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds     * Restore status control register (turn off clear enable).		\
3231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds     */									\
3241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds    WRITE_REG32(status_control, base + LBA_STAT_CTL);			\
3251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds    /*									\
3261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds     * Restore error config register (turn off smart mode).		\
3271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds     */									\
3281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds    WRITE_REG32(error_config, base + LBA_ERROR_CONFIG);			\
3291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	/*								\
3301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	 * Restore arb mask register (reenables DMA arbitration).	\
3311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	 */								\
3321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	WRITE_REG32(arb_mask, base + LBA_ARB_MASK);			\
3331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
3341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
3351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
3361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
3371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic unsigned int
3381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldslba_rd_cfg(struct lba_device *d, u32 tok, u8 reg, u32 size)
3391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
3401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	u32 data = ~0U;
3411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	int error = 0;
3421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	u32 arb_mask = 0;	/* used by LBA_CFG_SETUP/RESTORE */
3431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	u32 error_config = 0;	/* used by LBA_CFG_SETUP/RESTORE */
3441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	u32 status_control = 0;	/* used by LBA_CFG_SETUP/RESTORE */
3451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
3461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	LBA_CFG_SETUP(d, tok);
3471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	LBA_CFG_PROBE(d, tok);
3481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	LBA_CFG_MASTER_ABORT_CHECK(d, d->hba.base_addr, tok, error);
3491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (!error) {
3501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		void __iomem *data_reg = d->hba.base_addr + LBA_PCI_CFG_DATA;
3511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
3521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		LBA_CFG_ADDR_SETUP(d, tok | reg);
3531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		switch (size) {
3541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		case 1: data = (u32) READ_REG8(data_reg + (reg & 3)); break;
3551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		case 2: data = (u32) READ_REG16(data_reg+ (reg & 2)); break;
3561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		case 4: data = READ_REG32(data_reg); break;
3571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		}
3581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
3591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	LBA_CFG_RESTORE(d, d->hba.base_addr);
3601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	return(data);
3611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
3621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
3631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
3641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int elroy_cfg_read(struct pci_bus *bus, unsigned int devfn, int pos, int size, u32 *data)
3651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
3661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	struct lba_device *d = LBA_DEV(parisc_walk_tree(bus->bridge));
3671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	u32 local_bus = (bus->parent == NULL) ? 0 : bus->secondary;
3681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	u32 tok = LBA_CFG_TOK(local_bus, devfn);
3691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	void __iomem *data_reg = d->hba.base_addr + LBA_PCI_CFG_DATA;
3701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
3711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if ((pos > 255) || (devfn > 255))
3721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		return -EINVAL;
3731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
3741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* FIXME: B2K/C3600 workaround is always use old method... */
3751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	/* if (!LBA_SKIP_PROBE(d)) */ {
3761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		/* original - Generate config cycle on broken elroy
3771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		  with risk we will miss PCI bus errors. */
3781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		*data = lba_rd_cfg(d, tok, pos, size);
379a8043ecb17bd2e4b034006bee315efeea3936278Harvey Harrison		DBG_CFG("%s(%x+%2x) -> 0x%x (a)\n", __func__, tok, pos, *data);
3801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		return 0;
3811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
3821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
3831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (LBA_SKIP_PROBE(d) && !lba_device_present(bus->secondary, devfn, d)) {
384a8043ecb17bd2e4b034006bee315efeea3936278Harvey Harrison		DBG_CFG("%s(%x+%2x) -> -1 (b)\n", __func__, tok, pos);
3851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		/* either don't want to look or know device isn't present. */
3861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		*data = ~0U;
3871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		return(0);
3881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
3891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
3901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	/* Basic Algorithm
3911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	** Should only get here on fully working LBA rev.
3921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	** This is how simple the code should have been.
3931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	*/
3941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	LBA_CFG_ADDR_SETUP(d, tok | pos);
3951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	switch(size) {
3961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	case 1: *data = READ_REG8 (data_reg + (pos & 3)); break;
3971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	case 2: *data = READ_REG16(data_reg + (pos & 2)); break;
3981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	case 4: *data = READ_REG32(data_reg); break;
3991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
400a8043ecb17bd2e4b034006bee315efeea3936278Harvey Harrison	DBG_CFG("%s(%x+%2x) -> 0x%x (c)\n", __func__, tok, pos, *data);
4011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	return 0;
4021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
4031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
4041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
4051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic void
4061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldslba_wr_cfg(struct lba_device *d, u32 tok, u8 reg, u32 data, u32 size)
4071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
4081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	int error = 0;
4091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	u32 arb_mask = 0;
4101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	u32 error_config = 0;
4111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	u32 status_control = 0;
4121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	void __iomem *data_reg = d->hba.base_addr + LBA_PCI_CFG_DATA;
4131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
4141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	LBA_CFG_SETUP(d, tok);
4151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	LBA_CFG_ADDR_SETUP(d, tok | reg);
4161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	switch (size) {
4171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	case 1: WRITE_REG8 (data, data_reg + (reg & 3)); break;
4181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	case 2: WRITE_REG16(data, data_reg + (reg & 2)); break;
4191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	case 4: WRITE_REG32(data, data_reg);             break;
4201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
4211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	LBA_CFG_MASTER_ABORT_CHECK(d, d->hba.base_addr, tok, error);
4221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	LBA_CFG_RESTORE(d, d->hba.base_addr);
4231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
4241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
4251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
4261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/*
4271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * LBA 4.0 config write code implements non-postable semantics
4281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * by doing a read of CONFIG ADDR after the write.
4291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */
4301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
4311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int elroy_cfg_write(struct pci_bus *bus, unsigned int devfn, int pos, int size, u32 data)
4321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
4331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	struct lba_device *d = LBA_DEV(parisc_walk_tree(bus->bridge));
4341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	u32 local_bus = (bus->parent == NULL) ? 0 : bus->secondary;
4351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	u32 tok = LBA_CFG_TOK(local_bus,devfn);
4361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
4371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if ((pos > 255) || (devfn > 255))
4381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		return -EINVAL;
4391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
4401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (!LBA_SKIP_PROBE(d)) {
4411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		/* Original Workaround */
4421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		lba_wr_cfg(d, tok, pos, (u32) data, size);
443a8043ecb17bd2e4b034006bee315efeea3936278Harvey Harrison		DBG_CFG("%s(%x+%2x) = 0x%x (a)\n", __func__, tok, pos,data);
4441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		return 0;
4451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
4461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
4471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (LBA_SKIP_PROBE(d) && (!lba_device_present(bus->secondary, devfn, d))) {
448a8043ecb17bd2e4b034006bee315efeea3936278Harvey Harrison		DBG_CFG("%s(%x+%2x) = 0x%x (b)\n", __func__, tok, pos,data);
4491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		return 1; /* New Workaround */
4501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
4511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
452a8043ecb17bd2e4b034006bee315efeea3936278Harvey Harrison	DBG_CFG("%s(%x+%2x) = 0x%x (c)\n", __func__, tok, pos, data);
4531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
4541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	/* Basic Algorithm */
4551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	LBA_CFG_ADDR_SETUP(d, tok | pos);
4561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	switch(size) {
4571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	case 1: WRITE_REG8 (data, d->hba.base_addr + LBA_PCI_CFG_DATA + (pos & 3));
4581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		   break;
4591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	case 2: WRITE_REG16(data, d->hba.base_addr + LBA_PCI_CFG_DATA + (pos & 2));
4601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		   break;
4611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	case 4: WRITE_REG32(data, d->hba.base_addr + LBA_PCI_CFG_DATA);
4621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		   break;
4631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
4641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	/* flush posted write */
4651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	lba_t32 = READ_REG32(d->hba.base_addr + LBA_PCI_CFG_ADDR);
4661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	return 0;
4671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
4681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
4691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
4701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic struct pci_ops elroy_cfg_ops = {
4711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	.read =		elroy_cfg_read,
4721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	.write =	elroy_cfg_write,
4731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds};
4741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
4751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/*
4761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * The mercury_cfg_ops are slightly misnamed; they're also used for Elroy
4771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * TR4.0 as no additional bugs were found in this areea between Elroy and
4781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Mercury
4791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */
4801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
4811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int mercury_cfg_read(struct pci_bus *bus, unsigned int devfn, int pos, int size, u32 *data)
4821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
4831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	struct lba_device *d = LBA_DEV(parisc_walk_tree(bus->bridge));
4841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	u32 local_bus = (bus->parent == NULL) ? 0 : bus->secondary;
4851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	u32 tok = LBA_CFG_TOK(local_bus, devfn);
4861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	void __iomem *data_reg = d->hba.base_addr + LBA_PCI_CFG_DATA;
4871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
4881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if ((pos > 255) || (devfn > 255))
4891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		return -EINVAL;
4901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
4911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	LBA_CFG_TR4_ADDR_SETUP(d, tok | pos);
4921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	switch(size) {
4931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	case 1:
4941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		*data = READ_REG8(data_reg + (pos & 3));
4951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		break;
4961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	case 2:
4971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		*data = READ_REG16(data_reg + (pos & 2));
4981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		break;
4991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	case 4:
5001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		*data = READ_REG32(data_reg);             break;
5011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		break;
5021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
5031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
5041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	DBG_CFG("mercury_cfg_read(%x+%2x) -> 0x%x\n", tok, pos, *data);
5051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	return 0;
5061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
5071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
5081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/*
5091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * LBA 4.0 config write code implements non-postable semantics
5101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * by doing a read of CONFIG ADDR after the write.
5111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */
5121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
5131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int mercury_cfg_write(struct pci_bus *bus, unsigned int devfn, int pos, int size, u32 data)
5141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
5151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	struct lba_device *d = LBA_DEV(parisc_walk_tree(bus->bridge));
5161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	void __iomem *data_reg = d->hba.base_addr + LBA_PCI_CFG_DATA;
5171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	u32 local_bus = (bus->parent == NULL) ? 0 : bus->secondary;
5181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	u32 tok = LBA_CFG_TOK(local_bus,devfn);
5191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
5201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if ((pos > 255) || (devfn > 255))
5211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		return -EINVAL;
5221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
523a8043ecb17bd2e4b034006bee315efeea3936278Harvey Harrison	DBG_CFG("%s(%x+%2x) <- 0x%x (c)\n", __func__, tok, pos, data);
5241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
5251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	LBA_CFG_TR4_ADDR_SETUP(d, tok | pos);
5261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	switch(size) {
5271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	case 1:
5281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		WRITE_REG8 (data, data_reg + (pos & 3));
5291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		break;
5301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	case 2:
5311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		WRITE_REG16(data, data_reg + (pos & 2));
5321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		break;
5331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	case 4:
5341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		WRITE_REG32(data, data_reg);
5351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		break;
5361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
5371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
5381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	/* flush posted write */
5391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	lba_t32 = READ_U32(d->hba.base_addr + LBA_PCI_CFG_ADDR);
5401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	return 0;
5411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
5421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
5431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic struct pci_ops mercury_cfg_ops = {
5441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	.read =		mercury_cfg_read,
5451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	.write =	mercury_cfg_write,
5461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds};
5471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
5481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
5491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic void
5501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldslba_bios_init(void)
5511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
5521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	DBG(MODULE_NAME ": lba_bios_init\n");
5531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
5541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
5551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
5561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#ifdef CONFIG_64BIT
5571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
5581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/*
5596ca45a24ccb847251f71aec8906746d33e99f33eGrant Grundler * truncate_pat_collision:  Deal with overlaps or outright collisions
5606ca45a24ccb847251f71aec8906746d33e99f33eGrant Grundler *			between PAT PDC reported ranges.
5616ca45a24ccb847251f71aec8906746d33e99f33eGrant Grundler *
5626ca45a24ccb847251f71aec8906746d33e99f33eGrant Grundler *   Broken PA8800 firmware will report lmmio range that
5636ca45a24ccb847251f71aec8906746d33e99f33eGrant Grundler *   overlaps with CPU HPA. Just truncate the lmmio range.
5646ca45a24ccb847251f71aec8906746d33e99f33eGrant Grundler *
5656ca45a24ccb847251f71aec8906746d33e99f33eGrant Grundler *   BEWARE: conflicts with this lmmio range may be an
5666ca45a24ccb847251f71aec8906746d33e99f33eGrant Grundler *   elmmio range which is pointing down another rope.
5676ca45a24ccb847251f71aec8906746d33e99f33eGrant Grundler *
5686ca45a24ccb847251f71aec8906746d33e99f33eGrant Grundler *  FIXME: only deals with one collision per range...theoretically we
5696ca45a24ccb847251f71aec8906746d33e99f33eGrant Grundler *  could have several. Supporting more than one collision will get messy.
5706ca45a24ccb847251f71aec8906746d33e99f33eGrant Grundler */
5716ca45a24ccb847251f71aec8906746d33e99f33eGrant Grundlerstatic unsigned long
5726ca45a24ccb847251f71aec8906746d33e99f33eGrant Grundlertruncate_pat_collision(struct resource *root, struct resource *new)
5736ca45a24ccb847251f71aec8906746d33e99f33eGrant Grundler{
5746ca45a24ccb847251f71aec8906746d33e99f33eGrant Grundler	unsigned long start = new->start;
5756ca45a24ccb847251f71aec8906746d33e99f33eGrant Grundler	unsigned long end = new->end;
5766ca45a24ccb847251f71aec8906746d33e99f33eGrant Grundler	struct resource *tmp = root->child;
5776ca45a24ccb847251f71aec8906746d33e99f33eGrant Grundler
5786ca45a24ccb847251f71aec8906746d33e99f33eGrant Grundler	if (end <= start || start < root->start || !tmp)
5796ca45a24ccb847251f71aec8906746d33e99f33eGrant Grundler		return 0;
5806ca45a24ccb847251f71aec8906746d33e99f33eGrant Grundler
5816ca45a24ccb847251f71aec8906746d33e99f33eGrant Grundler	/* find first overlap */
5826ca45a24ccb847251f71aec8906746d33e99f33eGrant Grundler	while (tmp && tmp->end < start)
5836ca45a24ccb847251f71aec8906746d33e99f33eGrant Grundler		tmp = tmp->sibling;
5846ca45a24ccb847251f71aec8906746d33e99f33eGrant Grundler
5856ca45a24ccb847251f71aec8906746d33e99f33eGrant Grundler	/* no entries overlap */
5866ca45a24ccb847251f71aec8906746d33e99f33eGrant Grundler	if (!tmp)  return 0;
5876ca45a24ccb847251f71aec8906746d33e99f33eGrant Grundler
5886ca45a24ccb847251f71aec8906746d33e99f33eGrant Grundler	/* found one that starts behind the new one
5896ca45a24ccb847251f71aec8906746d33e99f33eGrant Grundler	** Don't need to do anything.
5906ca45a24ccb847251f71aec8906746d33e99f33eGrant Grundler	*/
5916ca45a24ccb847251f71aec8906746d33e99f33eGrant Grundler	if (tmp->start >= end) return 0;
5926ca45a24ccb847251f71aec8906746d33e99f33eGrant Grundler
5936ca45a24ccb847251f71aec8906746d33e99f33eGrant Grundler	if (tmp->start <= start) {
5946ca45a24ccb847251f71aec8906746d33e99f33eGrant Grundler		/* "front" of new one overlaps */
5956ca45a24ccb847251f71aec8906746d33e99f33eGrant Grundler		new->start = tmp->end + 1;
5966ca45a24ccb847251f71aec8906746d33e99f33eGrant Grundler
5976ca45a24ccb847251f71aec8906746d33e99f33eGrant Grundler		if (tmp->end >= end) {
5986ca45a24ccb847251f71aec8906746d33e99f33eGrant Grundler			/* AACCKK! totally overlaps! drop this range. */
5996ca45a24ccb847251f71aec8906746d33e99f33eGrant Grundler			return 1;
6006ca45a24ccb847251f71aec8906746d33e99f33eGrant Grundler		}
6016ca45a24ccb847251f71aec8906746d33e99f33eGrant Grundler	}
6026ca45a24ccb847251f71aec8906746d33e99f33eGrant Grundler
6036ca45a24ccb847251f71aec8906746d33e99f33eGrant Grundler	if (tmp->end < end ) {
6046ca45a24ccb847251f71aec8906746d33e99f33eGrant Grundler		/* "end" of new one overlaps */
6056ca45a24ccb847251f71aec8906746d33e99f33eGrant Grundler		new->end = tmp->start - 1;
6066ca45a24ccb847251f71aec8906746d33e99f33eGrant Grundler	}
6076ca45a24ccb847251f71aec8906746d33e99f33eGrant Grundler
6086ca45a24ccb847251f71aec8906746d33e99f33eGrant Grundler	printk(KERN_WARNING "LBA: Truncating lmmio_space [%lx/%lx] "
6096ca45a24ccb847251f71aec8906746d33e99f33eGrant Grundler					"to [%lx,%lx]\n",
6106ca45a24ccb847251f71aec8906746d33e99f33eGrant Grundler			start, end,
611645d11d4baa56c6830daac46a92d63b7093cbc09Matthew Wilcox			(long)new->start, (long)new->end );
6126ca45a24ccb847251f71aec8906746d33e99f33eGrant Grundler
6136ca45a24ccb847251f71aec8906746d33e99f33eGrant Grundler	return 0;	/* truncation successful */
6146ca45a24ccb847251f71aec8906746d33e99f33eGrant Grundler}
6156ca45a24ccb847251f71aec8906746d33e99f33eGrant Grundler
6161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#else
6176ca45a24ccb847251f71aec8906746d33e99f33eGrant Grundler#define truncate_pat_collision(r,n)  (0)
6181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#endif
6191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
6201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/*
6211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds** The algorithm is generic code.
6221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds** But it needs to access local data structures to get the IRQ base.
6231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds** Could make this a "pci_fixup_irq(bus, region)" but not sure
6241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds** it's worth it.
6251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds**
6261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds** Called by do_pci_scan_bus() immediately after each PCI bus is walked.
6271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds** Resources aren't allocated until recursive buswalk below HBA is completed.
6281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds*/
6291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic void
6301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldslba_fixup_bus(struct pci_bus *bus)
6311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
6321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	struct list_head *ln;
6331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#ifdef FBB_SUPPORT
6341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	u16 status;
6351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#endif
6361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	struct lba_device *ldev = LBA_DEV(parisc_walk_tree(bus->bridge));
6371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
6381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	DBG("lba_fixup_bus(0x%p) bus %d platform_data 0x%p\n",
6391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		bus, bus->secondary, bus->bridge->platform_data);
6401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
6411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	/*
6421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	** Properly Setup MMIO resources for this bus.
6431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	** pci_alloc_primary_bus() mangles this.
6441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	*/
6459785d646c10b0707412516ffe56b71b9eb18861fGrant Grundler	if (bus->parent) {
6469611f61eb5baf22b6b6ed46c2c196c10e1fade6aMatthew Wilcox		int i;
6471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		/* PCI-PCI Bridge */
6481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		pci_read_bridge_bases(bus);
6499611f61eb5baf22b6b6ed46c2c196c10e1fade6aMatthew Wilcox		for (i = PCI_BRIDGE_RESOURCES; i < PCI_NUM_RESOURCES; i++) {
6509611f61eb5baf22b6b6ed46c2c196c10e1fade6aMatthew Wilcox			pci_claim_resource(bus->self, i);
6519611f61eb5baf22b6b6ed46c2c196c10e1fade6aMatthew Wilcox		}
6521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	} else {
6531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		/* Host-PCI Bridge */
654dc7dce280a26d069ad5a58bf3da86e5e83415c65Bjorn Helgaas		int err;
6551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
6561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		DBG("lba_fixup_bus() %s [%lx/%lx]/%lx\n",
6571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			ldev->hba.io_space.name,
6581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			ldev->hba.io_space.start, ldev->hba.io_space.end,
6591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			ldev->hba.io_space.flags);
6601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		DBG("lba_fixup_bus() %s [%lx/%lx]/%lx\n",
6611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			ldev->hba.lmmio_space.name,
6621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			ldev->hba.lmmio_space.start, ldev->hba.lmmio_space.end,
6631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			ldev->hba.lmmio_space.flags);
6641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
6651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		err = request_resource(&ioport_resource, &(ldev->hba.io_space));
6661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		if (err < 0) {
6671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			lba_dump_res(&ioport_resource, 2);
6681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			BUG();
6691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		}
6701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
6711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		if (ldev->hba.elmmio_space.start) {
6721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			err = request_resource(&iomem_resource,
6731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds					&(ldev->hba.elmmio_space));
6741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			if (err < 0) {
6751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
6761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				printk("FAILED: lba_fixup_bus() request for "
6771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds						"elmmio_space [%lx/%lx]\n",
678645d11d4baa56c6830daac46a92d63b7093cbc09Matthew Wilcox						(long)ldev->hba.elmmio_space.start,
679645d11d4baa56c6830daac46a92d63b7093cbc09Matthew Wilcox						(long)ldev->hba.elmmio_space.end);
6801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
6811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				/* lba_dump_res(&iomem_resource, 2); */
6821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				/* BUG(); */
683dc7dce280a26d069ad5a58bf3da86e5e83415c65Bjorn Helgaas			}
6841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		}
6851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
686f4d9ea9abf04a6ad9643df5497e6243fbf64196eBjorn Helgaas		if (ldev->hba.lmmio_space.flags) {
6876ca45a24ccb847251f71aec8906746d33e99f33eGrant Grundler			err = request_resource(&iomem_resource, &(ldev->hba.lmmio_space));
6886ca45a24ccb847251f71aec8906746d33e99f33eGrant Grundler			if (err < 0) {
6896ca45a24ccb847251f71aec8906746d33e99f33eGrant Grundler				printk(KERN_ERR "FAILED: lba_fixup_bus() request for "
6901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds					"lmmio_space [%lx/%lx]\n",
691645d11d4baa56c6830daac46a92d63b7093cbc09Matthew Wilcox					(long)ldev->hba.lmmio_space.start,
692645d11d4baa56c6830daac46a92d63b7093cbc09Matthew Wilcox					(long)ldev->hba.lmmio_space.end);
693dc7dce280a26d069ad5a58bf3da86e5e83415c65Bjorn Helgaas			}
6941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		}
6951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
6961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#ifdef CONFIG_64BIT
6971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		/* GMMIO is  distributed range. Every LBA/Rope gets part it. */
6981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		if (ldev->hba.gmmio_space.flags) {
6991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			err = request_resource(&iomem_resource, &(ldev->hba.gmmio_space));
7001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			if (err < 0) {
7011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				printk("FAILED: lba_fixup_bus() request for "
7021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds					"gmmio_space [%lx/%lx]\n",
703645d11d4baa56c6830daac46a92d63b7093cbc09Matthew Wilcox					(long)ldev->hba.gmmio_space.start,
704645d11d4baa56c6830daac46a92d63b7093cbc09Matthew Wilcox					(long)ldev->hba.gmmio_space.end);
7051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				lba_dump_res(&iomem_resource, 2);
7061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				BUG();
7071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			}
7081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		}
7091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#endif
7101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
7111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
7121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
7131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	list_for_each(ln, &bus->devices) {
7141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		int i;
7151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		struct pci_dev *dev = pci_dev_b(ln);
7161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
7171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		DBG("lba_fixup_bus() %s\n", pci_name(dev));
7181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
7191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		/* Virtualize Device/Bridge Resources. */
7201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		for (i = 0; i < PCI_BRIDGE_RESOURCES; i++) {
7211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			struct resource *res = &dev->resource[i];
7221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
7231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			/* If resource not allocated - skip it */
7241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			if (!res->start)
7251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				continue;
7261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
72784f4506cb788d85a50c97b399f2999f90e6272b0Kyle McMartin			/*
72884f4506cb788d85a50c97b399f2999f90e6272b0Kyle McMartin			** FIXME: this will result in whinging for devices
72984f4506cb788d85a50c97b399f2999f90e6272b0Kyle McMartin			** that share expansion ROMs (think quad tulip), but
73084f4506cb788d85a50c97b399f2999f90e6272b0Kyle McMartin			** isn't harmful.
73184f4506cb788d85a50c97b399f2999f90e6272b0Kyle McMartin			*/
73284f4506cb788d85a50c97b399f2999f90e6272b0Kyle McMartin			pci_claim_resource(dev, i);
7331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		}
7341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
7351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#ifdef FBB_SUPPORT
7361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		/*
7371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		** If one device does not support FBB transfers,
7381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		** No one on the bus can be allowed to use them.
7391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		*/
7401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		(void) pci_read_config_word(dev, PCI_STATUS, &status);
7411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		bus->bridge_ctl &= ~(status & PCI_STATUS_FAST_BACK);
7421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#endif
7431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
7441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                /*
7451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		** P2PB's have no IRQs. ignore them.
7461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		*/
7471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		if ((dev->class >> 8) == PCI_CLASS_BRIDGE_PCI)
7481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			continue;
7491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
7501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		/* Adjust INTERRUPT_LINE for this dev */
7511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		iosapic_fixup_irq(ldev->iosapic_obj, dev);
7521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
7531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
7541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#ifdef FBB_SUPPORT
7551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* FIXME/REVISIT - finish figuring out to set FBB on both
7561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds** pci_setup_bridge() clobbers PCI_BRIDGE_CONTROL.
7571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds** Can't fixup here anyway....garr...
7581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds*/
7591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (fbb_enable) {
7609785d646c10b0707412516ffe56b71b9eb18861fGrant Grundler		if (bus->parent) {
7611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			u8 control;
7621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			/* enable on PPB */
7631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			(void) pci_read_config_byte(bus->self, PCI_BRIDGE_CONTROL, &control);
7641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			(void) pci_write_config_byte(bus->self, PCI_BRIDGE_CONTROL, control | PCI_STATUS_FAST_BACK);
7651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
7661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		} else {
7671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			/* enable on LBA */
7681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		}
7691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		fbb_enable = PCI_COMMAND_FAST_BACK;
7701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
7711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
7721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	/* Lastly enable FBB/PERR/SERR on all devices too */
7731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	list_for_each(ln, &bus->devices) {
7741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		(void) pci_read_config_word(dev, PCI_COMMAND, &status);
7751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		status |= PCI_COMMAND_PARITY | PCI_COMMAND_SERR | fbb_enable;
7761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		(void) pci_write_config_word(dev, PCI_COMMAND, status);
7771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
7781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#endif
7791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
7801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
7811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
782df8e5bc6b7b61c8b2aeaf58b6afd762d20a651ddAdrian Bunkstatic struct pci_bios_ops lba_bios_ops = {
7831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	.init =		lba_bios_init,
7841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	.fixup_bus =	lba_fixup_bus,
7851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds};
7861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
7871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
7881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
7891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
7901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/*******************************************************
7911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds**
7921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds** LBA Sprockets "I/O Port" Space Accessor Functions
7931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds**
7941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds** This set of accessor functions is intended for use with
7951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds** "legacy firmware" (ie Sprockets on Allegro/Forte boxes).
7961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds**
7971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds** Many PCI devices don't require use of I/O port space (eg Tulip,
7981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds** NCR720) since they export the same registers to both MMIO and
7991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds** I/O port space. In general I/O port space is slower than
8001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds** MMIO since drivers are designed so PIO writes can be posted.
8011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds**
8021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds********************************************************/
8031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
8041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define LBA_PORT_IN(size, mask) \
8051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic u##size lba_astro_in##size (struct pci_hba_data *d, u16 addr) \
8061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ \
8071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	u##size t; \
8081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	t = READ_REG##size(astro_iop_base + addr); \
8091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	DBG_PORT(" 0x%x\n", t); \
8101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	return (t); \
8111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
8121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
8131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus TorvaldsLBA_PORT_IN( 8, 3)
8141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus TorvaldsLBA_PORT_IN(16, 2)
8151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus TorvaldsLBA_PORT_IN(32, 0)
8161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
8171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
8181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
8191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/*
8201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds** BUG X4107:  Ordering broken - DMA RD return can bypass PIO WR
8211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds**
8221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds** Fixed in Elroy 2.2. The READ_U32(..., LBA_FUNC_ID) below is
8231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds** guarantee non-postable completion semantics - not avoid X4107.
8241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds** The READ_U32 only guarantees the write data gets to elroy but
8251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds** out to the PCI bus. We can't read stuff from I/O port space
8261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds** since we don't know what has side-effects. Attempting to read
8271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds** from configuration space would be suicidal given the number of
8281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds** bugs in that elroy functionality.
8291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds**
8301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds**      Description:
8311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds**          DMA read results can improperly pass PIO writes (X4107).  The
8321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds**          result of this bug is that if a processor modifies a location in
8331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds**          memory after having issued PIO writes, the PIO writes are not
8341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds**          guaranteed to be completed before a PCI device is allowed to see
8351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds**          the modified data in a DMA read.
8361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds**
8371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds**          Note that IKE bug X3719 in TR1 IKEs will result in the same
8381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds**          symptom.
8391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds**
8401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds**      Workaround:
8411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds**          The workaround for this bug is to always follow a PIO write with
8421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds**          a PIO read to the same bus before starting DMA on that PCI bus.
8431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds**
8441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds*/
8451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define LBA_PORT_OUT(size, mask) \
8461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic void lba_astro_out##size (struct pci_hba_data *d, u16 addr, u##size val) \
8471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ \
848a8043ecb17bd2e4b034006bee315efeea3936278Harvey Harrison	DBG_PORT("%s(0x%p, 0x%x, 0x%x)\n", __func__, d, addr, val); \
8491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	WRITE_REG##size(val, astro_iop_base + addr); \
8501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (LBA_DEV(d)->hw_rev < 3) \
8511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		lba_t32 = READ_U32(d->base_addr + LBA_FUNC_ID); \
8521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
8531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
8541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus TorvaldsLBA_PORT_OUT( 8, 3)
8551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus TorvaldsLBA_PORT_OUT(16, 2)
8561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus TorvaldsLBA_PORT_OUT(32, 0)
8571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
8581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
8591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic struct pci_port_ops lba_astro_port_ops = {
8601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	.inb =	lba_astro_in8,
8611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	.inw =	lba_astro_in16,
8621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	.inl =	lba_astro_in32,
8631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	.outb =	lba_astro_out8,
8641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	.outw =	lba_astro_out16,
8651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	.outl =	lba_astro_out32
8661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds};
8671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
8681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
8691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#ifdef CONFIG_64BIT
8701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define PIOP_TO_GMMIO(lba, addr) \
8711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	((lba)->iop_base + (((addr)&0xFFFC)<<10) + ((addr)&3))
8721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
8731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/*******************************************************
8741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds**
8751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds** LBA PAT "I/O Port" Space Accessor Functions
8761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds**
8771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds** This set of accessor functions is intended for use with
8781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds** "PAT PDC" firmware (ie Prelude/Rhapsody/Piranha boxes).
8791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds**
8801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds** This uses the PIOP space located in the first 64MB of GMMIO.
8811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds** Each rope gets a full 64*KB* (ie 4 bytes per page) this way.
8821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds** bits 1:0 stay the same.  bits 15:2 become 25:12.
8831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds** Then add the base and we can generate an I/O Port cycle.
8841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds********************************************************/
8851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#undef LBA_PORT_IN
8861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define LBA_PORT_IN(size, mask) \
8871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic u##size lba_pat_in##size (struct pci_hba_data *l, u16 addr) \
8881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ \
8891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	u##size t; \
890a8043ecb17bd2e4b034006bee315efeea3936278Harvey Harrison	DBG_PORT("%s(0x%p, 0x%x) ->", __func__, l, addr); \
8911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	t = READ_REG##size(PIOP_TO_GMMIO(LBA_DEV(l), addr)); \
8921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	DBG_PORT(" 0x%x\n", t); \
8931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	return (t); \
8941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
8951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
8961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus TorvaldsLBA_PORT_IN( 8, 3)
8971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus TorvaldsLBA_PORT_IN(16, 2)
8981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus TorvaldsLBA_PORT_IN(32, 0)
8991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
9001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
9011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#undef LBA_PORT_OUT
9021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define LBA_PORT_OUT(size, mask) \
9031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic void lba_pat_out##size (struct pci_hba_data *l, u16 addr, u##size val) \
9041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ \
905c2c4798e04ef836b12f5df04e7d1a1710cb39301Matthew Wilcox	void __iomem *where = PIOP_TO_GMMIO(LBA_DEV(l), addr); \
906a8043ecb17bd2e4b034006bee315efeea3936278Harvey Harrison	DBG_PORT("%s(0x%p, 0x%x, 0x%x)\n", __func__, l, addr, val); \
9071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	WRITE_REG##size(val, where); \
9081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	/* flush the I/O down to the elroy at least */ \
9091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	lba_t32 = READ_U32(l->base_addr + LBA_FUNC_ID); \
9101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
9111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
9121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus TorvaldsLBA_PORT_OUT( 8, 3)
9131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus TorvaldsLBA_PORT_OUT(16, 2)
9141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus TorvaldsLBA_PORT_OUT(32, 0)
9151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
9161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
9171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic struct pci_port_ops lba_pat_port_ops = {
9181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	.inb =	lba_pat_in8,
9191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	.inw =	lba_pat_in16,
9201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	.inl =	lba_pat_in32,
9211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	.outb =	lba_pat_out8,
9221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	.outw =	lba_pat_out16,
9231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	.outl =	lba_pat_out32
9241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds};
9251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
9261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
9271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
9281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/*
9291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds** make range information from PDC available to PCI subsystem.
9301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds** We make the PDC call here in order to get the PCI bus range
9311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds** numbers. The rest will get forwarded in pcibios_fixup_bus().
9321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds** We don't have a struct pci_bus assigned to us yet.
9331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds*/
9341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic void
9351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldslba_pat_resources(struct parisc_device *pa_dev, struct lba_device *lba_dev)
9361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
9371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	unsigned long bytecnt;
9381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	long io_count;
9391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	long status;	/* PDC return status */
9401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	long pa_count;
941e957f608f321a97a60d065bccd01949590eef52eGrant Grundler	pdc_pat_cell_mod_maddr_block_t *pa_pdc_cell;	/* PA_VIEW */
942e957f608f321a97a60d065bccd01949590eef52eGrant Grundler	pdc_pat_cell_mod_maddr_block_t *io_pdc_cell;	/* IO_VIEW */
9431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	int i;
9441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
945e957f608f321a97a60d065bccd01949590eef52eGrant Grundler	pa_pdc_cell = kzalloc(sizeof(pdc_pat_cell_mod_maddr_block_t), GFP_KERNEL);
946e957f608f321a97a60d065bccd01949590eef52eGrant Grundler	if (!pa_pdc_cell)
947e957f608f321a97a60d065bccd01949590eef52eGrant Grundler		return;
948e957f608f321a97a60d065bccd01949590eef52eGrant Grundler
949e957f608f321a97a60d065bccd01949590eef52eGrant Grundler	io_pdc_cell = kzalloc(sizeof(pdc_pat_cell_mod_maddr_block_t), GFP_KERNEL);
950450d6e306b4717bfae11218a02648509baf04ce1Stoyan Gaydarov	if (!io_pdc_cell) {
951e957f608f321a97a60d065bccd01949590eef52eGrant Grundler		kfree(pa_pdc_cell);
952e957f608f321a97a60d065bccd01949590eef52eGrant Grundler		return;
953e957f608f321a97a60d065bccd01949590eef52eGrant Grundler	}
954e957f608f321a97a60d065bccd01949590eef52eGrant Grundler
9551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	/* return cell module (IO view) */
9561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	status = pdc_pat_cell_module(&bytecnt, pa_dev->pcell_loc, pa_dev->mod_index,
957e957f608f321a97a60d065bccd01949590eef52eGrant Grundler				PA_VIEW, pa_pdc_cell);
958e957f608f321a97a60d065bccd01949590eef52eGrant Grundler	pa_count = pa_pdc_cell->mod[1];
9591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
9601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	status |= pdc_pat_cell_module(&bytecnt, pa_dev->pcell_loc, pa_dev->mod_index,
961e957f608f321a97a60d065bccd01949590eef52eGrant Grundler				IO_VIEW, io_pdc_cell);
962e957f608f321a97a60d065bccd01949590eef52eGrant Grundler	io_count = io_pdc_cell->mod[1];
9631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
9641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	/* We've already done this once for device discovery...*/
9651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (status != PDC_OK) {
9661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		panic("pdc_pat_cell_module() call failed for LBA!\n");
9671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
9681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
969e957f608f321a97a60d065bccd01949590eef52eGrant Grundler	if (PAT_GET_ENTITY(pa_pdc_cell->mod_info) != PAT_ENTITY_LBA) {
9701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		panic("pdc_pat_cell_module() entity returned != PAT_ENTITY_LBA!\n");
9711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
9721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
9731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	/*
9741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	** Inspect the resources PAT tells us about
9751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	*/
9761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	for (i = 0; i < pa_count; i++) {
9771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		struct {
9781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			unsigned long type;
9791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			unsigned long start;
9801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			unsigned long end;	/* aka finish */
9811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		} *p, *io;
9821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		struct resource *r;
9831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
984e957f608f321a97a60d065bccd01949590eef52eGrant Grundler		p = (void *) &(pa_pdc_cell->mod[2+i*3]);
985e957f608f321a97a60d065bccd01949590eef52eGrant Grundler		io = (void *) &(io_pdc_cell->mod[2+i*3]);
9861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
9871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		/* Convert the PAT range data to PCI "struct resource" */
9881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		switch(p->type & 0xff) {
9891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		case PAT_PBNUM:
9901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			lba_dev->hba.bus_num.start = p->start;
9911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			lba_dev->hba.bus_num.end   = p->end;
9921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			break;
9931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
9941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		case PAT_LMMIO:
9951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			/* used to fix up pre-initialized MEM BARs */
9961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			if (!lba_dev->hba.lmmio_space.start) {
9971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				sprintf(lba_dev->hba.lmmio_name,
998645d11d4baa56c6830daac46a92d63b7093cbc09Matthew Wilcox						"PCI%02x LMMIO",
999645d11d4baa56c6830daac46a92d63b7093cbc09Matthew Wilcox						(int)lba_dev->hba.bus_num.start);
10001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				lba_dev->hba.lmmio_space_offset = p->start -
10011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds					io->start;
10021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				r = &lba_dev->hba.lmmio_space;
10031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				r->name = lba_dev->hba.lmmio_name;
10041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			} else if (!lba_dev->hba.elmmio_space.start) {
10051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				sprintf(lba_dev->hba.elmmio_name,
1006645d11d4baa56c6830daac46a92d63b7093cbc09Matthew Wilcox						"PCI%02x ELMMIO",
1007645d11d4baa56c6830daac46a92d63b7093cbc09Matthew Wilcox						(int)lba_dev->hba.bus_num.start);
10081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				r = &lba_dev->hba.elmmio_space;
10091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				r->name = lba_dev->hba.elmmio_name;
10101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			} else {
10111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				printk(KERN_WARNING MODULE_NAME
10121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds					" only supports 2 LMMIO resources!\n");
10131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				break;
10141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			}
10151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
10161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			r->start  = p->start;
10171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			r->end    = p->end;
10181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			r->flags  = IORESOURCE_MEM;
10191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			r->parent = r->sibling = r->child = NULL;
10201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			break;
10211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
10221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		case PAT_GMMIO:
10231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			/* MMIO space > 4GB phys addr; for 64-bit BAR */
1024645d11d4baa56c6830daac46a92d63b7093cbc09Matthew Wilcox			sprintf(lba_dev->hba.gmmio_name, "PCI%02x GMMIO",
1025645d11d4baa56c6830daac46a92d63b7093cbc09Matthew Wilcox					(int)lba_dev->hba.bus_num.start);
10261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			r = &lba_dev->hba.gmmio_space;
10271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			r->name  = lba_dev->hba.gmmio_name;
10281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			r->start  = p->start;
10291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			r->end    = p->end;
10301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			r->flags  = IORESOURCE_MEM;
10311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			r->parent = r->sibling = r->child = NULL;
10321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			break;
10331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
10341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		case PAT_NPIOP:
10351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			printk(KERN_WARNING MODULE_NAME
10361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				" range[%d] : ignoring NPIOP (0x%lx)\n",
10371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				i, p->start);
10381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			break;
10391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
10401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		case PAT_PIOP:
10411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			/*
10421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			** Postable I/O port space is per PCI host adapter.
10431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			** base of 64MB PIOP region
10441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			*/
10455076c15862644edb91d2e3436b2fa3e07b28385dHelge Deller			lba_dev->iop_base = ioremap_nocache(p->start, 64 * 1024 * 1024);
10461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1047645d11d4baa56c6830daac46a92d63b7093cbc09Matthew Wilcox			sprintf(lba_dev->hba.io_name, "PCI%02x Ports",
1048645d11d4baa56c6830daac46a92d63b7093cbc09Matthew Wilcox					(int)lba_dev->hba.bus_num.start);
10491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			r = &lba_dev->hba.io_space;
10501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			r->name  = lba_dev->hba.io_name;
10511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			r->start  = HBA_PORT_BASE(lba_dev->hba.hba_num);
10521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			r->end    = r->start + HBA_PORT_SPACE_SIZE - 1;
10531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			r->flags  = IORESOURCE_IO;
10541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			r->parent = r->sibling = r->child = NULL;
10551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			break;
10561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
10571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		default:
10581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			printk(KERN_WARNING MODULE_NAME
10591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				" range[%d] : unknown pat range type (0x%lx)\n",
10601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				i, p->type & 0xff);
10611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			break;
10621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		}
10631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
1064e957f608f321a97a60d065bccd01949590eef52eGrant Grundler
1065e957f608f321a97a60d065bccd01949590eef52eGrant Grundler	kfree(pa_pdc_cell);
1066e957f608f321a97a60d065bccd01949590eef52eGrant Grundler	kfree(io_pdc_cell);
10671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
10681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#else
10691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* keep compiler from complaining about missing declarations */
10701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define lba_pat_port_ops lba_astro_port_ops
10711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define lba_pat_resources(pa_dev, lba_dev)
10721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#endif	/* CONFIG_64BIT */
10731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
10741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
10751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsextern void sba_distributed_lmmio(struct parisc_device *, struct resource *);
10761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsextern void sba_directed_lmmio(struct parisc_device *, struct resource *);
10771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
10781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
10791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic void
10801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldslba_legacy_resources(struct parisc_device *pa_dev, struct lba_device *lba_dev)
10811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
10821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	struct resource *r;
10831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	int lba_num;
10841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
10851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	lba_dev->hba.lmmio_space_offset = PCI_F_EXTEND;
10861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
10871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	/*
10881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	** With "legacy" firmware, the lowest byte of FW_SCRATCH
10891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	** represents bus->secondary and the second byte represents
10901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	** bus->subsidiary (i.e. highest PPB programmed by firmware).
10911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	** PCI bus walk *should* end up with the same result.
10921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	** FIXME: But we don't have sanity checks in PCI or LBA.
10931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	*/
10941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	lba_num = READ_REG32(lba_dev->hba.base_addr + LBA_FW_SCRATCH);
10951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	r = &(lba_dev->hba.bus_num);
10961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	r->name = "LBA PCI Busses";
10971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	r->start = lba_num & 0xff;
10981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	r->end = (lba_num>>8) & 0xff;
10991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
11001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	/* Set up local PCI Bus resources - we don't need them for
11011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	** Legacy boxes but it's nice to see in /proc/iomem.
11021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	*/
11031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	r = &(lba_dev->hba.lmmio_space);
1104645d11d4baa56c6830daac46a92d63b7093cbc09Matthew Wilcox	sprintf(lba_dev->hba.lmmio_name, "PCI%02x LMMIO",
1105645d11d4baa56c6830daac46a92d63b7093cbc09Matthew Wilcox					(int)lba_dev->hba.bus_num.start);
11061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	r->name  = lba_dev->hba.lmmio_name;
11071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
11081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#if 1
11091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	/* We want the CPU -> IO routing of addresses.
11101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	 * The SBA BASE/MASK registers control CPU -> IO routing.
11111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	 * Ask SBA what is routed to this rope/LBA.
11121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	 */
11131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	sba_distributed_lmmio(pa_dev, r);
11141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#else
11151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	/*
11161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	 * The LBA BASE/MASK registers control IO -> System routing.
11171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	 *
11181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	 * The following code works but doesn't get us what we want.
11191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	 * Well, only because firmware (v5.0) on C3000 doesn't program
11201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	 * the LBA BASE/MASE registers to be the exact inverse of
11211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	 * the corresponding SBA registers. Other Astro/Pluto
11221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	 * based platform firmware may do it right.
11231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	 *
11241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	 * Should someone want to mess with MSI, they may need to
11251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	 * reprogram LBA BASE/MASK registers. Thus preserve the code
11261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	 * below until MSI is known to work on C3000/A500/N4000/RP3440.
11271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	 *
11281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	 * Using the code below, /proc/iomem shows:
11291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	 * ...
11301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	 * f0000000-f0ffffff : PCI00 LMMIO
11311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	 *   f05d0000-f05d0000 : lcd_data
11321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	 *   f05d0008-f05d0008 : lcd_cmd
11331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	 * f1000000-f1ffffff : PCI01 LMMIO
11341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	 * f4000000-f4ffffff : PCI02 LMMIO
11351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	 *   f4000000-f4001fff : sym53c8xx
11361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	 *   f4002000-f4003fff : sym53c8xx
11371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	 *   f4004000-f40043ff : sym53c8xx
11381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	 *   f4005000-f40053ff : sym53c8xx
11391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	 *   f4007000-f4007fff : ohci_hcd
11401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	 *   f4008000-f40083ff : tulip
11411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	 * f6000000-f6ffffff : PCI03 LMMIO
11421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	 * f8000000-fbffffff : PCI00 ELMMIO
11431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	 *   fa100000-fa4fffff : stifb mmio
11441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	 *   fb000000-fb1fffff : stifb fb
11451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	 *
11461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	 * But everything listed under PCI02 actually lives under PCI00.
11471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	 * This is clearly wrong.
11481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	 *
11491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	 * Asking SBA how things are routed tells the correct story:
11501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	 * LMMIO_BASE/MASK/ROUTE f4000001 fc000000 00000000
11511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	 * DIR0_BASE/MASK/ROUTE fa000001 fe000000 00000006
11521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	 * DIR1_BASE/MASK/ROUTE f9000001 ff000000 00000004
11531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	 * DIR2_BASE/MASK/ROUTE f0000000 fc000000 00000000
11541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	 * DIR3_BASE/MASK/ROUTE f0000000 fc000000 00000000
11551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	 *
11561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	 * Which looks like this in /proc/iomem:
11571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	 * f4000000-f47fffff : PCI00 LMMIO
11581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	 *   f4000000-f4001fff : sym53c8xx
11591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	 *   ...[deteled core devices - same as above]...
11601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	 *   f4008000-f40083ff : tulip
11611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	 * f4800000-f4ffffff : PCI01 LMMIO
11621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	 * f6000000-f67fffff : PCI02 LMMIO
11631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	 * f7000000-f77fffff : PCI03 LMMIO
11641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	 * f9000000-f9ffffff : PCI02 ELMMIO
11651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	 * fa000000-fbffffff : PCI03 ELMMIO
11661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	 *   fa100000-fa4fffff : stifb mmio
11671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	 *   fb000000-fb1fffff : stifb fb
11681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	 *
11691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	 * ie all Built-in core are under now correctly under PCI00.
11701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	 * The "PCI02 ELMMIO" directed range is for:
11711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	 *  +-[02]---03.0  3Dfx Interactive, Inc. Voodoo 2
11721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	 *
11731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	 * All is well now.
11741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	 */
11751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	r->start = READ_REG32(lba_dev->hba.base_addr + LBA_LMMIO_BASE);
11761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (r->start & 1) {
11771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		unsigned long rsize;
11781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
11791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		r->flags = IORESOURCE_MEM;
11801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		/* mmio_mask also clears Enable bit */
11811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		r->start &= mmio_mask;
11821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		r->start = PCI_HOST_ADDR(HBA_DATA(lba_dev), r->start);
11831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		rsize = ~ READ_REG32(lba_dev->hba.base_addr + LBA_LMMIO_MASK);
11841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
11851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		/*
11861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		** Each rope only gets part of the distributed range.
11871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		** Adjust "window" for this rope.
11881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		*/
11891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		rsize /= ROPES_PER_IOC;
119053f01bba49938f115237fe43a261c31ac13ae5c6Matthew Wilcox		r->start += (rsize + 1) * LBA_NUM(pa_dev->hpa.start);
11911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		r->end = r->start + rsize;
11921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	} else {
11931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		r->end = r->start = 0;	/* Not enabled. */
11941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
11951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#endif
11961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
11971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	/*
11981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	** "Directed" ranges are used when the "distributed range" isn't
11991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	** sufficient for all devices below a given LBA.  Typically devices
12001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	** like graphics cards or X25 may need a directed range when the
12011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	** bus has multiple slots (ie multiple devices) or the device
12021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	** needs more than the typical 4 or 8MB a distributed range offers.
12031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	**
12041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	** The main reason for ignoring it now frigging complications.
12051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	** Directed ranges may overlap (and have precedence) over
12061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	** distributed ranges. Or a distributed range assigned to a unused
12071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	** rope may be used by a directed range on a different rope.
12081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	** Support for graphics devices may require fixing this
12091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	** since they may be assigned a directed range which overlaps
12101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	** an existing (but unused portion of) distributed range.
12111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	*/
12121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	r = &(lba_dev->hba.elmmio_space);
1213645d11d4baa56c6830daac46a92d63b7093cbc09Matthew Wilcox	sprintf(lba_dev->hba.elmmio_name, "PCI%02x ELMMIO",
1214645d11d4baa56c6830daac46a92d63b7093cbc09Matthew Wilcox					(int)lba_dev->hba.bus_num.start);
12151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	r->name  = lba_dev->hba.elmmio_name;
12161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
12171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#if 1
12181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	/* See comment which precedes call to sba_directed_lmmio() */
12191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	sba_directed_lmmio(pa_dev, r);
12201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#else
12211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	r->start = READ_REG32(lba_dev->hba.base_addr + LBA_ELMMIO_BASE);
12221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
12231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (r->start & 1) {
12241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		unsigned long rsize;
12251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		r->flags = IORESOURCE_MEM;
12261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		/* mmio_mask also clears Enable bit */
12271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		r->start &= mmio_mask;
12281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		r->start = PCI_HOST_ADDR(HBA_DATA(lba_dev), r->start);
12291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		rsize = READ_REG32(lba_dev->hba.base_addr + LBA_ELMMIO_MASK);
12301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		r->end = r->start + ~rsize;
12311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
12321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#endif
12331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
12341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	r = &(lba_dev->hba.io_space);
1235645d11d4baa56c6830daac46a92d63b7093cbc09Matthew Wilcox	sprintf(lba_dev->hba.io_name, "PCI%02x Ports",
1236645d11d4baa56c6830daac46a92d63b7093cbc09Matthew Wilcox					(int)lba_dev->hba.bus_num.start);
12371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	r->name  = lba_dev->hba.io_name;
12381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	r->flags = IORESOURCE_IO;
12391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	r->start = READ_REG32(lba_dev->hba.base_addr + LBA_IOS_BASE) & ~1L;
12401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	r->end   = r->start + (READ_REG32(lba_dev->hba.base_addr + LBA_IOS_MASK) ^ (HBA_PORT_SPACE_SIZE - 1));
12411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
12421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	/* Virtualize the I/O Port space ranges */
12431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	lba_num = HBA_PORT_BASE(lba_dev->hba.hba_num);
12441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	r->start |= lba_num;
12451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	r->end   |= lba_num;
12461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
12471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
12481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
12491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/**************************************************************************
12501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds**
12511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds**   LBA initialization code (HW and SW)
12521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds**
12531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds**   o identify LBA chip itself
12541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds**   o initialize LBA chip modes (HardFail)
12551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds**   o FIXME: initialize DMA hints for reasonable defaults
12561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds**   o enable configuration functions
12571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds**   o call pci_register_ops() to discover devs (fixup/fixup_bus get invoked)
12581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds**
12591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds**************************************************************************/
12601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
12611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int __init
12621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldslba_hw_init(struct lba_device *d)
12631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
12641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	u32 stat;
12651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	u32 bus_reset;	/* PDC_PAT_BUG */
12661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
12671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#if 0
12681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	printk(KERN_DEBUG "LBA %lx  STAT_CTL %Lx  ERROR_CFG %Lx  STATUS %Lx DMA_CTL %Lx\n",
12691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		d->hba.base_addr,
12701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		READ_REG64(d->hba.base_addr + LBA_STAT_CTL),
12711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		READ_REG64(d->hba.base_addr + LBA_ERROR_CONFIG),
12721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		READ_REG64(d->hba.base_addr + LBA_ERROR_STATUS),
12731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		READ_REG64(d->hba.base_addr + LBA_DMA_CTL) );
12741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	printk(KERN_DEBUG "	ARB mask %Lx  pri %Lx  mode %Lx  mtlt %Lx\n",
12751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		READ_REG64(d->hba.base_addr + LBA_ARB_MASK),
12761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		READ_REG64(d->hba.base_addr + LBA_ARB_PRI),
12771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		READ_REG64(d->hba.base_addr + LBA_ARB_MODE),
12781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		READ_REG64(d->hba.base_addr + LBA_ARB_MTLT) );
12791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	printk(KERN_DEBUG "	HINT cfg 0x%Lx\n",
12801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		READ_REG64(d->hba.base_addr + LBA_HINT_CFG));
12811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	printk(KERN_DEBUG "	HINT reg ");
12821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	{ int i;
12831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	for (i=LBA_HINT_BASE; i< (14*8 + LBA_HINT_BASE); i+=8)
12841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		printk(" %Lx", READ_REG64(d->hba.base_addr + i));
12851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
12861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	printk("\n");
12871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#endif	/* DEBUG_LBA_PAT */
12881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
12891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#ifdef CONFIG_64BIT
12901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/*
12911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * FIXME add support for PDC_PAT_IO "Get slot status" - OLAR support
12921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Only N-Class and up can really make use of Get slot status.
12931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * maybe L-class too but I've never played with it there.
12941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */
12951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#endif
12961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
12971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	/* PDC_PAT_BUG: exhibited in rev 40.48  on L2000 */
12981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	bus_reset = READ_REG32(d->hba.base_addr + LBA_STAT_CTL + 4) & 1;
12991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (bus_reset) {
13001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		printk(KERN_DEBUG "NOTICE: PCI bus reset still asserted! (clearing)\n");
13011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
13021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
13031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	stat = READ_REG32(d->hba.base_addr + LBA_ERROR_CONFIG);
13041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (stat & LBA_SMART_MODE) {
13051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		printk(KERN_DEBUG "NOTICE: LBA in SMART mode! (cleared)\n");
13061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		stat &= ~LBA_SMART_MODE;
13071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		WRITE_REG32(stat, d->hba.base_addr + LBA_ERROR_CONFIG);
13081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
13091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
13101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	/* Set HF mode as the default (vs. -1 mode). */
13111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        stat = READ_REG32(d->hba.base_addr + LBA_STAT_CTL);
13121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	WRITE_REG32(stat | HF_ENABLE, d->hba.base_addr + LBA_STAT_CTL);
13131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
13141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	/*
13151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	** Writing a zero to STAT_CTL.rf (bit 0) will clear reset signal
13161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	** if it's not already set. If we just cleared the PCI Bus Reset
13171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	** signal, wait a bit for the PCI devices to recover and setup.
13181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	*/
13191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (bus_reset)
13201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		mdelay(pci_post_reset_delay);
13211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
13221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (0 == READ_REG32(d->hba.base_addr + LBA_ARB_MASK)) {
13231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		/*
13241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		** PDC_PAT_BUG: PDC rev 40.48 on L2000.
13251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		** B2000/C3600/J6000 also have this problem?
13261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		**
13271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		** Elroys with hot pluggable slots don't get configured
13281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		** correctly if the slot is empty.  ARB_MASK is set to 0
13291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		** and we can't master transactions on the bus if it's
13301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		** not at least one. 0x3 enables elroy and first slot.
13311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		*/
13321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		printk(KERN_DEBUG "NOTICE: Enabling PCI Arbitration\n");
13331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		WRITE_REG32(0x3, d->hba.base_addr + LBA_ARB_MASK);
13341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
13351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
13361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	/*
13371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	** FIXME: Hint registers are programmed with default hint
13381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	** values by firmware. Hints should be sane even if we
13391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	** can't reprogram them the way drivers want.
13401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	*/
13411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	return 0;
13421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
13431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1344353dfe1290bdce1d40609e35ca6e42829623ff5fMatthew Wilcox/*
1345353dfe1290bdce1d40609e35ca6e42829623ff5fMatthew Wilcox * Unfortunately, when firmware numbers busses, it doesn't take into account
1346353dfe1290bdce1d40609e35ca6e42829623ff5fMatthew Wilcox * Cardbus bridges.  So we have to renumber the busses to suit ourselves.
1347353dfe1290bdce1d40609e35ca6e42829623ff5fMatthew Wilcox * Elroy/Mercury don't actually know what bus number they're attached to;
1348353dfe1290bdce1d40609e35ca6e42829623ff5fMatthew Wilcox * we use bus 0 to indicate the directly attached bus and any other bus
1349353dfe1290bdce1d40609e35ca6e42829623ff5fMatthew Wilcox * number will be taken care of by the PCI-PCI bridge.
1350353dfe1290bdce1d40609e35ca6e42829623ff5fMatthew Wilcox */
1351353dfe1290bdce1d40609e35ca6e42829623ff5fMatthew Wilcoxstatic unsigned int lba_next_bus = 0;
13521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
13531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/*
1354353dfe1290bdce1d40609e35ca6e42829623ff5fMatthew Wilcox * Determine if lba should claim this chip (return 0) or not (return 1).
1355353dfe1290bdce1d40609e35ca6e42829623ff5fMatthew Wilcox * If so, initialize the chip and tell other partners in crime they
1356353dfe1290bdce1d40609e35ca6e42829623ff5fMatthew Wilcox * have work to do.
1357353dfe1290bdce1d40609e35ca6e42829623ff5fMatthew Wilcox */
13581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int __init
13591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldslba_driver_probe(struct parisc_device *dev)
13601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
13611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	struct lba_device *lba_dev;
1362dc7dce280a26d069ad5a58bf3da86e5e83415c65Bjorn Helgaas	LIST_HEAD(resources);
13631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	struct pci_bus *lba_bus;
13641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	struct pci_ops *cfg_ops;
13651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	u32 func_class;
13661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	void *tmp_obj;
13671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	char *version;
13685076c15862644edb91d2e3436b2fa3e07b28385dHelge Deller	void __iomem *addr = ioremap_nocache(dev->hpa.start, 4096);
13691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
13701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	/* Read HW Rev First */
13711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	func_class = READ_REG32(addr + LBA_FCLASS);
13721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
13731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (IS_ELROY(dev)) {
13741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		func_class &= 0xf;
13751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		switch (func_class) {
13761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		case 0:	version = "TR1.0"; break;
13771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		case 1:	version = "TR2.0"; break;
13781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		case 2:	version = "TR2.1"; break;
13791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		case 3:	version = "TR2.2"; break;
13801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		case 4:	version = "TR3.0"; break;
13811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		case 5:	version = "TR4.0"; break;
13821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		default: version = "TR4+";
13831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		}
13841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1385ba9877b6734fb0313bca99ae2077613f24ff5b5cKyle McMartin		printk(KERN_INFO "Elroy version %s (0x%x) found at 0x%lx\n",
1386645d11d4baa56c6830daac46a92d63b7093cbc09Matthew Wilcox		       version, func_class & 0xf, (long)dev->hpa.start);
13871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
13881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		if (func_class < 2) {
13891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			printk(KERN_WARNING "Can't support LBA older than "
13901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				"TR2.1 - continuing under adversity.\n");
13911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		}
13921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
13931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#if 0
13941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* Elroy TR4.0 should work with simple algorithm.
13951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds   But it doesn't.  Still missing something. *sigh*
13961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds*/
13971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		if (func_class > 4) {
13981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			cfg_ops = &mercury_cfg_ops;
13991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		} else
14001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#endif
14011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		{
14021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			cfg_ops = &elroy_cfg_ops;
14031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		}
14041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
14051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	} else if (IS_MERCURY(dev) || IS_QUICKSILVER(dev)) {
1406ba9877b6734fb0313bca99ae2077613f24ff5b5cKyle McMartin		int major, minor;
1407ba9877b6734fb0313bca99ae2077613f24ff5b5cKyle McMartin
14081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		func_class &= 0xff;
1409ba9877b6734fb0313bca99ae2077613f24ff5b5cKyle McMartin		major = func_class >> 4, minor = func_class & 0xf;
1410ba9877b6734fb0313bca99ae2077613f24ff5b5cKyle McMartin
14111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		/* We could use one printk for both Elroy and Mercury,
14121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                 * but for the mask for func_class.
14131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                 */
1414ba9877b6734fb0313bca99ae2077613f24ff5b5cKyle McMartin		printk(KERN_INFO "%s version TR%d.%d (0x%x) found at 0x%lx\n",
1415ba9877b6734fb0313bca99ae2077613f24ff5b5cKyle McMartin		       IS_MERCURY(dev) ? "Mercury" : "Quicksilver", major,
1416645d11d4baa56c6830daac46a92d63b7093cbc09Matthew Wilcox		       minor, func_class, (long)dev->hpa.start);
1417ba9877b6734fb0313bca99ae2077613f24ff5b5cKyle McMartin
14181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		cfg_ops = &mercury_cfg_ops;
14191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	} else {
1420645d11d4baa56c6830daac46a92d63b7093cbc09Matthew Wilcox		printk(KERN_ERR "Unknown LBA found at 0x%lx\n",
1421645d11d4baa56c6830daac46a92d63b7093cbc09Matthew Wilcox			(long)dev->hpa.start);
14221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		return -ENODEV;
14231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
14241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1425353dfe1290bdce1d40609e35ca6e42829623ff5fMatthew Wilcox	/* Tell I/O SAPIC driver we have a IRQ handler/region. */
142653f01bba49938f115237fe43a261c31ac13ae5c6Matthew Wilcox	tmp_obj = iosapic_register(dev->hpa.start + LBA_IOSAPIC_BASE);
14271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
14281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	/* NOTE: PCI devices (e.g. 103c:1005 graphics card) which don't
14291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	**	have an IRT entry will get NULL back from iosapic code.
14301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	*/
14311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1432cb6fc18e9ca615f03d18e60c49855b434ca2e51eHelge Deller	lba_dev = kzalloc(sizeof(struct lba_device), GFP_KERNEL);
14331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (!lba_dev) {
14341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		printk(KERN_ERR "lba_init_chip - couldn't alloc lba_device\n");
14351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		return(1);
14361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
14371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
14381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
14391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	/* ---------- First : initialize data we already have --------- */
14401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
14411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	lba_dev->hw_rev = func_class;
14421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	lba_dev->hba.base_addr = addr;
14431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	lba_dev->hba.dev = dev;
14441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	lba_dev->iosapic_obj = tmp_obj;  /* save interrupt handle */
14451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	lba_dev->hba.iommu = sba_get_iommu(dev);  /* get iommu data */
1446b0eecc4da9c0a5261711e0d83280fd5d1e3db742Kyle McMartin	parisc_set_drvdata(dev, lba_dev);
14471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
14481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	/* ------------ Second : initialize common stuff ---------- */
14491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	pci_bios = &lba_bios_ops;
14501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	pcibios_register_hba(HBA_DATA(lba_dev));
14511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	spin_lock_init(&lba_dev->lba_lock);
14521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
14531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (lba_hw_init(lba_dev))
14541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		return(1);
14551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
14561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	/* ---------- Third : setup I/O Port and MMIO resources  --------- */
14571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
14581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (is_pdc_pat()) {
14591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		/* PDC PAT firmware uses PIOP region of GMMIO space. */
14601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		pci_port = &lba_pat_port_ops;
14611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		/* Go ask PDC PAT what resources this LBA has */
14621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		lba_pat_resources(dev, lba_dev);
14631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	} else {
14641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		if (!astro_iop_base) {
14651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			/* Sprockets PDC uses NPIOP region */
14665076c15862644edb91d2e3436b2fa3e07b28385dHelge Deller			astro_iop_base = ioremap_nocache(LBA_PORT_BASE, 64 * 1024);
14671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			pci_port = &lba_astro_port_ops;
14681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		}
14691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
14701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		/* Poke the chip a bit for /proc output */
14711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		lba_legacy_resources(dev, lba_dev);
14721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
14731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1474353dfe1290bdce1d40609e35ca6e42829623ff5fMatthew Wilcox	if (lba_dev->hba.bus_num.start < lba_next_bus)
1475353dfe1290bdce1d40609e35ca6e42829623ff5fMatthew Wilcox		lba_dev->hba.bus_num.start = lba_next_bus;
1476353dfe1290bdce1d40609e35ca6e42829623ff5fMatthew Wilcox
1477f4d9ea9abf04a6ad9643df5497e6243fbf64196eBjorn Helgaas	/*   Overlaps with elmmio can (and should) fail here.
1478f4d9ea9abf04a6ad9643df5497e6243fbf64196eBjorn Helgaas	 *   We will prune (or ignore) the distributed range.
1479f4d9ea9abf04a6ad9643df5497e6243fbf64196eBjorn Helgaas	 *
1480f4d9ea9abf04a6ad9643df5497e6243fbf64196eBjorn Helgaas	 *   FIXME: SBA code should register all elmmio ranges first.
1481f4d9ea9abf04a6ad9643df5497e6243fbf64196eBjorn Helgaas	 *      that would take care of elmmio ranges routed
1482f4d9ea9abf04a6ad9643df5497e6243fbf64196eBjorn Helgaas	 *	to a different rope (already discovered) from
1483f4d9ea9abf04a6ad9643df5497e6243fbf64196eBjorn Helgaas	 *	getting registered *after* LBA code has already
1484f4d9ea9abf04a6ad9643df5497e6243fbf64196eBjorn Helgaas	 *	registered it's distributed lmmio range.
1485f4d9ea9abf04a6ad9643df5497e6243fbf64196eBjorn Helgaas	 */
1486f4d9ea9abf04a6ad9643df5497e6243fbf64196eBjorn Helgaas	if (truncate_pat_collision(&iomem_resource,
1487f4d9ea9abf04a6ad9643df5497e6243fbf64196eBjorn Helgaas				   &(lba_dev->hba.lmmio_space))) {
1488f4d9ea9abf04a6ad9643df5497e6243fbf64196eBjorn Helgaas		printk(KERN_WARNING "LBA: lmmio_space [%lx/%lx] duplicate!\n",
1489f4d9ea9abf04a6ad9643df5497e6243fbf64196eBjorn Helgaas				(long)lba_dev->hba.lmmio_space.start,
1490f4d9ea9abf04a6ad9643df5497e6243fbf64196eBjorn Helgaas				(long)lba_dev->hba.lmmio_space.end);
1491f4d9ea9abf04a6ad9643df5497e6243fbf64196eBjorn Helgaas		lba_dev->hba.lmmio_space.flags = 0;
1492f4d9ea9abf04a6ad9643df5497e6243fbf64196eBjorn Helgaas	}
1493f4d9ea9abf04a6ad9643df5497e6243fbf64196eBjorn Helgaas
149439c2462e163448c7df466c7262109ec6a24d5f88Bjorn Helgaas	pci_add_resource_offset(&resources, &lba_dev->hba.io_space,
149539c2462e163448c7df466c7262109ec6a24d5f88Bjorn Helgaas				HBA_PORT_BASE(lba_dev->hba.hba_num));
1496dc7dce280a26d069ad5a58bf3da86e5e83415c65Bjorn Helgaas	if (lba_dev->hba.elmmio_space.start)
149739c2462e163448c7df466c7262109ec6a24d5f88Bjorn Helgaas		pci_add_resource_offset(&resources, &lba_dev->hba.elmmio_space,
149839c2462e163448c7df466c7262109ec6a24d5f88Bjorn Helgaas					lba_dev->hba.lmmio_space_offset);
1499dc7dce280a26d069ad5a58bf3da86e5e83415c65Bjorn Helgaas	if (lba_dev->hba.lmmio_space.flags)
150039c2462e163448c7df466c7262109ec6a24d5f88Bjorn Helgaas		pci_add_resource_offset(&resources, &lba_dev->hba.lmmio_space,
150139c2462e163448c7df466c7262109ec6a24d5f88Bjorn Helgaas					lba_dev->hba.lmmio_space_offset);
1502dc7dce280a26d069ad5a58bf3da86e5e83415c65Bjorn Helgaas	if (lba_dev->hba.gmmio_space.flags)
1503dc7dce280a26d069ad5a58bf3da86e5e83415c65Bjorn Helgaas		pci_add_resource(&resources, &lba_dev->hba.gmmio_space);
1504dc7dce280a26d069ad5a58bf3da86e5e83415c65Bjorn Helgaas
15051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	dev->dev.platform_data = lba_dev;
15061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	lba_bus = lba_dev->hba.hba_bus =
1507dc7dce280a26d069ad5a58bf3da86e5e83415c65Bjorn Helgaas		pci_create_root_bus(&dev->dev, lba_dev->hba.bus_num.start,
1508dc7dce280a26d069ad5a58bf3da86e5e83415c65Bjorn Helgaas				    cfg_ops, NULL, &resources);
1509dc7dce280a26d069ad5a58bf3da86e5e83415c65Bjorn Helgaas	if (!lba_bus) {
1510dc7dce280a26d069ad5a58bf3da86e5e83415c65Bjorn Helgaas		pci_free_resource_list(&resources);
151142605fa6665ea86bbbd4de61693a0b002830277bBjorn Helgaas		return 0;
1512dc7dce280a26d069ad5a58bf3da86e5e83415c65Bjorn Helgaas	}
151342605fa6665ea86bbbd4de61693a0b002830277bBjorn Helgaas
151442605fa6665ea86bbbd4de61693a0b002830277bBjorn Helgaas	lba_bus->subordinate = pci_scan_child_bus(lba_bus);
15151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
15161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	/* This is in lieu of calling pci_assign_unassigned_resources() */
15171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (is_pdc_pat()) {
15181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		/* assign resources to un-initialized devices */
15191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
15201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		DBG_PAT("LBA pci_bus_size_bridges()\n");
15211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		pci_bus_size_bridges(lba_bus);
15221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
15231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		DBG_PAT("LBA pci_bus_assign_resources()\n");
15241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		pci_bus_assign_resources(lba_bus);
15251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
15261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#ifdef DEBUG_LBA_PAT
15271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		DBG_PAT("\nLBA PIOP resource tree\n");
15281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		lba_dump_res(&lba_dev->hba.io_space, 2);
15291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		DBG_PAT("\nLBA LMMIO resource tree\n");
15301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		lba_dump_res(&lba_dev->hba.lmmio_space, 2);
15311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#endif
15321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
15331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	pci_enable_bridges(lba_bus);
15341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
15351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	/*
15361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	** Once PCI register ops has walked the bus, access to config
15371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	** space is restricted. Avoids master aborts on config cycles.
15381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	** Early LBA revs go fatal on *any* master abort.
15391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	*/
15401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (cfg_ops == &elroy_cfg_ops) {
15411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		lba_dev->flags |= LBA_FLAG_SKIP_PROBE;
15421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
15431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
154442605fa6665ea86bbbd4de61693a0b002830277bBjorn Helgaas	lba_next_bus = lba_bus->subordinate + 1;
154542605fa6665ea86bbbd4de61693a0b002830277bBjorn Helgaas	pci_bus_add_devices(lba_bus);
1546fed99b1e86f5ff4f1b41e37264bb869da67d3174Grant Grundler
15471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	/* Whew! Finally done! Tell services we got this one covered. */
15481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	return 0;
15491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
15501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
15511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic struct parisc_device_id lba_tbl[] = {
15521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	{ HPHW_BRIDGE, HVERSION_REV_ANY_ID, ELROY_HVERS, 0xa },
15531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	{ HPHW_BRIDGE, HVERSION_REV_ANY_ID, MERCURY_HVERS, 0xa },
15541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	{ HPHW_BRIDGE, HVERSION_REV_ANY_ID, QUICKSILVER_HVERS, 0xa },
15551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	{ 0, }
15561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds};
15571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
15581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic struct parisc_driver lba_driver = {
15591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	.name =		MODULE_NAME,
15601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	.id_table =	lba_tbl,
15611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	.probe =	lba_driver_probe,
15621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds};
15631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
15641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/*
15651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds** One time initialization to let the world know the LBA was found.
15661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds** Must be called exactly once before pci_init().
15671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds*/
15681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsvoid __init lba_init(void)
15691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
15701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	register_parisc_driver(&lba_driver);
15711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
15721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
15731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/*
15741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds** Initialize the IBASE/IMASK registers for LBA (Elroy).
15751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds** Only called from sba_iommu.c in order to route ranges (MMIO vs DMA).
15761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds** sba_iommu is responsible for locking (none needed at init time).
15771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds*/
15781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsvoid lba_set_iregs(struct parisc_device *lba, u32 ibase, u32 imask)
15791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
15805076c15862644edb91d2e3436b2fa3e07b28385dHelge Deller	void __iomem * base_addr = ioremap_nocache(lba->hpa.start, 4096);
15811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
15821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	imask <<= 2;	/* adjust for hints - 2 more bits */
15831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
15841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	/* Make sure we aren't trying to set bits that aren't writeable. */
15851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	WARN_ON((ibase & 0x001fffff) != 0);
15861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	WARN_ON((imask & 0x001fffff) != 0);
15871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1588a8043ecb17bd2e4b034006bee315efeea3936278Harvey Harrison	DBG("%s() ibase 0x%x imask 0x%x\n", __func__, ibase, imask);
15891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	WRITE_REG32( imask, base_addr + LBA_IMASK);
15901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	WRITE_REG32( ibase, base_addr + LBA_IBASE);
15911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	iounmap(base_addr);
15921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
15931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1594