3 * arch/ppc/kernel/mpc10x_common.c
5 * Common routines for the Motorola SPS MPC106, MPC107 and MPC8240 Host bridge,
8 * Author: Mark A. Greer
11 * Copyright 2001 MontaVista Software Inc.
13 * This program is free software; you can redistribute it and/or modify it
14 * under the terms of the GNU General Public License as published by the
15 * Free Software Foundation; either version 2 of the License, or (at your
16 * option) any later version.
20 * *** WARNING - A BAT MUST be set to access the PCI config addr/data regs ***
23 #include <linux/kernel.h>
24 #include <linux/init.h>
25 #include <linux/pci.h>
26 #include <linux/slab.h>
28 #include <asm/byteorder.h>
31 #include <asm/uaccess.h>
32 #include <asm/machdep.h>
33 #include <asm/pci-bridge.h>
34 #include <asm/open_pic.h>
35 #include <asm/mpc10x.h>
38 /* Set resources to match bridge memory map */
40 mpc10x_bridge_set_resources(int map, struct pci_controller *hose)
44 case MPC10X_MEM_MAP_A:
45 pci_init_resource(&hose->io_resource,
51 pci_init_resource (&hose->mem_resources[0],
57 case MPC10X_MEM_MAP_B:
58 pci_init_resource(&hose->io_resource,
64 pci_init_resource (&hose->mem_resources[0],
71 printk("mpc10x_bridge_set_resources: "
72 "Invalid map specified\n");
74 ppc_md.progress("mpc10x:exit1", 0x100);
78 * Do some initialization and put the EUMB registers at the specified address
79 * (also map the EPIC registers into virtual space--OpenPIC_Addr will be set).
81 * The EPIC is not on the 106, only the 8240 and 107.
84 mpc10x_bridge_init(struct pci_controller *hose,
89 int host_bridge, picr1, picr1_bit;
90 ulong pci_config_addr, pci_config_data;
93 if (ppc_md.progress) ppc_md.progress("mpc10x:enter", 0x100);
95 /* Set up for current map so we can get at config regs */
96 switch (current_map) {
97 case MPC10X_MEM_MAP_A:
98 setup_indirect_pci(hose,
99 MPC10X_MAPA_CNFG_ADDR,
100 MPC10X_MAPA_CNFG_DATA);
102 case MPC10X_MEM_MAP_B:
103 setup_indirect_pci(hose,
104 MPC10X_MAPB_CNFG_ADDR,
105 MPC10X_MAPB_CNFG_DATA);
108 printk("mpc10x_bridge_init: %s\n",
109 "Invalid current map specified");
111 ppc_md.progress("mpc10x:exit1", 0x100);
115 /* Make sure its a supported bridge */
116 early_read_config_dword(hose,
122 switch (host_bridge) {
123 case MPC10X_BRIDGE_106:
124 case MPC10X_BRIDGE_8240:
125 case MPC10X_BRIDGE_107:
126 case MPC10X_BRIDGE_8245:
130 ppc_md.progress("mpc10x:exit2", 0x100);
135 case MPC10X_MEM_MAP_A:
136 MPC10X_SETUP_HOSE(hose, A);
137 pci_config_addr = MPC10X_MAPA_CNFG_ADDR;
138 pci_config_data = MPC10X_MAPA_CNFG_DATA;
139 picr1_bit = MPC10X_CFG_PICR1_ADDR_MAP_A;
141 case MPC10X_MEM_MAP_B:
142 MPC10X_SETUP_HOSE(hose, B);
143 pci_config_addr = MPC10X_MAPB_CNFG_ADDR;
144 pci_config_data = MPC10X_MAPB_CNFG_DATA;
145 picr1_bit = MPC10X_CFG_PICR1_ADDR_MAP_B;
148 printk("mpc10x_bridge_init: %s\n",
149 "Invalid new map specified");
151 ppc_md.progress("mpc10x:exit3", 0x100);
155 /* Make bridge use the 'new_map', if not already usng it */
156 if (current_map != new_map) {
157 early_read_config_dword(hose,
160 MPC10X_CFG_PICR1_REG,
163 picr1 = (picr1 & ~MPC10X_CFG_PICR1_ADDR_MAP_MASK) |
166 early_write_config_dword(hose,
169 MPC10X_CFG_PICR1_REG,
172 asm volatile("sync");
174 /* Undo old mappings & map in new cfg data/addr regs */
175 iounmap((void *)hose->cfg_addr);
176 iounmap((void *)hose->cfg_data);
178 setup_indirect_pci(hose,
183 /* Setup resources to match map */
184 mpc10x_bridge_set_resources(new_map, hose);
187 * Want processor accesses of 0xFDxxxxxx to be mapped
188 * to PCI memory space at 0x00000000. Do not want
189 * host bridge to respond to PCI memory accesses of
190 * 0xFDxxxxxx. Do not want host bridge to respond
191 * to PCI memory addresses 0xFD000000-0xFDFFFFFF;
192 * want processor accesses from 0x000A0000-0x000BFFFF
193 * to be forwarded to system memory.
195 * Only valid if not in agent mode and using MAP B.
197 if (new_map == MPC10X_MEM_MAP_B) {
198 early_read_config_byte(hose,
201 MPC10X_CFG_MAPB_OPTIONS_REG,
204 byte &= ~(MPC10X_CFG_MAPB_OPTIONS_PFAE |
205 MPC10X_CFG_MAPB_OPTIONS_PCICH |
206 MPC10X_CFG_MAPB_OPTIONS_PROCCH);
208 if (host_bridge != MPC10X_BRIDGE_106) {
209 byte |= MPC10X_CFG_MAPB_OPTIONS_CFAE;
212 early_write_config_byte(hose,
215 MPC10X_CFG_MAPB_OPTIONS_REG,
219 if (host_bridge != MPC10X_BRIDGE_106) {
220 early_read_config_byte(hose,
226 if (pir != MPC10X_CFG_PIR_HOST_BRIDGE) {
227 printk("Host bridge in Agent mode\n");
228 /* Read or Set LMBAR & PCSRBAR? */
231 /* Set base addr of the 8240/107 EUMB. */
232 early_write_config_dword(hose,
238 /* Map EPIC register part of EUMB into vitual memory */
240 ioremap(phys_eumb_base + MPC10X_EUMB_EPIC_OFFSET,
241 MPC10X_EUMB_EPIC_SIZE);
242 printk("OpenPIC_Addr in mpc10x_bridge_init function is %p \n", OpenPIC_Addr);
245 #ifdef CONFIG_MPC10X_STORE_GATHERING
246 mpc10x_enable_store_gathering(hose);
248 mpc10x_disable_store_gathering(hose);
251 if (ppc_md.progress) ppc_md.progress("mpc10x:exit", 0x100);
256 * Need to make our own PCI config space access macros because
257 * mpc10x_get_mem_size() is called before the data structures are set up for
258 * the 'early_xxx' and 'indirect_xxx' routines to work.
261 #define MPC10X_CFG_read(val, addr, type, op) *val = op((type)(addr))
262 #define MPC10X_CFG_write(val, addr, type, op) op((type *)(addr), (val))
264 #define MPC10X_PCI_OP(rw, size, type, op, mask) \
266 mpc10x_##rw##_config_##size(uint *cfg_addr, uint *cfg_data, int devfn, int offset, type val) \
269 ((offset & 0xfc) << 24) | (devfn << 16) \
270 | (0 << 8) | 0x80); \
271 MPC10X_CFG_##rw(val, cfg_data + (offset & mask), type, op); \
275 MPC10X_PCI_OP(read, byte, u8 *, in_8, 3)
276 MPC10X_PCI_OP(read, dword, u32 *, in_le32, 0)
278 MPC10X_PCI_OP(write, byte, u8, out_8, 3)
279 MPC10X_PCI_OP(read, word, u16 *, in_le16, 2)
280 MPC10X_PCI_OP(write, word, u16, out_le16, 2)
281 MPC10X_PCI_OP(write, dword, u32, out_le32, 0)
285 * Read the memory controller registers to determine the amount of memory in
286 * the system. This assumes that the firmware has correctly set up the memory
287 * controller registers.
290 mpc10x_get_mem_size(uint mem_map)
292 uint *config_addr, *config_data, val;
293 ulong start, end, total, offset;
298 case MPC10X_MEM_MAP_A:
299 config_addr = (uint *)MPC10X_MAPA_CNFG_ADDR;
300 config_data = (uint *)MPC10X_MAPA_CNFG_DATA;
302 case MPC10X_MEM_MAP_B:
303 config_addr = (uint *)MPC10X_MAPB_CNFG_ADDR;
304 config_data = (uint *)MPC10X_MAPB_CNFG_DATA;
310 mpc10x_read_config_byte(config_addr,
313 MPC10X_MCTLR_MEM_BANK_ENABLES,
318 for (i=0; i<8; i++) {
319 if (bank_enables & (1 << i)) {
320 offset = MPC10X_MCTLR_MEM_START_1 + ((i > 3) ? 4 : 0);
321 mpc10x_read_config_dword(config_addr,
326 start = (val >> ((i & 3) << 3)) & 0xff;
328 offset = MPC10X_MCTLR_EXT_MEM_START_1 + ((i>3) ? 4 : 0);
329 mpc10x_read_config_dword(config_addr,
334 val = (val >> ((i & 3) << 3)) & 0x03;
335 start = (val << 28) | (start << 20);
337 offset = MPC10X_MCTLR_MEM_END_1 + ((i > 3) ? 4 : 0);
338 mpc10x_read_config_dword(config_addr,
343 end = (val >> ((i & 3) << 3)) & 0xff;
345 offset = MPC10X_MCTLR_EXT_MEM_END_1 + ((i > 3) ? 4 : 0);
346 mpc10x_read_config_dword(config_addr,
351 val = (val >> ((i & 3) << 3)) & 0x03;
352 end = (val << 28) | (end << 20) | 0xfffff;
354 total += (end - start + 1);
362 mpc10x_enable_store_gathering(struct pci_controller *hose)
366 early_read_config_dword(hose,
369 MPC10X_CFG_PICR1_REG,
372 picr1 |= MPC10X_CFG_PICR1_ST_GATH_EN;
374 early_write_config_dword(hose,
377 MPC10X_CFG_PICR1_REG,
384 mpc10x_disable_store_gathering(struct pci_controller *hose)
388 early_read_config_dword(hose,
391 MPC10X_CFG_PICR1_REG,
394 picr1 &= ~MPC10X_CFG_PICR1_ST_GATH_EN;
396 early_write_config_dword(hose,
399 MPC10X_CFG_PICR1_REG,