2 * Low-Level PCI and SB support for BCM47xx (Linux support code)
4 * Copyright (C) 2010, Broadcom Corporation. All Rights Reserved.
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.
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>
30 #include <asm/paccess.h>
42 /* Global SB handle */
43 extern si_t
*bcm947xx_sih
;
44 extern spinlock_t bcm947xx_sih_lock
;
46 /* Global USB capability */
48 int usb_hsic_cap_port
= 0;
49 EXPORT_SYMBOL(usb_hsic_cap
);
50 EXPORT_SYMBOL(usb_hsic_cap_port
);
53 #define sih bcm947xx_sih
54 #define sih_lock bcm947xx_sih_lock
57 sbpci_read_config_reg(struct pci_bus
*bus
, unsigned int devfn
, int where
,
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
;
71 sbpci_write_config_reg(struct pci_bus
*bus
, unsigned int devfn
, int where
,
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
;
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
);
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
);
121 pcibios_setup(char *str
)
123 if (!strncmp(str
, "ban=", 4)) {
124 hndpci_ban(simple_strtoul(str
+ 4, NULL
, 0));
132 pcibios_fixup_bus(struct pci_bus
*b
)
134 struct list_head
*ln
;
135 struct pci_dev
*d
, *dev
;
136 struct resource
*res
;
141 printk("PCI: Fixing up bus %d\n", b
->number
);
144 if (b
->number
== 0) {
145 for (ln
= b
->devices
.next
; ln
!= &b
->devices
; ln
= ln
->next
) {
147 /* Fix up interrupt lines */
148 pci_read_config_byte(d
, PCI_INTERRUPT_LINE
, &irq
);
150 pci_write_config_byte(d
, PCI_INTERRUPT_LINE
, d
->irq
);
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
) {
158 ((dev
->device
== PCI_CORE_ID
) ||
159 (dev
->device
== PCIE_CORE_ID
))) {
160 if (dev
->subordinate
&& dev
->subordinate
->number
== b
->number
) {
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
) {
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
;
179 size
= res
->end
- res
->start
+ 1;
180 if (*base
& (size
- 1))
181 *base
= (*base
+ size
) & ~(size
- 1);
183 res
->end
= res
->start
+ size
- 1;
185 pci_write_config_dword(d
,
186 PCI_BASE_ADDRESS_0
+ (pos
<< 2), res
->start
);
188 /* Fix up PCI bridge BAR0 only */
192 /* Fix up interrupt lines */
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
)
207 pcibios_enable_resources(struct pci_dev
*dev
)
213 /* External PCI only */
214 if (dev
->bus
->number
== 0)
217 pci_read_config_word(dev
, PCI_COMMAND
, &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
);
236 pcibios_enable_device(struct pci_dev
*dev
, int mask
)
239 uint coreidx
, coreid
;
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
)
253 spin_lock_irqsave(&sih_lock
, flags
);
254 coreidx
= si_coreidx(sih
);
255 regs
= si_setcoreidx(sih
, PCI_SLOT(dev
->devfn
));
257 printk("WARNING! PCIBIOS_DEVICE_NOT_FOUND\n");
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);
288 if (si_corerev(sih
) >= 5) {
290 /* Enable Misc PLL */
291 tmp
= readl(regs
+ 0x1e0);
293 writel(tmp
, regs
+ 0x1e0);
294 SPINWAIT((((tmp
= readl(regs
+ 0x1e0)) & (1 << 24))
296 /* Take out of resets */
297 writel(0x4ff, regs
+ 0x200);
299 writel(0x6ff, regs
+ 0x200);
302 /* Make sure digital and AFE are locked in USB PHY */
303 writel(0x6b, regs
+ 0x524);
305 tmp
= readl(regs
+ 0x524);
307 writel(0xab, regs
+ 0x524);
309 tmp
= readl(regs
+ 0x524);
311 writel(0x2b, regs
+ 0x524);
313 tmp
= readl(regs
+ 0x524);
315 writel(0x10ab, regs
+ 0x524);
317 tmp
= readl(regs
+ 0x524);
318 SPINWAIT((((tmp
= readl(regs
+ 0x528)) & 0xc000) !=
320 if ((tmp
& 0xc000) != 0xc000) {
321 printk("WARNING! USB20H mdio_rddata 0x%08x\n", tmp
);
324 writel(0x80000000, regs
+ 0x528);
325 tmp
= readl(regs
+ 0x314);
327 writel(0x7ff, regs
+ 0x200);
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);
335 /* make sure pll lock is on */
336 if (!(tmp
& 0x1000000)) {
339 writel(0x7ff, regs
+ 0x200);
342 writel(0x7ff, regs
+ 0x200);
346 /* PRxxxx: War for 5354 failures. */
347 if (si_corerev(sih
) == 1) {
350 /* Change Flush control reg */
351 tmp
= readl(regs
+ 0x400);
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);
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) {
366 usb_hsic_cap_port
= 2;
369 si_core_reset(sih
, 0, 0);
371 /* Initialize USBHC core OK */
374 si_setcoreidx(sih
, coreidx
);
375 spin_unlock_irqrestore(&sih_lock
, flags
);
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
);
388 si_gpioout(sih
, reset
, reset
, GPIO_DRV_PRIORITY
);
397 pcibios_update_resource(struct pci_dev
*dev
, struct resource
*root
,
398 struct resource
*res
, int resource
)
400 unsigned long where
, size
;
403 /* External PCI only */
404 if (dev
->bus
->number
== 0)
407 where
= PCI_BASE_ADDRESS_0
+ (resource
* 4);
408 size
= res
->end
- res
->start
;
409 pci_read_config_dword(dev
, where
, ®
);
410 reg
= (reg
& size
) | (((u32
)(res
->start
- root
->start
)) & ~size
);
411 pci_write_config_dword(dev
, where
, reg
);
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
)))
421 printk("PCI: Fixing up bridge\n");
423 /* Enable PCI bridge bus mastering and memory space */
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
);