ftp://ftp.kernel.org/pub/linux/kernel/v2.6/linux-2.6.6.tar.bz2
[linux-2.6.git] / arch / ppc / syslib / mpc10x_common.c
1 /*
2  * arch/ppc/syslib/mpc10x_common.c
3  *
4  * Common routines for the Motorola SPS MPC106, MPC107 and MPC8240 Host bridge,
5  * Mem ctlr, EPIC, etc.
6  *
7  * Author: Mark A. Greer
8  *         mgreer@mvista.com
9  *
10  * 2001 (c) MontaVista, Software, Inc.  This file is licensed under
11  * the terms of the GNU General Public License version 2.  This program
12  * is licensed "as is" without any warranty of any kind, whether express
13  * or implied.
14  */
15
16 /*
17  * *** WARNING - A BAT MUST be set to access the PCI config addr/data regs ***
18  */
19
20 #include <linux/kernel.h>
21 #include <linux/init.h>
22 #include <linux/pci.h>
23 #include <linux/slab.h>
24
25 #include <asm/byteorder.h>
26 #include <asm/io.h>
27 #include <asm/irq.h>
28 #include <asm/uaccess.h>
29 #include <asm/machdep.h>
30 #include <asm/pci-bridge.h>
31 #include <asm/open_pic.h>
32 #include <asm/mpc10x.h>
33
34
35 /* Set resources to match bridge memory map */
36 void __init
37 mpc10x_bridge_set_resources(int map, struct pci_controller *hose)
38 {
39
40         switch (map) {
41                 case MPC10X_MEM_MAP_A:
42                         pci_init_resource(&hose->io_resource,
43                                         0x00000000,
44                                         0x3f7fffff,
45                                         IORESOURCE_IO,
46                                         "PCI host bridge");
47
48                         pci_init_resource (&hose->mem_resources[0],
49                                         0xc0000000,
50                                         0xfeffffff,
51                                         IORESOURCE_MEM,
52                                         "PCI host bridge");
53                         break;
54                 case MPC10X_MEM_MAP_B:
55                         pci_init_resource(&hose->io_resource,
56                                         0x00000000,
57                                         0x00bfffff,
58                                         IORESOURCE_IO,
59                                         "PCI host bridge");
60
61                         pci_init_resource (&hose->mem_resources[0],
62                                         0x80000000,
63                                         0xfcffffff,
64                                         IORESOURCE_MEM,
65                                         "PCI host bridge");
66                         break;
67                 default:
68                         printk("mpc10x_bridge_set_resources: "
69                                         "Invalid map specified\n");
70                         if (ppc_md.progress)
71                                 ppc_md.progress("mpc10x:exit1", 0x100);
72         }
73 }
74 /*
75  * Do some initialization and put the EUMB registers at the specified address
76  * (also map the EPIC registers into virtual space--OpenPIC_Addr will be set).
77  *
78  * The EPIC is not on the 106, only the 8240 and 107.
79  */
80 int __init
81 mpc10x_bridge_init(struct pci_controller *hose,
82                    uint current_map,
83                    uint new_map,
84                    uint phys_eumb_base)
85 {
86         int     host_bridge, picr1, picr1_bit;
87         ulong   pci_config_addr, pci_config_data;
88         u_char  pir, byte;
89
90         if (ppc_md.progress) ppc_md.progress("mpc10x:enter", 0x100);
91
92         /* Set up for current map so we can get at config regs */
93         switch (current_map) {
94                 case MPC10X_MEM_MAP_A:
95                         setup_indirect_pci(hose,
96                                            MPC10X_MAPA_CNFG_ADDR,
97                                            MPC10X_MAPA_CNFG_DATA);
98                         break;
99                 case MPC10X_MEM_MAP_B:
100                         setup_indirect_pci(hose,
101                                            MPC10X_MAPB_CNFG_ADDR,
102                                            MPC10X_MAPB_CNFG_DATA);
103                         break;
104                 default:
105                         printk("mpc10x_bridge_init: %s\n",
106                                 "Invalid current map specified");
107                         if (ppc_md.progress)
108                                 ppc_md.progress("mpc10x:exit1", 0x100);
109                         return -1;
110         }
111
112         /* Make sure it's a supported bridge */
113         early_read_config_dword(hose,
114                                 0,
115                                 PCI_DEVFN(0,0),
116                                 PCI_VENDOR_ID,
117                                 &host_bridge);
118
119         switch (host_bridge) {
120                 case MPC10X_BRIDGE_106:
121                 case MPC10X_BRIDGE_8240:
122                 case MPC10X_BRIDGE_107:
123                 case MPC10X_BRIDGE_8245:
124                         break;
125                 default:
126                         if (ppc_md.progress)
127                                 ppc_md.progress("mpc10x:exit2", 0x100);
128                         return -1;
129         }
130
131         switch (new_map) {
132                 case MPC10X_MEM_MAP_A:
133                         MPC10X_SETUP_HOSE(hose, A);
134                         pci_config_addr = MPC10X_MAPA_CNFG_ADDR;
135                         pci_config_data = MPC10X_MAPA_CNFG_DATA;
136                         picr1_bit = MPC10X_CFG_PICR1_ADDR_MAP_A;
137                         break;
138                 case MPC10X_MEM_MAP_B:
139                         MPC10X_SETUP_HOSE(hose, B);
140                         pci_config_addr = MPC10X_MAPB_CNFG_ADDR;
141                         pci_config_data = MPC10X_MAPB_CNFG_DATA;
142                         picr1_bit = MPC10X_CFG_PICR1_ADDR_MAP_B;
143                         break;
144                 default:
145                         printk("mpc10x_bridge_init: %s\n",
146                                 "Invalid new map specified");
147                         if (ppc_md.progress)
148                                 ppc_md.progress("mpc10x:exit3", 0x100);
149                         return -1;
150         }
151
152         /* Make bridge use the 'new_map', if not already usng it */
153         if (current_map != new_map) {
154                 early_read_config_dword(hose,
155                                         0,
156                                         PCI_DEVFN(0,0),
157                                         MPC10X_CFG_PICR1_REG,
158                                         &picr1);
159
160                 picr1 = (picr1 & ~MPC10X_CFG_PICR1_ADDR_MAP_MASK) |
161                          picr1_bit;
162
163                 early_write_config_dword(hose,
164                                          0,
165                                          PCI_DEVFN(0,0),
166                                          MPC10X_CFG_PICR1_REG,
167                                          picr1);
168
169                 asm volatile("sync");
170
171                 /* Undo old mappings & map in new cfg data/addr regs */
172                 iounmap((void *)hose->cfg_addr);
173                 iounmap((void *)hose->cfg_data);
174
175                 setup_indirect_pci(hose,
176                                    pci_config_addr,
177                                    pci_config_data);
178         }
179
180         /* Setup resources to match map */
181         mpc10x_bridge_set_resources(new_map, hose);
182
183         /*
184          * Want processor accesses of 0xFDxxxxxx to be mapped
185          * to PCI memory space at 0x00000000.  Do not want
186          * host bridge to respond to PCI memory accesses of
187          * 0xFDxxxxxx.  Do not want host bridge to respond
188          * to PCI memory addresses 0xFD000000-0xFDFFFFFF;
189          * want processor accesses from 0x000A0000-0x000BFFFF
190          * to be forwarded to system memory.
191          *
192          * Only valid if not in agent mode and using MAP B.
193          */
194         if (new_map == MPC10X_MEM_MAP_B) {
195                 early_read_config_byte(hose,
196                                        0,
197                                        PCI_DEVFN(0,0),
198                                        MPC10X_CFG_MAPB_OPTIONS_REG,
199                                        &byte);
200
201                 byte &= ~(MPC10X_CFG_MAPB_OPTIONS_PFAE  |
202                           MPC10X_CFG_MAPB_OPTIONS_PCICH |
203                           MPC10X_CFG_MAPB_OPTIONS_PROCCH);
204
205                 if (host_bridge != MPC10X_BRIDGE_106) {
206                         byte |= MPC10X_CFG_MAPB_OPTIONS_CFAE;
207                 }
208
209                 early_write_config_byte(hose,
210                                         0,
211                                         PCI_DEVFN(0,0),
212                                         MPC10X_CFG_MAPB_OPTIONS_REG,
213                                         byte);
214         }
215
216         if (host_bridge != MPC10X_BRIDGE_106) {
217                 early_read_config_byte(hose,
218                                        0,
219                                        PCI_DEVFN(0,0),
220                                        MPC10X_CFG_PIR_REG,
221                                        &pir);
222
223                 if (pir != MPC10X_CFG_PIR_HOST_BRIDGE) {
224                         printk("Host bridge in Agent mode\n");
225                         /* Read or Set LMBAR & PCSRBAR? */
226                 }
227                 
228                 /* Set base addr of the 8240/107 EUMB.  */
229                 early_write_config_dword(hose,
230                                          0,
231                                          PCI_DEVFN(0,0),
232                                          MPC10X_CFG_EUMBBAR,
233                                          phys_eumb_base);
234
235                 /* Map EPIC register part of EUMB into vitual memory */
236                 OpenPIC_Addr =
237                         ioremap(phys_eumb_base + MPC10X_EUMB_EPIC_OFFSET,
238                                 MPC10X_EUMB_EPIC_SIZE);
239         }
240
241 #ifdef CONFIG_MPC10X_STORE_GATHERING
242         mpc10x_enable_store_gathering(hose);
243 #else
244         mpc10x_disable_store_gathering(hose);
245 #endif
246
247         if (ppc_md.progress) ppc_md.progress("mpc10x:exit", 0x100);
248         return 0;
249 }
250
251 /*
252  * Need to make our own PCI config space access macros because
253  * mpc10x_get_mem_size() is called before the data structures are set up for
254  * the 'early_xxx' and 'indirect_xxx' routines to work.
255  * Assumes bus 0.
256  */
257 #define MPC10X_CFG_read(val, addr, type, op)    *val = op((type)(addr))
258 #define MPC10X_CFG_write(val, addr, type, op)   op((type *)(addr), (val))
259
260 #define MPC10X_PCI_OP(rw, size, type, op, mask)                         \
261 static void                                                             \
262 mpc10x_##rw##_config_##size(uint *cfg_addr, uint *cfg_data, int devfn, int offset, type val) \
263 {                                                                       \
264         out_be32(cfg_addr,                                              \
265                  ((offset & 0xfc) << 24) | (devfn << 16)                \
266                  | (0 << 8) | 0x80);                                    \
267         MPC10X_CFG_##rw(val, cfg_data + (offset & mask), type, op);     \
268         return;                                                         \
269 }
270
271 MPC10X_PCI_OP(read,  byte,  u8 *, in_8, 3)
272 MPC10X_PCI_OP(read,  dword, u32 *, in_le32, 0)
273 #if 0   /* Not used */
274 MPC10X_PCI_OP(write, byte,  u8, out_8, 3)
275 MPC10X_PCI_OP(read,  word,  u16 *, in_le16, 2)
276 MPC10X_PCI_OP(write, word,  u16, out_le16, 2)
277 MPC10X_PCI_OP(write, dword, u32, out_le32, 0)
278 #endif
279
280 /*
281  * Read the memory controller registers to determine the amount of memory in
282  * the system.  This assumes that the firmware has correctly set up the memory
283  * controller registers.
284  */
285 unsigned long __init
286 mpc10x_get_mem_size(uint mem_map)
287 {
288         uint                    *config_addr, *config_data, val;
289         ulong                   start, end, total, offset;
290         int                     i;
291         u_char                  bank_enables;
292
293         switch (mem_map) {
294                 case MPC10X_MEM_MAP_A:
295                         config_addr = (uint *)MPC10X_MAPA_CNFG_ADDR;
296                         config_data = (uint *)MPC10X_MAPA_CNFG_DATA;
297                         break;
298                 case MPC10X_MEM_MAP_B:
299                         config_addr = (uint *)MPC10X_MAPB_CNFG_ADDR;
300                         config_data = (uint *)MPC10X_MAPB_CNFG_DATA;
301                         break;
302                 default:
303                         return 0;
304         }
305
306         mpc10x_read_config_byte(config_addr,
307                                 config_data,
308                                 PCI_DEVFN(0,0),
309                                 MPC10X_MCTLR_MEM_BANK_ENABLES,
310                                 &bank_enables);
311
312         total = 0;
313
314         for (i=0; i<8; i++) {
315                 if (bank_enables & (1 << i)) {
316                         offset = MPC10X_MCTLR_MEM_START_1 + ((i > 3) ? 4 : 0);
317                         mpc10x_read_config_dword(config_addr,
318                                                  config_data,
319                                                  PCI_DEVFN(0,0),
320                                                  offset,
321                                                  &val);
322                         start = (val >> ((i & 3) << 3)) & 0xff;
323
324                         offset = MPC10X_MCTLR_EXT_MEM_START_1 + ((i>3) ? 4 : 0);
325                         mpc10x_read_config_dword(config_addr,
326                                                  config_data,
327                                                  PCI_DEVFN(0,0),
328                                                  offset,
329                                                  &val);
330                         val = (val >> ((i & 3) << 3)) & 0x03;
331                         start = (val << 28) | (start << 20);
332
333                         offset = MPC10X_MCTLR_MEM_END_1 + ((i > 3) ? 4 : 0);
334                         mpc10x_read_config_dword(config_addr,
335                                                  config_data,
336                                                  PCI_DEVFN(0,0),
337                                                  offset,
338                                                  &val);
339                         end = (val >> ((i & 3) << 3)) & 0xff;
340
341                         offset = MPC10X_MCTLR_EXT_MEM_END_1 + ((i > 3) ? 4 : 0);
342                         mpc10x_read_config_dword(config_addr,
343                                                  config_data,
344                                                  PCI_DEVFN(0,0),
345                                                  offset,
346                                                  &val);
347                         val = (val >> ((i & 3) << 3)) & 0x03;
348                         end = (val << 28) | (end << 20) | 0xfffff;
349
350                         total += (end - start + 1);
351                 }
352         }
353
354         return total;
355 }
356
357 int __init
358 mpc10x_enable_store_gathering(struct pci_controller *hose)
359 {
360         uint picr1;
361
362         early_read_config_dword(hose,
363                                 0,
364                                 PCI_DEVFN(0,0),
365                                 MPC10X_CFG_PICR1_REG,
366                                 &picr1);
367
368         picr1 |= MPC10X_CFG_PICR1_ST_GATH_EN;
369
370         early_write_config_dword(hose,
371                                 0,
372                                 PCI_DEVFN(0,0),
373                                 MPC10X_CFG_PICR1_REG,
374                                 picr1);
375
376         return 0;
377 }
378
379 int __init
380 mpc10x_disable_store_gathering(struct pci_controller *hose)
381 {
382         uint picr1;
383
384         early_read_config_dword(hose,
385                                 0,
386                                 PCI_DEVFN(0,0),
387                                 MPC10X_CFG_PICR1_REG,
388                                 &picr1);
389
390         picr1 &= ~MPC10X_CFG_PICR1_ST_GATH_EN;
391
392         early_write_config_dword(hose,
393                                 0,
394                                 PCI_DEVFN(0,0),
395                                 MPC10X_CFG_PICR1_REG,
396                                 picr1);
397
398         return 0;
399 }