diff options
Diffstat (limited to 'arch/ppc/boot/simple/misc-spruce.c')
-rw-r--r-- | arch/ppc/boot/simple/misc-spruce.c | 271 |
1 files changed, 0 insertions, 271 deletions
diff --git a/arch/ppc/boot/simple/misc-spruce.c b/arch/ppc/boot/simple/misc-spruce.c deleted file mode 100644 index 5b3a6c6f113b..000000000000 --- a/arch/ppc/boot/simple/misc-spruce.c +++ /dev/null | |||
@@ -1,271 +0,0 @@ | |||
1 | /* | ||
2 | * Misc. bootloader code for IBM Spruce reference platform | ||
3 | * | ||
4 | * Authors: Johnnie Peters <jpeters@mvista.com> | ||
5 | * Matt Porter <mporter@mvista.com> | ||
6 | * | ||
7 | * Derived from arch/ppc/boot/prep/misc.c | ||
8 | * | ||
9 | * 2000-2001 (c) MontaVista, Software, Inc. This file is licensed under | ||
10 | * the terms of the GNU General Public License version 2. This program | ||
11 | * is licensed "as is" without any warranty of any kind, whether express | ||
12 | * or implied. | ||
13 | */ | ||
14 | |||
15 | #include <linux/types.h> | ||
16 | #include <linux/pci.h> | ||
17 | |||
18 | #include <asm/bootinfo.h> | ||
19 | |||
20 | extern unsigned long decompress_kernel(unsigned long load_addr, int num_words, | ||
21 | unsigned long cksum); | ||
22 | |||
23 | /* Define some important locations of the Spruce. */ | ||
24 | #define SPRUCE_PCI_CONFIG_ADDR 0xfec00000 | ||
25 | #define SPRUCE_PCI_CONFIG_DATA 0xfec00004 | ||
26 | |||
27 | /* PCI configuration space access routines. */ | ||
28 | unsigned int *pci_config_address = (unsigned int *)SPRUCE_PCI_CONFIG_ADDR; | ||
29 | unsigned char *pci_config_data = (unsigned char *)SPRUCE_PCI_CONFIG_DATA; | ||
30 | |||
31 | void cpc700_pcibios_read_config_byte(unsigned char bus, unsigned char dev_fn, | ||
32 | unsigned char offset, unsigned char *val) | ||
33 | { | ||
34 | out_le32(pci_config_address, | ||
35 | (((bus & 0xff)<<16) | (dev_fn<<8) | (offset&0xfc) | 0x80000000)); | ||
36 | |||
37 | *val= (in_le32((unsigned *)pci_config_data) >> (8 * (offset & 3))) & 0xff; | ||
38 | } | ||
39 | |||
40 | void cpc700_pcibios_write_config_byte(unsigned char bus, unsigned char dev_fn, | ||
41 | unsigned char offset, unsigned char val) | ||
42 | { | ||
43 | out_le32(pci_config_address, | ||
44 | (((bus & 0xff)<<16) | (dev_fn<<8) | (offset&0xfc) | 0x80000000)); | ||
45 | |||
46 | out_8(pci_config_data + (offset&3), val); | ||
47 | } | ||
48 | |||
49 | void cpc700_pcibios_read_config_word(unsigned char bus, unsigned char dev_fn, | ||
50 | unsigned char offset, unsigned short *val) | ||
51 | { | ||
52 | out_le32(pci_config_address, | ||
53 | (((bus & 0xff)<<16) | (dev_fn<<8) | (offset&0xfc) | 0x80000000)); | ||
54 | |||
55 | *val= in_le16((unsigned short *)(pci_config_data + (offset&3))); | ||
56 | } | ||
57 | |||
58 | void cpc700_pcibios_write_config_word(unsigned char bus, unsigned char dev_fn, | ||
59 | unsigned char offset, unsigned short val) | ||
60 | { | ||
61 | out_le32(pci_config_address, | ||
62 | (((bus & 0xff)<<16) | (dev_fn<<8) | (offset&0xfc) | 0x80000000)); | ||
63 | |||
64 | out_le16((unsigned short *)(pci_config_data + (offset&3)), val); | ||
65 | } | ||
66 | |||
67 | void cpc700_pcibios_read_config_dword(unsigned char bus, unsigned char dev_fn, | ||
68 | unsigned char offset, unsigned int *val) | ||
69 | { | ||
70 | out_le32(pci_config_address, | ||
71 | (((bus & 0xff)<<16) | (dev_fn<<8) | (offset&0xfc) | 0x80000000)); | ||
72 | |||
73 | *val= in_le32((unsigned *)pci_config_data); | ||
74 | } | ||
75 | |||
76 | void cpc700_pcibios_write_config_dword(unsigned char bus, unsigned char dev_fn, | ||
77 | unsigned char offset, unsigned int val) | ||
78 | { | ||
79 | out_le32(pci_config_address, | ||
80 | (((bus & 0xff)<<16) | (dev_fn<<8) | (offset&0xfc) | 0x80000000)); | ||
81 | |||
82 | out_le32((unsigned *)pci_config_data, val); | ||
83 | } | ||
84 | |||
85 | #define PCNET32_WIO_RDP 0x10 | ||
86 | #define PCNET32_WIO_RAP 0x12 | ||
87 | #define PCNET32_WIO_RESET 0x14 | ||
88 | |||
89 | #define PCNET32_DWIO_RDP 0x10 | ||
90 | #define PCNET32_DWIO_RAP 0x14 | ||
91 | #define PCNET32_DWIO_RESET 0x18 | ||
92 | |||
93 | /* Processor interface config register access */ | ||
94 | #define PIFCFGADDR 0xff500000 | ||
95 | #define PIFCFGDATA 0xff500004 | ||
96 | |||
97 | #define PLBMIFOPT 0x18 /* PLB Master Interface Options */ | ||
98 | |||
99 | #define MEM_MBEN 0x24 | ||
100 | #define MEM_TYPE 0x28 | ||
101 | #define MEM_B1SA 0x3c | ||
102 | #define MEM_B1EA 0x5c | ||
103 | #define MEM_B2SA 0x40 | ||
104 | #define MEM_B2EA 0x60 | ||
105 | |||
106 | unsigned long | ||
107 | get_mem_size(void) | ||
108 | { | ||
109 | int loop; | ||
110 | unsigned long mem_size = 0; | ||
111 | unsigned long mem_mben; | ||
112 | unsigned long mem_type; | ||
113 | unsigned long mem_start; | ||
114 | unsigned long mem_end; | ||
115 | volatile int *mem_addr = (int *)0xff500008; | ||
116 | volatile int *mem_data = (int *)0xff50000c; | ||
117 | |||
118 | /* Get the size of memory from the memory controller. */ | ||
119 | *mem_addr = MEM_MBEN; | ||
120 | asm("sync"); | ||
121 | mem_mben = *mem_data; | ||
122 | asm("sync"); | ||
123 | for(loop = 0; loop < 1000; loop++); | ||
124 | |||
125 | *mem_addr = MEM_TYPE; | ||
126 | asm("sync"); | ||
127 | mem_type = *mem_data; | ||
128 | asm("sync"); | ||
129 | for(loop = 0; loop < 1000; loop++); | ||
130 | |||
131 | *mem_addr = MEM_TYPE; | ||
132 | /* Confirm bank 1 has DRAM memory */ | ||
133 | if ((mem_mben & 0x40000000) && | ||
134 | ((mem_type & 0x30000000) == 0x10000000)) { | ||
135 | *mem_addr = MEM_B1SA; | ||
136 | asm("sync"); | ||
137 | mem_start = *mem_data; | ||
138 | asm("sync"); | ||
139 | for(loop = 0; loop < 1000; loop++); | ||
140 | |||
141 | *mem_addr = MEM_B1EA; | ||
142 | asm("sync"); | ||
143 | mem_end = *mem_data; | ||
144 | asm("sync"); | ||
145 | for(loop = 0; loop < 1000; loop++); | ||
146 | |||
147 | mem_size = mem_end - mem_start + 0x100000; | ||
148 | } | ||
149 | |||
150 | /* Confirm bank 2 has DRAM memory */ | ||
151 | if ((mem_mben & 0x20000000) && | ||
152 | ((mem_type & 0xc000000) == 0x4000000)) { | ||
153 | *mem_addr = MEM_B2SA; | ||
154 | asm("sync"); | ||
155 | mem_start = *mem_data; | ||
156 | asm("sync"); | ||
157 | for(loop = 0; loop < 1000; loop++); | ||
158 | |||
159 | *mem_addr = MEM_B2EA; | ||
160 | asm("sync"); | ||
161 | mem_end = *mem_data; | ||
162 | asm("sync"); | ||
163 | for(loop = 0; loop < 1000; loop++); | ||
164 | |||
165 | mem_size += mem_end - mem_start + 0x100000; | ||
166 | } | ||
167 | return mem_size; | ||
168 | } | ||
169 | |||
170 | unsigned long | ||
171 | load_kernel(unsigned long load_addr, int num_words, unsigned long cksum, | ||
172 | void *ign1, void *ign2) | ||
173 | { | ||
174 | int csr0; | ||
175 | int csr_id; | ||
176 | int pci_devfn; | ||
177 | int found_multi = 0; | ||
178 | unsigned short vendor; | ||
179 | unsigned short device; | ||
180 | unsigned short command; | ||
181 | unsigned char header_type; | ||
182 | unsigned int bar0; | ||
183 | volatile int *pif_addr = (int *)0xff500000; | ||
184 | volatile int *pif_data = (int *)0xff500004; | ||
185 | |||
186 | /* | ||
187 | * Gah, these firmware guys need to learn that hardware | ||
188 | * byte swapping is evil! Disable all hardware byte | ||
189 | * swapping so it doesn't hurt anyone. | ||
190 | */ | ||
191 | *pif_addr = PLBMIFOPT; | ||
192 | asm("sync"); | ||
193 | *pif_data = 0x00000000; | ||
194 | asm("sync"); | ||
195 | |||
196 | /* Search out and turn off the PcNet ethernet boot device. */ | ||
197 | for (pci_devfn = 1; pci_devfn < 0xff; pci_devfn++) { | ||
198 | if (PCI_FUNC(pci_devfn) && !found_multi) | ||
199 | continue; | ||
200 | |||
201 | cpc700_pcibios_read_config_byte(0, pci_devfn, | ||
202 | PCI_HEADER_TYPE, &header_type); | ||
203 | |||
204 | if (!PCI_FUNC(pci_devfn)) | ||
205 | found_multi = header_type & 0x80; | ||
206 | |||
207 | cpc700_pcibios_read_config_word(0, pci_devfn, PCI_VENDOR_ID, | ||
208 | &vendor); | ||
209 | |||
210 | if (vendor != 0xffff) { | ||
211 | cpc700_pcibios_read_config_word(0, pci_devfn, | ||
212 | PCI_DEVICE_ID, &device); | ||
213 | |||
214 | /* If this PCI device is the Lance PCNet board then turn it off */ | ||
215 | if ((vendor == PCI_VENDOR_ID_AMD) && | ||
216 | (device == PCI_DEVICE_ID_AMD_LANCE)) { | ||
217 | |||
218 | /* Turn on I/O Space on the board. */ | ||
219 | cpc700_pcibios_read_config_word(0, pci_devfn, | ||
220 | PCI_COMMAND, &command); | ||
221 | command |= 0x1; | ||
222 | cpc700_pcibios_write_config_word(0, pci_devfn, | ||
223 | PCI_COMMAND, command); | ||
224 | |||
225 | /* Get the I/O space address */ | ||
226 | cpc700_pcibios_read_config_dword(0, pci_devfn, | ||
227 | PCI_BASE_ADDRESS_0, &bar0); | ||
228 | bar0 &= 0xfffffffe; | ||
229 | |||
230 | /* Reset the PCNet Board */ | ||
231 | inl (bar0+PCNET32_DWIO_RESET); | ||
232 | inw (bar0+PCNET32_WIO_RESET); | ||
233 | |||
234 | /* First do a work oriented read of csr0. If the value is | ||
235 | * 4 then this is the correct mode to access the board. | ||
236 | * If not try a double word ortiented read. | ||
237 | */ | ||
238 | outw(0, bar0 + PCNET32_WIO_RAP); | ||
239 | csr0 = inw(bar0 + PCNET32_WIO_RDP); | ||
240 | |||
241 | if (csr0 == 4) { | ||
242 | /* Check the Chip id register */ | ||
243 | outw(88, bar0 + PCNET32_WIO_RAP); | ||
244 | csr_id = inw(bar0 + PCNET32_WIO_RDP); | ||
245 | |||
246 | if (csr_id) { | ||
247 | /* This is the valid mode - set the stop bit */ | ||
248 | outw(0, bar0 + PCNET32_WIO_RAP); | ||
249 | outw(csr0, bar0 + PCNET32_WIO_RDP); | ||
250 | } | ||
251 | } else { | ||
252 | outl(0, bar0 + PCNET32_DWIO_RAP); | ||
253 | csr0 = inl(bar0 + PCNET32_DWIO_RDP); | ||
254 | if (csr0 == 4) { | ||
255 | /* Check the Chip id register */ | ||
256 | outl(88, bar0 + PCNET32_WIO_RAP); | ||
257 | csr_id = inl(bar0 + PCNET32_WIO_RDP); | ||
258 | |||
259 | if (csr_id) { | ||
260 | /* This is the valid mode - set the stop bit*/ | ||
261 | outl(0, bar0 + PCNET32_WIO_RAP); | ||
262 | outl(csr0, bar0 + PCNET32_WIO_RDP); | ||
263 | } | ||
264 | } | ||
265 | } | ||
266 | } | ||
267 | } | ||
268 | } | ||
269 | |||
270 | return decompress_kernel(load_addr, num_words, cksum); | ||
271 | } | ||