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