added files
[bcm963xx.git] / kernel / linux / arch / mips / pci / ops-bcm96348.c
1 /*
2 <:copyright-gpl 
3  Copyright 2002 Broadcom Corp. All Rights Reserved. 
4  
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. 
8  
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 
12  for more details. 
13  
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. 
17 :>
18 */
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>
24
25 #include <bcm_intr.h>
26 #include <bcm_map_part.h>
27 #include <bcmpci.h>
28
29 #include <linux/delay.h>
30
31 #if defined(CONFIG_USB)
32 #if 0
33 #define DPRINT(x...)        printk(x)
34 #else
35 #define DPRINT(x...)
36 #endif
37
38 static int 
39 pci63xx_int_read(unsigned int devfn, int where, u32 * value, int size);
40 static int 
41 pci63xx_int_write(unsigned int devfn, int where, u32 * value, int size);
42
43 static bool usb_mem_size_rd = FALSE;
44 static uint32 usb_mem_base = 0;
45 static uint32 usb_cfg_space_cmd_reg = 0;
46 #endif
47 static bool pci_mem_size_rd = FALSE;
48
49 static volatile MpiRegisters * mpi = (MpiRegisters *)(MPI_BASE);
50
51 static void mpi_SetupPciConfigAccess(uint32 addr)
52 {
53     mpi->l2pcfgctl = (DIR_CFG_SEL | DIR_CFG_USEREG | addr) & ~CONFIG_TYPE;
54 }
55
56 static void mpi_ClearPciConfigAccess(void)
57 {
58     mpi->l2pcfgctl = 0x00000000;
59 }
60
61 #if defined(CONFIG_USB)
62 /* --------------------------------------------------------------------------
63     Name: pci63xx_int_write
64 Abstract: PCI Config write on internal device(s)
65  -------------------------------------------------------------------------- */
66 static int 
67 pci63xx_int_write(unsigned int devfn, int where, u32 * value, int size)
68 {
69     if (PCI_SLOT(devfn) != USB_HOST_SLOT) {
70         return PCIBIOS_SUCCESSFUL;
71     }
72
73     switch (size) {
74         case 1:
75             DPRINT("W => Slot: %d Where: %2X Len: %d Data: %02X\n", 
76                 PCI_SLOT(devfn), where, size, *value);
77             break;
78         case 2:
79             DPRINT("W => Slot: %d Where: %2X Len: %d Data: %04X\n", 
80                 PCI_SLOT(devfn), where, size, *value);
81             switch (where) {
82                 case PCI_COMMAND:
83                     usb_cfg_space_cmd_reg = *value;
84                     break;
85                 default:
86                     break;
87             }
88             break;
89         case 4:
90             DPRINT("W => Slot: %d Where: %2X Len: %d Data: %08lX\n", 
91                 PCI_SLOT(devfn), where, size, *value);
92             switch (where) {
93                 case PCI_BASE_ADDRESS_0:
94                     if (*value == 0xffffffff) {
95                         usb_mem_size_rd = TRUE;
96                     } else {
97                         usb_mem_base = *value;
98                     }
99                     break;
100                 default:
101                     break;
102             }
103             break;
104         default:
105             break;
106     }
107
108     return PCIBIOS_SUCCESSFUL;
109 }
110
111 /* --------------------------------------------------------------------------
112     Name: pci63xx_int_read
113 Abstract: PCI Config read on internal device(s)
114  -------------------------------------------------------------------------- */
115 static int 
116 pci63xx_int_read(unsigned int devfn, int where, u32 * value, int size)
117 {
118     uint32 retValue = 0xFFFFFFFF;
119
120     if (PCI_SLOT(devfn) != USB_HOST_SLOT) {
121         return PCIBIOS_SUCCESSFUL;
122     }
123
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
127     switch (where) {
128         case PCI_VENDOR_ID:     
129         case PCI_DEVICE_ID:
130             retValue = PCI_VENDOR_ID_BROADCOM | 0x63000000;
131             break;
132         case PCI_COMMAND:
133         case PCI_STATUS:
134             retValue = (0x0006 << 16) | usb_cfg_space_cmd_reg;
135             break;
136         case PCI_CLASS_REVISION:
137         case PCI_CLASS_DEVICE:
138             retValue = (PCI_CLASS_SERIAL_USB << 16) | (0x10 << 8) | 0x01;
139             break;
140         case PCI_BASE_ADDRESS_0:
141             if (usb_mem_size_rd) {
142                 retValue = USB_BAR0_MEM_SIZE;
143             } else {
144                 if (usb_mem_base != 0)
145                     retValue = usb_mem_base;
146                 else
147                     retValue = USB_HOST_BASE;
148             }
149             usb_mem_size_rd = FALSE;
150             break;
151         case PCI_CACHE_LINE_SIZE:
152         case PCI_LATENCY_TIMER:
153             retValue = 0;
154             break;
155         case PCI_HEADER_TYPE:
156             retValue = PCI_HEADER_TYPE_NORMAL;
157             break;
158         case PCI_SUBSYSTEM_VENDOR_ID:
159             retValue = PCI_VENDOR_ID_BROADCOM;
160             break;
161         case PCI_SUBSYSTEM_ID:
162             retValue = 0x6300;
163             break;
164         case PCI_INTERRUPT_LINE:
165             retValue = INTERRUPT_ID_USBH; 
166             break;
167         default:
168             break;
169     }
170
171     switch (size) {
172         case 1:
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);
176             break;
177         case 2:
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);
181             break;
182         case 4:
183             *value = retValue;
184             DPRINT("R <= Slot: %d Where: %2X Len: %d Data: %08lX\n", 
185                 PCI_SLOT(devfn), where, size, *value);
186             break;
187         default:
188             break;
189     }
190
191     return PCIBIOS_SUCCESSFUL;
192 }
193 #endif
194
195 static int bcm96348_pcibios_read(struct pci_bus *bus, unsigned int devfn,
196         int where, int size, u32 * val)
197 {
198     volatile unsigned char *ioBase = (unsigned char *)(mpi->l2piobase | KSEG1);
199     uint32 data;
200
201 #if defined(CONFIG_USB)
202     if (PCI_SLOT(devfn) == USB_HOST_SLOT)
203         return pci63xx_int_read(devfn, where, val, size);
204 #endif
205
206     mpi_SetupPciConfigAccess(BCM_PCI_CFG(PCI_SLOT(devfn), PCI_FUNC(devfn), where));
207     data = *(uint32 *)ioBase;
208     switch(size) {
209         case 1:
210             *val = (data >> ((where & 3) << 3)) & 0xff;
211             break;
212         case 2:
213             *val = (data >> ((where & 3) << 3)) & 0xffff;
214             break;
215         case 4:
216             *val = data;
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;
222                 }
223             }
224             break;
225         default:
226             break;
227     }
228     pci_mem_size_rd = FALSE;
229     mpi_ClearPciConfigAccess();
230
231     return PCIBIOS_SUCCESSFUL;
232 }
233
234 static int bcm96348_pcibios_write(struct pci_bus *bus, unsigned int devfn,
235         int where, int size, u32 val)
236 {
237     volatile unsigned char *ioBase = (unsigned char *)(mpi->l2piobase | KSEG1);
238     uint32 data;
239
240 #if defined(CONFIG_USB)
241     if (PCI_SLOT(devfn) == USB_HOST_SLOT)
242         return pci63xx_int_write(devfn, where, &val, size);
243 #endif
244     mpi_SetupPciConfigAccess(BCM_PCI_CFG(PCI_SLOT(devfn), PCI_FUNC(devfn), where));
245     data = *(uint32 *)ioBase;
246     switch(size) {
247         case 1:
248             data = (data & ~(0xff << ((where & 3) << 3))) |
249                 (val << ((where & 3) << 3));
250             break;
251         case 2:
252             data = (data & ~(0xffff << ((where & 3) << 3))) |
253                 (val << ((where & 3) << 3));
254             break;
255         case 4:
256             data = val;
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;
261             }
262             break;
263         default:
264             break;
265     }
266     *(uint32 *)ioBase = data;
267     udelay(500);
268     mpi_ClearPciConfigAccess();
269
270     return PCIBIOS_SUCCESSFUL;
271 }
272
273 struct pci_ops bcm96348_pci_ops = {
274     .read   = bcm96348_pcibios_read,
275     .write  = bcm96348_pcibios_write
276 };