1/* 2 * Low-Level PCI and SB support for BCM47xx (Linux support code) 3 * 4 * Copyright (C) 2011, Broadcom Corporation. All Rights Reserved. 5 * 6 * Permission to use, copy, modify, and/or distribute this software for any 7 * purpose with or without fee is hereby granted, provided that the above 8 * copyright notice and this permission notice appear in all copies. 9 * 10 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES 11 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 12 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY 13 * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 14 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION 15 * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN 16 * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 17 * 18 * $Id: pcibios.c,v 1.11 2011-01-10 23:25:05 $ 19 */ 20 21#include <linux/version.h> 22#include <linux/types.h> 23#include <linux/kernel.h> 24#include <linux/sched.h> 25#include <linux/pci.h> 26#include <linux/init.h> 27#include <linux/delay.h> 28#include <asm/io.h> 29#include <asm/irq.h> 30#include <asm/paccess.h> 31#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 36) 32#include <linux/config.h> 33#endif 34 35#include <typedefs.h> 36#include <bcmutils.h> 37#include <hndsoc.h> 38#include <siutils.h> 39#include <hndcpu.h> 40#include <hndpci.h> 41#include <pcicfg.h> 42#include <bcmdevs.h> 43#include <bcmnvram.h> 44 45/* Global SB handle */ 46extern si_t *bcm947xx_sih; 47extern spinlock_t bcm947xx_sih_lock; 48 49/* Global USB capability */ 50int usb_hsic_cap = 0; 51int usb_hsic_cap_port = 0; 52EXPORT_SYMBOL(usb_hsic_cap); 53EXPORT_SYMBOL(usb_hsic_cap_port); 54 55/* Convenience */ 56#define sih bcm947xx_sih 57#define sih_lock bcm947xx_sih_lock 58 59static int 60sbpci_read_config_reg(struct pci_bus *bus, unsigned int devfn, int where, 61 int size, u32 *value) 62{ 63 unsigned long flags; 64 int ret; 65 66 spin_lock_irqsave(&sih_lock, flags); 67 ret = hndpci_read_config(sih, bus->number, PCI_SLOT(devfn), 68 PCI_FUNC(devfn), where, value, size); 69 spin_unlock_irqrestore(&sih_lock, flags); 70 return ret ? PCIBIOS_DEVICE_NOT_FOUND : PCIBIOS_SUCCESSFUL; 71} 72 73static int 74sbpci_write_config_reg(struct pci_bus *bus, unsigned int devfn, int where, 75 int size, u32 value) 76{ 77 unsigned long flags; 78 int ret; 79 80 spin_lock_irqsave(&sih_lock, flags); 81 ret = hndpci_write_config(sih, bus->number, PCI_SLOT(devfn), 82 PCI_FUNC(devfn), where, &value, size); 83 spin_unlock_irqrestore(&sih_lock, flags); 84 return ret ? PCIBIOS_DEVICE_NOT_FOUND : PCIBIOS_SUCCESSFUL; 85} 86 87static struct pci_ops pcibios_ops = { 88 sbpci_read_config_reg, 89 sbpci_write_config_reg 90}; 91 92static u32 pci_iobase = 0x100; 93static u32 pci_membase = SI_PCI_DMA; 94 95#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,36) 96static struct resource bcm_pci_mem_resource = { 97 .name = "bcm947xx PCI memory space", 98 .start = SI_PCI_MEM /* BCM_PCI_MEM_BASE_PA */, 99 .end = SI_PCI_MEM + SI_PCI_MEM_SZ /* BCM_PCI_MEM_END_PA */, 100 .flags = IORESOURCE_MEM 101}; 102 103static struct resource bcm_pci_io_resource = { 104 .name = "bcm947xx PCI IO space", 105 .start = 0xc0000000 /* BCM_PCI_IO_BASE_PA */, 106 .end = 0xc0001000 /* BCM_PCI_IO_END_PA */, 107 .flags = IORESOURCE_IO 108}; 109 110struct pci_controller bcm947xxcontroller = { 111 .pci_ops = &pcibios_ops, 112 .io_resource = &bcm_pci_io_resource, 113 .mem_resource = &bcm_pci_mem_resource, 114}; 115#endif 116 117void __init 118pcibios_init(void) 119{ 120 ulong flags; 121 122 /* For 4716, use sbtopcie0 to access the device. We 123 * can't use address match 2 (1 GB window) region as MIPS 124 * can not generate 64-bit address on the backplane. 125 */ 126 if (sih->chip == BCM4716_CHIP_ID) { 127 printk(KERN_INFO "PCI: Using membase %x\n", SI_PCI_MEM); 128 pci_membase = SI_PCI_MEM; 129 } 130 131 if (!(sih = si_kattach(SI_OSH))) 132 panic("si_kattach failed"); 133 spin_lock_init(&sih_lock); 134 135 spin_lock_irqsave(&sih_lock, flags); 136 hndpci_init(sih); 137 spin_unlock_irqrestore(&sih_lock, flags); 138 139 set_io_port_base((unsigned long) ioremap_nocache(SI_PCI_MEM, 0x04000000)); 140 141 /* Scan the SB bus */ 142 printk(KERN_INFO "PCI: scanning bus %x\n", 0); 143#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,36) 144 register_pci_controller( &bcm947xxcontroller ); 145 pci_scan_bus(0, &pcibios_ops, &bcm947xxcontroller); 146#else 147 pci_scan_bus(0, &pcibios_ops, NULL); 148#endif 149} 150 151char * __init 152pcibios_setup(char *str) 153{ 154 if (!strncmp(str, "ban=", 4)) { 155 hndpci_ban(simple_strtoul(str + 4, NULL, 0)); 156 return NULL; 157 } 158 159 return (str); 160} 161 162void __devinit 163pcibios_fixup_bus(struct pci_bus *b) 164{ 165 struct list_head *ln; 166 struct pci_dev *d, *dev; 167 struct resource *res; 168 int pos, size; 169 u32 *base; 170 u8 irq; 171 172 printk("PCI: Fixing up bus %d\n", b->number); 173 174 /* Fix up SB */ 175 if (b->number == 0) { 176 for (ln = b->devices.next; ln != &b->devices; ln = ln->next) { 177 d = pci_dev_b(ln); 178 /* Fix up interrupt lines */ 179 pci_read_config_byte(d, PCI_INTERRUPT_LINE, &irq); 180 d->irq = irq + 2; 181 pci_write_config_byte(d, PCI_INTERRUPT_LINE, d->irq); 182 } 183 } else { 184 irq = 0; 185 /* Find the corresponding IRQ of the PCI/PCIe core per bus number */ 186 /* All devices on the bus use the same IRQ as the core */ 187 list_for_each_entry(dev, &((pci_find_bus(0, 0))->devices), bus_list) { 188 if ((dev != NULL) && 189 ((dev->device == PCI_CORE_ID) || 190 (dev->device == PCIE_CORE_ID))) { 191 if (dev->subordinate && dev->subordinate->number == b->number) { 192 irq = dev->irq; 193 break; 194 } 195 } 196 } 197 198 pci_membase = hndpci_get_membase(b->number); 199 /* Fix up external PCI */ 200 for (ln = b->devices.next; ln != &b->devices; ln = ln->next) { 201 bool is_hostbridge; 202 203 d = pci_dev_b(ln); 204 is_hostbridge = hndpci_is_hostbridge(b->number, PCI_SLOT(d->devfn)); 205 /* Fix up resource bases */ 206 for (pos = 0; pos < 6; pos++) { 207 res = &d->resource[pos]; 208 base = (res->flags & IORESOURCE_IO) ? &pci_iobase : &pci_membase; 209 if (res->end) { 210 size = res->end - res->start + 1; 211 if (*base & (size - 1)) 212 *base = (*base + size) & ~(size - 1); 213 res->start = *base; 214 res->end = res->start + size - 1; 215 *base += size; 216 pci_write_config_dword(d, 217 PCI_BASE_ADDRESS_0 + (pos << 2), res->start); 218 } 219 /* Fix up PCI bridge BAR0 only */ 220 if (is_hostbridge) 221 break; 222 } 223 /* Fix up interrupt lines */ 224 d->irq = irq; 225 pci_write_config_byte(d, PCI_INTERRUPT_LINE, d->irq); 226 } 227 hndpci_arb_park(sih, PCI_PARK_NVRAM); 228 } 229} 230 231int 232pcibios_map_irq(const struct pci_dev *dev, u8 slot, u8 pin) 233{ 234 return (dev->irq); 235} 236 237int 238pcibios_enable_resources(struct pci_dev *dev) 239{ 240 u16 cmd, old_cmd; 241 int idx; 242 struct resource *r; 243 244 /* External PCI only */ 245 if (dev->bus->number == 0) 246 return 0; 247 248 pci_read_config_word(dev, PCI_COMMAND, &cmd); 249 old_cmd = cmd; 250 for (idx = 0; idx < 6; idx++) { 251 r = &dev->resource[idx]; 252 if (r->flags & IORESOURCE_IO) 253 cmd |= PCI_COMMAND_IO; 254 if (r->flags & IORESOURCE_MEM) 255 cmd |= PCI_COMMAND_MEMORY; 256 } 257 if (dev->resource[PCI_ROM_RESOURCE].start) 258 cmd |= PCI_COMMAND_MEMORY; 259 if (cmd != old_cmd) { 260 printk("PCI: Enabling device %s (%04x -> %04x)\n", pci_name(dev), old_cmd, cmd); 261 pci_write_config_word(dev, PCI_COMMAND, cmd); 262 } 263 return 0; 264} 265 266int 267pcibios_enable_device(struct pci_dev *dev, int mask) 268{ 269 ulong flags; 270 uint coreidx, coreid; 271 void *regs; 272 int rc = -1; 273 274 /* External PCI device enable */ 275 if (dev->bus->number != 0) 276 return pcibios_enable_resources(dev); 277 278 /* These cores come out of reset enabled */ 279 if (dev->device == MIPS_CORE_ID || 280 dev->device == MIPS33_CORE_ID || 281 dev->device == CC_CORE_ID) 282 return 0; 283 284 spin_lock_irqsave(&sih_lock, flags); 285 286 regs = si_setcoreidx(sih, PCI_SLOT(dev->devfn)); 287 coreidx = si_coreidx(sih); 288 coreid = si_coreid(sih); 289 290 if (!regs) { 291 printk(KERN_ERR "WARNING! PCIBIOS_DEVICE_NOT_FOUND\n"); 292 goto out; 293 } 294 295 /* 296 * The USB core requires a special bit to be set during core 297 * reset to enable host (OHCI) mode. Resetting the SB core in 298 * pcibios_enable_device() is a hack for compatibility with 299 * vanilla usb-ohci so that it does not have to know about 300 * SB. A driver that wants to use the USB core in device mode 301 * should know about SB and should reset the bit back to 0 302 * after calling pcibios_enable_device(). 303 */ 304 if (coreid == USB_CORE_ID) { 305 si_core_disable(sih, si_core_cflags(sih, 0, 0)); 306 si_core_reset(sih, 1 << 29, 0); 307 } 308 /* 309 * USB 2.0 special considerations: 310 * 311 * 1. Since the core supports both OHCI and EHCI functions, it must 312 * only be reset once. 313 * 314 * 2. In addition to the standard SB reset sequence, the Host Control 315 * Register must be programmed to bring the USB core and various 316 * phy components out of reset. 317 */ 318 else if (coreid == USB20H_CORE_ID) { 319 if (!si_iscoreup(sih)) { 320 si_core_reset(sih, 0, 0); 321 mdelay(10); 322 if (si_corerev(sih) >= 5) { 323 uint32 tmp; 324 /* Enable Misc PLL */ 325 tmp = readl(regs + 0x1e0); 326 tmp |= 0x100; 327 writel(tmp, regs + 0x1e0); 328 SPINWAIT((((tmp = readl(regs + 0x1e0)) & (1 << 24)) 329 == 0), 1000); 330 /* Take out of resets */ 331 writel(0x4ff, regs + 0x200); 332 udelay(25); 333 writel(0x6ff, regs + 0x200); 334 udelay(25); 335 336 /* Make sure digital and AFE are locked in USB PHY */ 337 writel(0x6b, regs + 0x524); 338 udelay(50); 339 tmp = readl(regs + 0x524); 340 udelay(50); 341 writel(0xab, regs + 0x524); 342 udelay(50); 343 tmp = readl(regs + 0x524); 344 udelay(50); 345 writel(0x2b, regs + 0x524); 346 udelay(50); 347 tmp = readl(regs + 0x524); 348 udelay(50); 349 writel(0x10ab, regs + 0x524); 350 udelay(50); 351 tmp = readl(regs + 0x524); 352 SPINWAIT((((tmp = readl(regs + 0x528)) & 0xc000) != 353 0xc000), 100000); 354 if ((tmp & 0xc000) != 0xc000) { 355 printk(KERN_WARNING "WARNING! USB20H mdio_rddata 0x%08x\n", tmp); 356 goto out; 357 } 358 writel(0x80000000, regs + 0x528); 359 tmp = readl(regs + 0x314); 360 udelay(265); 361 writel(0x7ff, regs + 0x200); 362 udelay(10); 363 364 /* Take USB and HSIC out of non-driving modes */ 365 writel(0, regs + 0x510); 366 } else { 367 writel(0x7ff, regs + 0x200); 368 udelay(1); 369 } 370 } 371 /* PRxxxx: War for 5354 failures. */ 372 if (si_corerev(sih) == 1) { 373 uint32 tmp; 374 375 /* Change Flush control reg */ 376 tmp = readl(regs + 0x400); 377 tmp &= ~8; 378 writel(tmp, regs + 0x400); 379 tmp = readl(regs + 0x400); 380 printk(KERN_DEBUG "USB20H fcr: 0x%x\n", tmp); 381 382 /* Change Shim control reg */ 383 tmp = readl(regs + 0x304); 384 tmp &= ~0x100; 385 writel(tmp, regs + 0x304); 386 tmp = readl(regs + 0x304); 387 printk(KERN_DEBUG "USB20H shim cr: 0x%x\n", tmp); 388 } 389 if (si_corerev(sih) == 5) { 390 usb_hsic_cap = 1; 391 usb_hsic_cap_port = 2; 392 } 393 } else { 394 si_core_reset(sih, 0, 0); 395 } 396 397 /* Initialize USBHC core OK */ 398 rc = 0; 399out: 400 si_setcoreidx(sih, coreidx); 401 spin_unlock_irqrestore(&sih_lock, flags); 402 403 /* Reset the device */ 404 if (coreid == USB20H_CORE_ID || coreid == USB_CORE_ID) { 405 int wombo_reset = GPIO_PIN_NOTDEFINED; 406 407 if ((wombo_reset = getgpiopin(NULL, "wombo_reset", GPIO_PIN_NOTDEFINED)) != 408 GPIO_PIN_NOTDEFINED) { 409 int reset = 1 << wombo_reset; 410 411 printk("wombo_reset set to gpio %d\n", wombo_reset); 412 413 si_gpioout(sih, reset, 0, GPIO_DRV_PRIORITY); 414 si_gpioouten(sih, reset, reset, GPIO_DRV_PRIORITY); 415 mdelay(50); 416 417 si_gpioout(sih, reset, reset, GPIO_DRV_PRIORITY); 418 mdelay(20); 419 } 420 } 421 422 return rc; 423} 424 425void 426pcibios_update_resource(struct pci_dev *dev, struct resource *root, 427 struct resource *res, int resource) 428{ 429 unsigned long where, size; 430 u32 reg; 431 432 /* External PCI only */ 433 if (dev->bus->number == 0) 434 return; 435 436 where = PCI_BASE_ADDRESS_0 + (resource * 4); 437 size = res->end - res->start; 438 pci_read_config_dword(dev, where, ®); 439 reg = (reg & size) | (((u32)(res->start - root->start)) & ~size); 440 pci_write_config_dword(dev, where, reg); 441} 442 443static void __init 444quirk_sbpci_bridge(struct pci_dev *dev) 445{ 446 if (dev->bus->number == 0 || 447 !hndpci_is_hostbridge(dev->bus->number, PCI_SLOT(dev->devfn))) 448 return; 449 450 printk("PCI: Fixing up bridge\n"); 451 452 /* Enable PCI bridge bus mastering and memory space */ 453 pci_set_master(dev); 454 pcibios_enable_resources(dev); 455 456 /* Enable PCI bridge BAR1 prefetch and burst */ 457 pci_write_config_dword(dev, PCI_BAR1_CONTROL, 3); 458} 459 460DECLARE_PCI_FIXUP_HEADER(PCI_ANY_ID, PCI_ANY_ID, quirk_sbpci_bridge); 461