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