Commit | Line | Data |
---|---|---|
1da177e4 | 1 | /* |
1da177e4 LT |
2 | * Maintainer: Tom Rini <trini@kernel.crashing.org> |
3 | * | |
4 | * In the past: Gary Thomas, Cort Dougan <cort@cs.nmt.edu> | |
5 | */ | |
6 | ||
7 | #include <linux/config.h> | |
8 | #include <linux/pci_ids.h> | |
9 | #include <linux/types.h> | |
10 | #include <asm/residual.h> | |
11 | #include <asm/string.h> | |
12 | #include <asm/byteorder.h> | |
13 | #include "mpc10x.h" | |
14 | #include "of1275.h" | |
15 | #include "nonstdio.h" | |
16 | ||
17 | extern int keyb_present; /* keyboard controller is present by default */ | |
18 | RESIDUAL hold_resid_buf; | |
19 | RESIDUAL *hold_residual = &hold_resid_buf; | |
20 | static void *OFW_interface; /* Pointer to OF, if available. */ | |
21 | ||
22 | #ifdef CONFIG_VGA_CONSOLE | |
23 | char *vidmem = (char *)0xC00B8000; | |
24 | int lines = 25, cols = 80; | |
25 | int orig_x, orig_y = 24; | |
26 | #endif /* CONFIG_VGA_CONSOLE */ | |
27 | ||
28 | extern int CRT_tstc(void); | |
29 | extern int vga_init(unsigned char *ISA_mem); | |
30 | extern void gunzip(void *, int, unsigned char *, int *); | |
31 | extern unsigned long serial_init(int chan, void *ignored); | |
32 | extern void serial_fixups(void); | |
33 | extern struct bi_record *decompress_kernel(unsigned long load_addr, | |
34 | int num_words, unsigned long cksum); | |
35 | extern void disable_6xx_mmu(void); | |
36 | extern unsigned long mpc10x_get_mem_size(void); | |
37 | ||
38 | static void | |
39 | writel(unsigned int val, unsigned int address) | |
40 | { | |
41 | /* Ensure I/O operations complete */ | |
42 | __asm__ volatile("eieio"); | |
43 | *(unsigned int *)address = cpu_to_le32(val); | |
44 | } | |
45 | ||
46 | #define PCI_CFG_ADDR(dev,off) ((0x80<<24) | (dev<<8) | (off&0xfc)) | |
47 | #define PCI_CFG_DATA(off) (MPC10X_MAPA_CNFG_DATA+(off&3)) | |
48 | ||
49 | static void | |
50 | pci_read_config_32(unsigned char devfn, | |
51 | unsigned char offset, | |
52 | unsigned int *val) | |
53 | { | |
54 | /* Ensure I/O operations complete */ | |
55 | __asm__ volatile("eieio"); | |
56 | *(unsigned int *)PCI_CFG_ADDR(devfn,offset) = | |
57 | cpu_to_le32(MPC10X_MAPA_CNFG_ADDR); | |
58 | /* Ensure I/O operations complete */ | |
59 | __asm__ volatile("eieio"); | |
60 | *val = le32_to_cpu(*(unsigned int *)PCI_CFG_DATA(offset)); | |
61 | return; | |
62 | } | |
63 | ||
64 | #ifdef CONFIG_VGA_CONSOLE | |
65 | void | |
66 | scroll(void) | |
67 | { | |
68 | int i; | |
69 | ||
70 | memcpy ( vidmem, vidmem + cols * 2, ( lines - 1 ) * cols * 2 ); | |
71 | for ( i = ( lines - 1 ) * cols * 2; i < lines * cols * 2; i += 2 ) | |
72 | vidmem[i] = ' '; | |
73 | } | |
74 | #endif /* CONFIG_VGA_CONSOLE */ | |
75 | ||
76 | unsigned long | |
77 | load_kernel(unsigned long load_addr, int num_words, unsigned long cksum, | |
78 | RESIDUAL *residual, void *OFW) | |
79 | { | |
80 | int start_multi = 0; | |
81 | unsigned int pci_viddid, pci_did, tulip_pci_base, tulip_base; | |
82 | ||
83 | /* If we have Open Firmware, initialise it immediately */ | |
84 | if (OFW) { | |
85 | OFW_interface = OFW; | |
86 | ofinit(OFW_interface); | |
87 | } | |
88 | ||
89 | board_isa_init(); | |
90 | #if defined(CONFIG_VGA_CONSOLE) | |
91 | vga_init((unsigned char *)0xC0000000); | |
92 | #endif /* CONFIG_VGA_CONSOLE */ | |
93 | ||
94 | if (residual) { | |
95 | /* Is this Motorola PPCBug? */ | |
96 | if ((1 & residual->VitalProductData.FirmwareSupports) && | |
97 | (1 == residual->VitalProductData.FirmwareSupplier)) { | |
98 | unsigned char base_mod; | |
99 | unsigned char board_type = inb(0x801) & 0xF0; | |
100 | ||
101 | /* | |
102 | * Reset the onboard 21x4x Ethernet | |
103 | * Motorola Ethernet is at IDSEL 14 (devfn 0x70) | |
104 | */ | |
105 | pci_read_config_32(0x70, 0x00, &pci_viddid); | |
106 | pci_did = (pci_viddid & 0xffff0000) >> 16; | |
107 | /* Be sure we've really found a 21x4x chip */ | |
108 | if (((pci_viddid & 0xffff) == PCI_VENDOR_ID_DEC) && | |
109 | ((pci_did == PCI_DEVICE_ID_DEC_TULIP_FAST) || | |
110 | (pci_did == PCI_DEVICE_ID_DEC_TULIP) || | |
111 | (pci_did == PCI_DEVICE_ID_DEC_TULIP_PLUS) || | |
112 | (pci_did == PCI_DEVICE_ID_DEC_21142))) { | |
113 | pci_read_config_32(0x70, | |
114 | 0x10, | |
115 | &tulip_pci_base); | |
116 | /* Get the physical base address */ | |
117 | tulip_base = | |
118 | (tulip_pci_base & ~0x03UL) + 0x80000000; | |
119 | /* Strobe the 21x4x reset bit in CSR0 */ | |
120 | writel(0x1, tulip_base); | |
121 | } | |
122 | ||
123 | /* If this is genesis 2 board then check for no | |
124 | * keyboard controller and more than one processor. | |
125 | */ | |
126 | if (board_type == 0xe0) { | |
127 | base_mod = inb(0x803); | |
128 | /* if a MVME2300/2400 or a Sitka then no keyboard */ | |
129 | if((base_mod == 0xFA) || (base_mod == 0xF9) || | |
130 | (base_mod == 0xE1)) { | |
131 | keyb_present = 0; /* no keyboard */ | |
132 | } | |
133 | } | |
134 | /* If this is a multiprocessor system then | |
135 | * park the other processor so that the | |
136 | * kernel knows where to find them. | |
137 | */ | |
138 | if (residual->MaxNumCpus > 1) | |
139 | start_multi = 1; | |
140 | } | |
141 | memcpy(hold_residual,residual,sizeof(RESIDUAL)); | |
142 | } | |
143 | ||
144 | /* Call decompress_kernel */ | |
145 | decompress_kernel(load_addr, num_words, cksum); | |
146 | ||
147 | if (start_multi) { | |
148 | residual->VitalProductData.SmpIar = (unsigned long)0xc0; | |
149 | residual->Cpus[1].CpuState = CPU_GOOD; | |
150 | hold_residual->VitalProductData.Reserved5 = 0xdeadbeef; | |
151 | } | |
152 | ||
153 | /* Now go and clear out the BATs and ensure that our MSR is | |
154 | * correct .*/ | |
155 | disable_6xx_mmu(); | |
156 | ||
157 | /* Make r3 be a pointer to the residual data. */ | |
158 | return (unsigned long)hold_residual; | |
159 | } | |
160 | ||
161 | unsigned long | |
162 | get_mem_size(void) | |
163 | { | |
164 | unsigned int pci_viddid, pci_did; | |
165 | ||
166 | /* First, figure out what kind of host bridge we are on. If it's | |
167 | * an MPC10x, we can ask it directly how much memory it has. | |
168 | * Otherwise, see if the residual data has anything. This isn't | |
169 | * the best way, but it can be the only way. If there's nothing, | |
170 | * assume 32MB. -- Tom. | |
171 | */ | |
172 | /* See what our host bridge is. */ | |
173 | pci_read_config_32(0x00, 0x00, &pci_viddid); | |
174 | pci_did = (pci_viddid & 0xffff0000) >> 16; | |
175 | /* See if we are on an MPC10x. */ | |
176 | if (((pci_viddid & 0xffff) == PCI_VENDOR_ID_MOTOROLA) | |
177 | && ((pci_did == PCI_DEVICE_ID_MOTOROLA_MPC105) | |
178 | || (pci_did == PCI_DEVICE_ID_MOTOROLA_MPC106) | |
179 | || (pci_did == PCI_DEVICE_ID_MOTOROLA_MPC107))) | |
180 | return mpc10x_get_mem_size(); | |
181 | /* If it's not, see if we have anything in the residual data. */ | |
182 | else if (hold_residual && hold_residual->TotalMemory) | |
183 | return hold_residual->TotalMemory; | |
184 | else if (OFW_interface) { | |
185 | /* | |
186 | * This is a 'best guess' check. We want to make sure | |
187 | * we don't try this on a PReP box without OF | |
188 | * -- Cort | |
189 | */ | |
190 | while (OFW_interface) | |
191 | { | |
192 | phandle dev_handle; | |
193 | int mem_info[2]; | |
194 | ||
195 | /* get handle to memory description */ | |
196 | if (!(dev_handle = finddevice("/memory@0"))) | |
197 | break; | |
198 | ||
199 | /* get the info */ | |
200 | if (getprop(dev_handle, "reg", mem_info, | |
201 | sizeof(mem_info)) != 8) | |
202 | break; | |
203 | ||
204 | return mem_info[1]; | |
205 | } | |
206 | } | |
207 | ||
208 | /* Fall back to hard-coding 32MB. */ | |
209 | return 32*1024*1024; | |
210 | } |