18c2ecf20Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0-or-later 28c2ecf20Sopenharmony_ci/* 38c2ecf20Sopenharmony_ci** 48c2ecf20Sopenharmony_ci** PCI Lower Bus Adapter (LBA) manager 58c2ecf20Sopenharmony_ci** 68c2ecf20Sopenharmony_ci** (c) Copyright 1999,2000 Grant Grundler 78c2ecf20Sopenharmony_ci** (c) Copyright 1999,2000 Hewlett-Packard Company 88c2ecf20Sopenharmony_ci** 98c2ecf20Sopenharmony_ci** 108c2ecf20Sopenharmony_ci** 118c2ecf20Sopenharmony_ci** This module primarily provides access to PCI bus (config/IOport 128c2ecf20Sopenharmony_ci** spaces) on platforms with an SBA/LBA chipset. A/B/C/J/L/N-class 138c2ecf20Sopenharmony_ci** with 4 digit model numbers - eg C3000 (and A400...sigh). 148c2ecf20Sopenharmony_ci** 158c2ecf20Sopenharmony_ci** LBA driver isn't as simple as the Dino driver because: 168c2ecf20Sopenharmony_ci** (a) this chip has substantial bug fixes between revisions 178c2ecf20Sopenharmony_ci** (Only one Dino bug has a software workaround :^( ) 188c2ecf20Sopenharmony_ci** (b) has more options which we don't (yet) support (DMA hints, OLARD) 198c2ecf20Sopenharmony_ci** (c) IRQ support lives in the I/O SAPIC driver (not with PCI driver) 208c2ecf20Sopenharmony_ci** (d) play nicely with both PAT and "Legacy" PA-RISC firmware (PDC). 218c2ecf20Sopenharmony_ci** (dino only deals with "Legacy" PDC) 228c2ecf20Sopenharmony_ci** 238c2ecf20Sopenharmony_ci** LBA driver passes the I/O SAPIC HPA to the I/O SAPIC driver. 248c2ecf20Sopenharmony_ci** (I/O SAPIC is integratd in the LBA chip). 258c2ecf20Sopenharmony_ci** 268c2ecf20Sopenharmony_ci** FIXME: Add support to SBA and LBA drivers for DMA hint sets 278c2ecf20Sopenharmony_ci** FIXME: Add support for PCI card hot-plug (OLARD). 288c2ecf20Sopenharmony_ci*/ 298c2ecf20Sopenharmony_ci 308c2ecf20Sopenharmony_ci#include <linux/delay.h> 318c2ecf20Sopenharmony_ci#include <linux/types.h> 328c2ecf20Sopenharmony_ci#include <linux/kernel.h> 338c2ecf20Sopenharmony_ci#include <linux/spinlock.h> 348c2ecf20Sopenharmony_ci#include <linux/init.h> /* for __init */ 358c2ecf20Sopenharmony_ci#include <linux/pci.h> 368c2ecf20Sopenharmony_ci#include <linux/ioport.h> 378c2ecf20Sopenharmony_ci#include <linux/slab.h> 388c2ecf20Sopenharmony_ci 398c2ecf20Sopenharmony_ci#include <asm/byteorder.h> 408c2ecf20Sopenharmony_ci#include <asm/pdc.h> 418c2ecf20Sopenharmony_ci#include <asm/pdcpat.h> 428c2ecf20Sopenharmony_ci#include <asm/page.h> 438c2ecf20Sopenharmony_ci 448c2ecf20Sopenharmony_ci#include <asm/ropes.h> 458c2ecf20Sopenharmony_ci#include <asm/hardware.h> /* for register_parisc_driver() stuff */ 468c2ecf20Sopenharmony_ci#include <asm/parisc-device.h> 478c2ecf20Sopenharmony_ci#include <asm/io.h> /* read/write stuff */ 488c2ecf20Sopenharmony_ci 498c2ecf20Sopenharmony_ci#include "iommu.h" 508c2ecf20Sopenharmony_ci 518c2ecf20Sopenharmony_ci#undef DEBUG_LBA /* general stuff */ 528c2ecf20Sopenharmony_ci#undef DEBUG_LBA_PORT /* debug I/O Port access */ 538c2ecf20Sopenharmony_ci#undef DEBUG_LBA_CFG /* debug Config Space Access (ie PCI Bus walk) */ 548c2ecf20Sopenharmony_ci#undef DEBUG_LBA_PAT /* debug PCI Resource Mgt code - PDC PAT only */ 558c2ecf20Sopenharmony_ci 568c2ecf20Sopenharmony_ci#undef FBB_SUPPORT /* Fast Back-Back xfers - NOT READY YET */ 578c2ecf20Sopenharmony_ci 588c2ecf20Sopenharmony_ci 598c2ecf20Sopenharmony_ci#ifdef DEBUG_LBA 608c2ecf20Sopenharmony_ci#define DBG(x...) printk(x) 618c2ecf20Sopenharmony_ci#else 628c2ecf20Sopenharmony_ci#define DBG(x...) 638c2ecf20Sopenharmony_ci#endif 648c2ecf20Sopenharmony_ci 658c2ecf20Sopenharmony_ci#ifdef DEBUG_LBA_PORT 668c2ecf20Sopenharmony_ci#define DBG_PORT(x...) printk(x) 678c2ecf20Sopenharmony_ci#else 688c2ecf20Sopenharmony_ci#define DBG_PORT(x...) 698c2ecf20Sopenharmony_ci#endif 708c2ecf20Sopenharmony_ci 718c2ecf20Sopenharmony_ci#ifdef DEBUG_LBA_CFG 728c2ecf20Sopenharmony_ci#define DBG_CFG(x...) printk(x) 738c2ecf20Sopenharmony_ci#else 748c2ecf20Sopenharmony_ci#define DBG_CFG(x...) 758c2ecf20Sopenharmony_ci#endif 768c2ecf20Sopenharmony_ci 778c2ecf20Sopenharmony_ci#ifdef DEBUG_LBA_PAT 788c2ecf20Sopenharmony_ci#define DBG_PAT(x...) printk(x) 798c2ecf20Sopenharmony_ci#else 808c2ecf20Sopenharmony_ci#define DBG_PAT(x...) 818c2ecf20Sopenharmony_ci#endif 828c2ecf20Sopenharmony_ci 838c2ecf20Sopenharmony_ci 848c2ecf20Sopenharmony_ci/* 858c2ecf20Sopenharmony_ci** Config accessor functions only pass in the 8-bit bus number and not 868c2ecf20Sopenharmony_ci** the 8-bit "PCI Segment" number. Each LBA will be assigned a PCI bus 878c2ecf20Sopenharmony_ci** number based on what firmware wrote into the scratch register. 888c2ecf20Sopenharmony_ci** 898c2ecf20Sopenharmony_ci** The "secondary" bus number is set to this before calling 908c2ecf20Sopenharmony_ci** pci_register_ops(). If any PPB's are present, the scan will 918c2ecf20Sopenharmony_ci** discover them and update the "secondary" and "subordinate" 928c2ecf20Sopenharmony_ci** fields in the pci_bus structure. 938c2ecf20Sopenharmony_ci** 948c2ecf20Sopenharmony_ci** Changes in the configuration *may* result in a different 958c2ecf20Sopenharmony_ci** bus number for each LBA depending on what firmware does. 968c2ecf20Sopenharmony_ci*/ 978c2ecf20Sopenharmony_ci 988c2ecf20Sopenharmony_ci#define MODULE_NAME "LBA" 998c2ecf20Sopenharmony_ci 1008c2ecf20Sopenharmony_ci/* non-postable I/O port space, densely packed */ 1018c2ecf20Sopenharmony_ci#define LBA_PORT_BASE (PCI_F_EXTEND | 0xfee00000UL) 1028c2ecf20Sopenharmony_cistatic void __iomem *astro_iop_base __read_mostly; 1038c2ecf20Sopenharmony_ci 1048c2ecf20Sopenharmony_cistatic u32 lba_t32; 1058c2ecf20Sopenharmony_ci 1068c2ecf20Sopenharmony_ci/* lba flags */ 1078c2ecf20Sopenharmony_ci#define LBA_FLAG_SKIP_PROBE 0x10 1088c2ecf20Sopenharmony_ci 1098c2ecf20Sopenharmony_ci#define LBA_SKIP_PROBE(d) ((d)->flags & LBA_FLAG_SKIP_PROBE) 1108c2ecf20Sopenharmony_ci 1118c2ecf20Sopenharmony_cistatic inline struct lba_device *LBA_DEV(struct pci_hba_data *hba) 1128c2ecf20Sopenharmony_ci{ 1138c2ecf20Sopenharmony_ci return container_of(hba, struct lba_device, hba); 1148c2ecf20Sopenharmony_ci} 1158c2ecf20Sopenharmony_ci 1168c2ecf20Sopenharmony_ci/* 1178c2ecf20Sopenharmony_ci** Only allow 8 subsidiary busses per LBA 1188c2ecf20Sopenharmony_ci** Problem is the PCI bus numbering is globally shared. 1198c2ecf20Sopenharmony_ci*/ 1208c2ecf20Sopenharmony_ci#define LBA_MAX_NUM_BUSES 8 1218c2ecf20Sopenharmony_ci 1228c2ecf20Sopenharmony_ci/************************************ 1238c2ecf20Sopenharmony_ci * LBA register read and write support 1248c2ecf20Sopenharmony_ci * 1258c2ecf20Sopenharmony_ci * BE WARNED: register writes are posted. 1268c2ecf20Sopenharmony_ci * (ie follow writes which must reach HW with a read) 1278c2ecf20Sopenharmony_ci */ 1288c2ecf20Sopenharmony_ci#define READ_U8(addr) __raw_readb(addr) 1298c2ecf20Sopenharmony_ci#define READ_U16(addr) __raw_readw(addr) 1308c2ecf20Sopenharmony_ci#define READ_U32(addr) __raw_readl(addr) 1318c2ecf20Sopenharmony_ci#define WRITE_U8(value, addr) __raw_writeb(value, addr) 1328c2ecf20Sopenharmony_ci#define WRITE_U16(value, addr) __raw_writew(value, addr) 1338c2ecf20Sopenharmony_ci#define WRITE_U32(value, addr) __raw_writel(value, addr) 1348c2ecf20Sopenharmony_ci 1358c2ecf20Sopenharmony_ci#define READ_REG8(addr) readb(addr) 1368c2ecf20Sopenharmony_ci#define READ_REG16(addr) readw(addr) 1378c2ecf20Sopenharmony_ci#define READ_REG32(addr) readl(addr) 1388c2ecf20Sopenharmony_ci#define READ_REG64(addr) readq(addr) 1398c2ecf20Sopenharmony_ci#define WRITE_REG8(value, addr) writeb(value, addr) 1408c2ecf20Sopenharmony_ci#define WRITE_REG16(value, addr) writew(value, addr) 1418c2ecf20Sopenharmony_ci#define WRITE_REG32(value, addr) writel(value, addr) 1428c2ecf20Sopenharmony_ci 1438c2ecf20Sopenharmony_ci 1448c2ecf20Sopenharmony_ci#define LBA_CFG_TOK(bus,dfn) ((u32) ((bus)<<16 | (dfn)<<8)) 1458c2ecf20Sopenharmony_ci#define LBA_CFG_BUS(tok) ((u8) ((tok)>>16)) 1468c2ecf20Sopenharmony_ci#define LBA_CFG_DEV(tok) ((u8) ((tok)>>11) & 0x1f) 1478c2ecf20Sopenharmony_ci#define LBA_CFG_FUNC(tok) ((u8) ((tok)>>8 ) & 0x7) 1488c2ecf20Sopenharmony_ci 1498c2ecf20Sopenharmony_ci 1508c2ecf20Sopenharmony_ci/* 1518c2ecf20Sopenharmony_ci** Extract LBA (Rope) number from HPA 1528c2ecf20Sopenharmony_ci** REVISIT: 16 ropes for Stretch/Ike? 1538c2ecf20Sopenharmony_ci*/ 1548c2ecf20Sopenharmony_ci#define ROPES_PER_IOC 8 1558c2ecf20Sopenharmony_ci#define LBA_NUM(x) ((((unsigned long) x) >> 13) & (ROPES_PER_IOC-1)) 1568c2ecf20Sopenharmony_ci 1578c2ecf20Sopenharmony_ci 1588c2ecf20Sopenharmony_cistatic void 1598c2ecf20Sopenharmony_cilba_dump_res(struct resource *r, int d) 1608c2ecf20Sopenharmony_ci{ 1618c2ecf20Sopenharmony_ci int i; 1628c2ecf20Sopenharmony_ci 1638c2ecf20Sopenharmony_ci if (NULL == r) 1648c2ecf20Sopenharmony_ci return; 1658c2ecf20Sopenharmony_ci 1668c2ecf20Sopenharmony_ci printk(KERN_DEBUG "(%p)", r->parent); 1678c2ecf20Sopenharmony_ci for (i = d; i ; --i) printk(" "); 1688c2ecf20Sopenharmony_ci printk(KERN_DEBUG "%p [%lx,%lx]/%lx\n", r, 1698c2ecf20Sopenharmony_ci (long)r->start, (long)r->end, r->flags); 1708c2ecf20Sopenharmony_ci lba_dump_res(r->child, d+2); 1718c2ecf20Sopenharmony_ci lba_dump_res(r->sibling, d); 1728c2ecf20Sopenharmony_ci} 1738c2ecf20Sopenharmony_ci 1748c2ecf20Sopenharmony_ci 1758c2ecf20Sopenharmony_ci/* 1768c2ecf20Sopenharmony_ci** LBA rev 2.0, 2.1, 2.2, and 3.0 bus walks require a complex 1778c2ecf20Sopenharmony_ci** workaround for cfg cycles: 1788c2ecf20Sopenharmony_ci** -- preserve LBA state 1798c2ecf20Sopenharmony_ci** -- prevent any DMA from occurring 1808c2ecf20Sopenharmony_ci** -- turn on smart mode 1818c2ecf20Sopenharmony_ci** -- probe with config writes before doing config reads 1828c2ecf20Sopenharmony_ci** -- check ERROR_STATUS 1838c2ecf20Sopenharmony_ci** -- clear ERROR_STATUS 1848c2ecf20Sopenharmony_ci** -- restore LBA state 1858c2ecf20Sopenharmony_ci** 1868c2ecf20Sopenharmony_ci** The workaround is only used for device discovery. 1878c2ecf20Sopenharmony_ci*/ 1888c2ecf20Sopenharmony_ci 1898c2ecf20Sopenharmony_cistatic int lba_device_present(u8 bus, u8 dfn, struct lba_device *d) 1908c2ecf20Sopenharmony_ci{ 1918c2ecf20Sopenharmony_ci u8 first_bus = d->hba.hba_bus->busn_res.start; 1928c2ecf20Sopenharmony_ci u8 last_sub_bus = d->hba.hba_bus->busn_res.end; 1938c2ecf20Sopenharmony_ci 1948c2ecf20Sopenharmony_ci if ((bus < first_bus) || 1958c2ecf20Sopenharmony_ci (bus > last_sub_bus) || 1968c2ecf20Sopenharmony_ci ((bus - first_bus) >= LBA_MAX_NUM_BUSES)) { 1978c2ecf20Sopenharmony_ci return 0; 1988c2ecf20Sopenharmony_ci } 1998c2ecf20Sopenharmony_ci 2008c2ecf20Sopenharmony_ci return 1; 2018c2ecf20Sopenharmony_ci} 2028c2ecf20Sopenharmony_ci 2038c2ecf20Sopenharmony_ci 2048c2ecf20Sopenharmony_ci 2058c2ecf20Sopenharmony_ci#define LBA_CFG_SETUP(d, tok) { \ 2068c2ecf20Sopenharmony_ci /* Save contents of error config register. */ \ 2078c2ecf20Sopenharmony_ci error_config = READ_REG32(d->hba.base_addr + LBA_ERROR_CONFIG); \ 2088c2ecf20Sopenharmony_ci\ 2098c2ecf20Sopenharmony_ci /* Save contents of status control register. */ \ 2108c2ecf20Sopenharmony_ci status_control = READ_REG32(d->hba.base_addr + LBA_STAT_CTL); \ 2118c2ecf20Sopenharmony_ci\ 2128c2ecf20Sopenharmony_ci /* For LBA rev 2.0, 2.1, 2.2, and 3.0, we must disable DMA \ 2138c2ecf20Sopenharmony_ci ** arbitration for full bus walks. \ 2148c2ecf20Sopenharmony_ci */ \ 2158c2ecf20Sopenharmony_ci /* Save contents of arb mask register. */ \ 2168c2ecf20Sopenharmony_ci arb_mask = READ_REG32(d->hba.base_addr + LBA_ARB_MASK); \ 2178c2ecf20Sopenharmony_ci\ 2188c2ecf20Sopenharmony_ci /* \ 2198c2ecf20Sopenharmony_ci * Turn off all device arbitration bits (i.e. everything \ 2208c2ecf20Sopenharmony_ci * except arbitration enable bit). \ 2218c2ecf20Sopenharmony_ci */ \ 2228c2ecf20Sopenharmony_ci WRITE_REG32(0x1, d->hba.base_addr + LBA_ARB_MASK); \ 2238c2ecf20Sopenharmony_ci\ 2248c2ecf20Sopenharmony_ci /* \ 2258c2ecf20Sopenharmony_ci * Set the smart mode bit so that master aborts don't cause \ 2268c2ecf20Sopenharmony_ci * LBA to go into PCI fatal mode (required). \ 2278c2ecf20Sopenharmony_ci */ \ 2288c2ecf20Sopenharmony_ci WRITE_REG32(error_config | LBA_SMART_MODE, d->hba.base_addr + LBA_ERROR_CONFIG); \ 2298c2ecf20Sopenharmony_ci} 2308c2ecf20Sopenharmony_ci 2318c2ecf20Sopenharmony_ci 2328c2ecf20Sopenharmony_ci#define LBA_CFG_PROBE(d, tok) { \ 2338c2ecf20Sopenharmony_ci /* \ 2348c2ecf20Sopenharmony_ci * Setup Vendor ID write and read back the address register \ 2358c2ecf20Sopenharmony_ci * to make sure that LBA is the bus master. \ 2368c2ecf20Sopenharmony_ci */ \ 2378c2ecf20Sopenharmony_ci WRITE_REG32(tok | PCI_VENDOR_ID, (d)->hba.base_addr + LBA_PCI_CFG_ADDR);\ 2388c2ecf20Sopenharmony_ci /* \ 2398c2ecf20Sopenharmony_ci * Read address register to ensure that LBA is the bus master, \ 2408c2ecf20Sopenharmony_ci * which implies that DMA traffic has stopped when DMA arb is off. \ 2418c2ecf20Sopenharmony_ci */ \ 2428c2ecf20Sopenharmony_ci lba_t32 = READ_REG32((d)->hba.base_addr + LBA_PCI_CFG_ADDR); \ 2438c2ecf20Sopenharmony_ci /* \ 2448c2ecf20Sopenharmony_ci * Generate a cfg write cycle (will have no affect on \ 2458c2ecf20Sopenharmony_ci * Vendor ID register since read-only). \ 2468c2ecf20Sopenharmony_ci */ \ 2478c2ecf20Sopenharmony_ci WRITE_REG32(~0, (d)->hba.base_addr + LBA_PCI_CFG_DATA); \ 2488c2ecf20Sopenharmony_ci /* \ 2498c2ecf20Sopenharmony_ci * Make sure write has completed before proceeding further, \ 2508c2ecf20Sopenharmony_ci * i.e. before setting clear enable. \ 2518c2ecf20Sopenharmony_ci */ \ 2528c2ecf20Sopenharmony_ci lba_t32 = READ_REG32((d)->hba.base_addr + LBA_PCI_CFG_ADDR); \ 2538c2ecf20Sopenharmony_ci} 2548c2ecf20Sopenharmony_ci 2558c2ecf20Sopenharmony_ci 2568c2ecf20Sopenharmony_ci/* 2578c2ecf20Sopenharmony_ci * HPREVISIT: 2588c2ecf20Sopenharmony_ci * -- Can't tell if config cycle got the error. 2598c2ecf20Sopenharmony_ci * 2608c2ecf20Sopenharmony_ci * OV bit is broken until rev 4.0, so can't use OV bit and 2618c2ecf20Sopenharmony_ci * LBA_ERROR_LOG_ADDR to tell if error belongs to config cycle. 2628c2ecf20Sopenharmony_ci * 2638c2ecf20Sopenharmony_ci * As of rev 4.0, no longer need the error check. 2648c2ecf20Sopenharmony_ci * 2658c2ecf20Sopenharmony_ci * -- Even if we could tell, we still want to return -1 2668c2ecf20Sopenharmony_ci * for **ANY** error (not just master abort). 2678c2ecf20Sopenharmony_ci * 2688c2ecf20Sopenharmony_ci * -- Only clear non-fatal errors (we don't want to bring 2698c2ecf20Sopenharmony_ci * LBA out of pci-fatal mode). 2708c2ecf20Sopenharmony_ci * 2718c2ecf20Sopenharmony_ci * Actually, there is still a race in which 2728c2ecf20Sopenharmony_ci * we could be clearing a fatal error. We will 2738c2ecf20Sopenharmony_ci * live with this during our initial bus walk 2748c2ecf20Sopenharmony_ci * until rev 4.0 (no driver activity during 2758c2ecf20Sopenharmony_ci * initial bus walk). The initial bus walk 2768c2ecf20Sopenharmony_ci * has race conditions concerning the use of 2778c2ecf20Sopenharmony_ci * smart mode as well. 2788c2ecf20Sopenharmony_ci */ 2798c2ecf20Sopenharmony_ci 2808c2ecf20Sopenharmony_ci#define LBA_MASTER_ABORT_ERROR 0xc 2818c2ecf20Sopenharmony_ci#define LBA_FATAL_ERROR 0x10 2828c2ecf20Sopenharmony_ci 2838c2ecf20Sopenharmony_ci#define LBA_CFG_MASTER_ABORT_CHECK(d, base, tok, error) { \ 2848c2ecf20Sopenharmony_ci u32 error_status = 0; \ 2858c2ecf20Sopenharmony_ci /* \ 2868c2ecf20Sopenharmony_ci * Set clear enable (CE) bit. Unset by HW when new \ 2878c2ecf20Sopenharmony_ci * errors are logged -- LBA HW ERS section 14.3.3). \ 2888c2ecf20Sopenharmony_ci */ \ 2898c2ecf20Sopenharmony_ci WRITE_REG32(status_control | CLEAR_ERRLOG_ENABLE, base + LBA_STAT_CTL); \ 2908c2ecf20Sopenharmony_ci error_status = READ_REG32(base + LBA_ERROR_STATUS); \ 2918c2ecf20Sopenharmony_ci if ((error_status & 0x1f) != 0) { \ 2928c2ecf20Sopenharmony_ci /* \ 2938c2ecf20Sopenharmony_ci * Fail the config read request. \ 2948c2ecf20Sopenharmony_ci */ \ 2958c2ecf20Sopenharmony_ci error = 1; \ 2968c2ecf20Sopenharmony_ci if ((error_status & LBA_FATAL_ERROR) == 0) { \ 2978c2ecf20Sopenharmony_ci /* \ 2988c2ecf20Sopenharmony_ci * Clear error status (if fatal bit not set) by setting \ 2998c2ecf20Sopenharmony_ci * clear error log bit (CL). \ 3008c2ecf20Sopenharmony_ci */ \ 3018c2ecf20Sopenharmony_ci WRITE_REG32(status_control | CLEAR_ERRLOG, base + LBA_STAT_CTL); \ 3028c2ecf20Sopenharmony_ci } \ 3038c2ecf20Sopenharmony_ci } \ 3048c2ecf20Sopenharmony_ci} 3058c2ecf20Sopenharmony_ci 3068c2ecf20Sopenharmony_ci#define LBA_CFG_TR4_ADDR_SETUP(d, addr) \ 3078c2ecf20Sopenharmony_ci WRITE_REG32(((addr) & ~3), (d)->hba.base_addr + LBA_PCI_CFG_ADDR); 3088c2ecf20Sopenharmony_ci 3098c2ecf20Sopenharmony_ci#define LBA_CFG_ADDR_SETUP(d, addr) { \ 3108c2ecf20Sopenharmony_ci WRITE_REG32(((addr) & ~3), (d)->hba.base_addr + LBA_PCI_CFG_ADDR); \ 3118c2ecf20Sopenharmony_ci /* \ 3128c2ecf20Sopenharmony_ci * Read address register to ensure that LBA is the bus master, \ 3138c2ecf20Sopenharmony_ci * which implies that DMA traffic has stopped when DMA arb is off. \ 3148c2ecf20Sopenharmony_ci */ \ 3158c2ecf20Sopenharmony_ci lba_t32 = READ_REG32((d)->hba.base_addr + LBA_PCI_CFG_ADDR); \ 3168c2ecf20Sopenharmony_ci} 3178c2ecf20Sopenharmony_ci 3188c2ecf20Sopenharmony_ci 3198c2ecf20Sopenharmony_ci#define LBA_CFG_RESTORE(d, base) { \ 3208c2ecf20Sopenharmony_ci /* \ 3218c2ecf20Sopenharmony_ci * Restore status control register (turn off clear enable). \ 3228c2ecf20Sopenharmony_ci */ \ 3238c2ecf20Sopenharmony_ci WRITE_REG32(status_control, base + LBA_STAT_CTL); \ 3248c2ecf20Sopenharmony_ci /* \ 3258c2ecf20Sopenharmony_ci * Restore error config register (turn off smart mode). \ 3268c2ecf20Sopenharmony_ci */ \ 3278c2ecf20Sopenharmony_ci WRITE_REG32(error_config, base + LBA_ERROR_CONFIG); \ 3288c2ecf20Sopenharmony_ci /* \ 3298c2ecf20Sopenharmony_ci * Restore arb mask register (reenables DMA arbitration). \ 3308c2ecf20Sopenharmony_ci */ \ 3318c2ecf20Sopenharmony_ci WRITE_REG32(arb_mask, base + LBA_ARB_MASK); \ 3328c2ecf20Sopenharmony_ci} 3338c2ecf20Sopenharmony_ci 3348c2ecf20Sopenharmony_ci 3358c2ecf20Sopenharmony_ci 3368c2ecf20Sopenharmony_cistatic unsigned int 3378c2ecf20Sopenharmony_cilba_rd_cfg(struct lba_device *d, u32 tok, u8 reg, u32 size) 3388c2ecf20Sopenharmony_ci{ 3398c2ecf20Sopenharmony_ci u32 data = ~0U; 3408c2ecf20Sopenharmony_ci int error = 0; 3418c2ecf20Sopenharmony_ci u32 arb_mask = 0; /* used by LBA_CFG_SETUP/RESTORE */ 3428c2ecf20Sopenharmony_ci u32 error_config = 0; /* used by LBA_CFG_SETUP/RESTORE */ 3438c2ecf20Sopenharmony_ci u32 status_control = 0; /* used by LBA_CFG_SETUP/RESTORE */ 3448c2ecf20Sopenharmony_ci 3458c2ecf20Sopenharmony_ci LBA_CFG_SETUP(d, tok); 3468c2ecf20Sopenharmony_ci LBA_CFG_PROBE(d, tok); 3478c2ecf20Sopenharmony_ci LBA_CFG_MASTER_ABORT_CHECK(d, d->hba.base_addr, tok, error); 3488c2ecf20Sopenharmony_ci if (!error) { 3498c2ecf20Sopenharmony_ci void __iomem *data_reg = d->hba.base_addr + LBA_PCI_CFG_DATA; 3508c2ecf20Sopenharmony_ci 3518c2ecf20Sopenharmony_ci LBA_CFG_ADDR_SETUP(d, tok | reg); 3528c2ecf20Sopenharmony_ci switch (size) { 3538c2ecf20Sopenharmony_ci case 1: data = (u32) READ_REG8(data_reg + (reg & 3)); break; 3548c2ecf20Sopenharmony_ci case 2: data = (u32) READ_REG16(data_reg+ (reg & 2)); break; 3558c2ecf20Sopenharmony_ci case 4: data = READ_REG32(data_reg); break; 3568c2ecf20Sopenharmony_ci } 3578c2ecf20Sopenharmony_ci } 3588c2ecf20Sopenharmony_ci LBA_CFG_RESTORE(d, d->hba.base_addr); 3598c2ecf20Sopenharmony_ci return(data); 3608c2ecf20Sopenharmony_ci} 3618c2ecf20Sopenharmony_ci 3628c2ecf20Sopenharmony_ci 3638c2ecf20Sopenharmony_cistatic int elroy_cfg_read(struct pci_bus *bus, unsigned int devfn, int pos, int size, u32 *data) 3648c2ecf20Sopenharmony_ci{ 3658c2ecf20Sopenharmony_ci struct lba_device *d = LBA_DEV(parisc_walk_tree(bus->bridge)); 3668c2ecf20Sopenharmony_ci u32 local_bus = (bus->parent == NULL) ? 0 : bus->busn_res.start; 3678c2ecf20Sopenharmony_ci u32 tok = LBA_CFG_TOK(local_bus, devfn); 3688c2ecf20Sopenharmony_ci void __iomem *data_reg = d->hba.base_addr + LBA_PCI_CFG_DATA; 3698c2ecf20Sopenharmony_ci 3708c2ecf20Sopenharmony_ci if ((pos > 255) || (devfn > 255)) 3718c2ecf20Sopenharmony_ci return -EINVAL; 3728c2ecf20Sopenharmony_ci 3738c2ecf20Sopenharmony_ci/* FIXME: B2K/C3600 workaround is always use old method... */ 3748c2ecf20Sopenharmony_ci /* if (!LBA_SKIP_PROBE(d)) */ { 3758c2ecf20Sopenharmony_ci /* original - Generate config cycle on broken elroy 3768c2ecf20Sopenharmony_ci with risk we will miss PCI bus errors. */ 3778c2ecf20Sopenharmony_ci *data = lba_rd_cfg(d, tok, pos, size); 3788c2ecf20Sopenharmony_ci DBG_CFG("%s(%x+%2x) -> 0x%x (a)\n", __func__, tok, pos, *data); 3798c2ecf20Sopenharmony_ci return 0; 3808c2ecf20Sopenharmony_ci } 3818c2ecf20Sopenharmony_ci 3828c2ecf20Sopenharmony_ci if (LBA_SKIP_PROBE(d) && !lba_device_present(bus->busn_res.start, devfn, d)) { 3838c2ecf20Sopenharmony_ci DBG_CFG("%s(%x+%2x) -> -1 (b)\n", __func__, tok, pos); 3848c2ecf20Sopenharmony_ci /* either don't want to look or know device isn't present. */ 3858c2ecf20Sopenharmony_ci *data = ~0U; 3868c2ecf20Sopenharmony_ci return(0); 3878c2ecf20Sopenharmony_ci } 3888c2ecf20Sopenharmony_ci 3898c2ecf20Sopenharmony_ci /* Basic Algorithm 3908c2ecf20Sopenharmony_ci ** Should only get here on fully working LBA rev. 3918c2ecf20Sopenharmony_ci ** This is how simple the code should have been. 3928c2ecf20Sopenharmony_ci */ 3938c2ecf20Sopenharmony_ci LBA_CFG_ADDR_SETUP(d, tok | pos); 3948c2ecf20Sopenharmony_ci switch(size) { 3958c2ecf20Sopenharmony_ci case 1: *data = READ_REG8 (data_reg + (pos & 3)); break; 3968c2ecf20Sopenharmony_ci case 2: *data = READ_REG16(data_reg + (pos & 2)); break; 3978c2ecf20Sopenharmony_ci case 4: *data = READ_REG32(data_reg); break; 3988c2ecf20Sopenharmony_ci } 3998c2ecf20Sopenharmony_ci DBG_CFG("%s(%x+%2x) -> 0x%x (c)\n", __func__, tok, pos, *data); 4008c2ecf20Sopenharmony_ci return 0; 4018c2ecf20Sopenharmony_ci} 4028c2ecf20Sopenharmony_ci 4038c2ecf20Sopenharmony_ci 4048c2ecf20Sopenharmony_cistatic void 4058c2ecf20Sopenharmony_cilba_wr_cfg(struct lba_device *d, u32 tok, u8 reg, u32 data, u32 size) 4068c2ecf20Sopenharmony_ci{ 4078c2ecf20Sopenharmony_ci int error = 0; 4088c2ecf20Sopenharmony_ci u32 arb_mask = 0; 4098c2ecf20Sopenharmony_ci u32 error_config = 0; 4108c2ecf20Sopenharmony_ci u32 status_control = 0; 4118c2ecf20Sopenharmony_ci void __iomem *data_reg = d->hba.base_addr + LBA_PCI_CFG_DATA; 4128c2ecf20Sopenharmony_ci 4138c2ecf20Sopenharmony_ci LBA_CFG_SETUP(d, tok); 4148c2ecf20Sopenharmony_ci LBA_CFG_ADDR_SETUP(d, tok | reg); 4158c2ecf20Sopenharmony_ci switch (size) { 4168c2ecf20Sopenharmony_ci case 1: WRITE_REG8 (data, data_reg + (reg & 3)); break; 4178c2ecf20Sopenharmony_ci case 2: WRITE_REG16(data, data_reg + (reg & 2)); break; 4188c2ecf20Sopenharmony_ci case 4: WRITE_REG32(data, data_reg); break; 4198c2ecf20Sopenharmony_ci } 4208c2ecf20Sopenharmony_ci LBA_CFG_MASTER_ABORT_CHECK(d, d->hba.base_addr, tok, error); 4218c2ecf20Sopenharmony_ci LBA_CFG_RESTORE(d, d->hba.base_addr); 4228c2ecf20Sopenharmony_ci} 4238c2ecf20Sopenharmony_ci 4248c2ecf20Sopenharmony_ci 4258c2ecf20Sopenharmony_ci/* 4268c2ecf20Sopenharmony_ci * LBA 4.0 config write code implements non-postable semantics 4278c2ecf20Sopenharmony_ci * by doing a read of CONFIG ADDR after the write. 4288c2ecf20Sopenharmony_ci */ 4298c2ecf20Sopenharmony_ci 4308c2ecf20Sopenharmony_cistatic int elroy_cfg_write(struct pci_bus *bus, unsigned int devfn, int pos, int size, u32 data) 4318c2ecf20Sopenharmony_ci{ 4328c2ecf20Sopenharmony_ci struct lba_device *d = LBA_DEV(parisc_walk_tree(bus->bridge)); 4338c2ecf20Sopenharmony_ci u32 local_bus = (bus->parent == NULL) ? 0 : bus->busn_res.start; 4348c2ecf20Sopenharmony_ci u32 tok = LBA_CFG_TOK(local_bus,devfn); 4358c2ecf20Sopenharmony_ci 4368c2ecf20Sopenharmony_ci if ((pos > 255) || (devfn > 255)) 4378c2ecf20Sopenharmony_ci return -EINVAL; 4388c2ecf20Sopenharmony_ci 4398c2ecf20Sopenharmony_ci if (!LBA_SKIP_PROBE(d)) { 4408c2ecf20Sopenharmony_ci /* Original Workaround */ 4418c2ecf20Sopenharmony_ci lba_wr_cfg(d, tok, pos, (u32) data, size); 4428c2ecf20Sopenharmony_ci DBG_CFG("%s(%x+%2x) = 0x%x (a)\n", __func__, tok, pos,data); 4438c2ecf20Sopenharmony_ci return 0; 4448c2ecf20Sopenharmony_ci } 4458c2ecf20Sopenharmony_ci 4468c2ecf20Sopenharmony_ci if (LBA_SKIP_PROBE(d) && (!lba_device_present(bus->busn_res.start, devfn, d))) { 4478c2ecf20Sopenharmony_ci DBG_CFG("%s(%x+%2x) = 0x%x (b)\n", __func__, tok, pos,data); 4488c2ecf20Sopenharmony_ci return 1; /* New Workaround */ 4498c2ecf20Sopenharmony_ci } 4508c2ecf20Sopenharmony_ci 4518c2ecf20Sopenharmony_ci DBG_CFG("%s(%x+%2x) = 0x%x (c)\n", __func__, tok, pos, data); 4528c2ecf20Sopenharmony_ci 4538c2ecf20Sopenharmony_ci /* Basic Algorithm */ 4548c2ecf20Sopenharmony_ci LBA_CFG_ADDR_SETUP(d, tok | pos); 4558c2ecf20Sopenharmony_ci switch(size) { 4568c2ecf20Sopenharmony_ci case 1: WRITE_REG8 (data, d->hba.base_addr + LBA_PCI_CFG_DATA + (pos & 3)); 4578c2ecf20Sopenharmony_ci break; 4588c2ecf20Sopenharmony_ci case 2: WRITE_REG16(data, d->hba.base_addr + LBA_PCI_CFG_DATA + (pos & 2)); 4598c2ecf20Sopenharmony_ci break; 4608c2ecf20Sopenharmony_ci case 4: WRITE_REG32(data, d->hba.base_addr + LBA_PCI_CFG_DATA); 4618c2ecf20Sopenharmony_ci break; 4628c2ecf20Sopenharmony_ci } 4638c2ecf20Sopenharmony_ci /* flush posted write */ 4648c2ecf20Sopenharmony_ci lba_t32 = READ_REG32(d->hba.base_addr + LBA_PCI_CFG_ADDR); 4658c2ecf20Sopenharmony_ci return 0; 4668c2ecf20Sopenharmony_ci} 4678c2ecf20Sopenharmony_ci 4688c2ecf20Sopenharmony_ci 4698c2ecf20Sopenharmony_cistatic struct pci_ops elroy_cfg_ops = { 4708c2ecf20Sopenharmony_ci .read = elroy_cfg_read, 4718c2ecf20Sopenharmony_ci .write = elroy_cfg_write, 4728c2ecf20Sopenharmony_ci}; 4738c2ecf20Sopenharmony_ci 4748c2ecf20Sopenharmony_ci/* 4758c2ecf20Sopenharmony_ci * The mercury_cfg_ops are slightly misnamed; they're also used for Elroy 4768c2ecf20Sopenharmony_ci * TR4.0 as no additional bugs were found in this areea between Elroy and 4778c2ecf20Sopenharmony_ci * Mercury 4788c2ecf20Sopenharmony_ci */ 4798c2ecf20Sopenharmony_ci 4808c2ecf20Sopenharmony_cistatic int mercury_cfg_read(struct pci_bus *bus, unsigned int devfn, int pos, int size, u32 *data) 4818c2ecf20Sopenharmony_ci{ 4828c2ecf20Sopenharmony_ci struct lba_device *d = LBA_DEV(parisc_walk_tree(bus->bridge)); 4838c2ecf20Sopenharmony_ci u32 local_bus = (bus->parent == NULL) ? 0 : bus->busn_res.start; 4848c2ecf20Sopenharmony_ci u32 tok = LBA_CFG_TOK(local_bus, devfn); 4858c2ecf20Sopenharmony_ci void __iomem *data_reg = d->hba.base_addr + LBA_PCI_CFG_DATA; 4868c2ecf20Sopenharmony_ci 4878c2ecf20Sopenharmony_ci if ((pos > 255) || (devfn > 255)) 4888c2ecf20Sopenharmony_ci return -EINVAL; 4898c2ecf20Sopenharmony_ci 4908c2ecf20Sopenharmony_ci LBA_CFG_TR4_ADDR_SETUP(d, tok | pos); 4918c2ecf20Sopenharmony_ci switch(size) { 4928c2ecf20Sopenharmony_ci case 1: 4938c2ecf20Sopenharmony_ci *data = READ_REG8(data_reg + (pos & 3)); 4948c2ecf20Sopenharmony_ci break; 4958c2ecf20Sopenharmony_ci case 2: 4968c2ecf20Sopenharmony_ci *data = READ_REG16(data_reg + (pos & 2)); 4978c2ecf20Sopenharmony_ci break; 4988c2ecf20Sopenharmony_ci case 4: 4998c2ecf20Sopenharmony_ci *data = READ_REG32(data_reg); break; 5008c2ecf20Sopenharmony_ci break; 5018c2ecf20Sopenharmony_ci } 5028c2ecf20Sopenharmony_ci 5038c2ecf20Sopenharmony_ci DBG_CFG("mercury_cfg_read(%x+%2x) -> 0x%x\n", tok, pos, *data); 5048c2ecf20Sopenharmony_ci return 0; 5058c2ecf20Sopenharmony_ci} 5068c2ecf20Sopenharmony_ci 5078c2ecf20Sopenharmony_ci/* 5088c2ecf20Sopenharmony_ci * LBA 4.0 config write code implements non-postable semantics 5098c2ecf20Sopenharmony_ci * by doing a read of CONFIG ADDR after the write. 5108c2ecf20Sopenharmony_ci */ 5118c2ecf20Sopenharmony_ci 5128c2ecf20Sopenharmony_cistatic int mercury_cfg_write(struct pci_bus *bus, unsigned int devfn, int pos, int size, u32 data) 5138c2ecf20Sopenharmony_ci{ 5148c2ecf20Sopenharmony_ci struct lba_device *d = LBA_DEV(parisc_walk_tree(bus->bridge)); 5158c2ecf20Sopenharmony_ci void __iomem *data_reg = d->hba.base_addr + LBA_PCI_CFG_DATA; 5168c2ecf20Sopenharmony_ci u32 local_bus = (bus->parent == NULL) ? 0 : bus->busn_res.start; 5178c2ecf20Sopenharmony_ci u32 tok = LBA_CFG_TOK(local_bus,devfn); 5188c2ecf20Sopenharmony_ci 5198c2ecf20Sopenharmony_ci if ((pos > 255) || (devfn > 255)) 5208c2ecf20Sopenharmony_ci return -EINVAL; 5218c2ecf20Sopenharmony_ci 5228c2ecf20Sopenharmony_ci DBG_CFG("%s(%x+%2x) <- 0x%x (c)\n", __func__, tok, pos, data); 5238c2ecf20Sopenharmony_ci 5248c2ecf20Sopenharmony_ci LBA_CFG_TR4_ADDR_SETUP(d, tok | pos); 5258c2ecf20Sopenharmony_ci switch(size) { 5268c2ecf20Sopenharmony_ci case 1: 5278c2ecf20Sopenharmony_ci WRITE_REG8 (data, data_reg + (pos & 3)); 5288c2ecf20Sopenharmony_ci break; 5298c2ecf20Sopenharmony_ci case 2: 5308c2ecf20Sopenharmony_ci WRITE_REG16(data, data_reg + (pos & 2)); 5318c2ecf20Sopenharmony_ci break; 5328c2ecf20Sopenharmony_ci case 4: 5338c2ecf20Sopenharmony_ci WRITE_REG32(data, data_reg); 5348c2ecf20Sopenharmony_ci break; 5358c2ecf20Sopenharmony_ci } 5368c2ecf20Sopenharmony_ci 5378c2ecf20Sopenharmony_ci /* flush posted write */ 5388c2ecf20Sopenharmony_ci lba_t32 = READ_U32(d->hba.base_addr + LBA_PCI_CFG_ADDR); 5398c2ecf20Sopenharmony_ci return 0; 5408c2ecf20Sopenharmony_ci} 5418c2ecf20Sopenharmony_ci 5428c2ecf20Sopenharmony_cistatic struct pci_ops mercury_cfg_ops = { 5438c2ecf20Sopenharmony_ci .read = mercury_cfg_read, 5448c2ecf20Sopenharmony_ci .write = mercury_cfg_write, 5458c2ecf20Sopenharmony_ci}; 5468c2ecf20Sopenharmony_ci 5478c2ecf20Sopenharmony_ci 5488c2ecf20Sopenharmony_cistatic void 5498c2ecf20Sopenharmony_cilba_bios_init(void) 5508c2ecf20Sopenharmony_ci{ 5518c2ecf20Sopenharmony_ci DBG(MODULE_NAME ": lba_bios_init\n"); 5528c2ecf20Sopenharmony_ci} 5538c2ecf20Sopenharmony_ci 5548c2ecf20Sopenharmony_ci 5558c2ecf20Sopenharmony_ci#ifdef CONFIG_64BIT 5568c2ecf20Sopenharmony_ci 5578c2ecf20Sopenharmony_ci/* 5588c2ecf20Sopenharmony_ci * truncate_pat_collision: Deal with overlaps or outright collisions 5598c2ecf20Sopenharmony_ci * between PAT PDC reported ranges. 5608c2ecf20Sopenharmony_ci * 5618c2ecf20Sopenharmony_ci * Broken PA8800 firmware will report lmmio range that 5628c2ecf20Sopenharmony_ci * overlaps with CPU HPA. Just truncate the lmmio range. 5638c2ecf20Sopenharmony_ci * 5648c2ecf20Sopenharmony_ci * BEWARE: conflicts with this lmmio range may be an 5658c2ecf20Sopenharmony_ci * elmmio range which is pointing down another rope. 5668c2ecf20Sopenharmony_ci * 5678c2ecf20Sopenharmony_ci * FIXME: only deals with one collision per range...theoretically we 5688c2ecf20Sopenharmony_ci * could have several. Supporting more than one collision will get messy. 5698c2ecf20Sopenharmony_ci */ 5708c2ecf20Sopenharmony_cistatic unsigned long 5718c2ecf20Sopenharmony_citruncate_pat_collision(struct resource *root, struct resource *new) 5728c2ecf20Sopenharmony_ci{ 5738c2ecf20Sopenharmony_ci unsigned long start = new->start; 5748c2ecf20Sopenharmony_ci unsigned long end = new->end; 5758c2ecf20Sopenharmony_ci struct resource *tmp = root->child; 5768c2ecf20Sopenharmony_ci 5778c2ecf20Sopenharmony_ci if (end <= start || start < root->start || !tmp) 5788c2ecf20Sopenharmony_ci return 0; 5798c2ecf20Sopenharmony_ci 5808c2ecf20Sopenharmony_ci /* find first overlap */ 5818c2ecf20Sopenharmony_ci while (tmp && tmp->end < start) 5828c2ecf20Sopenharmony_ci tmp = tmp->sibling; 5838c2ecf20Sopenharmony_ci 5848c2ecf20Sopenharmony_ci /* no entries overlap */ 5858c2ecf20Sopenharmony_ci if (!tmp) return 0; 5868c2ecf20Sopenharmony_ci 5878c2ecf20Sopenharmony_ci /* found one that starts behind the new one 5888c2ecf20Sopenharmony_ci ** Don't need to do anything. 5898c2ecf20Sopenharmony_ci */ 5908c2ecf20Sopenharmony_ci if (tmp->start >= end) return 0; 5918c2ecf20Sopenharmony_ci 5928c2ecf20Sopenharmony_ci if (tmp->start <= start) { 5938c2ecf20Sopenharmony_ci /* "front" of new one overlaps */ 5948c2ecf20Sopenharmony_ci new->start = tmp->end + 1; 5958c2ecf20Sopenharmony_ci 5968c2ecf20Sopenharmony_ci if (tmp->end >= end) { 5978c2ecf20Sopenharmony_ci /* AACCKK! totally overlaps! drop this range. */ 5988c2ecf20Sopenharmony_ci return 1; 5998c2ecf20Sopenharmony_ci } 6008c2ecf20Sopenharmony_ci } 6018c2ecf20Sopenharmony_ci 6028c2ecf20Sopenharmony_ci if (tmp->end < end ) { 6038c2ecf20Sopenharmony_ci /* "end" of new one overlaps */ 6048c2ecf20Sopenharmony_ci new->end = tmp->start - 1; 6058c2ecf20Sopenharmony_ci } 6068c2ecf20Sopenharmony_ci 6078c2ecf20Sopenharmony_ci printk(KERN_WARNING "LBA: Truncating lmmio_space [%lx/%lx] " 6088c2ecf20Sopenharmony_ci "to [%lx,%lx]\n", 6098c2ecf20Sopenharmony_ci start, end, 6108c2ecf20Sopenharmony_ci (long)new->start, (long)new->end ); 6118c2ecf20Sopenharmony_ci 6128c2ecf20Sopenharmony_ci return 0; /* truncation successful */ 6138c2ecf20Sopenharmony_ci} 6148c2ecf20Sopenharmony_ci 6158c2ecf20Sopenharmony_ci/* 6168c2ecf20Sopenharmony_ci * extend_lmmio_len: extend lmmio range to maximum length 6178c2ecf20Sopenharmony_ci * 6188c2ecf20Sopenharmony_ci * This is needed at least on C8000 systems to get the ATI FireGL card 6198c2ecf20Sopenharmony_ci * working. On other systems we will currently not extend the lmmio space. 6208c2ecf20Sopenharmony_ci */ 6218c2ecf20Sopenharmony_cistatic unsigned long 6228c2ecf20Sopenharmony_ciextend_lmmio_len(unsigned long start, unsigned long end, unsigned long lba_len) 6238c2ecf20Sopenharmony_ci{ 6248c2ecf20Sopenharmony_ci struct resource *tmp; 6258c2ecf20Sopenharmony_ci 6268c2ecf20Sopenharmony_ci /* exit if not a C8000 */ 6278c2ecf20Sopenharmony_ci if (boot_cpu_data.cpu_type < mako) 6288c2ecf20Sopenharmony_ci return end; 6298c2ecf20Sopenharmony_ci 6308c2ecf20Sopenharmony_ci pr_debug("LMMIO mismatch: PAT length = 0x%lx, MASK register = 0x%lx\n", 6318c2ecf20Sopenharmony_ci end - start, lba_len); 6328c2ecf20Sopenharmony_ci 6338c2ecf20Sopenharmony_ci lba_len = min(lba_len+1, 256UL*1024*1024); /* limit to 256 MB */ 6348c2ecf20Sopenharmony_ci 6358c2ecf20Sopenharmony_ci pr_debug("LBA: lmmio_space [0x%lx-0x%lx] - original\n", start, end); 6368c2ecf20Sopenharmony_ci 6378c2ecf20Sopenharmony_ci 6388c2ecf20Sopenharmony_ci end += lba_len; 6398c2ecf20Sopenharmony_ci if (end < start) /* fix overflow */ 6408c2ecf20Sopenharmony_ci end = -1ULL; 6418c2ecf20Sopenharmony_ci 6428c2ecf20Sopenharmony_ci pr_debug("LBA: lmmio_space [0x%lx-0x%lx] - current\n", start, end); 6438c2ecf20Sopenharmony_ci 6448c2ecf20Sopenharmony_ci /* first overlap */ 6458c2ecf20Sopenharmony_ci for (tmp = iomem_resource.child; tmp; tmp = tmp->sibling) { 6468c2ecf20Sopenharmony_ci pr_debug("LBA: testing %pR\n", tmp); 6478c2ecf20Sopenharmony_ci if (tmp->start == start) 6488c2ecf20Sopenharmony_ci continue; /* ignore ourself */ 6498c2ecf20Sopenharmony_ci if (tmp->end < start) 6508c2ecf20Sopenharmony_ci continue; 6518c2ecf20Sopenharmony_ci if (tmp->start > end) 6528c2ecf20Sopenharmony_ci continue; 6538c2ecf20Sopenharmony_ci if (end >= tmp->start) 6548c2ecf20Sopenharmony_ci end = tmp->start - 1; 6558c2ecf20Sopenharmony_ci } 6568c2ecf20Sopenharmony_ci 6578c2ecf20Sopenharmony_ci pr_info("LBA: lmmio_space [0x%lx-0x%lx] - new\n", start, end); 6588c2ecf20Sopenharmony_ci 6598c2ecf20Sopenharmony_ci /* return new end */ 6608c2ecf20Sopenharmony_ci return end; 6618c2ecf20Sopenharmony_ci} 6628c2ecf20Sopenharmony_ci 6638c2ecf20Sopenharmony_ci#else 6648c2ecf20Sopenharmony_ci#define truncate_pat_collision(r,n) (0) 6658c2ecf20Sopenharmony_ci#endif 6668c2ecf20Sopenharmony_ci 6678c2ecf20Sopenharmony_cistatic void pcibios_allocate_bridge_resources(struct pci_dev *dev) 6688c2ecf20Sopenharmony_ci{ 6698c2ecf20Sopenharmony_ci int idx; 6708c2ecf20Sopenharmony_ci struct resource *r; 6718c2ecf20Sopenharmony_ci 6728c2ecf20Sopenharmony_ci for (idx = PCI_BRIDGE_RESOURCES; idx < PCI_NUM_RESOURCES; idx++) { 6738c2ecf20Sopenharmony_ci r = &dev->resource[idx]; 6748c2ecf20Sopenharmony_ci if (!r->flags) 6758c2ecf20Sopenharmony_ci continue; 6768c2ecf20Sopenharmony_ci if (r->parent) /* Already allocated */ 6778c2ecf20Sopenharmony_ci continue; 6788c2ecf20Sopenharmony_ci if (!r->start || pci_claim_bridge_resource(dev, idx) < 0) { 6798c2ecf20Sopenharmony_ci /* 6808c2ecf20Sopenharmony_ci * Something is wrong with the region. 6818c2ecf20Sopenharmony_ci * Invalidate the resource to prevent 6828c2ecf20Sopenharmony_ci * child resource allocations in this 6838c2ecf20Sopenharmony_ci * range. 6848c2ecf20Sopenharmony_ci */ 6858c2ecf20Sopenharmony_ci r->start = r->end = 0; 6868c2ecf20Sopenharmony_ci r->flags = 0; 6878c2ecf20Sopenharmony_ci } 6888c2ecf20Sopenharmony_ci } 6898c2ecf20Sopenharmony_ci} 6908c2ecf20Sopenharmony_ci 6918c2ecf20Sopenharmony_cistatic void pcibios_allocate_bus_resources(struct pci_bus *bus) 6928c2ecf20Sopenharmony_ci{ 6938c2ecf20Sopenharmony_ci struct pci_bus *child; 6948c2ecf20Sopenharmony_ci 6958c2ecf20Sopenharmony_ci /* Depth-First Search on bus tree */ 6968c2ecf20Sopenharmony_ci if (bus->self) 6978c2ecf20Sopenharmony_ci pcibios_allocate_bridge_resources(bus->self); 6988c2ecf20Sopenharmony_ci list_for_each_entry(child, &bus->children, node) 6998c2ecf20Sopenharmony_ci pcibios_allocate_bus_resources(child); 7008c2ecf20Sopenharmony_ci} 7018c2ecf20Sopenharmony_ci 7028c2ecf20Sopenharmony_ci 7038c2ecf20Sopenharmony_ci/* 7048c2ecf20Sopenharmony_ci** The algorithm is generic code. 7058c2ecf20Sopenharmony_ci** But it needs to access local data structures to get the IRQ base. 7068c2ecf20Sopenharmony_ci** Could make this a "pci_fixup_irq(bus, region)" but not sure 7078c2ecf20Sopenharmony_ci** it's worth it. 7088c2ecf20Sopenharmony_ci** 7098c2ecf20Sopenharmony_ci** Called by do_pci_scan_bus() immediately after each PCI bus is walked. 7108c2ecf20Sopenharmony_ci** Resources aren't allocated until recursive buswalk below HBA is completed. 7118c2ecf20Sopenharmony_ci*/ 7128c2ecf20Sopenharmony_cistatic void 7138c2ecf20Sopenharmony_cilba_fixup_bus(struct pci_bus *bus) 7148c2ecf20Sopenharmony_ci{ 7158c2ecf20Sopenharmony_ci struct pci_dev *dev; 7168c2ecf20Sopenharmony_ci#ifdef FBB_SUPPORT 7178c2ecf20Sopenharmony_ci u16 status; 7188c2ecf20Sopenharmony_ci#endif 7198c2ecf20Sopenharmony_ci struct lba_device *ldev = LBA_DEV(parisc_walk_tree(bus->bridge)); 7208c2ecf20Sopenharmony_ci 7218c2ecf20Sopenharmony_ci DBG("lba_fixup_bus(0x%p) bus %d platform_data 0x%p\n", 7228c2ecf20Sopenharmony_ci bus, (int)bus->busn_res.start, bus->bridge->platform_data); 7238c2ecf20Sopenharmony_ci 7248c2ecf20Sopenharmony_ci /* 7258c2ecf20Sopenharmony_ci ** Properly Setup MMIO resources for this bus. 7268c2ecf20Sopenharmony_ci ** pci_alloc_primary_bus() mangles this. 7278c2ecf20Sopenharmony_ci */ 7288c2ecf20Sopenharmony_ci if (bus->parent) { 7298c2ecf20Sopenharmony_ci /* PCI-PCI Bridge */ 7308c2ecf20Sopenharmony_ci pci_read_bridge_bases(bus); 7318c2ecf20Sopenharmony_ci 7328c2ecf20Sopenharmony_ci /* check and allocate bridge resources */ 7338c2ecf20Sopenharmony_ci pcibios_allocate_bus_resources(bus); 7348c2ecf20Sopenharmony_ci } else { 7358c2ecf20Sopenharmony_ci /* Host-PCI Bridge */ 7368c2ecf20Sopenharmony_ci int err; 7378c2ecf20Sopenharmony_ci 7388c2ecf20Sopenharmony_ci DBG("lba_fixup_bus() %s [%lx/%lx]/%lx\n", 7398c2ecf20Sopenharmony_ci ldev->hba.io_space.name, 7408c2ecf20Sopenharmony_ci ldev->hba.io_space.start, ldev->hba.io_space.end, 7418c2ecf20Sopenharmony_ci ldev->hba.io_space.flags); 7428c2ecf20Sopenharmony_ci DBG("lba_fixup_bus() %s [%lx/%lx]/%lx\n", 7438c2ecf20Sopenharmony_ci ldev->hba.lmmio_space.name, 7448c2ecf20Sopenharmony_ci ldev->hba.lmmio_space.start, ldev->hba.lmmio_space.end, 7458c2ecf20Sopenharmony_ci ldev->hba.lmmio_space.flags); 7468c2ecf20Sopenharmony_ci 7478c2ecf20Sopenharmony_ci err = request_resource(&ioport_resource, &(ldev->hba.io_space)); 7488c2ecf20Sopenharmony_ci if (err < 0) { 7498c2ecf20Sopenharmony_ci lba_dump_res(&ioport_resource, 2); 7508c2ecf20Sopenharmony_ci BUG(); 7518c2ecf20Sopenharmony_ci } 7528c2ecf20Sopenharmony_ci 7538c2ecf20Sopenharmony_ci if (ldev->hba.elmmio_space.flags) { 7548c2ecf20Sopenharmony_ci err = request_resource(&iomem_resource, 7558c2ecf20Sopenharmony_ci &(ldev->hba.elmmio_space)); 7568c2ecf20Sopenharmony_ci if (err < 0) { 7578c2ecf20Sopenharmony_ci 7588c2ecf20Sopenharmony_ci printk("FAILED: lba_fixup_bus() request for " 7598c2ecf20Sopenharmony_ci "elmmio_space [%lx/%lx]\n", 7608c2ecf20Sopenharmony_ci (long)ldev->hba.elmmio_space.start, 7618c2ecf20Sopenharmony_ci (long)ldev->hba.elmmio_space.end); 7628c2ecf20Sopenharmony_ci 7638c2ecf20Sopenharmony_ci /* lba_dump_res(&iomem_resource, 2); */ 7648c2ecf20Sopenharmony_ci /* BUG(); */ 7658c2ecf20Sopenharmony_ci } 7668c2ecf20Sopenharmony_ci } 7678c2ecf20Sopenharmony_ci 7688c2ecf20Sopenharmony_ci if (ldev->hba.lmmio_space.flags) { 7698c2ecf20Sopenharmony_ci err = request_resource(&iomem_resource, &(ldev->hba.lmmio_space)); 7708c2ecf20Sopenharmony_ci if (err < 0) { 7718c2ecf20Sopenharmony_ci printk(KERN_ERR "FAILED: lba_fixup_bus() request for " 7728c2ecf20Sopenharmony_ci "lmmio_space [%lx/%lx]\n", 7738c2ecf20Sopenharmony_ci (long)ldev->hba.lmmio_space.start, 7748c2ecf20Sopenharmony_ci (long)ldev->hba.lmmio_space.end); 7758c2ecf20Sopenharmony_ci } 7768c2ecf20Sopenharmony_ci } 7778c2ecf20Sopenharmony_ci 7788c2ecf20Sopenharmony_ci#ifdef CONFIG_64BIT 7798c2ecf20Sopenharmony_ci /* GMMIO is distributed range. Every LBA/Rope gets part it. */ 7808c2ecf20Sopenharmony_ci if (ldev->hba.gmmio_space.flags) { 7818c2ecf20Sopenharmony_ci err = request_resource(&iomem_resource, &(ldev->hba.gmmio_space)); 7828c2ecf20Sopenharmony_ci if (err < 0) { 7838c2ecf20Sopenharmony_ci printk("FAILED: lba_fixup_bus() request for " 7848c2ecf20Sopenharmony_ci "gmmio_space [%lx/%lx]\n", 7858c2ecf20Sopenharmony_ci (long)ldev->hba.gmmio_space.start, 7868c2ecf20Sopenharmony_ci (long)ldev->hba.gmmio_space.end); 7878c2ecf20Sopenharmony_ci lba_dump_res(&iomem_resource, 2); 7888c2ecf20Sopenharmony_ci BUG(); 7898c2ecf20Sopenharmony_ci } 7908c2ecf20Sopenharmony_ci } 7918c2ecf20Sopenharmony_ci#endif 7928c2ecf20Sopenharmony_ci 7938c2ecf20Sopenharmony_ci } 7948c2ecf20Sopenharmony_ci 7958c2ecf20Sopenharmony_ci list_for_each_entry(dev, &bus->devices, bus_list) { 7968c2ecf20Sopenharmony_ci int i; 7978c2ecf20Sopenharmony_ci 7988c2ecf20Sopenharmony_ci DBG("lba_fixup_bus() %s\n", pci_name(dev)); 7998c2ecf20Sopenharmony_ci 8008c2ecf20Sopenharmony_ci /* Virtualize Device/Bridge Resources. */ 8018c2ecf20Sopenharmony_ci for (i = 0; i < PCI_BRIDGE_RESOURCES; i++) { 8028c2ecf20Sopenharmony_ci struct resource *res = &dev->resource[i]; 8038c2ecf20Sopenharmony_ci 8048c2ecf20Sopenharmony_ci /* If resource not allocated - skip it */ 8058c2ecf20Sopenharmony_ci if (!res->start) 8068c2ecf20Sopenharmony_ci continue; 8078c2ecf20Sopenharmony_ci 8088c2ecf20Sopenharmony_ci /* 8098c2ecf20Sopenharmony_ci ** FIXME: this will result in whinging for devices 8108c2ecf20Sopenharmony_ci ** that share expansion ROMs (think quad tulip), but 8118c2ecf20Sopenharmony_ci ** isn't harmful. 8128c2ecf20Sopenharmony_ci */ 8138c2ecf20Sopenharmony_ci pci_claim_resource(dev, i); 8148c2ecf20Sopenharmony_ci } 8158c2ecf20Sopenharmony_ci 8168c2ecf20Sopenharmony_ci#ifdef FBB_SUPPORT 8178c2ecf20Sopenharmony_ci /* 8188c2ecf20Sopenharmony_ci ** If one device does not support FBB transfers, 8198c2ecf20Sopenharmony_ci ** No one on the bus can be allowed to use them. 8208c2ecf20Sopenharmony_ci */ 8218c2ecf20Sopenharmony_ci (void) pci_read_config_word(dev, PCI_STATUS, &status); 8228c2ecf20Sopenharmony_ci bus->bridge_ctl &= ~(status & PCI_STATUS_FAST_BACK); 8238c2ecf20Sopenharmony_ci#endif 8248c2ecf20Sopenharmony_ci 8258c2ecf20Sopenharmony_ci /* 8268c2ecf20Sopenharmony_ci ** P2PB's have no IRQs. ignore them. 8278c2ecf20Sopenharmony_ci */ 8288c2ecf20Sopenharmony_ci if ((dev->class >> 8) == PCI_CLASS_BRIDGE_PCI) { 8298c2ecf20Sopenharmony_ci pcibios_init_bridge(dev); 8308c2ecf20Sopenharmony_ci continue; 8318c2ecf20Sopenharmony_ci } 8328c2ecf20Sopenharmony_ci 8338c2ecf20Sopenharmony_ci /* Adjust INTERRUPT_LINE for this dev */ 8348c2ecf20Sopenharmony_ci iosapic_fixup_irq(ldev->iosapic_obj, dev); 8358c2ecf20Sopenharmony_ci } 8368c2ecf20Sopenharmony_ci 8378c2ecf20Sopenharmony_ci#ifdef FBB_SUPPORT 8388c2ecf20Sopenharmony_ci/* FIXME/REVISIT - finish figuring out to set FBB on both 8398c2ecf20Sopenharmony_ci** pci_setup_bridge() clobbers PCI_BRIDGE_CONTROL. 8408c2ecf20Sopenharmony_ci** Can't fixup here anyway....garr... 8418c2ecf20Sopenharmony_ci*/ 8428c2ecf20Sopenharmony_ci if (fbb_enable) { 8438c2ecf20Sopenharmony_ci if (bus->parent) { 8448c2ecf20Sopenharmony_ci u8 control; 8458c2ecf20Sopenharmony_ci /* enable on PPB */ 8468c2ecf20Sopenharmony_ci (void) pci_read_config_byte(bus->self, PCI_BRIDGE_CONTROL, &control); 8478c2ecf20Sopenharmony_ci (void) pci_write_config_byte(bus->self, PCI_BRIDGE_CONTROL, control | PCI_STATUS_FAST_BACK); 8488c2ecf20Sopenharmony_ci 8498c2ecf20Sopenharmony_ci } else { 8508c2ecf20Sopenharmony_ci /* enable on LBA */ 8518c2ecf20Sopenharmony_ci } 8528c2ecf20Sopenharmony_ci fbb_enable = PCI_COMMAND_FAST_BACK; 8538c2ecf20Sopenharmony_ci } 8548c2ecf20Sopenharmony_ci 8558c2ecf20Sopenharmony_ci /* Lastly enable FBB/PERR/SERR on all devices too */ 8568c2ecf20Sopenharmony_ci list_for_each_entry(dev, &bus->devices, bus_list) { 8578c2ecf20Sopenharmony_ci (void) pci_read_config_word(dev, PCI_COMMAND, &status); 8588c2ecf20Sopenharmony_ci status |= PCI_COMMAND_PARITY | PCI_COMMAND_SERR | fbb_enable; 8598c2ecf20Sopenharmony_ci (void) pci_write_config_word(dev, PCI_COMMAND, status); 8608c2ecf20Sopenharmony_ci } 8618c2ecf20Sopenharmony_ci#endif 8628c2ecf20Sopenharmony_ci} 8638c2ecf20Sopenharmony_ci 8648c2ecf20Sopenharmony_ci 8658c2ecf20Sopenharmony_cistatic struct pci_bios_ops lba_bios_ops = { 8668c2ecf20Sopenharmony_ci .init = lba_bios_init, 8678c2ecf20Sopenharmony_ci .fixup_bus = lba_fixup_bus, 8688c2ecf20Sopenharmony_ci}; 8698c2ecf20Sopenharmony_ci 8708c2ecf20Sopenharmony_ci 8718c2ecf20Sopenharmony_ci 8728c2ecf20Sopenharmony_ci 8738c2ecf20Sopenharmony_ci/******************************************************* 8748c2ecf20Sopenharmony_ci** 8758c2ecf20Sopenharmony_ci** LBA Sprockets "I/O Port" Space Accessor Functions 8768c2ecf20Sopenharmony_ci** 8778c2ecf20Sopenharmony_ci** This set of accessor functions is intended for use with 8788c2ecf20Sopenharmony_ci** "legacy firmware" (ie Sprockets on Allegro/Forte boxes). 8798c2ecf20Sopenharmony_ci** 8808c2ecf20Sopenharmony_ci** Many PCI devices don't require use of I/O port space (eg Tulip, 8818c2ecf20Sopenharmony_ci** NCR720) since they export the same registers to both MMIO and 8828c2ecf20Sopenharmony_ci** I/O port space. In general I/O port space is slower than 8838c2ecf20Sopenharmony_ci** MMIO since drivers are designed so PIO writes can be posted. 8848c2ecf20Sopenharmony_ci** 8858c2ecf20Sopenharmony_ci********************************************************/ 8868c2ecf20Sopenharmony_ci 8878c2ecf20Sopenharmony_ci#define LBA_PORT_IN(size, mask) \ 8888c2ecf20Sopenharmony_cistatic u##size lba_astro_in##size (struct pci_hba_data *d, u16 addr) \ 8898c2ecf20Sopenharmony_ci{ \ 8908c2ecf20Sopenharmony_ci u##size t; \ 8918c2ecf20Sopenharmony_ci t = READ_REG##size(astro_iop_base + addr); \ 8928c2ecf20Sopenharmony_ci DBG_PORT(" 0x%x\n", t); \ 8938c2ecf20Sopenharmony_ci return (t); \ 8948c2ecf20Sopenharmony_ci} 8958c2ecf20Sopenharmony_ci 8968c2ecf20Sopenharmony_ciLBA_PORT_IN( 8, 3) 8978c2ecf20Sopenharmony_ciLBA_PORT_IN(16, 2) 8988c2ecf20Sopenharmony_ciLBA_PORT_IN(32, 0) 8998c2ecf20Sopenharmony_ci 9008c2ecf20Sopenharmony_ci 9018c2ecf20Sopenharmony_ci 9028c2ecf20Sopenharmony_ci/* 9038c2ecf20Sopenharmony_ci** BUG X4107: Ordering broken - DMA RD return can bypass PIO WR 9048c2ecf20Sopenharmony_ci** 9058c2ecf20Sopenharmony_ci** Fixed in Elroy 2.2. The READ_U32(..., LBA_FUNC_ID) below is 9068c2ecf20Sopenharmony_ci** guarantee non-postable completion semantics - not avoid X4107. 9078c2ecf20Sopenharmony_ci** The READ_U32 only guarantees the write data gets to elroy but 9088c2ecf20Sopenharmony_ci** out to the PCI bus. We can't read stuff from I/O port space 9098c2ecf20Sopenharmony_ci** since we don't know what has side-effects. Attempting to read 9108c2ecf20Sopenharmony_ci** from configuration space would be suicidal given the number of 9118c2ecf20Sopenharmony_ci** bugs in that elroy functionality. 9128c2ecf20Sopenharmony_ci** 9138c2ecf20Sopenharmony_ci** Description: 9148c2ecf20Sopenharmony_ci** DMA read results can improperly pass PIO writes (X4107). The 9158c2ecf20Sopenharmony_ci** result of this bug is that if a processor modifies a location in 9168c2ecf20Sopenharmony_ci** memory after having issued PIO writes, the PIO writes are not 9178c2ecf20Sopenharmony_ci** guaranteed to be completed before a PCI device is allowed to see 9188c2ecf20Sopenharmony_ci** the modified data in a DMA read. 9198c2ecf20Sopenharmony_ci** 9208c2ecf20Sopenharmony_ci** Note that IKE bug X3719 in TR1 IKEs will result in the same 9218c2ecf20Sopenharmony_ci** symptom. 9228c2ecf20Sopenharmony_ci** 9238c2ecf20Sopenharmony_ci** Workaround: 9248c2ecf20Sopenharmony_ci** The workaround for this bug is to always follow a PIO write with 9258c2ecf20Sopenharmony_ci** a PIO read to the same bus before starting DMA on that PCI bus. 9268c2ecf20Sopenharmony_ci** 9278c2ecf20Sopenharmony_ci*/ 9288c2ecf20Sopenharmony_ci#define LBA_PORT_OUT(size, mask) \ 9298c2ecf20Sopenharmony_cistatic void lba_astro_out##size (struct pci_hba_data *d, u16 addr, u##size val) \ 9308c2ecf20Sopenharmony_ci{ \ 9318c2ecf20Sopenharmony_ci DBG_PORT("%s(0x%p, 0x%x, 0x%x)\n", __func__, d, addr, val); \ 9328c2ecf20Sopenharmony_ci WRITE_REG##size(val, astro_iop_base + addr); \ 9338c2ecf20Sopenharmony_ci if (LBA_DEV(d)->hw_rev < 3) \ 9348c2ecf20Sopenharmony_ci lba_t32 = READ_U32(d->base_addr + LBA_FUNC_ID); \ 9358c2ecf20Sopenharmony_ci} 9368c2ecf20Sopenharmony_ci 9378c2ecf20Sopenharmony_ciLBA_PORT_OUT( 8, 3) 9388c2ecf20Sopenharmony_ciLBA_PORT_OUT(16, 2) 9398c2ecf20Sopenharmony_ciLBA_PORT_OUT(32, 0) 9408c2ecf20Sopenharmony_ci 9418c2ecf20Sopenharmony_ci 9428c2ecf20Sopenharmony_cistatic struct pci_port_ops lba_astro_port_ops = { 9438c2ecf20Sopenharmony_ci .inb = lba_astro_in8, 9448c2ecf20Sopenharmony_ci .inw = lba_astro_in16, 9458c2ecf20Sopenharmony_ci .inl = lba_astro_in32, 9468c2ecf20Sopenharmony_ci .outb = lba_astro_out8, 9478c2ecf20Sopenharmony_ci .outw = lba_astro_out16, 9488c2ecf20Sopenharmony_ci .outl = lba_astro_out32 9498c2ecf20Sopenharmony_ci}; 9508c2ecf20Sopenharmony_ci 9518c2ecf20Sopenharmony_ci 9528c2ecf20Sopenharmony_ci#ifdef CONFIG_64BIT 9538c2ecf20Sopenharmony_ci#define PIOP_TO_GMMIO(lba, addr) \ 9548c2ecf20Sopenharmony_ci ((lba)->iop_base + (((addr)&0xFFFC)<<10) + ((addr)&3)) 9558c2ecf20Sopenharmony_ci 9568c2ecf20Sopenharmony_ci/******************************************************* 9578c2ecf20Sopenharmony_ci** 9588c2ecf20Sopenharmony_ci** LBA PAT "I/O Port" Space Accessor Functions 9598c2ecf20Sopenharmony_ci** 9608c2ecf20Sopenharmony_ci** This set of accessor functions is intended for use with 9618c2ecf20Sopenharmony_ci** "PAT PDC" firmware (ie Prelude/Rhapsody/Piranha boxes). 9628c2ecf20Sopenharmony_ci** 9638c2ecf20Sopenharmony_ci** This uses the PIOP space located in the first 64MB of GMMIO. 9648c2ecf20Sopenharmony_ci** Each rope gets a full 64*KB* (ie 4 bytes per page) this way. 9658c2ecf20Sopenharmony_ci** bits 1:0 stay the same. bits 15:2 become 25:12. 9668c2ecf20Sopenharmony_ci** Then add the base and we can generate an I/O Port cycle. 9678c2ecf20Sopenharmony_ci********************************************************/ 9688c2ecf20Sopenharmony_ci#undef LBA_PORT_IN 9698c2ecf20Sopenharmony_ci#define LBA_PORT_IN(size, mask) \ 9708c2ecf20Sopenharmony_cistatic u##size lba_pat_in##size (struct pci_hba_data *l, u16 addr) \ 9718c2ecf20Sopenharmony_ci{ \ 9728c2ecf20Sopenharmony_ci u##size t; \ 9738c2ecf20Sopenharmony_ci DBG_PORT("%s(0x%p, 0x%x) ->", __func__, l, addr); \ 9748c2ecf20Sopenharmony_ci t = READ_REG##size(PIOP_TO_GMMIO(LBA_DEV(l), addr)); \ 9758c2ecf20Sopenharmony_ci DBG_PORT(" 0x%x\n", t); \ 9768c2ecf20Sopenharmony_ci return (t); \ 9778c2ecf20Sopenharmony_ci} 9788c2ecf20Sopenharmony_ci 9798c2ecf20Sopenharmony_ciLBA_PORT_IN( 8, 3) 9808c2ecf20Sopenharmony_ciLBA_PORT_IN(16, 2) 9818c2ecf20Sopenharmony_ciLBA_PORT_IN(32, 0) 9828c2ecf20Sopenharmony_ci 9838c2ecf20Sopenharmony_ci 9848c2ecf20Sopenharmony_ci#undef LBA_PORT_OUT 9858c2ecf20Sopenharmony_ci#define LBA_PORT_OUT(size, mask) \ 9868c2ecf20Sopenharmony_cistatic void lba_pat_out##size (struct pci_hba_data *l, u16 addr, u##size val) \ 9878c2ecf20Sopenharmony_ci{ \ 9888c2ecf20Sopenharmony_ci void __iomem *where = PIOP_TO_GMMIO(LBA_DEV(l), addr); \ 9898c2ecf20Sopenharmony_ci DBG_PORT("%s(0x%p, 0x%x, 0x%x)\n", __func__, l, addr, val); \ 9908c2ecf20Sopenharmony_ci WRITE_REG##size(val, where); \ 9918c2ecf20Sopenharmony_ci /* flush the I/O down to the elroy at least */ \ 9928c2ecf20Sopenharmony_ci lba_t32 = READ_U32(l->base_addr + LBA_FUNC_ID); \ 9938c2ecf20Sopenharmony_ci} 9948c2ecf20Sopenharmony_ci 9958c2ecf20Sopenharmony_ciLBA_PORT_OUT( 8, 3) 9968c2ecf20Sopenharmony_ciLBA_PORT_OUT(16, 2) 9978c2ecf20Sopenharmony_ciLBA_PORT_OUT(32, 0) 9988c2ecf20Sopenharmony_ci 9998c2ecf20Sopenharmony_ci 10008c2ecf20Sopenharmony_cistatic struct pci_port_ops lba_pat_port_ops = { 10018c2ecf20Sopenharmony_ci .inb = lba_pat_in8, 10028c2ecf20Sopenharmony_ci .inw = lba_pat_in16, 10038c2ecf20Sopenharmony_ci .inl = lba_pat_in32, 10048c2ecf20Sopenharmony_ci .outb = lba_pat_out8, 10058c2ecf20Sopenharmony_ci .outw = lba_pat_out16, 10068c2ecf20Sopenharmony_ci .outl = lba_pat_out32 10078c2ecf20Sopenharmony_ci}; 10088c2ecf20Sopenharmony_ci 10098c2ecf20Sopenharmony_ci 10108c2ecf20Sopenharmony_ci 10118c2ecf20Sopenharmony_ci/* 10128c2ecf20Sopenharmony_ci** make range information from PDC available to PCI subsystem. 10138c2ecf20Sopenharmony_ci** We make the PDC call here in order to get the PCI bus range 10148c2ecf20Sopenharmony_ci** numbers. The rest will get forwarded in pcibios_fixup_bus(). 10158c2ecf20Sopenharmony_ci** We don't have a struct pci_bus assigned to us yet. 10168c2ecf20Sopenharmony_ci*/ 10178c2ecf20Sopenharmony_cistatic void 10188c2ecf20Sopenharmony_cilba_pat_resources(struct parisc_device *pa_dev, struct lba_device *lba_dev) 10198c2ecf20Sopenharmony_ci{ 10208c2ecf20Sopenharmony_ci unsigned long bytecnt; 10218c2ecf20Sopenharmony_ci long io_count; 10228c2ecf20Sopenharmony_ci long status; /* PDC return status */ 10238c2ecf20Sopenharmony_ci long pa_count; 10248c2ecf20Sopenharmony_ci pdc_pat_cell_mod_maddr_block_t *pa_pdc_cell; /* PA_VIEW */ 10258c2ecf20Sopenharmony_ci pdc_pat_cell_mod_maddr_block_t *io_pdc_cell; /* IO_VIEW */ 10268c2ecf20Sopenharmony_ci int i; 10278c2ecf20Sopenharmony_ci 10288c2ecf20Sopenharmony_ci pa_pdc_cell = kzalloc(sizeof(pdc_pat_cell_mod_maddr_block_t), GFP_KERNEL); 10298c2ecf20Sopenharmony_ci if (!pa_pdc_cell) 10308c2ecf20Sopenharmony_ci return; 10318c2ecf20Sopenharmony_ci 10328c2ecf20Sopenharmony_ci io_pdc_cell = kzalloc(sizeof(pdc_pat_cell_mod_maddr_block_t), GFP_KERNEL); 10338c2ecf20Sopenharmony_ci if (!io_pdc_cell) { 10348c2ecf20Sopenharmony_ci kfree(pa_pdc_cell); 10358c2ecf20Sopenharmony_ci return; 10368c2ecf20Sopenharmony_ci } 10378c2ecf20Sopenharmony_ci 10388c2ecf20Sopenharmony_ci /* return cell module (IO view) */ 10398c2ecf20Sopenharmony_ci status = pdc_pat_cell_module(&bytecnt, pa_dev->pcell_loc, pa_dev->mod_index, 10408c2ecf20Sopenharmony_ci PA_VIEW, pa_pdc_cell); 10418c2ecf20Sopenharmony_ci pa_count = pa_pdc_cell->mod[1]; 10428c2ecf20Sopenharmony_ci 10438c2ecf20Sopenharmony_ci status |= pdc_pat_cell_module(&bytecnt, pa_dev->pcell_loc, pa_dev->mod_index, 10448c2ecf20Sopenharmony_ci IO_VIEW, io_pdc_cell); 10458c2ecf20Sopenharmony_ci io_count = io_pdc_cell->mod[1]; 10468c2ecf20Sopenharmony_ci 10478c2ecf20Sopenharmony_ci /* We've already done this once for device discovery...*/ 10488c2ecf20Sopenharmony_ci if (status != PDC_OK) { 10498c2ecf20Sopenharmony_ci panic("pdc_pat_cell_module() call failed for LBA!\n"); 10508c2ecf20Sopenharmony_ci } 10518c2ecf20Sopenharmony_ci 10528c2ecf20Sopenharmony_ci if (PAT_GET_ENTITY(pa_pdc_cell->mod_info) != PAT_ENTITY_LBA) { 10538c2ecf20Sopenharmony_ci panic("pdc_pat_cell_module() entity returned != PAT_ENTITY_LBA!\n"); 10548c2ecf20Sopenharmony_ci } 10558c2ecf20Sopenharmony_ci 10568c2ecf20Sopenharmony_ci /* 10578c2ecf20Sopenharmony_ci ** Inspect the resources PAT tells us about 10588c2ecf20Sopenharmony_ci */ 10598c2ecf20Sopenharmony_ci for (i = 0; i < pa_count; i++) { 10608c2ecf20Sopenharmony_ci struct { 10618c2ecf20Sopenharmony_ci unsigned long type; 10628c2ecf20Sopenharmony_ci unsigned long start; 10638c2ecf20Sopenharmony_ci unsigned long end; /* aka finish */ 10648c2ecf20Sopenharmony_ci } *p, *io; 10658c2ecf20Sopenharmony_ci struct resource *r; 10668c2ecf20Sopenharmony_ci 10678c2ecf20Sopenharmony_ci p = (void *) &(pa_pdc_cell->mod[2+i*3]); 10688c2ecf20Sopenharmony_ci io = (void *) &(io_pdc_cell->mod[2+i*3]); 10698c2ecf20Sopenharmony_ci 10708c2ecf20Sopenharmony_ci /* Convert the PAT range data to PCI "struct resource" */ 10718c2ecf20Sopenharmony_ci switch(p->type & 0xff) { 10728c2ecf20Sopenharmony_ci case PAT_PBNUM: 10738c2ecf20Sopenharmony_ci lba_dev->hba.bus_num.start = p->start; 10748c2ecf20Sopenharmony_ci lba_dev->hba.bus_num.end = p->end; 10758c2ecf20Sopenharmony_ci lba_dev->hba.bus_num.flags = IORESOURCE_BUS; 10768c2ecf20Sopenharmony_ci break; 10778c2ecf20Sopenharmony_ci 10788c2ecf20Sopenharmony_ci case PAT_LMMIO: 10798c2ecf20Sopenharmony_ci /* used to fix up pre-initialized MEM BARs */ 10808c2ecf20Sopenharmony_ci if (!lba_dev->hba.lmmio_space.flags) { 10818c2ecf20Sopenharmony_ci unsigned long lba_len; 10828c2ecf20Sopenharmony_ci 10838c2ecf20Sopenharmony_ci lba_len = ~READ_REG32(lba_dev->hba.base_addr 10848c2ecf20Sopenharmony_ci + LBA_LMMIO_MASK); 10858c2ecf20Sopenharmony_ci if ((p->end - p->start) != lba_len) 10868c2ecf20Sopenharmony_ci p->end = extend_lmmio_len(p->start, 10878c2ecf20Sopenharmony_ci p->end, lba_len); 10888c2ecf20Sopenharmony_ci 10898c2ecf20Sopenharmony_ci sprintf(lba_dev->hba.lmmio_name, 10908c2ecf20Sopenharmony_ci "PCI%02x LMMIO", 10918c2ecf20Sopenharmony_ci (int)lba_dev->hba.bus_num.start); 10928c2ecf20Sopenharmony_ci lba_dev->hba.lmmio_space_offset = p->start - 10938c2ecf20Sopenharmony_ci io->start; 10948c2ecf20Sopenharmony_ci r = &lba_dev->hba.lmmio_space; 10958c2ecf20Sopenharmony_ci r->name = lba_dev->hba.lmmio_name; 10968c2ecf20Sopenharmony_ci } else if (!lba_dev->hba.elmmio_space.flags) { 10978c2ecf20Sopenharmony_ci sprintf(lba_dev->hba.elmmio_name, 10988c2ecf20Sopenharmony_ci "PCI%02x ELMMIO", 10998c2ecf20Sopenharmony_ci (int)lba_dev->hba.bus_num.start); 11008c2ecf20Sopenharmony_ci r = &lba_dev->hba.elmmio_space; 11018c2ecf20Sopenharmony_ci r->name = lba_dev->hba.elmmio_name; 11028c2ecf20Sopenharmony_ci } else { 11038c2ecf20Sopenharmony_ci printk(KERN_WARNING MODULE_NAME 11048c2ecf20Sopenharmony_ci " only supports 2 LMMIO resources!\n"); 11058c2ecf20Sopenharmony_ci break; 11068c2ecf20Sopenharmony_ci } 11078c2ecf20Sopenharmony_ci 11088c2ecf20Sopenharmony_ci r->start = p->start; 11098c2ecf20Sopenharmony_ci r->end = p->end; 11108c2ecf20Sopenharmony_ci r->flags = IORESOURCE_MEM; 11118c2ecf20Sopenharmony_ci r->parent = r->sibling = r->child = NULL; 11128c2ecf20Sopenharmony_ci break; 11138c2ecf20Sopenharmony_ci 11148c2ecf20Sopenharmony_ci case PAT_GMMIO: 11158c2ecf20Sopenharmony_ci /* MMIO space > 4GB phys addr; for 64-bit BAR */ 11168c2ecf20Sopenharmony_ci sprintf(lba_dev->hba.gmmio_name, "PCI%02x GMMIO", 11178c2ecf20Sopenharmony_ci (int)lba_dev->hba.bus_num.start); 11188c2ecf20Sopenharmony_ci r = &lba_dev->hba.gmmio_space; 11198c2ecf20Sopenharmony_ci r->name = lba_dev->hba.gmmio_name; 11208c2ecf20Sopenharmony_ci r->start = p->start; 11218c2ecf20Sopenharmony_ci r->end = p->end; 11228c2ecf20Sopenharmony_ci r->flags = IORESOURCE_MEM; 11238c2ecf20Sopenharmony_ci r->parent = r->sibling = r->child = NULL; 11248c2ecf20Sopenharmony_ci break; 11258c2ecf20Sopenharmony_ci 11268c2ecf20Sopenharmony_ci case PAT_NPIOP: 11278c2ecf20Sopenharmony_ci printk(KERN_WARNING MODULE_NAME 11288c2ecf20Sopenharmony_ci " range[%d] : ignoring NPIOP (0x%lx)\n", 11298c2ecf20Sopenharmony_ci i, p->start); 11308c2ecf20Sopenharmony_ci break; 11318c2ecf20Sopenharmony_ci 11328c2ecf20Sopenharmony_ci case PAT_PIOP: 11338c2ecf20Sopenharmony_ci /* 11348c2ecf20Sopenharmony_ci ** Postable I/O port space is per PCI host adapter. 11358c2ecf20Sopenharmony_ci ** base of 64MB PIOP region 11368c2ecf20Sopenharmony_ci */ 11378c2ecf20Sopenharmony_ci lba_dev->iop_base = ioremap(p->start, 64 * 1024 * 1024); 11388c2ecf20Sopenharmony_ci 11398c2ecf20Sopenharmony_ci sprintf(lba_dev->hba.io_name, "PCI%02x Ports", 11408c2ecf20Sopenharmony_ci (int)lba_dev->hba.bus_num.start); 11418c2ecf20Sopenharmony_ci r = &lba_dev->hba.io_space; 11428c2ecf20Sopenharmony_ci r->name = lba_dev->hba.io_name; 11438c2ecf20Sopenharmony_ci r->start = HBA_PORT_BASE(lba_dev->hba.hba_num); 11448c2ecf20Sopenharmony_ci r->end = r->start + HBA_PORT_SPACE_SIZE - 1; 11458c2ecf20Sopenharmony_ci r->flags = IORESOURCE_IO; 11468c2ecf20Sopenharmony_ci r->parent = r->sibling = r->child = NULL; 11478c2ecf20Sopenharmony_ci break; 11488c2ecf20Sopenharmony_ci 11498c2ecf20Sopenharmony_ci default: 11508c2ecf20Sopenharmony_ci printk(KERN_WARNING MODULE_NAME 11518c2ecf20Sopenharmony_ci " range[%d] : unknown pat range type (0x%lx)\n", 11528c2ecf20Sopenharmony_ci i, p->type & 0xff); 11538c2ecf20Sopenharmony_ci break; 11548c2ecf20Sopenharmony_ci } 11558c2ecf20Sopenharmony_ci } 11568c2ecf20Sopenharmony_ci 11578c2ecf20Sopenharmony_ci kfree(pa_pdc_cell); 11588c2ecf20Sopenharmony_ci kfree(io_pdc_cell); 11598c2ecf20Sopenharmony_ci} 11608c2ecf20Sopenharmony_ci#else 11618c2ecf20Sopenharmony_ci/* keep compiler from complaining about missing declarations */ 11628c2ecf20Sopenharmony_ci#define lba_pat_port_ops lba_astro_port_ops 11638c2ecf20Sopenharmony_ci#define lba_pat_resources(pa_dev, lba_dev) 11648c2ecf20Sopenharmony_ci#endif /* CONFIG_64BIT */ 11658c2ecf20Sopenharmony_ci 11668c2ecf20Sopenharmony_ci 11678c2ecf20Sopenharmony_ciextern void sba_distributed_lmmio(struct parisc_device *, struct resource *); 11688c2ecf20Sopenharmony_ciextern void sba_directed_lmmio(struct parisc_device *, struct resource *); 11698c2ecf20Sopenharmony_ci 11708c2ecf20Sopenharmony_ci 11718c2ecf20Sopenharmony_cistatic void 11728c2ecf20Sopenharmony_cilba_legacy_resources(struct parisc_device *pa_dev, struct lba_device *lba_dev) 11738c2ecf20Sopenharmony_ci{ 11748c2ecf20Sopenharmony_ci struct resource *r; 11758c2ecf20Sopenharmony_ci int lba_num; 11768c2ecf20Sopenharmony_ci 11778c2ecf20Sopenharmony_ci lba_dev->hba.lmmio_space_offset = PCI_F_EXTEND; 11788c2ecf20Sopenharmony_ci 11798c2ecf20Sopenharmony_ci /* 11808c2ecf20Sopenharmony_ci ** With "legacy" firmware, the lowest byte of FW_SCRATCH 11818c2ecf20Sopenharmony_ci ** represents bus->secondary and the second byte represents 11828c2ecf20Sopenharmony_ci ** bus->subsidiary (i.e. highest PPB programmed by firmware). 11838c2ecf20Sopenharmony_ci ** PCI bus walk *should* end up with the same result. 11848c2ecf20Sopenharmony_ci ** FIXME: But we don't have sanity checks in PCI or LBA. 11858c2ecf20Sopenharmony_ci */ 11868c2ecf20Sopenharmony_ci lba_num = READ_REG32(lba_dev->hba.base_addr + LBA_FW_SCRATCH); 11878c2ecf20Sopenharmony_ci r = &(lba_dev->hba.bus_num); 11888c2ecf20Sopenharmony_ci r->name = "LBA PCI Busses"; 11898c2ecf20Sopenharmony_ci r->start = lba_num & 0xff; 11908c2ecf20Sopenharmony_ci r->end = (lba_num>>8) & 0xff; 11918c2ecf20Sopenharmony_ci r->flags = IORESOURCE_BUS; 11928c2ecf20Sopenharmony_ci 11938c2ecf20Sopenharmony_ci /* Set up local PCI Bus resources - we don't need them for 11948c2ecf20Sopenharmony_ci ** Legacy boxes but it's nice to see in /proc/iomem. 11958c2ecf20Sopenharmony_ci */ 11968c2ecf20Sopenharmony_ci r = &(lba_dev->hba.lmmio_space); 11978c2ecf20Sopenharmony_ci sprintf(lba_dev->hba.lmmio_name, "PCI%02x LMMIO", 11988c2ecf20Sopenharmony_ci (int)lba_dev->hba.bus_num.start); 11998c2ecf20Sopenharmony_ci r->name = lba_dev->hba.lmmio_name; 12008c2ecf20Sopenharmony_ci 12018c2ecf20Sopenharmony_ci#if 1 12028c2ecf20Sopenharmony_ci /* We want the CPU -> IO routing of addresses. 12038c2ecf20Sopenharmony_ci * The SBA BASE/MASK registers control CPU -> IO routing. 12048c2ecf20Sopenharmony_ci * Ask SBA what is routed to this rope/LBA. 12058c2ecf20Sopenharmony_ci */ 12068c2ecf20Sopenharmony_ci sba_distributed_lmmio(pa_dev, r); 12078c2ecf20Sopenharmony_ci#else 12088c2ecf20Sopenharmony_ci /* 12098c2ecf20Sopenharmony_ci * The LBA BASE/MASK registers control IO -> System routing. 12108c2ecf20Sopenharmony_ci * 12118c2ecf20Sopenharmony_ci * The following code works but doesn't get us what we want. 12128c2ecf20Sopenharmony_ci * Well, only because firmware (v5.0) on C3000 doesn't program 12138c2ecf20Sopenharmony_ci * the LBA BASE/MASE registers to be the exact inverse of 12148c2ecf20Sopenharmony_ci * the corresponding SBA registers. Other Astro/Pluto 12158c2ecf20Sopenharmony_ci * based platform firmware may do it right. 12168c2ecf20Sopenharmony_ci * 12178c2ecf20Sopenharmony_ci * Should someone want to mess with MSI, they may need to 12188c2ecf20Sopenharmony_ci * reprogram LBA BASE/MASK registers. Thus preserve the code 12198c2ecf20Sopenharmony_ci * below until MSI is known to work on C3000/A500/N4000/RP3440. 12208c2ecf20Sopenharmony_ci * 12218c2ecf20Sopenharmony_ci * Using the code below, /proc/iomem shows: 12228c2ecf20Sopenharmony_ci * ... 12238c2ecf20Sopenharmony_ci * f0000000-f0ffffff : PCI00 LMMIO 12248c2ecf20Sopenharmony_ci * f05d0000-f05d0000 : lcd_data 12258c2ecf20Sopenharmony_ci * f05d0008-f05d0008 : lcd_cmd 12268c2ecf20Sopenharmony_ci * f1000000-f1ffffff : PCI01 LMMIO 12278c2ecf20Sopenharmony_ci * f4000000-f4ffffff : PCI02 LMMIO 12288c2ecf20Sopenharmony_ci * f4000000-f4001fff : sym53c8xx 12298c2ecf20Sopenharmony_ci * f4002000-f4003fff : sym53c8xx 12308c2ecf20Sopenharmony_ci * f4004000-f40043ff : sym53c8xx 12318c2ecf20Sopenharmony_ci * f4005000-f40053ff : sym53c8xx 12328c2ecf20Sopenharmony_ci * f4007000-f4007fff : ohci_hcd 12338c2ecf20Sopenharmony_ci * f4008000-f40083ff : tulip 12348c2ecf20Sopenharmony_ci * f6000000-f6ffffff : PCI03 LMMIO 12358c2ecf20Sopenharmony_ci * f8000000-fbffffff : PCI00 ELMMIO 12368c2ecf20Sopenharmony_ci * fa100000-fa4fffff : stifb mmio 12378c2ecf20Sopenharmony_ci * fb000000-fb1fffff : stifb fb 12388c2ecf20Sopenharmony_ci * 12398c2ecf20Sopenharmony_ci * But everything listed under PCI02 actually lives under PCI00. 12408c2ecf20Sopenharmony_ci * This is clearly wrong. 12418c2ecf20Sopenharmony_ci * 12428c2ecf20Sopenharmony_ci * Asking SBA how things are routed tells the correct story: 12438c2ecf20Sopenharmony_ci * LMMIO_BASE/MASK/ROUTE f4000001 fc000000 00000000 12448c2ecf20Sopenharmony_ci * DIR0_BASE/MASK/ROUTE fa000001 fe000000 00000006 12458c2ecf20Sopenharmony_ci * DIR1_BASE/MASK/ROUTE f9000001 ff000000 00000004 12468c2ecf20Sopenharmony_ci * DIR2_BASE/MASK/ROUTE f0000000 fc000000 00000000 12478c2ecf20Sopenharmony_ci * DIR3_BASE/MASK/ROUTE f0000000 fc000000 00000000 12488c2ecf20Sopenharmony_ci * 12498c2ecf20Sopenharmony_ci * Which looks like this in /proc/iomem: 12508c2ecf20Sopenharmony_ci * f4000000-f47fffff : PCI00 LMMIO 12518c2ecf20Sopenharmony_ci * f4000000-f4001fff : sym53c8xx 12528c2ecf20Sopenharmony_ci * ...[deteled core devices - same as above]... 12538c2ecf20Sopenharmony_ci * f4008000-f40083ff : tulip 12548c2ecf20Sopenharmony_ci * f4800000-f4ffffff : PCI01 LMMIO 12558c2ecf20Sopenharmony_ci * f6000000-f67fffff : PCI02 LMMIO 12568c2ecf20Sopenharmony_ci * f7000000-f77fffff : PCI03 LMMIO 12578c2ecf20Sopenharmony_ci * f9000000-f9ffffff : PCI02 ELMMIO 12588c2ecf20Sopenharmony_ci * fa000000-fbffffff : PCI03 ELMMIO 12598c2ecf20Sopenharmony_ci * fa100000-fa4fffff : stifb mmio 12608c2ecf20Sopenharmony_ci * fb000000-fb1fffff : stifb fb 12618c2ecf20Sopenharmony_ci * 12628c2ecf20Sopenharmony_ci * ie all Built-in core are under now correctly under PCI00. 12638c2ecf20Sopenharmony_ci * The "PCI02 ELMMIO" directed range is for: 12648c2ecf20Sopenharmony_ci * +-[02]---03.0 3Dfx Interactive, Inc. Voodoo 2 12658c2ecf20Sopenharmony_ci * 12668c2ecf20Sopenharmony_ci * All is well now. 12678c2ecf20Sopenharmony_ci */ 12688c2ecf20Sopenharmony_ci r->start = READ_REG32(lba_dev->hba.base_addr + LBA_LMMIO_BASE); 12698c2ecf20Sopenharmony_ci if (r->start & 1) { 12708c2ecf20Sopenharmony_ci unsigned long rsize; 12718c2ecf20Sopenharmony_ci 12728c2ecf20Sopenharmony_ci r->flags = IORESOURCE_MEM; 12738c2ecf20Sopenharmony_ci /* mmio_mask also clears Enable bit */ 12748c2ecf20Sopenharmony_ci r->start &= mmio_mask; 12758c2ecf20Sopenharmony_ci r->start = PCI_HOST_ADDR(&lba_dev->hba, r->start); 12768c2ecf20Sopenharmony_ci rsize = ~ READ_REG32(lba_dev->hba.base_addr + LBA_LMMIO_MASK); 12778c2ecf20Sopenharmony_ci 12788c2ecf20Sopenharmony_ci /* 12798c2ecf20Sopenharmony_ci ** Each rope only gets part of the distributed range. 12808c2ecf20Sopenharmony_ci ** Adjust "window" for this rope. 12818c2ecf20Sopenharmony_ci */ 12828c2ecf20Sopenharmony_ci rsize /= ROPES_PER_IOC; 12838c2ecf20Sopenharmony_ci r->start += (rsize + 1) * LBA_NUM(pa_dev->hpa.start); 12848c2ecf20Sopenharmony_ci r->end = r->start + rsize; 12858c2ecf20Sopenharmony_ci } else { 12868c2ecf20Sopenharmony_ci r->end = r->start = 0; /* Not enabled. */ 12878c2ecf20Sopenharmony_ci } 12888c2ecf20Sopenharmony_ci#endif 12898c2ecf20Sopenharmony_ci 12908c2ecf20Sopenharmony_ci /* 12918c2ecf20Sopenharmony_ci ** "Directed" ranges are used when the "distributed range" isn't 12928c2ecf20Sopenharmony_ci ** sufficient for all devices below a given LBA. Typically devices 12938c2ecf20Sopenharmony_ci ** like graphics cards or X25 may need a directed range when the 12948c2ecf20Sopenharmony_ci ** bus has multiple slots (ie multiple devices) or the device 12958c2ecf20Sopenharmony_ci ** needs more than the typical 4 or 8MB a distributed range offers. 12968c2ecf20Sopenharmony_ci ** 12978c2ecf20Sopenharmony_ci ** The main reason for ignoring it now frigging complications. 12988c2ecf20Sopenharmony_ci ** Directed ranges may overlap (and have precedence) over 12998c2ecf20Sopenharmony_ci ** distributed ranges. Or a distributed range assigned to a unused 13008c2ecf20Sopenharmony_ci ** rope may be used by a directed range on a different rope. 13018c2ecf20Sopenharmony_ci ** Support for graphics devices may require fixing this 13028c2ecf20Sopenharmony_ci ** since they may be assigned a directed range which overlaps 13038c2ecf20Sopenharmony_ci ** an existing (but unused portion of) distributed range. 13048c2ecf20Sopenharmony_ci */ 13058c2ecf20Sopenharmony_ci r = &(lba_dev->hba.elmmio_space); 13068c2ecf20Sopenharmony_ci sprintf(lba_dev->hba.elmmio_name, "PCI%02x ELMMIO", 13078c2ecf20Sopenharmony_ci (int)lba_dev->hba.bus_num.start); 13088c2ecf20Sopenharmony_ci r->name = lba_dev->hba.elmmio_name; 13098c2ecf20Sopenharmony_ci 13108c2ecf20Sopenharmony_ci#if 1 13118c2ecf20Sopenharmony_ci /* See comment which precedes call to sba_directed_lmmio() */ 13128c2ecf20Sopenharmony_ci sba_directed_lmmio(pa_dev, r); 13138c2ecf20Sopenharmony_ci#else 13148c2ecf20Sopenharmony_ci r->start = READ_REG32(lba_dev->hba.base_addr + LBA_ELMMIO_BASE); 13158c2ecf20Sopenharmony_ci 13168c2ecf20Sopenharmony_ci if (r->start & 1) { 13178c2ecf20Sopenharmony_ci unsigned long rsize; 13188c2ecf20Sopenharmony_ci r->flags = IORESOURCE_MEM; 13198c2ecf20Sopenharmony_ci /* mmio_mask also clears Enable bit */ 13208c2ecf20Sopenharmony_ci r->start &= mmio_mask; 13218c2ecf20Sopenharmony_ci r->start = PCI_HOST_ADDR(&lba_dev->hba, r->start); 13228c2ecf20Sopenharmony_ci rsize = READ_REG32(lba_dev->hba.base_addr + LBA_ELMMIO_MASK); 13238c2ecf20Sopenharmony_ci r->end = r->start + ~rsize; 13248c2ecf20Sopenharmony_ci } 13258c2ecf20Sopenharmony_ci#endif 13268c2ecf20Sopenharmony_ci 13278c2ecf20Sopenharmony_ci r = &(lba_dev->hba.io_space); 13288c2ecf20Sopenharmony_ci sprintf(lba_dev->hba.io_name, "PCI%02x Ports", 13298c2ecf20Sopenharmony_ci (int)lba_dev->hba.bus_num.start); 13308c2ecf20Sopenharmony_ci r->name = lba_dev->hba.io_name; 13318c2ecf20Sopenharmony_ci r->flags = IORESOURCE_IO; 13328c2ecf20Sopenharmony_ci r->start = READ_REG32(lba_dev->hba.base_addr + LBA_IOS_BASE) & ~1L; 13338c2ecf20Sopenharmony_ci r->end = r->start + (READ_REG32(lba_dev->hba.base_addr + LBA_IOS_MASK) ^ (HBA_PORT_SPACE_SIZE - 1)); 13348c2ecf20Sopenharmony_ci 13358c2ecf20Sopenharmony_ci /* Virtualize the I/O Port space ranges */ 13368c2ecf20Sopenharmony_ci lba_num = HBA_PORT_BASE(lba_dev->hba.hba_num); 13378c2ecf20Sopenharmony_ci r->start |= lba_num; 13388c2ecf20Sopenharmony_ci r->end |= lba_num; 13398c2ecf20Sopenharmony_ci} 13408c2ecf20Sopenharmony_ci 13418c2ecf20Sopenharmony_ci 13428c2ecf20Sopenharmony_ci/************************************************************************** 13438c2ecf20Sopenharmony_ci** 13448c2ecf20Sopenharmony_ci** LBA initialization code (HW and SW) 13458c2ecf20Sopenharmony_ci** 13468c2ecf20Sopenharmony_ci** o identify LBA chip itself 13478c2ecf20Sopenharmony_ci** o initialize LBA chip modes (HardFail) 13488c2ecf20Sopenharmony_ci** o FIXME: initialize DMA hints for reasonable defaults 13498c2ecf20Sopenharmony_ci** o enable configuration functions 13508c2ecf20Sopenharmony_ci** o call pci_register_ops() to discover devs (fixup/fixup_bus get invoked) 13518c2ecf20Sopenharmony_ci** 13528c2ecf20Sopenharmony_ci**************************************************************************/ 13538c2ecf20Sopenharmony_ci 13548c2ecf20Sopenharmony_cistatic int __init 13558c2ecf20Sopenharmony_cilba_hw_init(struct lba_device *d) 13568c2ecf20Sopenharmony_ci{ 13578c2ecf20Sopenharmony_ci u32 stat; 13588c2ecf20Sopenharmony_ci u32 bus_reset; /* PDC_PAT_BUG */ 13598c2ecf20Sopenharmony_ci 13608c2ecf20Sopenharmony_ci#if 0 13618c2ecf20Sopenharmony_ci printk(KERN_DEBUG "LBA %lx STAT_CTL %Lx ERROR_CFG %Lx STATUS %Lx DMA_CTL %Lx\n", 13628c2ecf20Sopenharmony_ci d->hba.base_addr, 13638c2ecf20Sopenharmony_ci READ_REG64(d->hba.base_addr + LBA_STAT_CTL), 13648c2ecf20Sopenharmony_ci READ_REG64(d->hba.base_addr + LBA_ERROR_CONFIG), 13658c2ecf20Sopenharmony_ci READ_REG64(d->hba.base_addr + LBA_ERROR_STATUS), 13668c2ecf20Sopenharmony_ci READ_REG64(d->hba.base_addr + LBA_DMA_CTL) ); 13678c2ecf20Sopenharmony_ci printk(KERN_DEBUG " ARB mask %Lx pri %Lx mode %Lx mtlt %Lx\n", 13688c2ecf20Sopenharmony_ci READ_REG64(d->hba.base_addr + LBA_ARB_MASK), 13698c2ecf20Sopenharmony_ci READ_REG64(d->hba.base_addr + LBA_ARB_PRI), 13708c2ecf20Sopenharmony_ci READ_REG64(d->hba.base_addr + LBA_ARB_MODE), 13718c2ecf20Sopenharmony_ci READ_REG64(d->hba.base_addr + LBA_ARB_MTLT) ); 13728c2ecf20Sopenharmony_ci printk(KERN_DEBUG " HINT cfg 0x%Lx\n", 13738c2ecf20Sopenharmony_ci READ_REG64(d->hba.base_addr + LBA_HINT_CFG)); 13748c2ecf20Sopenharmony_ci printk(KERN_DEBUG " HINT reg "); 13758c2ecf20Sopenharmony_ci { int i; 13768c2ecf20Sopenharmony_ci for (i=LBA_HINT_BASE; i< (14*8 + LBA_HINT_BASE); i+=8) 13778c2ecf20Sopenharmony_ci printk(" %Lx", READ_REG64(d->hba.base_addr + i)); 13788c2ecf20Sopenharmony_ci } 13798c2ecf20Sopenharmony_ci printk("\n"); 13808c2ecf20Sopenharmony_ci#endif /* DEBUG_LBA_PAT */ 13818c2ecf20Sopenharmony_ci 13828c2ecf20Sopenharmony_ci#ifdef CONFIG_64BIT 13838c2ecf20Sopenharmony_ci/* 13848c2ecf20Sopenharmony_ci * FIXME add support for PDC_PAT_IO "Get slot status" - OLAR support 13858c2ecf20Sopenharmony_ci * Only N-Class and up can really make use of Get slot status. 13868c2ecf20Sopenharmony_ci * maybe L-class too but I've never played with it there. 13878c2ecf20Sopenharmony_ci */ 13888c2ecf20Sopenharmony_ci#endif 13898c2ecf20Sopenharmony_ci 13908c2ecf20Sopenharmony_ci /* PDC_PAT_BUG: exhibited in rev 40.48 on L2000 */ 13918c2ecf20Sopenharmony_ci bus_reset = READ_REG32(d->hba.base_addr + LBA_STAT_CTL + 4) & 1; 13928c2ecf20Sopenharmony_ci if (bus_reset) { 13938c2ecf20Sopenharmony_ci printk(KERN_DEBUG "NOTICE: PCI bus reset still asserted! (clearing)\n"); 13948c2ecf20Sopenharmony_ci } 13958c2ecf20Sopenharmony_ci 13968c2ecf20Sopenharmony_ci stat = READ_REG32(d->hba.base_addr + LBA_ERROR_CONFIG); 13978c2ecf20Sopenharmony_ci if (stat & LBA_SMART_MODE) { 13988c2ecf20Sopenharmony_ci printk(KERN_DEBUG "NOTICE: LBA in SMART mode! (cleared)\n"); 13998c2ecf20Sopenharmony_ci stat &= ~LBA_SMART_MODE; 14008c2ecf20Sopenharmony_ci WRITE_REG32(stat, d->hba.base_addr + LBA_ERROR_CONFIG); 14018c2ecf20Sopenharmony_ci } 14028c2ecf20Sopenharmony_ci 14038c2ecf20Sopenharmony_ci 14048c2ecf20Sopenharmony_ci /* 14058c2ecf20Sopenharmony_ci * Hard Fail vs. Soft Fail on PCI "Master Abort". 14068c2ecf20Sopenharmony_ci * 14078c2ecf20Sopenharmony_ci * "Master Abort" means the MMIO transaction timed out - usually due to 14088c2ecf20Sopenharmony_ci * the device not responding to an MMIO read. We would like HF to be 14098c2ecf20Sopenharmony_ci * enabled to find driver problems, though it means the system will 14108c2ecf20Sopenharmony_ci * crash with a HPMC. 14118c2ecf20Sopenharmony_ci * 14128c2ecf20Sopenharmony_ci * In SoftFail mode "~0L" is returned as a result of a timeout on the 14138c2ecf20Sopenharmony_ci * pci bus. This is like how PCI busses on x86 and most other 14148c2ecf20Sopenharmony_ci * architectures behave. In order to increase compatibility with 14158c2ecf20Sopenharmony_ci * existing (x86) PCI hardware and existing Linux drivers we enable 14168c2ecf20Sopenharmony_ci * Soft Faul mode on PA-RISC now too. 14178c2ecf20Sopenharmony_ci */ 14188c2ecf20Sopenharmony_ci stat = READ_REG32(d->hba.base_addr + LBA_STAT_CTL); 14198c2ecf20Sopenharmony_ci#if defined(ENABLE_HARDFAIL) 14208c2ecf20Sopenharmony_ci WRITE_REG32(stat | HF_ENABLE, d->hba.base_addr + LBA_STAT_CTL); 14218c2ecf20Sopenharmony_ci#else 14228c2ecf20Sopenharmony_ci WRITE_REG32(stat & ~HF_ENABLE, d->hba.base_addr + LBA_STAT_CTL); 14238c2ecf20Sopenharmony_ci#endif 14248c2ecf20Sopenharmony_ci 14258c2ecf20Sopenharmony_ci /* 14268c2ecf20Sopenharmony_ci ** Writing a zero to STAT_CTL.rf (bit 0) will clear reset signal 14278c2ecf20Sopenharmony_ci ** if it's not already set. If we just cleared the PCI Bus Reset 14288c2ecf20Sopenharmony_ci ** signal, wait a bit for the PCI devices to recover and setup. 14298c2ecf20Sopenharmony_ci */ 14308c2ecf20Sopenharmony_ci if (bus_reset) 14318c2ecf20Sopenharmony_ci mdelay(pci_post_reset_delay); 14328c2ecf20Sopenharmony_ci 14338c2ecf20Sopenharmony_ci if (0 == READ_REG32(d->hba.base_addr + LBA_ARB_MASK)) { 14348c2ecf20Sopenharmony_ci /* 14358c2ecf20Sopenharmony_ci ** PDC_PAT_BUG: PDC rev 40.48 on L2000. 14368c2ecf20Sopenharmony_ci ** B2000/C3600/J6000 also have this problem? 14378c2ecf20Sopenharmony_ci ** 14388c2ecf20Sopenharmony_ci ** Elroys with hot pluggable slots don't get configured 14398c2ecf20Sopenharmony_ci ** correctly if the slot is empty. ARB_MASK is set to 0 14408c2ecf20Sopenharmony_ci ** and we can't master transactions on the bus if it's 14418c2ecf20Sopenharmony_ci ** not at least one. 0x3 enables elroy and first slot. 14428c2ecf20Sopenharmony_ci */ 14438c2ecf20Sopenharmony_ci printk(KERN_DEBUG "NOTICE: Enabling PCI Arbitration\n"); 14448c2ecf20Sopenharmony_ci WRITE_REG32(0x3, d->hba.base_addr + LBA_ARB_MASK); 14458c2ecf20Sopenharmony_ci } 14468c2ecf20Sopenharmony_ci 14478c2ecf20Sopenharmony_ci /* 14488c2ecf20Sopenharmony_ci ** FIXME: Hint registers are programmed with default hint 14498c2ecf20Sopenharmony_ci ** values by firmware. Hints should be sane even if we 14508c2ecf20Sopenharmony_ci ** can't reprogram them the way drivers want. 14518c2ecf20Sopenharmony_ci */ 14528c2ecf20Sopenharmony_ci return 0; 14538c2ecf20Sopenharmony_ci} 14548c2ecf20Sopenharmony_ci 14558c2ecf20Sopenharmony_ci/* 14568c2ecf20Sopenharmony_ci * Unfortunately, when firmware numbers busses, it doesn't take into account 14578c2ecf20Sopenharmony_ci * Cardbus bridges. So we have to renumber the busses to suit ourselves. 14588c2ecf20Sopenharmony_ci * Elroy/Mercury don't actually know what bus number they're attached to; 14598c2ecf20Sopenharmony_ci * we use bus 0 to indicate the directly attached bus and any other bus 14608c2ecf20Sopenharmony_ci * number will be taken care of by the PCI-PCI bridge. 14618c2ecf20Sopenharmony_ci */ 14628c2ecf20Sopenharmony_cistatic unsigned int lba_next_bus = 0; 14638c2ecf20Sopenharmony_ci 14648c2ecf20Sopenharmony_ci/* 14658c2ecf20Sopenharmony_ci * Determine if lba should claim this chip (return 0) or not (return 1). 14668c2ecf20Sopenharmony_ci * If so, initialize the chip and tell other partners in crime they 14678c2ecf20Sopenharmony_ci * have work to do. 14688c2ecf20Sopenharmony_ci */ 14698c2ecf20Sopenharmony_cistatic int __init 14708c2ecf20Sopenharmony_cilba_driver_probe(struct parisc_device *dev) 14718c2ecf20Sopenharmony_ci{ 14728c2ecf20Sopenharmony_ci struct lba_device *lba_dev; 14738c2ecf20Sopenharmony_ci LIST_HEAD(resources); 14748c2ecf20Sopenharmony_ci struct pci_bus *lba_bus; 14758c2ecf20Sopenharmony_ci struct pci_ops *cfg_ops; 14768c2ecf20Sopenharmony_ci u32 func_class; 14778c2ecf20Sopenharmony_ci void *tmp_obj; 14788c2ecf20Sopenharmony_ci char *version; 14798c2ecf20Sopenharmony_ci void __iomem *addr; 14808c2ecf20Sopenharmony_ci int max; 14818c2ecf20Sopenharmony_ci 14828c2ecf20Sopenharmony_ci addr = ioremap(dev->hpa.start, 4096); 14838c2ecf20Sopenharmony_ci if (addr == NULL) 14848c2ecf20Sopenharmony_ci return -ENOMEM; 14858c2ecf20Sopenharmony_ci 14868c2ecf20Sopenharmony_ci /* Read HW Rev First */ 14878c2ecf20Sopenharmony_ci func_class = READ_REG32(addr + LBA_FCLASS); 14888c2ecf20Sopenharmony_ci 14898c2ecf20Sopenharmony_ci if (IS_ELROY(dev)) { 14908c2ecf20Sopenharmony_ci func_class &= 0xf; 14918c2ecf20Sopenharmony_ci switch (func_class) { 14928c2ecf20Sopenharmony_ci case 0: version = "TR1.0"; break; 14938c2ecf20Sopenharmony_ci case 1: version = "TR2.0"; break; 14948c2ecf20Sopenharmony_ci case 2: version = "TR2.1"; break; 14958c2ecf20Sopenharmony_ci case 3: version = "TR2.2"; break; 14968c2ecf20Sopenharmony_ci case 4: version = "TR3.0"; break; 14978c2ecf20Sopenharmony_ci case 5: version = "TR4.0"; break; 14988c2ecf20Sopenharmony_ci default: version = "TR4+"; 14998c2ecf20Sopenharmony_ci } 15008c2ecf20Sopenharmony_ci 15018c2ecf20Sopenharmony_ci printk(KERN_INFO "Elroy version %s (0x%x) found at 0x%lx\n", 15028c2ecf20Sopenharmony_ci version, func_class & 0xf, (long)dev->hpa.start); 15038c2ecf20Sopenharmony_ci 15048c2ecf20Sopenharmony_ci if (func_class < 2) { 15058c2ecf20Sopenharmony_ci printk(KERN_WARNING "Can't support LBA older than " 15068c2ecf20Sopenharmony_ci "TR2.1 - continuing under adversity.\n"); 15078c2ecf20Sopenharmony_ci } 15088c2ecf20Sopenharmony_ci 15098c2ecf20Sopenharmony_ci#if 0 15108c2ecf20Sopenharmony_ci/* Elroy TR4.0 should work with simple algorithm. 15118c2ecf20Sopenharmony_ci But it doesn't. Still missing something. *sigh* 15128c2ecf20Sopenharmony_ci*/ 15138c2ecf20Sopenharmony_ci if (func_class > 4) { 15148c2ecf20Sopenharmony_ci cfg_ops = &mercury_cfg_ops; 15158c2ecf20Sopenharmony_ci } else 15168c2ecf20Sopenharmony_ci#endif 15178c2ecf20Sopenharmony_ci { 15188c2ecf20Sopenharmony_ci cfg_ops = &elroy_cfg_ops; 15198c2ecf20Sopenharmony_ci } 15208c2ecf20Sopenharmony_ci 15218c2ecf20Sopenharmony_ci } else if (IS_MERCURY(dev) || IS_QUICKSILVER(dev)) { 15228c2ecf20Sopenharmony_ci int major, minor; 15238c2ecf20Sopenharmony_ci 15248c2ecf20Sopenharmony_ci func_class &= 0xff; 15258c2ecf20Sopenharmony_ci major = func_class >> 4, minor = func_class & 0xf; 15268c2ecf20Sopenharmony_ci 15278c2ecf20Sopenharmony_ci /* We could use one printk for both Elroy and Mercury, 15288c2ecf20Sopenharmony_ci * but for the mask for func_class. 15298c2ecf20Sopenharmony_ci */ 15308c2ecf20Sopenharmony_ci printk(KERN_INFO "%s version TR%d.%d (0x%x) found at 0x%lx\n", 15318c2ecf20Sopenharmony_ci IS_MERCURY(dev) ? "Mercury" : "Quicksilver", major, 15328c2ecf20Sopenharmony_ci minor, func_class, (long)dev->hpa.start); 15338c2ecf20Sopenharmony_ci 15348c2ecf20Sopenharmony_ci cfg_ops = &mercury_cfg_ops; 15358c2ecf20Sopenharmony_ci } else { 15368c2ecf20Sopenharmony_ci printk(KERN_ERR "Unknown LBA found at 0x%lx\n", 15378c2ecf20Sopenharmony_ci (long)dev->hpa.start); 15388c2ecf20Sopenharmony_ci return -ENODEV; 15398c2ecf20Sopenharmony_ci } 15408c2ecf20Sopenharmony_ci 15418c2ecf20Sopenharmony_ci /* Tell I/O SAPIC driver we have a IRQ handler/region. */ 15428c2ecf20Sopenharmony_ci tmp_obj = iosapic_register(dev->hpa.start + LBA_IOSAPIC_BASE); 15438c2ecf20Sopenharmony_ci 15448c2ecf20Sopenharmony_ci /* NOTE: PCI devices (e.g. 103c:1005 graphics card) which don't 15458c2ecf20Sopenharmony_ci ** have an IRT entry will get NULL back from iosapic code. 15468c2ecf20Sopenharmony_ci */ 15478c2ecf20Sopenharmony_ci 15488c2ecf20Sopenharmony_ci lba_dev = kzalloc(sizeof(struct lba_device), GFP_KERNEL); 15498c2ecf20Sopenharmony_ci if (!lba_dev) { 15508c2ecf20Sopenharmony_ci printk(KERN_ERR "lba_init_chip - couldn't alloc lba_device\n"); 15518c2ecf20Sopenharmony_ci return(1); 15528c2ecf20Sopenharmony_ci } 15538c2ecf20Sopenharmony_ci 15548c2ecf20Sopenharmony_ci 15558c2ecf20Sopenharmony_ci /* ---------- First : initialize data we already have --------- */ 15568c2ecf20Sopenharmony_ci 15578c2ecf20Sopenharmony_ci lba_dev->hw_rev = func_class; 15588c2ecf20Sopenharmony_ci lba_dev->hba.base_addr = addr; 15598c2ecf20Sopenharmony_ci lba_dev->hba.dev = dev; 15608c2ecf20Sopenharmony_ci lba_dev->iosapic_obj = tmp_obj; /* save interrupt handle */ 15618c2ecf20Sopenharmony_ci lba_dev->hba.iommu = sba_get_iommu(dev); /* get iommu data */ 15628c2ecf20Sopenharmony_ci parisc_set_drvdata(dev, lba_dev); 15638c2ecf20Sopenharmony_ci 15648c2ecf20Sopenharmony_ci /* ------------ Second : initialize common stuff ---------- */ 15658c2ecf20Sopenharmony_ci pci_bios = &lba_bios_ops; 15668c2ecf20Sopenharmony_ci pcibios_register_hba(&lba_dev->hba); 15678c2ecf20Sopenharmony_ci spin_lock_init(&lba_dev->lba_lock); 15688c2ecf20Sopenharmony_ci 15698c2ecf20Sopenharmony_ci if (lba_hw_init(lba_dev)) 15708c2ecf20Sopenharmony_ci return(1); 15718c2ecf20Sopenharmony_ci 15728c2ecf20Sopenharmony_ci /* ---------- Third : setup I/O Port and MMIO resources --------- */ 15738c2ecf20Sopenharmony_ci 15748c2ecf20Sopenharmony_ci if (is_pdc_pat()) { 15758c2ecf20Sopenharmony_ci /* PDC PAT firmware uses PIOP region of GMMIO space. */ 15768c2ecf20Sopenharmony_ci pci_port = &lba_pat_port_ops; 15778c2ecf20Sopenharmony_ci /* Go ask PDC PAT what resources this LBA has */ 15788c2ecf20Sopenharmony_ci lba_pat_resources(dev, lba_dev); 15798c2ecf20Sopenharmony_ci } else { 15808c2ecf20Sopenharmony_ci if (!astro_iop_base) { 15818c2ecf20Sopenharmony_ci /* Sprockets PDC uses NPIOP region */ 15828c2ecf20Sopenharmony_ci astro_iop_base = ioremap(LBA_PORT_BASE, 64 * 1024); 15838c2ecf20Sopenharmony_ci pci_port = &lba_astro_port_ops; 15848c2ecf20Sopenharmony_ci } 15858c2ecf20Sopenharmony_ci 15868c2ecf20Sopenharmony_ci /* Poke the chip a bit for /proc output */ 15878c2ecf20Sopenharmony_ci lba_legacy_resources(dev, lba_dev); 15888c2ecf20Sopenharmony_ci } 15898c2ecf20Sopenharmony_ci 15908c2ecf20Sopenharmony_ci if (lba_dev->hba.bus_num.start < lba_next_bus) 15918c2ecf20Sopenharmony_ci lba_dev->hba.bus_num.start = lba_next_bus; 15928c2ecf20Sopenharmony_ci 15938c2ecf20Sopenharmony_ci /* Overlaps with elmmio can (and should) fail here. 15948c2ecf20Sopenharmony_ci * We will prune (or ignore) the distributed range. 15958c2ecf20Sopenharmony_ci * 15968c2ecf20Sopenharmony_ci * FIXME: SBA code should register all elmmio ranges first. 15978c2ecf20Sopenharmony_ci * that would take care of elmmio ranges routed 15988c2ecf20Sopenharmony_ci * to a different rope (already discovered) from 15998c2ecf20Sopenharmony_ci * getting registered *after* LBA code has already 16008c2ecf20Sopenharmony_ci * registered it's distributed lmmio range. 16018c2ecf20Sopenharmony_ci */ 16028c2ecf20Sopenharmony_ci if (truncate_pat_collision(&iomem_resource, 16038c2ecf20Sopenharmony_ci &(lba_dev->hba.lmmio_space))) { 16048c2ecf20Sopenharmony_ci printk(KERN_WARNING "LBA: lmmio_space [%lx/%lx] duplicate!\n", 16058c2ecf20Sopenharmony_ci (long)lba_dev->hba.lmmio_space.start, 16068c2ecf20Sopenharmony_ci (long)lba_dev->hba.lmmio_space.end); 16078c2ecf20Sopenharmony_ci lba_dev->hba.lmmio_space.flags = 0; 16088c2ecf20Sopenharmony_ci } 16098c2ecf20Sopenharmony_ci 16108c2ecf20Sopenharmony_ci pci_add_resource_offset(&resources, &lba_dev->hba.io_space, 16118c2ecf20Sopenharmony_ci HBA_PORT_BASE(lba_dev->hba.hba_num)); 16128c2ecf20Sopenharmony_ci if (lba_dev->hba.elmmio_space.flags) 16138c2ecf20Sopenharmony_ci pci_add_resource_offset(&resources, &lba_dev->hba.elmmio_space, 16148c2ecf20Sopenharmony_ci lba_dev->hba.lmmio_space_offset); 16158c2ecf20Sopenharmony_ci if (lba_dev->hba.lmmio_space.flags) 16168c2ecf20Sopenharmony_ci pci_add_resource_offset(&resources, &lba_dev->hba.lmmio_space, 16178c2ecf20Sopenharmony_ci lba_dev->hba.lmmio_space_offset); 16188c2ecf20Sopenharmony_ci if (lba_dev->hba.gmmio_space.flags) { 16198c2ecf20Sopenharmony_ci /* Not registering GMMIO space - according to docs it's not 16208c2ecf20Sopenharmony_ci * even used on HP-UX. */ 16218c2ecf20Sopenharmony_ci /* pci_add_resource(&resources, &lba_dev->hba.gmmio_space); */ 16228c2ecf20Sopenharmony_ci } 16238c2ecf20Sopenharmony_ci 16248c2ecf20Sopenharmony_ci pci_add_resource(&resources, &lba_dev->hba.bus_num); 16258c2ecf20Sopenharmony_ci 16268c2ecf20Sopenharmony_ci dev->dev.platform_data = lba_dev; 16278c2ecf20Sopenharmony_ci lba_bus = lba_dev->hba.hba_bus = 16288c2ecf20Sopenharmony_ci pci_create_root_bus(&dev->dev, lba_dev->hba.bus_num.start, 16298c2ecf20Sopenharmony_ci cfg_ops, NULL, &resources); 16308c2ecf20Sopenharmony_ci if (!lba_bus) { 16318c2ecf20Sopenharmony_ci pci_free_resource_list(&resources); 16328c2ecf20Sopenharmony_ci return 0; 16338c2ecf20Sopenharmony_ci } 16348c2ecf20Sopenharmony_ci 16358c2ecf20Sopenharmony_ci max = pci_scan_child_bus(lba_bus); 16368c2ecf20Sopenharmony_ci 16378c2ecf20Sopenharmony_ci /* This is in lieu of calling pci_assign_unassigned_resources() */ 16388c2ecf20Sopenharmony_ci if (is_pdc_pat()) { 16398c2ecf20Sopenharmony_ci /* assign resources to un-initialized devices */ 16408c2ecf20Sopenharmony_ci 16418c2ecf20Sopenharmony_ci DBG_PAT("LBA pci_bus_size_bridges()\n"); 16428c2ecf20Sopenharmony_ci pci_bus_size_bridges(lba_bus); 16438c2ecf20Sopenharmony_ci 16448c2ecf20Sopenharmony_ci DBG_PAT("LBA pci_bus_assign_resources()\n"); 16458c2ecf20Sopenharmony_ci pci_bus_assign_resources(lba_bus); 16468c2ecf20Sopenharmony_ci 16478c2ecf20Sopenharmony_ci#ifdef DEBUG_LBA_PAT 16488c2ecf20Sopenharmony_ci DBG_PAT("\nLBA PIOP resource tree\n"); 16498c2ecf20Sopenharmony_ci lba_dump_res(&lba_dev->hba.io_space, 2); 16508c2ecf20Sopenharmony_ci DBG_PAT("\nLBA LMMIO resource tree\n"); 16518c2ecf20Sopenharmony_ci lba_dump_res(&lba_dev->hba.lmmio_space, 2); 16528c2ecf20Sopenharmony_ci#endif 16538c2ecf20Sopenharmony_ci } 16548c2ecf20Sopenharmony_ci 16558c2ecf20Sopenharmony_ci /* 16568c2ecf20Sopenharmony_ci ** Once PCI register ops has walked the bus, access to config 16578c2ecf20Sopenharmony_ci ** space is restricted. Avoids master aborts on config cycles. 16588c2ecf20Sopenharmony_ci ** Early LBA revs go fatal on *any* master abort. 16598c2ecf20Sopenharmony_ci */ 16608c2ecf20Sopenharmony_ci if (cfg_ops == &elroy_cfg_ops) { 16618c2ecf20Sopenharmony_ci lba_dev->flags |= LBA_FLAG_SKIP_PROBE; 16628c2ecf20Sopenharmony_ci } 16638c2ecf20Sopenharmony_ci 16648c2ecf20Sopenharmony_ci lba_next_bus = max + 1; 16658c2ecf20Sopenharmony_ci pci_bus_add_devices(lba_bus); 16668c2ecf20Sopenharmony_ci 16678c2ecf20Sopenharmony_ci /* Whew! Finally done! Tell services we got this one covered. */ 16688c2ecf20Sopenharmony_ci return 0; 16698c2ecf20Sopenharmony_ci} 16708c2ecf20Sopenharmony_ci 16718c2ecf20Sopenharmony_cistatic const struct parisc_device_id lba_tbl[] __initconst = { 16728c2ecf20Sopenharmony_ci { HPHW_BRIDGE, HVERSION_REV_ANY_ID, ELROY_HVERS, 0xa }, 16738c2ecf20Sopenharmony_ci { HPHW_BRIDGE, HVERSION_REV_ANY_ID, MERCURY_HVERS, 0xa }, 16748c2ecf20Sopenharmony_ci { HPHW_BRIDGE, HVERSION_REV_ANY_ID, QUICKSILVER_HVERS, 0xa }, 16758c2ecf20Sopenharmony_ci { 0, } 16768c2ecf20Sopenharmony_ci}; 16778c2ecf20Sopenharmony_ci 16788c2ecf20Sopenharmony_cistatic struct parisc_driver lba_driver __refdata = { 16798c2ecf20Sopenharmony_ci .name = MODULE_NAME, 16808c2ecf20Sopenharmony_ci .id_table = lba_tbl, 16818c2ecf20Sopenharmony_ci .probe = lba_driver_probe, 16828c2ecf20Sopenharmony_ci}; 16838c2ecf20Sopenharmony_ci 16848c2ecf20Sopenharmony_ci/* 16858c2ecf20Sopenharmony_ci** One time initialization to let the world know the LBA was found. 16868c2ecf20Sopenharmony_ci** Must be called exactly once before pci_init(). 16878c2ecf20Sopenharmony_ci*/ 16888c2ecf20Sopenharmony_civoid __init lba_init(void) 16898c2ecf20Sopenharmony_ci{ 16908c2ecf20Sopenharmony_ci register_parisc_driver(&lba_driver); 16918c2ecf20Sopenharmony_ci} 16928c2ecf20Sopenharmony_ci 16938c2ecf20Sopenharmony_ci/* 16948c2ecf20Sopenharmony_ci** Initialize the IBASE/IMASK registers for LBA (Elroy). 16958c2ecf20Sopenharmony_ci** Only called from sba_iommu.c in order to route ranges (MMIO vs DMA). 16968c2ecf20Sopenharmony_ci** sba_iommu is responsible for locking (none needed at init time). 16978c2ecf20Sopenharmony_ci*/ 16988c2ecf20Sopenharmony_civoid lba_set_iregs(struct parisc_device *lba, u32 ibase, u32 imask) 16998c2ecf20Sopenharmony_ci{ 17008c2ecf20Sopenharmony_ci void __iomem * base_addr = ioremap(lba->hpa.start, 4096); 17018c2ecf20Sopenharmony_ci 17028c2ecf20Sopenharmony_ci imask <<= 2; /* adjust for hints - 2 more bits */ 17038c2ecf20Sopenharmony_ci 17048c2ecf20Sopenharmony_ci /* Make sure we aren't trying to set bits that aren't writeable. */ 17058c2ecf20Sopenharmony_ci WARN_ON((ibase & 0x001fffff) != 0); 17068c2ecf20Sopenharmony_ci WARN_ON((imask & 0x001fffff) != 0); 17078c2ecf20Sopenharmony_ci 17088c2ecf20Sopenharmony_ci DBG("%s() ibase 0x%x imask 0x%x\n", __func__, ibase, imask); 17098c2ecf20Sopenharmony_ci WRITE_REG32( imask, base_addr + LBA_IMASK); 17108c2ecf20Sopenharmony_ci WRITE_REG32( ibase, base_addr + LBA_IBASE); 17118c2ecf20Sopenharmony_ci iounmap(base_addr); 17128c2ecf20Sopenharmony_ci} 17138c2ecf20Sopenharmony_ci 17148c2ecf20Sopenharmony_ci 17158c2ecf20Sopenharmony_ci/* 17168c2ecf20Sopenharmony_ci * The design of the Diva management card in rp34x0 machines (rp3410, rp3440) 17178c2ecf20Sopenharmony_ci * seems rushed, so that many built-in components simply don't work. 17188c2ecf20Sopenharmony_ci * The following quirks disable the serial AUX port and the built-in ATI RV100 17198c2ecf20Sopenharmony_ci * Radeon 7000 graphics card which both don't have any external connectors and 17208c2ecf20Sopenharmony_ci * thus are useless, and even worse, e.g. the AUX port occupies ttyS0 and as 17218c2ecf20Sopenharmony_ci * such makes those machines the only PARISC machines on which we can't use 17228c2ecf20Sopenharmony_ci * ttyS0 as boot console. 17238c2ecf20Sopenharmony_ci */ 17248c2ecf20Sopenharmony_cistatic void quirk_diva_ati_card(struct pci_dev *dev) 17258c2ecf20Sopenharmony_ci{ 17268c2ecf20Sopenharmony_ci if (dev->subsystem_vendor != PCI_VENDOR_ID_HP || 17278c2ecf20Sopenharmony_ci dev->subsystem_device != 0x1292) 17288c2ecf20Sopenharmony_ci return; 17298c2ecf20Sopenharmony_ci 17308c2ecf20Sopenharmony_ci dev_info(&dev->dev, "Hiding Diva built-in ATI card"); 17318c2ecf20Sopenharmony_ci dev->device = 0; 17328c2ecf20Sopenharmony_ci} 17338c2ecf20Sopenharmony_ciDECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_ATI, PCI_DEVICE_ID_ATI_RADEON_QY, 17348c2ecf20Sopenharmony_ci quirk_diva_ati_card); 17358c2ecf20Sopenharmony_ci 17368c2ecf20Sopenharmony_cistatic void quirk_diva_aux_disable(struct pci_dev *dev) 17378c2ecf20Sopenharmony_ci{ 17388c2ecf20Sopenharmony_ci if (dev->subsystem_vendor != PCI_VENDOR_ID_HP || 17398c2ecf20Sopenharmony_ci dev->subsystem_device != 0x1291) 17408c2ecf20Sopenharmony_ci return; 17418c2ecf20Sopenharmony_ci 17428c2ecf20Sopenharmony_ci dev_info(&dev->dev, "Hiding Diva built-in AUX serial device"); 17438c2ecf20Sopenharmony_ci dev->device = 0; 17448c2ecf20Sopenharmony_ci} 17458c2ecf20Sopenharmony_ciDECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_HP, PCI_DEVICE_ID_HP_DIVA_AUX, 17468c2ecf20Sopenharmony_ci quirk_diva_aux_disable); 17478c2ecf20Sopenharmony_ci 17488c2ecf20Sopenharmony_cistatic void quirk_tosca_aux_disable(struct pci_dev *dev) 17498c2ecf20Sopenharmony_ci{ 17508c2ecf20Sopenharmony_ci if (dev->subsystem_vendor != PCI_VENDOR_ID_HP || 17518c2ecf20Sopenharmony_ci dev->subsystem_device != 0x104a) 17528c2ecf20Sopenharmony_ci return; 17538c2ecf20Sopenharmony_ci 17548c2ecf20Sopenharmony_ci dev_info(&dev->dev, "Hiding Tosca secondary built-in AUX serial device"); 17558c2ecf20Sopenharmony_ci dev->device = 0; 17568c2ecf20Sopenharmony_ci} 17578c2ecf20Sopenharmony_ciDECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_HP, PCI_DEVICE_ID_HP_DIVA, 17588c2ecf20Sopenharmony_ci quirk_tosca_aux_disable); 1759