1/* 2 * Copyright (C) 2006 Benjamin Herrenschmidt <benh@kernel.crashing.org> 3 * IBM, Corp. 4 * 5 * This program is free software; you can redistribute it and/or modify 6 * it under the terms of the GNU General Public License version 2 as 7 * published by the Free Software Foundation. 8 */ 9#undef DEBUG 10 11#include <linux/kernel.h> 12#include <linux/mm.h> 13#include <linux/pci.h> 14#include <asm/io.h> 15#include <asm/machdep.h> 16#include <asm/pci-bridge.h> 17#include <asm/ppc-pci.h> 18 19 20#define SPIDER_PCI_REG_BASE 0xd000 21#define SPIDER_PCI_VCI_CNTL_STAT 0x0110 22#define SPIDER_PCI_DUMMY_READ 0x0810 23#define SPIDER_PCI_DUMMY_READ_BASE 0x0814 24 25#define SPIDER_DISABLE_PREFETCH 26 27#define MAX_SPIDERS 3 28 29static struct spider_pci_bus { 30 void __iomem *regs; 31 unsigned long mmio_start; 32 unsigned long mmio_end; 33 unsigned long pio_vstart; 34 unsigned long pio_vend; 35} spider_pci_busses[MAX_SPIDERS]; 36static int spider_pci_count; 37 38static struct spider_pci_bus *spider_pci_find(unsigned long vaddr, 39 unsigned long paddr) 40{ 41 int i; 42 43 for (i = 0; i < spider_pci_count; i++) { 44 struct spider_pci_bus *bus = &spider_pci_busses[i]; 45 if (paddr && paddr >= bus->mmio_start && paddr < bus->mmio_end) 46 return bus; 47 if (vaddr && vaddr >= bus->pio_vstart && vaddr < bus->pio_vend) 48 return bus; 49 } 50 return NULL; 51} 52 53static void spider_io_flush(const volatile void __iomem *addr) 54{ 55 struct spider_pci_bus *bus; 56 int token; 57 58 /* Get platform token (set by ioremap) from address */ 59 token = PCI_GET_ADDR_TOKEN(addr); 60 61 if (token && token <= spider_pci_count) 62 bus = &spider_pci_busses[token - 1]; 63 else { 64 unsigned long vaddr, paddr; 65 pte_t *ptep; 66 67 /* Fixup physical address */ 68 vaddr = (unsigned long)PCI_FIX_ADDR(addr); 69 70 /* Check if it's in allowed range for PIO */ 71 if (vaddr < PHBS_IO_BASE || vaddr >= IMALLOC_BASE) 72 return; 73 74 /* Try to find a PTE. If not, clear the paddr, we'll do 75 * a vaddr only lookup (PIO only) 76 */ 77 ptep = find_linux_pte(init_mm.pgd, vaddr); 78 if (ptep == NULL) 79 paddr = 0; 80 else 81 paddr = pte_pfn(*ptep) << PAGE_SHIFT; 82 83 bus = spider_pci_find(vaddr, paddr); 84 if (bus == NULL) 85 return; 86 } 87 88 (void)in_be32(bus->regs + SPIDER_PCI_DUMMY_READ); 89} 90 91static u8 spider_readb(const volatile void __iomem *addr) 92{ 93 u8 val = __do_readb(addr); 94 spider_io_flush(addr); 95 return val; 96} 97 98static u16 spider_readw(const volatile void __iomem *addr) 99{ 100 u16 val = __do_readw(addr); 101 spider_io_flush(addr); 102 return val; 103} 104 105static u32 spider_readl(const volatile void __iomem *addr) 106{ 107 u32 val = __do_readl(addr); 108 spider_io_flush(addr); 109 return val; 110} 111 112static u64 spider_readq(const volatile void __iomem *addr) 113{ 114 u64 val = __do_readq(addr); 115 spider_io_flush(addr); 116 return val; 117} 118 119static u16 spider_readw_be(const volatile void __iomem *addr) 120{ 121 u16 val = __do_readw_be(addr); 122 spider_io_flush(addr); 123 return val; 124} 125 126static u32 spider_readl_be(const volatile void __iomem *addr) 127{ 128 u32 val = __do_readl_be(addr); 129 spider_io_flush(addr); 130 return val; 131} 132 133static u64 spider_readq_be(const volatile void __iomem *addr) 134{ 135 u64 val = __do_readq_be(addr); 136 spider_io_flush(addr); 137 return val; 138} 139 140static void spider_readsb(const volatile void __iomem *addr, void *buf, 141 unsigned long count) 142{ 143 __do_readsb(addr, buf, count); 144 spider_io_flush(addr); 145} 146 147static void spider_readsw(const volatile void __iomem *addr, void *buf, 148 unsigned long count) 149{ 150 __do_readsw(addr, buf, count); 151 spider_io_flush(addr); 152} 153 154static void spider_readsl(const volatile void __iomem *addr, void *buf, 155 unsigned long count) 156{ 157 __do_readsl(addr, buf, count); 158 spider_io_flush(addr); 159} 160 161static void spider_memcpy_fromio(void *dest, const volatile void __iomem *src, 162 unsigned long n) 163{ 164 __do_memcpy_fromio(dest, src, n); 165 spider_io_flush(src); 166} 167 168 169static void __iomem * spider_ioremap(unsigned long addr, unsigned long size, 170 unsigned long flags) 171{ 172 struct spider_pci_bus *bus; 173 void __iomem *res = __ioremap(addr, size, flags); 174 int busno; 175 176 pr_debug("spider_ioremap(0x%lx, 0x%lx, 0x%lx) -> 0x%p\n", 177 addr, size, flags, res); 178 179 bus = spider_pci_find(0, addr); 180 if (bus != NULL) { 181 busno = bus - spider_pci_busses; 182 pr_debug(" found bus %d, setting token\n", busno); 183 PCI_SET_ADDR_TOKEN(res, busno + 1); 184 } 185 pr_debug(" result=0x%p\n", res); 186 187 return res; 188} 189 190static void __init spider_pci_setup_chip(struct spider_pci_bus *bus) 191{ 192#ifdef SPIDER_DISABLE_PREFETCH 193 u32 val = in_be32(bus->regs + SPIDER_PCI_VCI_CNTL_STAT); 194 pr_debug(" PVCI_Control_Status was 0x%08x\n", val); 195 out_be32(bus->regs + SPIDER_PCI_VCI_CNTL_STAT, val | 0x8); 196#endif 197 198 out_be32(bus->regs + SPIDER_PCI_DUMMY_READ_BASE, 0x80000000); 199} 200 201static void __init spider_pci_add_one(struct pci_controller *phb) 202{ 203 struct spider_pci_bus *bus = &spider_pci_busses[spider_pci_count]; 204 struct device_node *np = phb->arch_data; 205 struct resource rsrc; 206 void __iomem *regs; 207 208 if (spider_pci_count >= MAX_SPIDERS) { 209 printk(KERN_ERR "Too many spider bridges, workarounds" 210 " disabled for %s\n", np->full_name); 211 return; 212 } 213 214 /* Get the registers for the beast */ 215 if (of_address_to_resource(np, 0, &rsrc)) { 216 printk(KERN_ERR "Failed to get registers for spider %s" 217 " workarounds disabled\n", np->full_name); 218 return; 219 } 220 221 /* Mask out some useless bits in there to get to the base of the 222 * spider chip 223 */ 224 rsrc.start &= ~0xfffffffful; 225 226 /* Map them */ 227 regs = ioremap(rsrc.start + SPIDER_PCI_REG_BASE, 0x1000); 228 if (regs == NULL) { 229 printk(KERN_ERR "Failed to map registers for spider %s" 230 " workarounds disabled\n", np->full_name); 231 return; 232 } 233 234 spider_pci_count++; 235 236 /* We assume spiders only have one MMIO resource */ 237 bus->mmio_start = phb->mem_resources[0].start; 238 bus->mmio_end = phb->mem_resources[0].end + 1; 239 240 bus->pio_vstart = (unsigned long)phb->io_base_virt; 241 bus->pio_vend = bus->pio_vstart + phb->pci_io_size; 242 243 bus->regs = regs; 244 245 printk(KERN_INFO "PCI: Spider MMIO workaround for %s\n",np->full_name); 246 247 pr_debug(" mmio (P) = 0x%016lx..0x%016lx\n", 248 bus->mmio_start, bus->mmio_end); 249 pr_debug(" pio (V) = 0x%016lx..0x%016lx\n", 250 bus->pio_vstart, bus->pio_vend); 251 pr_debug(" regs (P) = 0x%016lx (V) = 0x%p\n", 252 rsrc.start + SPIDER_PCI_REG_BASE, bus->regs); 253 254 spider_pci_setup_chip(bus); 255} 256 257static struct ppc_pci_io __initdata spider_pci_io = { 258 .readb = spider_readb, 259 .readw = spider_readw, 260 .readl = spider_readl, 261 .readq = spider_readq, 262 .readw_be = spider_readw_be, 263 .readl_be = spider_readl_be, 264 .readq_be = spider_readq_be, 265 .readsb = spider_readsb, 266 .readsw = spider_readsw, 267 .readsl = spider_readsl, 268 .memcpy_fromio = spider_memcpy_fromio, 269}; 270 271static int __init spider_pci_workaround_init(void) 272{ 273 struct pci_controller *phb; 274 275 if (!machine_is(cell)) 276 return 0; 277 278 /* Find spider bridges. We assume they have been all probed 279 * in setup_arch(). If that was to change, we would need to 280 * update this code to cope with dynamically added busses 281 */ 282 list_for_each_entry(phb, &hose_list, list_node) { 283 struct device_node *np = phb->arch_data; 284 const char *model = of_get_property(np, "model", NULL); 285 286 /* If no model property or name isn't exactly "pci", skip */ 287 if (model == NULL || strcmp(np->name, "pci")) 288 continue; 289 /* If model is not "Spider", skip */ 290 if (strcmp(model, "Spider")) 291 continue; 292 spider_pci_add_one(phb); 293 } 294 295 /* No Spider PCI found, exit */ 296 if (spider_pci_count == 0) 297 return 0; 298 299 /* Setup IO callbacks. We only setup MMIO reads. PIO reads will 300 * fallback to MMIO reads (though without a token, thus slower) 301 */ 302 ppc_pci_io = spider_pci_io; 303 304 /* Setup ioremap callback */ 305 ppc_md.ioremap = spider_ioremap; 306 307 return 0; 308} 309arch_initcall(spider_pci_workaround_init); 310