New routers supported
[tomato.git] / release / src-rt / linux / linux-2.6 / arch / mips / brcm-boards / bcm947xx / pcibios.c
blob674a13011605f74b219cf0851d297422d7ed0e92
1 /*
2 * Low-Level PCI and SB support for BCM47xx (Linux support code)
4 * Copyright (C) 2010, 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.
18 * $Id: pcibios.c,v 1.11 2011-01-10 23:25:05 Exp $
21 #include <linux/config.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>
32 #include <typedefs.h>
33 #include <bcmutils.h>
34 #include <hndsoc.h>
35 #include <siutils.h>
36 #include <hndcpu.h>
37 #include <hndpci.h>
38 #include <pcicfg.h>
39 #include <bcmdevs.h>
40 #include <bcmnvram.h>
42 /* Global SB handle */
43 extern si_t *bcm947xx_sih;
44 extern spinlock_t bcm947xx_sih_lock;
46 /* Global USB capability */
47 int usb_hsic_cap = 0;
48 int usb_hsic_cap_port = 0;
49 EXPORT_SYMBOL(usb_hsic_cap);
50 EXPORT_SYMBOL(usb_hsic_cap_port);
52 /* Convenience */
53 #define sih bcm947xx_sih
54 #define sih_lock bcm947xx_sih_lock
56 static int
57 sbpci_read_config_reg(struct pci_bus *bus, unsigned int devfn, int where,
58 int size, u32 *value)
60 unsigned long flags;
61 int ret;
63 spin_lock_irqsave(&sih_lock, flags);
64 ret = hndpci_read_config(sih, bus->number, PCI_SLOT(devfn),
65 PCI_FUNC(devfn), where, value, size);
66 spin_unlock_irqrestore(&sih_lock, flags);
67 return ret ? PCIBIOS_DEVICE_NOT_FOUND : PCIBIOS_SUCCESSFUL;
70 static int
71 sbpci_write_config_reg(struct pci_bus *bus, unsigned int devfn, int where,
72 int size, u32 value)
74 unsigned long flags;
75 int ret;
77 spin_lock_irqsave(&sih_lock, flags);
78 ret = hndpci_write_config(sih, bus->number, PCI_SLOT(devfn),
79 PCI_FUNC(devfn), where, &value, size);
80 spin_unlock_irqrestore(&sih_lock, flags);
81 return ret ? PCIBIOS_DEVICE_NOT_FOUND : PCIBIOS_SUCCESSFUL;
84 static struct pci_ops pcibios_ops = {
85 sbpci_read_config_reg,
86 sbpci_write_config_reg
89 static u32 pci_iobase = 0x100;
90 static u32 pci_membase = SI_PCI_DMA;
92 void __init
93 pcibios_init(void)
95 ulong flags;
97 /* For 4716, use sbtopcie0 to access the device. We
98 * can't use address match 2 (1 GB window) region as MIPS
99 * can not generate 64-bit address on the backplane.
101 if (sih->chip == BCM4716_CHIP_ID) {
102 printk("PCI: Using membase %x\n", SI_PCI_MEM);
103 pci_membase = SI_PCI_MEM;
106 if (!(sih = si_kattach(SI_OSH)))
107 panic("si_kattach failed");
108 spin_lock_init(&sih_lock);
110 spin_lock_irqsave(&sih_lock, flags);
111 hndpci_init(sih);
112 spin_unlock_irqrestore(&sih_lock, flags);
114 set_io_port_base((unsigned long) ioremap_nocache(SI_PCI_MEM, 0x04000000));
116 /* Scan the SB bus */
117 pci_scan_bus(0, &pcibios_ops, NULL);
120 char * __init
121 pcibios_setup(char *str)
123 if (!strncmp(str, "ban=", 4)) {
124 hndpci_ban(simple_strtoul(str + 4, NULL, 0));
125 return NULL;
128 return (str);
131 void __init
132 pcibios_fixup_bus(struct pci_bus *b)
134 struct list_head *ln;
135 struct pci_dev *d, *dev;
136 struct resource *res;
137 int pos, size;
138 u32 *base;
139 u8 irq;
141 printk("PCI: Fixing up bus %d\n", b->number);
143 /* Fix up SB */
144 if (b->number == 0) {
145 for (ln = b->devices.next; ln != &b->devices; ln = ln->next) {
146 d = pci_dev_b(ln);
147 /* Fix up interrupt lines */
148 pci_read_config_byte(d, PCI_INTERRUPT_LINE, &irq);
149 d->irq = irq + 2;
150 pci_write_config_byte(d, PCI_INTERRUPT_LINE, d->irq);
152 } else {
153 irq = 0;
154 /* Find the corresponding IRQ of the PCI/PCIe core per bus number */
155 /* All devices on the bus use the same IRQ as the core */
156 list_for_each_entry(dev, &((pci_find_bus(0, 0))->devices), bus_list) {
157 if ((dev != NULL) &&
158 ((dev->device == PCI_CORE_ID) ||
159 (dev->device == PCIE_CORE_ID))) {
160 if (dev->subordinate && dev->subordinate->number == b->number) {
161 irq = dev->irq;
162 break;
167 pci_membase = hndpci_get_membase(b->number);
168 /* Fix up external PCI */
169 for (ln = b->devices.next; ln != &b->devices; ln = ln->next) {
170 bool is_hostbridge;
172 d = pci_dev_b(ln);
173 is_hostbridge = hndpci_is_hostbridge(b->number, PCI_SLOT(d->devfn));
174 /* Fix up resource bases */
175 for (pos = 0; pos < 6; pos++) {
176 res = &d->resource[pos];
177 base = (res->flags & IORESOURCE_IO) ? &pci_iobase : &pci_membase;
178 if (res->end) {
179 size = res->end - res->start + 1;
180 if (*base & (size - 1))
181 *base = (*base + size) & ~(size - 1);
182 res->start = *base;
183 res->end = res->start + size - 1;
184 *base += size;
185 pci_write_config_dword(d,
186 PCI_BASE_ADDRESS_0 + (pos << 2), res->start);
188 /* Fix up PCI bridge BAR0 only */
189 if (is_hostbridge)
190 break;
192 /* Fix up interrupt lines */
193 d->irq = irq;
194 pci_write_config_byte(d, PCI_INTERRUPT_LINE, d->irq);
196 hndpci_arb_park(sih, PCI_PARK_NVRAM);
201 pcibios_map_irq(struct pci_dev *dev, u8 slot, u8 pin)
203 return (dev->irq);
207 pcibios_enable_resources(struct pci_dev *dev)
209 u16 cmd, old_cmd;
210 int idx;
211 struct resource *r;
213 /* External PCI only */
214 if (dev->bus->number == 0)
215 return 0;
217 pci_read_config_word(dev, PCI_COMMAND, &cmd);
218 old_cmd = cmd;
219 for (idx = 0; idx < 6; idx++) {
220 r = &dev->resource[idx];
221 if (r->flags & IORESOURCE_IO)
222 cmd |= PCI_COMMAND_IO;
223 if (r->flags & IORESOURCE_MEM)
224 cmd |= PCI_COMMAND_MEMORY;
226 if (dev->resource[PCI_ROM_RESOURCE].start)
227 cmd |= PCI_COMMAND_MEMORY;
228 if (cmd != old_cmd) {
229 printk("PCI: Enabling device %s (%04x -> %04x)\n", pci_name(dev), old_cmd, cmd);
230 pci_write_config_word(dev, PCI_COMMAND, cmd);
232 return 0;
236 pcibios_enable_device(struct pci_dev *dev, int mask)
238 ulong flags;
239 uint coreidx, coreid;
240 void *regs;
241 int rc = -1;
243 /* External PCI device enable */
244 if (dev->bus->number != 0)
245 return pcibios_enable_resources(dev);
247 /* These cores come out of reset enabled */
248 if (dev->device == MIPS_CORE_ID ||
249 dev->device == MIPS33_CORE_ID ||
250 dev->device == CC_CORE_ID)
251 return 0;
253 spin_lock_irqsave(&sih_lock, flags);
254 coreidx = si_coreidx(sih);
255 regs = si_setcoreidx(sih, PCI_SLOT(dev->devfn));
256 if (!regs) {
257 printk("WARNING! PCIBIOS_DEVICE_NOT_FOUND\n");
258 goto out;
262 * The USB core requires a special bit to be set during core
263 * reset to enable host (OHCI) mode. Resetting the SB core in
264 * pcibios_enable_device() is a hack for compatibility with
265 * vanilla usb-ohci so that it does not have to know about
266 * SB. A driver that wants to use the USB core in device mode
267 * should know about SB and should reset the bit back to 0
268 * after calling pcibios_enable_device().
270 if ((coreid = si_coreid(sih)) == USB_CORE_ID) {
271 si_core_disable(sih, si_core_cflags(sih, 0, 0));
272 si_core_reset(sih, 1 << 29, 0);
275 * USB 2.0 special considerations:
277 * 1. Since the core supports both OHCI and EHCI functions, it must
278 * only be reset once.
280 * 2. In addition to the standard SB reset sequence, the Host Control
281 * Register must be programmed to bring the USB core and various
282 * phy components out of reset.
284 else if (coreid == USB20H_CORE_ID) {
285 if (!si_iscoreup(sih)) {
286 si_core_reset(sih, 0, 0);
287 mdelay(10);
288 if (si_corerev(sih) >= 5) {
289 uint32 tmp;
290 /* Enable Misc PLL */
291 tmp = readl(regs + 0x1e0);
292 tmp |= 0x100;
293 writel(tmp, regs + 0x1e0);
294 SPINWAIT((((tmp = readl(regs + 0x1e0)) & (1 << 24))
295 == 0), 1000);
296 /* Take out of resets */
297 writel(0x4ff, regs + 0x200);
298 udelay(25);
299 writel(0x6ff, regs + 0x200);
300 udelay(25);
302 /* Make sure digital and AFE are locked in USB PHY */
303 writel(0x6b, regs + 0x524);
304 udelay(50);
305 tmp = readl(regs + 0x524);
306 udelay(50);
307 writel(0xab, regs + 0x524);
308 udelay(50);
309 tmp = readl(regs + 0x524);
310 udelay(50);
311 writel(0x2b, regs + 0x524);
312 udelay(50);
313 tmp = readl(regs + 0x524);
314 udelay(50);
315 writel(0x10ab, regs + 0x524);
316 udelay(50);
317 tmp = readl(regs + 0x524);
318 SPINWAIT((((tmp = readl(regs + 0x528)) & 0xc000) !=
319 0xc000), 100000);
320 if ((tmp & 0xc000) != 0xc000) {
321 printk("WARNING! USB20H mdio_rddata 0x%08x\n", tmp);
322 goto out;
324 writel(0x80000000, regs + 0x528);
325 tmp = readl(regs + 0x314);
326 udelay(265);
327 writel(0x7ff, regs + 0x200);
328 udelay(10);
330 /* Take USB and HSIC out of non-driving modes */
331 writel(0, regs + 0x510);
332 } else if (si_corerev(sih) >= 3) {
333 uint32 tmp = readl(regs + 0x50c);
334 udelay(50);
335 /* make sure pll lock is on */
336 if (!(tmp & 0x1000000)) {
337 goto out;
339 writel(0x7ff, regs + 0x200);
340 udelay(1);
341 } else {
342 writel(0x7ff, regs + 0x200);
343 udelay(1);
346 /* PRxxxx: War for 5354 failures. */
347 if (si_corerev(sih) == 1) {
348 uint32 tmp;
350 /* Change Flush control reg */
351 tmp = readl(regs + 0x400);
352 tmp &= ~8;
353 writel(tmp, regs + 0x400);
354 tmp = readl(regs + 0x400);
355 printk("USB20H fcr: 0x%x\n", tmp);
357 /* Change Shim control reg */
358 tmp = readl(regs + 0x304);
359 tmp &= ~0x100;
360 writel(tmp, regs + 0x304);
361 tmp = readl(regs + 0x304);
362 printk("USB20H shim cr: 0x%x\n", tmp);
364 if (si_corerev(sih) == 5) {
365 usb_hsic_cap = 1;
366 usb_hsic_cap_port = 2;
368 } else
369 si_core_reset(sih, 0, 0);
371 /* Initialize USBHC core OK */
372 rc = 0;
373 out:
374 si_setcoreidx(sih, coreidx);
375 spin_unlock_irqrestore(&sih_lock, flags);
377 #if 0
378 /* Reset the device */
379 if (coreid == USB20H_CORE_ID || coreid == USB_CORE_ID) {
380 int wombo_reset = GPIO_PIN_NOTDEFINED;
381 if ((wombo_reset = getgpiopin(NULL, "wombo_reset", GPIO_PIN_NOTDEFINED)) !=
382 GPIO_PIN_NOTDEFINED) {
383 int reset = 1 << wombo_reset;
384 printk("wombo_reset set to gpio %d\n", wombo_reset);
385 si_gpioout(sih, reset, 0, GPIO_DRV_PRIORITY);
386 si_gpioouten(sih, reset, reset, GPIO_DRV_PRIORITY);
387 mdelay(50);
388 si_gpioout(sih, reset, reset, GPIO_DRV_PRIORITY);
389 mdelay(20);
392 #endif
393 return rc;
396 void
397 pcibios_update_resource(struct pci_dev *dev, struct resource *root,
398 struct resource *res, int resource)
400 unsigned long where, size;
401 u32 reg;
403 /* External PCI only */
404 if (dev->bus->number == 0)
405 return;
407 where = PCI_BASE_ADDRESS_0 + (resource * 4);
408 size = res->end - res->start;
409 pci_read_config_dword(dev, where, &reg);
410 reg = (reg & size) | (((u32)(res->start - root->start)) & ~size);
411 pci_write_config_dword(dev, where, reg);
414 static void __init
415 quirk_sbpci_bridge(struct pci_dev *dev)
417 if (dev->bus->number == 0 ||
418 !hndpci_is_hostbridge(dev->bus->number, PCI_SLOT(dev->devfn)))
419 return;
421 printk("PCI: Fixing up bridge\n");
423 /* Enable PCI bridge bus mastering and memory space */
424 pci_set_master(dev);
425 pcibios_enable_resources(dev);
427 /* Enable PCI bridge BAR1 prefetch and burst */
428 pci_write_config_dword(dev, PCI_BAR1_CONTROL, 3);
431 DECLARE_PCI_FIXUP_HEADER(PCI_ANY_ID, PCI_ANY_ID, quirk_sbpci_bridge);