ftp://ftp.kernel.org/pub/linux/kernel/v2.6/linux-2.6.6.tar.bz2
[linux-2.6.git] / arch / ppc / boot / simple / mpc10x_memory.c
1 /*
2  * arch/ppc/boot/common/mpc10x_common.c
3  *
4  * A routine to find out how much memory the machine has.
5  *
6  * Based on:
7  * arch/ppc/kernel/mpc10x_common.c
8  *
9  * Author: Mark A. Greer
10  *         mgreer@mvista.com
11  *
12  * 2001-2002 (c) MontaVista, Software, Inc.  This file is licensed under
13  * the terms of the GNU General Public License version 2.  This program
14  * is licensed "as is" without any warranty of any kind, whether express
15  * or implied.
16  */
17
18 #include <linux/pci.h>
19 #include <asm/types.h>
20 #include <asm/io.h>
21 #include "mpc10x.h"
22
23 /*
24  * *** WARNING - A BAT MUST be set to access the PCI config addr/data regs ***
25  */
26
27 /*
28  * PCI config space macros, similar to indirect_xxx and early_xxx macros.
29  * We assume bus 0.
30  */
31 #define MPC10X_CFG_read(val, addr, type, op)    *val = op((type)(addr))
32 #define MPC10X_CFG_write(val, addr, type, op)   op((type *)(addr), (val))
33
34 #define MPC10X_PCI_OP(rw, size, type, op, mask)                         \
35 static void                                                             \
36 mpc10x_##rw##_config_##size(unsigned int *cfg_addr,                     \
37                 unsigned int *cfg_data, int devfn, int offset,          \
38                 type val)                                               \
39 {                                                                       \
40         out_be32(cfg_addr,                                              \
41                  ((offset & 0xfc) << 24) | (devfn << 16)                \
42                  | (0 << 8) | 0x80);                                    \
43         MPC10X_CFG_##rw(val, cfg_data + (offset & mask), type, op);     \
44         return;                                                         \
45 }
46
47 MPC10X_PCI_OP(read, byte,  u8 *, in_8, 3)
48 MPC10X_PCI_OP(read, dword, u32 *, in_le32, 0)
49
50 /*
51  * Read the memory controller registers to determine the amount of memory in
52  * the system.  This assumes that the firmware has correctly set up the memory
53  * controller registers.  On CONFIG_PPC_PREP, we know we are being called
54  * under a PReP memory map. On all other machines, we assume we are under
55  * a CHRP memory map.  Further, on CONFIG_PPC_MULTIPLATFORM we must rename
56  * this function.
57  */
58 #ifdef CONFIG_PPC_MULTIPLATFORM
59 #define get_mem_size mpc10x_get_mem_size
60 #endif
61 unsigned long
62 get_mem_size(void)
63 {
64         unsigned int *config_addr, *config_data, val;
65         unsigned long start, end, total, offset;
66         int i;
67         unsigned char bank_enables;
68
69 #ifdef CONFIG_PPC_PREP
70         config_addr = (unsigned int *)MPC10X_MAPA_CNFG_ADDR;
71         config_data = (unsigned int *)MPC10X_MAPA_CNFG_DATA;
72 #else
73         config_addr = (unsigned int *)MPC10X_MAPB_CNFG_ADDR;
74         config_data = (unsigned int *)MPC10X_MAPB_CNFG_DATA;
75 #endif
76
77         mpc10x_read_config_byte(config_addr, config_data, PCI_DEVFN(0,0),
78                         MPC10X_MCTLR_MEM_BANK_ENABLES, &bank_enables);
79
80         total = 0;
81
82         for (i = 0; i < 8; i++) {
83                 if (bank_enables & (1 << i)) {
84                         offset = MPC10X_MCTLR_MEM_START_1 + ((i > 3) ? 4 : 0);
85                         mpc10x_read_config_dword(config_addr, config_data,
86                                         PCI_DEVFN(0,0), offset, &val);
87                         start = (val >> ((i & 3) << 3)) & 0xff;
88
89                         offset = MPC10X_MCTLR_EXT_MEM_START_1 + ((i>3) ? 4 : 0);
90                         mpc10x_read_config_dword(config_addr, config_data,
91                                         PCI_DEVFN(0,0), offset, &val);
92                         val = (val >> ((i & 3) << 3)) & 0x03;
93                         start = (val << 28) | (start << 20);
94
95                         offset = MPC10X_MCTLR_MEM_END_1 + ((i > 3) ? 4 : 0);
96                         mpc10x_read_config_dword(config_addr, config_data,
97                                         PCI_DEVFN(0,0), offset, &val);
98                         end = (val >> ((i & 3) << 3)) & 0xff;
99
100                         offset = MPC10X_MCTLR_EXT_MEM_END_1 + ((i > 3) ? 4 : 0);
101                         mpc10x_read_config_dword(config_addr, config_data,
102                                         PCI_DEVFN(0,0), offset, &val);
103                         val = (val >> ((i & 3) << 3)) & 0x03;
104                         end = (val << 28) | (end << 20) | 0xfffff;
105
106                         total += (end - start + 1);
107                 }
108         }
109
110         return total;
111 }