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>
27 #include <6348_intr.h>
28 #include <6348_map_part.h>
31 #include <linux/delay.h>
33 #if defined(CONFIG_USB)
35 #define DPRINT(x...) printk(x)
41 pci63xx_int_read(unsigned int devfn, int where, u32 * value, int size);
43 pci63xx_int_write(unsigned int devfn, int where, u32 * value, int size);
45 static bool usb_mem_size_rd = FALSE;
46 static uint32 usb_mem_base = 0;
47 static uint32 usb_cfg_space_cmd_reg = 0;
49 static bool pci_mem_size_rd = FALSE;
51 static volatile MpiRegisters * mpi = (MpiRegisters *)(MPI_BASE);
53 static void mpi_SetupPciConfigAccess(uint32 addr)
55 mpi->l2pcfgctl = (DIR_CFG_SEL | DIR_CFG_USEREG | addr) & ~CONFIG_TYPE;
58 static void mpi_ClearPciConfigAccess(void)
60 mpi->l2pcfgctl = 0x00000000;
63 #if defined(CONFIG_USB)
64 /* --------------------------------------------------------------------------
65 Name: pci63xx_int_write
66 Abstract: PCI Config write on internal device(s)
67 -------------------------------------------------------------------------- */
69 pci63xx_int_write(unsigned int devfn, int where, u32 * value, int size)
71 if (PCI_SLOT(devfn) != USB_HOST_SLOT) {
72 return PCIBIOS_SUCCESSFUL;
77 DPRINT("W => Slot: %d Where: %2X Len: %d Data: %02X\n",
78 PCI_SLOT(devfn), where, size, *value);
81 DPRINT("W => Slot: %d Where: %2X Len: %d Data: %04X\n",
82 PCI_SLOT(devfn), where, size, *value);
85 usb_cfg_space_cmd_reg = *value;
92 DPRINT("W => Slot: %d Where: %2X Len: %d Data: %08lX\n",
93 PCI_SLOT(devfn), where, size, *value);
95 case PCI_BASE_ADDRESS_0:
96 if (*value == 0xffffffff) {
97 usb_mem_size_rd = TRUE;
99 usb_mem_base = *value;
110 return PCIBIOS_SUCCESSFUL;
113 /* --------------------------------------------------------------------------
114 Name: pci63xx_int_read
115 Abstract: PCI Config read on internal device(s)
116 -------------------------------------------------------------------------- */
118 pci63xx_int_read(unsigned int devfn, int where, u32 * value, int size)
120 uint32 retValue = 0xFFFFFFFF;
122 if (PCI_SLOT(devfn) != USB_HOST_SLOT) {
123 return PCIBIOS_SUCCESSFUL;
126 // For now, this is specific to the USB Host controller. We can
127 // make it more general if we have to...
128 // Emulate PCI Config accesses
132 retValue = PCI_VENDOR_ID_BROADCOM | 0x63000000;
136 retValue = (0x0006 << 16) | usb_cfg_space_cmd_reg;
138 case PCI_CLASS_REVISION:
139 case PCI_CLASS_DEVICE:
140 retValue = (PCI_CLASS_SERIAL_USB << 16) | (0x10 << 8) | 0x01;
142 case PCI_BASE_ADDRESS_0:
143 if (usb_mem_size_rd) {
144 retValue = USB_BAR0_MEM_SIZE;
146 if (usb_mem_base != 0)
147 retValue = usb_mem_base;
149 retValue = USB_HOST_BASE;
151 usb_mem_size_rd = FALSE;
153 case PCI_CACHE_LINE_SIZE:
154 case PCI_LATENCY_TIMER:
157 case PCI_HEADER_TYPE:
158 retValue = PCI_HEADER_TYPE_NORMAL;
160 case PCI_SUBSYSTEM_VENDOR_ID:
161 retValue = PCI_VENDOR_ID_BROADCOM;
163 case PCI_SUBSYSTEM_ID:
166 case PCI_INTERRUPT_LINE:
167 retValue = INTERRUPT_ID_USBH;
175 *value = (retValue >> ((where & 3) << 3)) & 0xff;
176 DPRINT("R <= Slot: %d Where: %2X Len: %d Data: %02X\n",
177 PCI_SLOT(devfn), where, size, *value);
180 *value = (retValue >> ((where & 3) << 3)) & 0xffff;
181 DPRINT("R <= Slot: %d Where: %2X Len: %d Data: %04X\n",
182 PCI_SLOT(devfn), where, size, *value);
186 DPRINT("R <= Slot: %d Where: %2X Len: %d Data: %08lX\n",
187 PCI_SLOT(devfn), where, size, *value);
193 return PCIBIOS_SUCCESSFUL;
197 static int bcm96348_pcibios_read(struct pci_bus *bus, unsigned int devfn,
198 int where, int size, u32 * val)
200 volatile unsigned char *ioBase = (unsigned char *)(mpi->l2piobase | KSEG1);
203 #if defined(CONFIG_USB)
204 if (PCI_SLOT(devfn) == USB_HOST_SLOT)
205 return pci63xx_int_read(devfn, where, val, size);
208 mpi_SetupPciConfigAccess(BCM_PCI_CFG(PCI_SLOT(devfn), PCI_FUNC(devfn), where));
209 data = *(uint32 *)ioBase;
212 *val = (data >> ((where & 3) << 3)) & 0xff;
215 *val = (data >> ((where & 3) << 3)) & 0xffff;
219 /* Special case for reading PCI device range */
220 if ((where >= PCI_BASE_ADDRESS_0) && (where <= PCI_BASE_ADDRESS_5)) {
221 if (pci_mem_size_rd) {
222 /* bcm6348 PCI memory window minimum size is 64K */
223 *val &= PCI_SIZE_64K;
230 pci_mem_size_rd = FALSE;
231 mpi_ClearPciConfigAccess();
233 return PCIBIOS_SUCCESSFUL;
236 static int bcm96348_pcibios_write(struct pci_bus *bus, unsigned int devfn,
237 int where, int size, u32 val)
239 volatile unsigned char *ioBase = (unsigned char *)(mpi->l2piobase | KSEG1);
242 #if defined(CONFIG_USB)
243 if (PCI_SLOT(devfn) == USB_HOST_SLOT)
244 return pci63xx_int_write(devfn, where, &val, size);
246 mpi_SetupPciConfigAccess(BCM_PCI_CFG(PCI_SLOT(devfn), PCI_FUNC(devfn), where));
247 data = *(uint32 *)ioBase;
250 data = (data & ~(0xff << ((where & 3) << 3))) |
251 (val << ((where & 3) << 3));
254 data = (data & ~(0xffff << ((where & 3) << 3))) |
255 (val << ((where & 3) << 3));
259 /* Special case for reading PCI device range */
260 if ((where >= PCI_BASE_ADDRESS_0) && (where <= PCI_BASE_ADDRESS_5)) {
261 if (val == 0xffffffff)
262 pci_mem_size_rd = TRUE;
268 *(uint32 *)ioBase = data;
270 mpi_ClearPciConfigAccess();
272 return PCIBIOS_SUCCESSFUL;
275 struct pci_ops bcm96348_pci_ops = {
276 .read = bcm96348_pcibios_read,
277 .write = bcm96348_pcibios_write