3 Copyright 2002 Broadcom Corp. All Rights Reserved.
5 This program is free software; you can distribute it and/or modify it
6 under the terms of the GNU General Public License (Version 2) as
7 published by the Free Software Foundation.
9 This program is distributed in the hope it will be useful, but WITHOUT
10 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
11 FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
14 You should have received a copy of the GNU General Public License along
15 with this program; if not, write to the Free Software Foundation, Inc.,
16 59 Temple Place - Suite 330, Boston MA 02111-1307, USA.
19 #include <linux/types.h>
20 #include <linux/pci.h>
21 #include <linux/kernel.h>
22 #include <linux/init.h>
23 #include <asm/addrspace.h>
26 #include <bcm_map_part.h>
29 #include <linux/delay.h>
31 #if defined(CONFIG_USB)
33 #define DPRINT(x...) printk(x)
39 pci63xx_int_read(unsigned int devfn, int where, u32 * value, int size);
41 pci63xx_int_write(unsigned int devfn, int where, u32 * value, int size);
43 static bool usb_mem_size_rd = FALSE;
44 static uint32 usb_mem_base = 0;
45 static uint32 usb_cfg_space_cmd_reg = 0;
47 static bool pci_mem_size_rd = FALSE;
49 static volatile MpiRegisters * mpi = (MpiRegisters *)(MPI_BASE);
51 static void mpi_SetupPciConfigAccess(uint32 addr)
53 mpi->l2pcfgctl = (DIR_CFG_SEL | DIR_CFG_USEREG | addr) & ~CONFIG_TYPE;
56 static void mpi_ClearPciConfigAccess(void)
58 mpi->l2pcfgctl = 0x00000000;
61 #if defined(CONFIG_USB)
62 /* --------------------------------------------------------------------------
63 Name: pci63xx_int_write
64 Abstract: PCI Config write on internal device(s)
65 -------------------------------------------------------------------------- */
67 pci63xx_int_write(unsigned int devfn, int where, u32 * value, int size)
69 if (PCI_SLOT(devfn) != USB_HOST_SLOT) {
70 return PCIBIOS_SUCCESSFUL;
75 DPRINT("W => Slot: %d Where: %2X Len: %d Data: %02X\n",
76 PCI_SLOT(devfn), where, size, *value);
79 DPRINT("W => Slot: %d Where: %2X Len: %d Data: %04X\n",
80 PCI_SLOT(devfn), where, size, *value);
83 usb_cfg_space_cmd_reg = *value;
90 DPRINT("W => Slot: %d Where: %2X Len: %d Data: %08lX\n",
91 PCI_SLOT(devfn), where, size, *value);
93 case PCI_BASE_ADDRESS_0:
94 if (*value == 0xffffffff) {
95 usb_mem_size_rd = TRUE;
97 usb_mem_base = *value;
108 return PCIBIOS_SUCCESSFUL;
111 /* --------------------------------------------------------------------------
112 Name: pci63xx_int_read
113 Abstract: PCI Config read on internal device(s)
114 -------------------------------------------------------------------------- */
116 pci63xx_int_read(unsigned int devfn, int where, u32 * value, int size)
118 uint32 retValue = 0xFFFFFFFF;
120 if (PCI_SLOT(devfn) != USB_HOST_SLOT) {
121 return PCIBIOS_SUCCESSFUL;
124 // For now, this is specific to the USB Host controller. We can
125 // make it more general if we have to...
126 // Emulate PCI Config accesses
130 retValue = PCI_VENDOR_ID_BROADCOM | 0x63000000;
134 retValue = (0x0006 << 16) | usb_cfg_space_cmd_reg;
136 case PCI_CLASS_REVISION:
137 case PCI_CLASS_DEVICE:
138 retValue = (PCI_CLASS_SERIAL_USB << 16) | (0x10 << 8) | 0x01;
140 case PCI_BASE_ADDRESS_0:
141 if (usb_mem_size_rd) {
142 retValue = USB_BAR0_MEM_SIZE;
144 if (usb_mem_base != 0)
145 retValue = usb_mem_base;
147 retValue = USB_HOST_BASE;
149 usb_mem_size_rd = FALSE;
151 case PCI_CACHE_LINE_SIZE:
152 case PCI_LATENCY_TIMER:
155 case PCI_HEADER_TYPE:
156 retValue = PCI_HEADER_TYPE_NORMAL;
158 case PCI_SUBSYSTEM_VENDOR_ID:
159 retValue = PCI_VENDOR_ID_BROADCOM;
161 case PCI_SUBSYSTEM_ID:
164 case PCI_INTERRUPT_LINE:
165 retValue = INTERRUPT_ID_USBH;
173 *value = (retValue >> ((where & 3) << 3)) & 0xff;
174 DPRINT("R <= Slot: %d Where: %2X Len: %d Data: %02X\n",
175 PCI_SLOT(devfn), where, size, *value);
178 *value = (retValue >> ((where & 3) << 3)) & 0xffff;
179 DPRINT("R <= Slot: %d Where: %2X Len: %d Data: %04X\n",
180 PCI_SLOT(devfn), where, size, *value);
184 DPRINT("R <= Slot: %d Where: %2X Len: %d Data: %08lX\n",
185 PCI_SLOT(devfn), where, size, *value);
191 return PCIBIOS_SUCCESSFUL;
195 static int bcm96348_pcibios_read(struct pci_bus *bus, unsigned int devfn,
196 int where, int size, u32 * val)
198 volatile unsigned char *ioBase = (unsigned char *)(mpi->l2piobase | KSEG1);
201 #if defined(CONFIG_USB)
202 if (PCI_SLOT(devfn) == USB_HOST_SLOT)
203 return pci63xx_int_read(devfn, where, val, size);
206 mpi_SetupPciConfigAccess(BCM_PCI_CFG(PCI_SLOT(devfn), PCI_FUNC(devfn), where));
207 data = *(uint32 *)ioBase;
210 *val = (data >> ((where & 3) << 3)) & 0xff;
213 *val = (data >> ((where & 3) << 3)) & 0xffff;
217 /* Special case for reading PCI device range */
218 if ((where >= PCI_BASE_ADDRESS_0) && (where <= PCI_BASE_ADDRESS_5)) {
219 if (pci_mem_size_rd) {
220 /* bcm6348 PCI memory window minimum size is 64K */
221 *val &= PCI_SIZE_64K;
228 pci_mem_size_rd = FALSE;
229 mpi_ClearPciConfigAccess();
231 return PCIBIOS_SUCCESSFUL;
234 static int bcm96348_pcibios_write(struct pci_bus *bus, unsigned int devfn,
235 int where, int size, u32 val)
237 volatile unsigned char *ioBase = (unsigned char *)(mpi->l2piobase | KSEG1);
240 #if defined(CONFIG_USB)
241 if (PCI_SLOT(devfn) == USB_HOST_SLOT)
242 return pci63xx_int_write(devfn, where, &val, size);
244 mpi_SetupPciConfigAccess(BCM_PCI_CFG(PCI_SLOT(devfn), PCI_FUNC(devfn), where));
245 data = *(uint32 *)ioBase;
248 data = (data & ~(0xff << ((where & 3) << 3))) |
249 (val << ((where & 3) << 3));
252 data = (data & ~(0xffff << ((where & 3) << 3))) |
253 (val << ((where & 3) << 3));
257 /* Special case for reading PCI device range */
258 if ((where >= PCI_BASE_ADDRESS_0) && (where <= PCI_BASE_ADDRESS_5)) {
259 if (val == 0xffffffff)
260 pci_mem_size_rd = TRUE;
266 *(uint32 *)ioBase = data;
268 mpi_ClearPciConfigAccess();
270 return PCIBIOS_SUCCESSFUL;
273 struct pci_ops bcm96348_pci_ops = {
274 .read = bcm96348_pcibios_read,
275 .write = bcm96348_pcibios_write