diff options
author | Linus Torvalds <torvalds@ppc970.osdl.org> | 2005-04-16 18:20:36 -0400 |
---|---|---|
committer | Linus Torvalds <torvalds@ppc970.osdl.org> | 2005-04-16 18:20:36 -0400 |
commit | 1da177e4c3f41524e886b7f1b8a0c1fc7321cac2 (patch) | |
tree | 0bba044c4ce775e45a88a51686b5d9f90697ea9d /arch/ppc/platforms |
Linux-2.6.12-rc2v2.6.12-rc2
Initial git repository build. I'm not bothering with the full history,
even though we have it. We can create a separate "historical" git
archive of that later if we want to, and in the meantime it's about
3.2GB when imported into git - space that would just make the early
git days unnecessarily complicated, when we don't have a lot of good
infrastructure for it.
Let it rip!
Diffstat (limited to 'arch/ppc/platforms')
169 files changed, 41379 insertions, 0 deletions
diff --git a/arch/ppc/platforms/4xx/Kconfig b/arch/ppc/platforms/4xx/Kconfig new file mode 100644 index 000000000000..a0612a86455a --- /dev/null +++ b/arch/ppc/platforms/4xx/Kconfig | |||
@@ -0,0 +1,247 @@ | |||
1 | config 4xx | ||
2 | bool | ||
3 | depends on 40x || 44x | ||
4 | default y | ||
5 | |||
6 | menu "IBM 4xx options" | ||
7 | depends on 4xx | ||
8 | |||
9 | choice | ||
10 | prompt "Machine Type" | ||
11 | depends on 40x | ||
12 | default WALNUT | ||
13 | |||
14 | config ASH | ||
15 | bool "Ash" | ||
16 | help | ||
17 | This option enables support for the IBM NP405H evaluation board. | ||
18 | |||
19 | config BUBINGA | ||
20 | bool "Bubinga" | ||
21 | help | ||
22 | This option enables support for the IBM 405EP evaluation board. | ||
23 | |||
24 | config CPCI405 | ||
25 | bool "CPCI405" | ||
26 | help | ||
27 | This option enables support for the CPCI405 board. | ||
28 | |||
29 | config EP405 | ||
30 | bool "EP405/EP405PC" | ||
31 | help | ||
32 | This option enables support for the EP405/EP405PC boards. | ||
33 | |||
34 | config OAK | ||
35 | bool "Oak" | ||
36 | help | ||
37 | This option enables support for the IBM 403GCX evaluation board. | ||
38 | |||
39 | config REDWOOD_5 | ||
40 | bool "Redwood-5" | ||
41 | help | ||
42 | This option enables support for the IBM STB04 evaluation board. | ||
43 | |||
44 | config REDWOOD_6 | ||
45 | bool "Redwood-6" | ||
46 | help | ||
47 | This option enables support for the IBM STBx25xx evaluation board. | ||
48 | |||
49 | config SYCAMORE | ||
50 | bool "Sycamore" | ||
51 | help | ||
52 | This option enables support for the IBM PPC405GPr evaluation board. | ||
53 | |||
54 | config WALNUT | ||
55 | bool "Walnut" | ||
56 | help | ||
57 | This option enables support for the IBM PPC405GP evaluation board. | ||
58 | |||
59 | config XILINX_ML300 | ||
60 | bool "Xilinx-ML300" | ||
61 | help | ||
62 | This option enables support for the Xilinx ML300 evaluation board. | ||
63 | |||
64 | endchoice | ||
65 | |||
66 | choice | ||
67 | prompt "Machine Type" | ||
68 | depends on 44x | ||
69 | default EBONY | ||
70 | |||
71 | config EBONY | ||
72 | bool "Ebony" | ||
73 | help | ||
74 | This option enables support for the IBM PPC440GP evaluation board. | ||
75 | |||
76 | config LUAN | ||
77 | bool "Luan" | ||
78 | help | ||
79 | This option enables support for the IBM PPC440SP evaluation board. | ||
80 | |||
81 | config OCOTEA | ||
82 | bool "Ocotea" | ||
83 | help | ||
84 | This option enables support for the IBM PPC440GX evaluation board. | ||
85 | |||
86 | endchoice | ||
87 | |||
88 | config EP405PC | ||
89 | bool "EP405PC Support" | ||
90 | depends on EP405 | ||
91 | |||
92 | |||
93 | # It's often necessary to know the specific 4xx processor type. | ||
94 | # Fortunately, it is impled (so far) from the board type, so we | ||
95 | # don't need to ask more redundant questions. | ||
96 | config NP405H | ||
97 | bool | ||
98 | depends on ASH | ||
99 | default y | ||
100 | |||
101 | config 440GP | ||
102 | bool | ||
103 | depends on EBONY | ||
104 | default y | ||
105 | |||
106 | config 440GX | ||
107 | bool | ||
108 | depends on OCOTEA | ||
109 | default y | ||
110 | |||
111 | config 440SP | ||
112 | bool | ||
113 | depends on LUAN | ||
114 | default y | ||
115 | |||
116 | config 440 | ||
117 | bool | ||
118 | depends on 440GP || 440SP | ||
119 | default y | ||
120 | |||
121 | config 440A | ||
122 | bool | ||
123 | depends on 440GX | ||
124 | default y | ||
125 | |||
126 | # All 405-based cores up until the 405GPR and 405EP have this errata. | ||
127 | config IBM405_ERR77 | ||
128 | bool | ||
129 | depends on 40x && !403GCX && !405GPR | ||
130 | default y | ||
131 | |||
132 | # All 40x-based cores, up until the 405GPR and 405EP have this errata. | ||
133 | config IBM405_ERR51 | ||
134 | bool | ||
135 | depends on 40x && !405GPR | ||
136 | default y | ||
137 | |||
138 | config BOOKE | ||
139 | bool | ||
140 | depends on 44x | ||
141 | default y | ||
142 | |||
143 | config IBM_OCP | ||
144 | bool | ||
145 | depends on ASH || BUBINGA || CPCI405 || EBONY || EP405 || LUAN || OCOTEA || REDWOOD_5 || REDWOOD_6 || SYCAMORE || WALNUT | ||
146 | default y | ||
147 | |||
148 | config XILINX_OCP | ||
149 | bool | ||
150 | depends on XILINX_ML300 | ||
151 | default y | ||
152 | |||
153 | config IBM_EMAC4 | ||
154 | bool | ||
155 | depends on 440GX || 440SP | ||
156 | default y | ||
157 | |||
158 | config BIOS_FIXUP | ||
159 | bool | ||
160 | depends on BUBINGA || EP405 || SYCAMORE || WALNUT | ||
161 | default y | ||
162 | |||
163 | config 403GCX | ||
164 | bool | ||
165 | depends OAK | ||
166 | default y | ||
167 | |||
168 | config 405EP | ||
169 | bool | ||
170 | depends on BUBINGA | ||
171 | default y | ||
172 | |||
173 | config 405GP | ||
174 | bool | ||
175 | depends on CPCI405 || EP405 || WALNUT | ||
176 | default y | ||
177 | |||
178 | config 405GPR | ||
179 | bool | ||
180 | depends on SYCAMORE | ||
181 | default y | ||
182 | |||
183 | config VIRTEX_II_PRO | ||
184 | bool | ||
185 | depends on XILINX_ML300 | ||
186 | default y | ||
187 | |||
188 | config STB03xxx | ||
189 | bool | ||
190 | depends on REDWOOD_5 || REDWOOD_6 | ||
191 | default y | ||
192 | |||
193 | config EMBEDDEDBOOT | ||
194 | bool | ||
195 | depends on EP405 || XILINX_ML300 | ||
196 | default y | ||
197 | |||
198 | config IBM_OPENBIOS | ||
199 | bool | ||
200 | depends on ASH || BUBINGA || REDWOOD_5 || REDWOOD_6 || SYCAMORE || WALNUT | ||
201 | default y | ||
202 | |||
203 | config PPC4xx_DMA | ||
204 | bool "PPC4xx DMA controller support" | ||
205 | depends on 4xx | ||
206 | |||
207 | config PPC4xx_EDMA | ||
208 | bool | ||
209 | depends on !STB03xxx && PPC4xx_DMA | ||
210 | default y | ||
211 | |||
212 | config PPC_GEN550 | ||
213 | bool | ||
214 | depends on 4xx | ||
215 | default y | ||
216 | |||
217 | config PM | ||
218 | bool "Power Management support (EXPERIMENTAL)" | ||
219 | depends on 4xx && EXPERIMENTAL | ||
220 | |||
221 | choice | ||
222 | prompt "TTYS0 device and default console" | ||
223 | depends on 40x | ||
224 | default UART0_TTYS0 | ||
225 | |||
226 | config UART0_TTYS0 | ||
227 | bool "UART0" | ||
228 | |||
229 | config UART0_TTYS1 | ||
230 | bool "UART1" | ||
231 | |||
232 | endchoice | ||
233 | |||
234 | config SERIAL_SICC | ||
235 | bool "SICC Serial port support" | ||
236 | depends on STB03xxx | ||
237 | |||
238 | config UART1_DFLT_CONSOLE | ||
239 | bool | ||
240 | depends on SERIAL_SICC && UART0_TTYS1 | ||
241 | default y | ||
242 | |||
243 | config SERIAL_SICC_CONSOLE | ||
244 | bool | ||
245 | depends on SERIAL_SICC && UART0_TTYS1 | ||
246 | default y | ||
247 | endmenu | ||
diff --git a/arch/ppc/platforms/4xx/Makefile b/arch/ppc/platforms/4xx/Makefile new file mode 100644 index 000000000000..ea470c6adbb6 --- /dev/null +++ b/arch/ppc/platforms/4xx/Makefile | |||
@@ -0,0 +1,27 @@ | |||
1 | # | ||
2 | # Makefile for the PowerPC 4xx linux kernel. | ||
3 | |||
4 | obj-$(CONFIG_ASH) += ash.o | ||
5 | obj-$(CONFIG_CPCI405) += cpci405.o | ||
6 | obj-$(CONFIG_EBONY) += ebony.o | ||
7 | obj-$(CONFIG_EP405) += ep405.o | ||
8 | obj-$(CONFIG_BUBINGA) += bubinga.o | ||
9 | obj-$(CONFIG_LUAN) += luan.o | ||
10 | obj-$(CONFIG_OAK) += oak.o | ||
11 | obj-$(CONFIG_OCOTEA) += ocotea.o | ||
12 | obj-$(CONFIG_REDWOOD_5) += redwood5.o | ||
13 | obj-$(CONFIG_REDWOOD_6) += redwood6.o | ||
14 | obj-$(CONFIG_SYCAMORE) += sycamore.o | ||
15 | obj-$(CONFIG_WALNUT) += walnut.o | ||
16 | obj-$(CONFIG_XILINX_ML300) += xilinx_ml300.o | ||
17 | |||
18 | obj-$(CONFIG_405GP) += ibm405gp.o | ||
19 | obj-$(CONFIG_REDWOOD_5) += ibmstb4.o | ||
20 | obj-$(CONFIG_NP405H) += ibmnp405h.o | ||
21 | obj-$(CONFIG_REDWOOD_6) += ibmstbx25.o | ||
22 | obj-$(CONFIG_440GP) += ibm440gp.o | ||
23 | obj-$(CONFIG_440GX) += ibm440gx.o | ||
24 | obj-$(CONFIG_440SP) += ibm440sp.o | ||
25 | obj-$(CONFIG_405EP) += ibm405ep.o | ||
26 | obj-$(CONFIG_405GPR) += ibm405gpr.o | ||
27 | obj-$(CONFIG_VIRTEX_II_PRO) += virtex-ii_pro.o | ||
diff --git a/arch/ppc/platforms/4xx/ash.c b/arch/ppc/platforms/4xx/ash.c new file mode 100644 index 000000000000..ce2911793716 --- /dev/null +++ b/arch/ppc/platforms/4xx/ash.c | |||
@@ -0,0 +1,250 @@ | |||
1 | /* | ||
2 | * arch/ppc/platforms/4xx/ash.c | ||
3 | * | ||
4 | * Support for the IBM NP405H ash eval board | ||
5 | * | ||
6 | * Author: Armin Kuster <akuster@mvista.com> | ||
7 | * | ||
8 | * 2001-2002 (c) MontaVista, Software, Inc. This file is licensed under | ||
9 | * the terms of the GNU General Public License version 2. This program | ||
10 | * is licensed "as is" without any warranty of any kind, whether express | ||
11 | * or implied. | ||
12 | */ | ||
13 | #include <linux/config.h> | ||
14 | #include <linux/init.h> | ||
15 | #include <linux/pagemap.h> | ||
16 | #include <linux/pci.h> | ||
17 | |||
18 | #include <asm/machdep.h> | ||
19 | #include <asm/pci-bridge.h> | ||
20 | #include <asm/io.h> | ||
21 | #include <asm/ocp.h> | ||
22 | #include <asm/ibm_ocp_pci.h> | ||
23 | #include <asm/todc.h> | ||
24 | |||
25 | #ifdef DEBUG | ||
26 | #define DBG(x...) printk(x) | ||
27 | #else | ||
28 | #define DBG(x...) | ||
29 | #endif | ||
30 | |||
31 | void *ash_rtc_base; | ||
32 | |||
33 | /* Some IRQs unique to Walnut. | ||
34 | * Used by the generic 405 PCI setup functions in ppc4xx_pci.c | ||
35 | */ | ||
36 | int __init | ||
37 | ppc405_map_irq(struct pci_dev *dev, unsigned char idsel, unsigned char pin) | ||
38 | { | ||
39 | static char pci_irq_table[][4] = | ||
40 | /* | ||
41 | * PCI IDSEL/INTPIN->INTLINE | ||
42 | * A B C D | ||
43 | */ | ||
44 | { | ||
45 | {24, 24, 24, 24}, /* IDSEL 1 - PCI slot 1 */ | ||
46 | {25, 25, 25, 25}, /* IDSEL 2 - PCI slot 2 */ | ||
47 | {26, 26, 26, 26}, /* IDSEL 3 - PCI slot 3 */ | ||
48 | {27, 27, 27, 27}, /* IDSEL 4 - PCI slot 4 */ | ||
49 | }; | ||
50 | |||
51 | const long min_idsel = 1, max_idsel = 4, irqs_per_slot = 4; | ||
52 | return PCI_IRQ_TABLE_LOOKUP; | ||
53 | } | ||
54 | |||
55 | void __init | ||
56 | ash_setup_arch(void) | ||
57 | { | ||
58 | ppc4xx_setup_arch(); | ||
59 | |||
60 | ibm_ocp_set_emac(0, 3); | ||
61 | |||
62 | #ifdef CONFIG_DEBUG_BRINGUP | ||
63 | int i; | ||
64 | printk("\n"); | ||
65 | printk("machine\t: %s\n", PPC4xx_MACHINE_NAME); | ||
66 | printk("\n"); | ||
67 | printk("bi_s_version\t %s\n", bip->bi_s_version); | ||
68 | printk("bi_r_version\t %s\n", bip->bi_r_version); | ||
69 | printk("bi_memsize\t 0x%8.8x\t %dMBytes\n", bip->bi_memsize, | ||
70 | bip->bi_memsize / (1024 * 1000)); | ||
71 | for (i = 0; i < EMAC_NUMS; i++) { | ||
72 | printk("bi_enetaddr %d\t %2.2x%2.2x%2.2x-%2.2x%2.2x%2.2x\n", i, | ||
73 | bip->bi_enetaddr[i][0], bip->bi_enetaddr[i][1], | ||
74 | bip->bi_enetaddr[i][2], bip->bi_enetaddr[i][3], | ||
75 | bip->bi_enetaddr[i][4], bip->bi_enetaddr[i][5]); | ||
76 | } | ||
77 | printk("bi_pci_enetaddr %d\t %2.2x%2.2x%2.2x-%2.2x%2.2x%2.2x\n", 0, | ||
78 | bip->bi_pci_enetaddr[0], bip->bi_pci_enetaddr[1], | ||
79 | bip->bi_pci_enetaddr[2], bip->bi_pci_enetaddr[3], | ||
80 | bip->bi_pci_enetaddr[4], bip->bi_pci_enetaddr[5]); | ||
81 | |||
82 | printk("bi_intfreq\t 0x%8.8x\t clock:\t %dMhz\n", | ||
83 | bip->bi_intfreq, bip->bi_intfreq / 1000000); | ||
84 | |||
85 | printk("bi_busfreq\t 0x%8.8x\t plb bus clock:\t %dMHz\n", | ||
86 | bip->bi_busfreq, bip->bi_busfreq / 1000000); | ||
87 | printk("bi_pci_busfreq\t 0x%8.8x\t pci bus clock:\t %dMHz\n", | ||
88 | bip->bi_pci_busfreq, bip->bi_pci_busfreq / 1000000); | ||
89 | |||
90 | printk("\n"); | ||
91 | #endif | ||
92 | /* RTC step for ash */ | ||
93 | ash_rtc_base = (void *) ASH_RTC_VADDR; | ||
94 | TODC_INIT(TODC_TYPE_DS1743, ash_rtc_base, ash_rtc_base, ash_rtc_base, | ||
95 | 8); | ||
96 | } | ||
97 | |||
98 | void __init | ||
99 | bios_fixup(struct pci_controller *hose, struct pcil0_regs *pcip) | ||
100 | { | ||
101 | /* | ||
102 | * Expected PCI mapping: | ||
103 | * | ||
104 | * PLB addr PCI memory addr | ||
105 | * --------------------- --------------------- | ||
106 | * 0000'0000 - 7fff'ffff <--- 0000'0000 - 7fff'ffff | ||
107 | * 8000'0000 - Bfff'ffff ---> 8000'0000 - Bfff'ffff | ||
108 | * | ||
109 | * PLB addr PCI io addr | ||
110 | * --------------------- --------------------- | ||
111 | * e800'0000 - e800'ffff ---> 0000'0000 - 0001'0000 | ||
112 | * | ||
113 | * The following code is simplified by assuming that the bootrom | ||
114 | * has been well behaved in following this mapping. | ||
115 | */ | ||
116 | |||
117 | #ifdef DEBUG | ||
118 | int i; | ||
119 | |||
120 | printk("ioremap PCLIO_BASE = 0x%x\n", pcip); | ||
121 | printk("PCI bridge regs before fixup \n"); | ||
122 | for (i = 0; i <= 2; i++) { | ||
123 | printk(" pmm%dma\t0x%x\n", i, in_le32(&(pcip->pmm[i].ma))); | ||
124 | printk(" pmm%dla\t0x%x\n", i, in_le32(&(pcip->pmm[i].la))); | ||
125 | printk(" pmm%dpcila\t0x%x\n", i, | ||
126 | in_le32(&(pcip->pmm[i].pcila))); | ||
127 | printk(" pmm%dpciha\t0x%x\n", i, | ||
128 | in_le32(&(pcip->pmm[i].pciha))); | ||
129 | } | ||
130 | printk(" ptm1ms\t0x%x\n", in_le32(&(pcip->ptm1ms))); | ||
131 | printk(" ptm1la\t0x%x\n", in_le32(&(pcip->ptm1la))); | ||
132 | printk(" ptm2ms\t0x%x\n", in_le32(&(pcip->ptm2ms))); | ||
133 | printk(" ptm2la\t0x%x\n", in_le32(&(pcip->ptm2la))); | ||
134 | for (bar = PCI_BASE_ADDRESS_1; bar <= PCI_BASE_ADDRESS_2; bar += 4) { | ||
135 | early_read_config_dword(hose, hose->first_busno, | ||
136 | PCI_FUNC(hose->first_busno), bar, | ||
137 | &bar_response); | ||
138 | DBG("BUS %d, device %d, Function %d bar 0x%8.8x is 0x%8.8x\n", | ||
139 | hose->first_busno, PCI_SLOT(hose->first_busno), | ||
140 | PCI_FUNC(hose->first_busno), bar, bar_response); | ||
141 | } | ||
142 | |||
143 | #endif | ||
144 | if (ppc_md.progress) | ||
145 | ppc_md.progress("bios_fixup(): enter", 0x800); | ||
146 | |||
147 | /* added for IBM boot rom version 1.15 bios bar changes -AK */ | ||
148 | |||
149 | /* Disable region first */ | ||
150 | out_le32((void *) &(pcip->pmm[0].ma), 0x00000000); | ||
151 | /* PLB starting addr, PCI: 0x80000000 */ | ||
152 | out_le32((void *) &(pcip->pmm[0].la), 0x80000000); | ||
153 | /* PCI start addr, 0x80000000 */ | ||
154 | out_le32((void *) &(pcip->pmm[0].pcila), PPC405_PCI_MEM_BASE); | ||
155 | /* 512MB range of PLB to PCI */ | ||
156 | out_le32((void *) &(pcip->pmm[0].pciha), 0x00000000); | ||
157 | /* Enable no pre-fetch, enable region */ | ||
158 | out_le32((void *) &(pcip->pmm[0].ma), ((0xffffffff - | ||
159 | (PPC405_PCI_UPPER_MEM - | ||
160 | PPC405_PCI_MEM_BASE)) | 0x01)); | ||
161 | |||
162 | /* Disable region one */ | ||
163 | out_le32((void *) &(pcip->pmm[1].ma), 0x00000000); | ||
164 | out_le32((void *) &(pcip->pmm[1].la), 0x00000000); | ||
165 | out_le32((void *) &(pcip->pmm[1].pcila), 0x00000000); | ||
166 | out_le32((void *) &(pcip->pmm[1].pciha), 0x00000000); | ||
167 | out_le32((void *) &(pcip->pmm[1].ma), 0x00000000); | ||
168 | |||
169 | /* Disable region two */ | ||
170 | out_le32((void *) &(pcip->pmm[2].ma), 0x00000000); | ||
171 | out_le32((void *) &(pcip->pmm[2].la), 0x00000000); | ||
172 | out_le32((void *) &(pcip->pmm[2].pcila), 0x00000000); | ||
173 | out_le32((void *) &(pcip->pmm[2].pciha), 0x00000000); | ||
174 | out_le32((void *) &(pcip->pmm[2].ma), 0x00000000); | ||
175 | |||
176 | /* Enable PTM1 and PTM2, mapped to PLB address 0. */ | ||
177 | |||
178 | out_le32((void *) &(pcip->ptm1la), 0x00000000); | ||
179 | out_le32((void *) &(pcip->ptm1ms), 0x00000001); | ||
180 | out_le32((void *) &(pcip->ptm2la), 0x00000000); | ||
181 | out_le32((void *) &(pcip->ptm2ms), 0x00000001); | ||
182 | |||
183 | /* Write zero to PTM1 BAR. */ | ||
184 | |||
185 | early_write_config_dword(hose, hose->first_busno, | ||
186 | PCI_FUNC(hose->first_busno), | ||
187 | PCI_BASE_ADDRESS_1, | ||
188 | 0x00000000); | ||
189 | |||
190 | /* Disable PTM2 (unused) */ | ||
191 | |||
192 | out_le32((void *) &(pcip->ptm2la), 0x00000000); | ||
193 | out_le32((void *) &(pcip->ptm2ms), 0x00000000); | ||
194 | |||
195 | /* end work arround */ | ||
196 | if (ppc_md.progress) | ||
197 | ppc_md.progress("bios_fixup(): done", 0x800); | ||
198 | |||
199 | #ifdef DEBUG | ||
200 | printk("PCI bridge regs after fixup \n"); | ||
201 | for (i = 0; i <= 2; i++) { | ||
202 | printk(" pmm%dma\t0x%x\n", i, in_le32(&(pcip->pmm[i].ma))); | ||
203 | printk(" pmm%dla\t0x%x\n", i, in_le32(&(pcip->pmm[i].la))); | ||
204 | printk(" pmm%dpcila\t0x%x\n", i, | ||
205 | in_le32(&(pcip->pmm[i].pcila))); | ||
206 | printk(" pmm%dpciha\t0x%x\n", i, | ||
207 | in_le32(&(pcip->pmm[i].pciha))); | ||
208 | } | ||
209 | printk(" ptm1ms\t0x%x\n", in_le32(&(pcip->ptm1ms))); | ||
210 | printk(" ptm1la\t0x%x\n", in_le32(&(pcip->ptm1la))); | ||
211 | printk(" ptm2ms\t0x%x\n", in_le32(&(pcip->ptm2ms))); | ||
212 | printk(" ptm2la\t0x%x\n", in_le32(&(pcip->ptm2la))); | ||
213 | |||
214 | for (bar = PCI_BASE_ADDRESS_1; bar <= PCI_BASE_ADDRESS_2; bar += 4) { | ||
215 | early_read_config_dword(hose, hose->first_busno, | ||
216 | PCI_FUNC(hose->first_busno), bar, | ||
217 | &bar_response); | ||
218 | DBG("BUS %d, device %d, Function %d bar 0x%8.8x is 0x%8.8x\n", | ||
219 | hose->first_busno, PCI_SLOT(hose->first_busno), | ||
220 | PCI_FUNC(hose->first_busno), bar, bar_response); | ||
221 | } | ||
222 | |||
223 | |||
224 | #endif | ||
225 | } | ||
226 | |||
227 | void __init | ||
228 | ash_map_io(void) | ||
229 | { | ||
230 | ppc4xx_map_io(); | ||
231 | io_block_mapping(ASH_RTC_VADDR, ASH_RTC_PADDR, ASH_RTC_SIZE, _PAGE_IO); | ||
232 | } | ||
233 | |||
234 | void __init | ||
235 | platform_init(unsigned long r3, unsigned long r4, unsigned long r5, | ||
236 | unsigned long r6, unsigned long r7) | ||
237 | { | ||
238 | ppc4xx_init(r3, r4, r5, r6, r7); | ||
239 | |||
240 | ppc_md.setup_arch = ash_setup_arch; | ||
241 | ppc_md.setup_io_mappings = ash_map_io; | ||
242 | |||
243 | #ifdef CONFIG_PPC_RTC | ||
244 | ppc_md.time_init = todc_time_init; | ||
245 | ppc_md.set_rtc_time = todc_set_rtc_time; | ||
246 | ppc_md.get_rtc_time = todc_get_rtc_time; | ||
247 | ppc_md.nvram_read_val = todc_direct_read_val; | ||
248 | ppc_md.nvram_write_val = todc_direct_write_val; | ||
249 | #endif | ||
250 | } | ||
diff --git a/arch/ppc/platforms/4xx/ash.h b/arch/ppc/platforms/4xx/ash.h new file mode 100644 index 000000000000..5f7448ea418d --- /dev/null +++ b/arch/ppc/platforms/4xx/ash.h | |||
@@ -0,0 +1,83 @@ | |||
1 | /* | ||
2 | * arch/ppc/platforms/4xx/ash.h | ||
3 | * | ||
4 | * Macros, definitions, and data structures specific to the IBM PowerPC | ||
5 | * Ash eval board. | ||
6 | * | ||
7 | * Author: Armin Kuster <akuster@mvista.com> | ||
8 | * | ||
9 | * 2000-2002 (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 | #ifdef __KERNEL__ | ||
16 | #ifndef __ASM_ASH_H__ | ||
17 | #define __ASM_ASH_H__ | ||
18 | #include <platforms/4xx/ibmnp405h.h> | ||
19 | |||
20 | #ifndef __ASSEMBLY__ | ||
21 | /* | ||
22 | * Data structure defining board information maintained by the boot | ||
23 | * ROM on IBM's "Ash" evaluation board. An effort has been made to | ||
24 | * keep the field names consistent with the 8xx 'bd_t' board info | ||
25 | * structures. | ||
26 | */ | ||
27 | |||
28 | typedef struct board_info { | ||
29 | unsigned char bi_s_version[4]; /* Version of this structure */ | ||
30 | unsigned char bi_r_version[30]; /* Version of the IBM ROM */ | ||
31 | unsigned int bi_memsize; /* DRAM installed, in bytes */ | ||
32 | unsigned char bi_enetaddr[4][6]; /* Local Ethernet MAC address */ | ||
33 | unsigned char bi_pci_enetaddr[6]; | ||
34 | unsigned int bi_intfreq; /* Processor speed, in Hz */ | ||
35 | unsigned int bi_busfreq; /* PLB Bus speed, in Hz */ | ||
36 | unsigned int bi_pci_busfreq; /* PCI speed in Hz */ | ||
37 | } bd_t; | ||
38 | |||
39 | /* Some 4xx parts use a different timebase frequency from the internal clock. | ||
40 | */ | ||
41 | #define bi_tbfreq bi_intfreq | ||
42 | |||
43 | /* Memory map for the IBM "Ash" NP405H evaluation board. | ||
44 | */ | ||
45 | |||
46 | extern void *ash_rtc_base; | ||
47 | #define ASH_RTC_PADDR ((uint)0xf0000000) | ||
48 | #define ASH_RTC_VADDR ASH_RTC_PADDR | ||
49 | #define ASH_RTC_SIZE ((uint)8*1024) | ||
50 | |||
51 | |||
52 | /* Early initialization address mapping for block_io. | ||
53 | * Standard 405GP map. | ||
54 | */ | ||
55 | #define PPC4xx_PCI_IO_PADDR ((uint)PPC405_PCI_PHY_IO_BASE) | ||
56 | #define PPC4xx_PCI_IO_VADDR PPC4xx_PCI_IO_PADDR | ||
57 | #define PPC4xx_PCI_IO_SIZE ((uint)64*1024) | ||
58 | #define PPC4xx_PCI_CFG_PADDR ((uint)PPC405_PCI_CONFIG_ADDR) | ||
59 | #define PPC4xx_PCI_CFG_VADDR PPC4xx_PCI_CFG_PADDR | ||
60 | #define PPC4xx_PCI_CFG_SIZE ((uint)4*1024) | ||
61 | #define PPC4xx_PCI_LCFG_PADDR ((uint)0xef400000) | ||
62 | #define PPC4xx_PCI_LCFG_VADDR PPC4xx_PCI_LCFG_PADDR | ||
63 | #define PPC4xx_PCI_LCFG_SIZE ((uint)4*1024) | ||
64 | #define PPC4xx_ONB_IO_PADDR ((uint)0xef600000) | ||
65 | #define PPC4xx_ONB_IO_VADDR PPC4xx_ONB_IO_PADDR | ||
66 | #define PPC4xx_ONB_IO_SIZE ((uint)4*1024) | ||
67 | |||
68 | #define NR_BOARD_IRQS 32 | ||
69 | |||
70 | #ifdef CONFIG_PPC405GP_INTERNAL_CLOCK | ||
71 | #define BASE_BAUD 201600 | ||
72 | #else | ||
73 | #define BASE_BAUD 691200 | ||
74 | #endif | ||
75 | |||
76 | #define PPC4xx_MACHINE_NAME "IBM NP405H Ash" | ||
77 | |||
78 | extern char pci_irq_table[][4]; | ||
79 | |||
80 | |||
81 | #endif /* !__ASSEMBLY__ */ | ||
82 | #endif /* __ASM_ASH_H__ */ | ||
83 | #endif /* __KERNEL__ */ | ||
diff --git a/arch/ppc/platforms/4xx/bubinga.c b/arch/ppc/platforms/4xx/bubinga.c new file mode 100644 index 000000000000..3678abf86313 --- /dev/null +++ b/arch/ppc/platforms/4xx/bubinga.c | |||
@@ -0,0 +1,263 @@ | |||
1 | /* | ||
2 | * Support for IBM PPC 405EP evaluation board (Bubinga). | ||
3 | * | ||
4 | * Author: SAW (IBM), derived from walnut.c. | ||
5 | * Maintained by MontaVista Software <source@mvista.com> | ||
6 | * | ||
7 | * 2003 (c) MontaVista Softare Inc. This file is licensed under the | ||
8 | * terms of the GNU General Public License version 2. This program is | ||
9 | * licensed "as is" without any warranty of any kind, whether express | ||
10 | * or implied. | ||
11 | */ | ||
12 | |||
13 | #include <linux/config.h> | ||
14 | #include <linux/init.h> | ||
15 | #include <linux/smp.h> | ||
16 | #include <linux/threads.h> | ||
17 | #include <linux/param.h> | ||
18 | #include <linux/string.h> | ||
19 | #include <linux/blkdev.h> | ||
20 | #include <linux/pci.h> | ||
21 | #include <linux/rtc.h> | ||
22 | #include <linux/tty.h> | ||
23 | #include <linux/serial.h> | ||
24 | #include <linux/serial_core.h> | ||
25 | |||
26 | #include <asm/system.h> | ||
27 | #include <asm/pci-bridge.h> | ||
28 | #include <asm/processor.h> | ||
29 | #include <asm/machdep.h> | ||
30 | #include <asm/page.h> | ||
31 | #include <asm/time.h> | ||
32 | #include <asm/io.h> | ||
33 | #include <asm/todc.h> | ||
34 | #include <asm/kgdb.h> | ||
35 | #include <asm/ocp.h> | ||
36 | #include <asm/ibm_ocp_pci.h> | ||
37 | |||
38 | #include <platforms/4xx/ibm405ep.h> | ||
39 | |||
40 | #undef DEBUG | ||
41 | |||
42 | #ifdef DEBUG | ||
43 | #define DBG(x...) printk(x) | ||
44 | #else | ||
45 | #define DBG(x...) | ||
46 | #endif | ||
47 | |||
48 | extern bd_t __res; | ||
49 | |||
50 | void *bubinga_rtc_base; | ||
51 | |||
52 | /* Some IRQs unique to the board | ||
53 | * Used by the generic 405 PCI setup functions in ppc4xx_pci.c | ||
54 | */ | ||
55 | int __init | ||
56 | ppc405_map_irq(struct pci_dev *dev, unsigned char idsel, unsigned char pin) | ||
57 | { | ||
58 | static char pci_irq_table[][4] = | ||
59 | /* | ||
60 | * PCI IDSEL/INTPIN->INTLINE | ||
61 | * A B C D | ||
62 | */ | ||
63 | { | ||
64 | {28, 28, 28, 28}, /* IDSEL 1 - PCI slot 1 */ | ||
65 | {29, 29, 29, 29}, /* IDSEL 2 - PCI slot 2 */ | ||
66 | {30, 30, 30, 30}, /* IDSEL 3 - PCI slot 3 */ | ||
67 | {31, 31, 31, 31}, /* IDSEL 4 - PCI slot 4 */ | ||
68 | }; | ||
69 | |||
70 | const long min_idsel = 1, max_idsel = 4, irqs_per_slot = 4; | ||
71 | return PCI_IRQ_TABLE_LOOKUP; | ||
72 | }; | ||
73 | |||
74 | /* The serial clock for the chip is an internal clock determined by | ||
75 | * different clock speeds/dividers. | ||
76 | * Calculate the proper input baud rate and setup the serial driver. | ||
77 | */ | ||
78 | static void __init | ||
79 | bubinga_early_serial_map(void) | ||
80 | { | ||
81 | u32 uart_div; | ||
82 | int uart_clock; | ||
83 | struct uart_port port; | ||
84 | |||
85 | /* Calculate the serial clock input frequency | ||
86 | * | ||
87 | * The base baud is the PLL OUTA (provided in the board info | ||
88 | * structure) divided by the external UART Divisor, divided | ||
89 | * by 16. | ||
90 | */ | ||
91 | uart_div = (mfdcr(DCRN_CPC0_UCR_BASE) & DCRN_CPC0_UCR_U0DIV); | ||
92 | uart_clock = __res.bi_pllouta_freq / uart_div; | ||
93 | |||
94 | /* Setup serial port access */ | ||
95 | memset(&port, 0, sizeof(port)); | ||
96 | port.membase = (void*)ACTING_UART0_IO_BASE; | ||
97 | port.irq = ACTING_UART0_INT; | ||
98 | port.uartclk = uart_clock; | ||
99 | port.regshift = 0; | ||
100 | port.iotype = SERIAL_IO_MEM; | ||
101 | port.flags = ASYNC_BOOT_AUTOCONF | ASYNC_SKIP_TEST; | ||
102 | port.line = 0; | ||
103 | |||
104 | if (early_serial_setup(&port) != 0) { | ||
105 | printk("Early serial init of port 0 failed\n"); | ||
106 | } | ||
107 | |||
108 | port.membase = (void*)ACTING_UART1_IO_BASE; | ||
109 | port.irq = ACTING_UART1_INT; | ||
110 | port.line = 1; | ||
111 | |||
112 | if (early_serial_setup(&port) != 0) { | ||
113 | printk("Early serial init of port 1 failed\n"); | ||
114 | } | ||
115 | } | ||
116 | |||
117 | void __init | ||
118 | bios_fixup(struct pci_controller *hose, struct pcil0_regs *pcip) | ||
119 | { | ||
120 | |||
121 | unsigned int bar_response, bar; | ||
122 | /* | ||
123 | * Expected PCI mapping: | ||
124 | * | ||
125 | * PLB addr PCI memory addr | ||
126 | * --------------------- --------------------- | ||
127 | * 0000'0000 - 7fff'ffff <--- 0000'0000 - 7fff'ffff | ||
128 | * 8000'0000 - Bfff'ffff ---> 8000'0000 - Bfff'ffff | ||
129 | * | ||
130 | * PLB addr PCI io addr | ||
131 | * --------------------- --------------------- | ||
132 | * e800'0000 - e800'ffff ---> 0000'0000 - 0001'0000 | ||
133 | * | ||
134 | * The following code is simplified by assuming that the bootrom | ||
135 | * has been well behaved in following this mapping. | ||
136 | */ | ||
137 | |||
138 | #ifdef DEBUG | ||
139 | int i; | ||
140 | |||
141 | printk("ioremap PCLIO_BASE = 0x%x\n", pcip); | ||
142 | printk("PCI bridge regs before fixup \n"); | ||
143 | for (i = 0; i <= 3; i++) { | ||
144 | printk(" pmm%dma\t0x%x\n", i, in_le32(&(pcip->pmm[i].ma))); | ||
145 | printk(" pmm%dma\t0x%x\n", i, in_le32(&(pcip->pmm[i].la))); | ||
146 | printk(" pmm%dma\t0x%x\n", i, in_le32(&(pcip->pmm[i].pcila))); | ||
147 | printk(" pmm%dma\t0x%x\n", i, in_le32(&(pcip->pmm[i].pciha))); | ||
148 | } | ||
149 | printk(" ptm1ms\t0x%x\n", in_le32(&(pcip->ptm1ms))); | ||
150 | printk(" ptm1la\t0x%x\n", in_le32(&(pcip->ptm1la))); | ||
151 | printk(" ptm2ms\t0x%x\n", in_le32(&(pcip->ptm2ms))); | ||
152 | printk(" ptm2la\t0x%x\n", in_le32(&(pcip->ptm2la))); | ||
153 | |||
154 | #endif | ||
155 | |||
156 | /* added for IBM boot rom version 1.15 bios bar changes -AK */ | ||
157 | |||
158 | /* Disable region first */ | ||
159 | out_le32((void *) &(pcip->pmm[0].ma), 0x00000000); | ||
160 | /* PLB starting addr, PCI: 0x80000000 */ | ||
161 | out_le32((void *) &(pcip->pmm[0].la), 0x80000000); | ||
162 | /* PCI start addr, 0x80000000 */ | ||
163 | out_le32((void *) &(pcip->pmm[0].pcila), PPC405_PCI_MEM_BASE); | ||
164 | /* 512MB range of PLB to PCI */ | ||
165 | out_le32((void *) &(pcip->pmm[0].pciha), 0x00000000); | ||
166 | /* Enable no pre-fetch, enable region */ | ||
167 | out_le32((void *) &(pcip->pmm[0].ma), ((0xffffffff - | ||
168 | (PPC405_PCI_UPPER_MEM - | ||
169 | PPC405_PCI_MEM_BASE)) | 0x01)); | ||
170 | |||
171 | /* Disable region one */ | ||
172 | out_le32((void *) &(pcip->pmm[1].ma), 0x00000000); | ||
173 | out_le32((void *) &(pcip->pmm[1].la), 0x00000000); | ||
174 | out_le32((void *) &(pcip->pmm[1].pcila), 0x00000000); | ||
175 | out_le32((void *) &(pcip->pmm[1].pciha), 0x00000000); | ||
176 | out_le32((void *) &(pcip->pmm[1].ma), 0x00000000); | ||
177 | out_le32((void *) &(pcip->ptm1ms), 0x00000001); | ||
178 | |||
179 | /* Disable region two */ | ||
180 | out_le32((void *) &(pcip->pmm[2].ma), 0x00000000); | ||
181 | out_le32((void *) &(pcip->pmm[2].la), 0x00000000); | ||
182 | out_le32((void *) &(pcip->pmm[2].pcila), 0x00000000); | ||
183 | out_le32((void *) &(pcip->pmm[2].pciha), 0x00000000); | ||
184 | out_le32((void *) &(pcip->pmm[2].ma), 0x00000000); | ||
185 | out_le32((void *) &(pcip->ptm2ms), 0x00000000); | ||
186 | out_le32((void *) &(pcip->ptm2la), 0x00000000); | ||
187 | |||
188 | /* Zero config bars */ | ||
189 | for (bar = PCI_BASE_ADDRESS_1; bar <= PCI_BASE_ADDRESS_2; bar += 4) { | ||
190 | early_write_config_dword(hose, hose->first_busno, | ||
191 | PCI_FUNC(hose->first_busno), bar, | ||
192 | 0x00000000); | ||
193 | early_read_config_dword(hose, hose->first_busno, | ||
194 | PCI_FUNC(hose->first_busno), bar, | ||
195 | &bar_response); | ||
196 | DBG("BUS %d, device %d, Function %d bar 0x%8.8x is 0x%8.8x\n", | ||
197 | hose->first_busno, PCI_SLOT(hose->first_busno), | ||
198 | PCI_FUNC(hose->first_busno), bar, bar_response); | ||
199 | } | ||
200 | /* end work arround */ | ||
201 | |||
202 | #ifdef DEBUG | ||
203 | printk("PCI bridge regs after fixup \n"); | ||
204 | for (i = 0; i <= 3; i++) { | ||
205 | printk(" pmm%dma\t0x%x\n", i, in_le32(&(pcip->pmm[i].ma))); | ||
206 | printk(" pmm%dma\t0x%x\n", i, in_le32(&(pcip->pmm[i].la))); | ||
207 | printk(" pmm%dma\t0x%x\n", i, in_le32(&(pcip->pmm[i].pcila))); | ||
208 | printk(" pmm%dma\t0x%x\n", i, in_le32(&(pcip->pmm[i].pciha))); | ||
209 | } | ||
210 | printk(" ptm1ms\t0x%x\n", in_le32(&(pcip->ptm1ms))); | ||
211 | printk(" ptm1la\t0x%x\n", in_le32(&(pcip->ptm1la))); | ||
212 | printk(" ptm2ms\t0x%x\n", in_le32(&(pcip->ptm2ms))); | ||
213 | printk(" ptm2la\t0x%x\n", in_le32(&(pcip->ptm2la))); | ||
214 | |||
215 | #endif | ||
216 | } | ||
217 | |||
218 | void __init | ||
219 | bubinga_setup_arch(void) | ||
220 | { | ||
221 | ppc4xx_setup_arch(); | ||
222 | |||
223 | ibm_ocp_set_emac(0, 1); | ||
224 | |||
225 | bubinga_early_serial_map(); | ||
226 | |||
227 | /* RTC step for the evb405ep */ | ||
228 | bubinga_rtc_base = (void *) BUBINGA_RTC_VADDR; | ||
229 | TODC_INIT(TODC_TYPE_DS1743, bubinga_rtc_base, bubinga_rtc_base, | ||
230 | bubinga_rtc_base, 8); | ||
231 | /* Identify the system */ | ||
232 | printk("IBM Bubinga port (MontaVista Software, Inc. <source@mvista.com>)\n"); | ||
233 | } | ||
234 | |||
235 | void __init | ||
236 | bubinga_map_io(void) | ||
237 | { | ||
238 | ppc4xx_map_io(); | ||
239 | io_block_mapping(BUBINGA_RTC_VADDR, | ||
240 | BUBINGA_RTC_PADDR, BUBINGA_RTC_SIZE, _PAGE_IO); | ||
241 | } | ||
242 | |||
243 | void __init | ||
244 | platform_init(unsigned long r3, unsigned long r4, unsigned long r5, | ||
245 | unsigned long r6, unsigned long r7) | ||
246 | { | ||
247 | ppc4xx_init(r3, r4, r5, r6, r7); | ||
248 | |||
249 | ppc_md.setup_arch = bubinga_setup_arch; | ||
250 | ppc_md.setup_io_mappings = bubinga_map_io; | ||
251 | |||
252 | #ifdef CONFIG_GEN_RTC | ||
253 | ppc_md.time_init = todc_time_init; | ||
254 | ppc_md.set_rtc_time = todc_set_rtc_time; | ||
255 | ppc_md.get_rtc_time = todc_get_rtc_time; | ||
256 | ppc_md.nvram_read_val = todc_direct_read_val; | ||
257 | ppc_md.nvram_write_val = todc_direct_write_val; | ||
258 | #endif | ||
259 | #ifdef CONFIG_KGDB | ||
260 | ppc_md.early_serial_map = bubinga_early_serial_map; | ||
261 | #endif | ||
262 | } | ||
263 | |||
diff --git a/arch/ppc/platforms/4xx/bubinga.h b/arch/ppc/platforms/4xx/bubinga.h new file mode 100644 index 000000000000..b1df856f8e22 --- /dev/null +++ b/arch/ppc/platforms/4xx/bubinga.h | |||
@@ -0,0 +1,69 @@ | |||
1 | /* | ||
2 | * Support for IBM PPC 405EP evaluation board (Bubinga). | ||
3 | * | ||
4 | * Author: SAW (IBM), derived from walnut.h. | ||
5 | * Maintained by MontaVista Software <source@mvista.com> | ||
6 | * | ||
7 | * 2003 (c) MontaVista Softare Inc. This file is licensed under the | ||
8 | * terms of the GNU General Public License version 2. This program is | ||
9 | * licensed "as is" without any warranty of any kind, whether express | ||
10 | * or implied. | ||
11 | */ | ||
12 | |||
13 | #ifdef __KERNEL__ | ||
14 | #ifndef __BUBINGA_H__ | ||
15 | #define __BUBINGA_H__ | ||
16 | |||
17 | /* 405EP */ | ||
18 | #include <platforms/4xx/ibm405ep.h> | ||
19 | |||
20 | #ifndef __ASSEMBLY__ | ||
21 | /* | ||
22 | * Data structure defining board information maintained by the boot | ||
23 | * ROM on IBM's evaluation board. An effort has been made to | ||
24 | * keep the field names consistent with the 8xx 'bd_t' board info | ||
25 | * structures. | ||
26 | */ | ||
27 | |||
28 | typedef struct board_info { | ||
29 | unsigned char bi_s_version[4]; /* Version of this structure */ | ||
30 | unsigned char bi_r_version[30]; /* Version of the IBM ROM */ | ||
31 | unsigned int bi_memsize; /* DRAM installed, in bytes */ | ||
32 | unsigned char bi_enetaddr[2][6]; /* Local Ethernet MAC address */ unsigned char bi_pci_enetaddr[6]; /* PCI Ethernet MAC address */ | ||
33 | unsigned int bi_intfreq; /* Processor speed, in Hz */ | ||
34 | unsigned int bi_busfreq; /* PLB Bus speed, in Hz */ | ||
35 | unsigned int bi_pci_busfreq; /* PCI Bus speed, in Hz */ | ||
36 | unsigned int bi_opb_busfreq; /* OPB Bus speed, in Hz */ | ||
37 | unsigned int bi_pllouta_freq; /* PLL OUTA speed, in Hz */ | ||
38 | } bd_t; | ||
39 | |||
40 | /* Some 4xx parts use a different timebase frequency from the internal clock. | ||
41 | */ | ||
42 | #define bi_tbfreq bi_intfreq | ||
43 | |||
44 | |||
45 | /* Memory map for the Bubinga board. | ||
46 | * Generic 4xx plus RTC. | ||
47 | */ | ||
48 | |||
49 | extern void *bubinga_rtc_base; | ||
50 | #define BUBINGA_RTC_PADDR ((uint)0xf0000000) | ||
51 | #define BUBINGA_RTC_VADDR BUBINGA_RTC_PADDR | ||
52 | #define BUBINGA_RTC_SIZE ((uint)8*1024) | ||
53 | |||
54 | /* The UART clock is based off an internal clock - | ||
55 | * define BASE_BAUD based on the internal clock and divider(s). | ||
56 | * Since BASE_BAUD must be a constant, we will initialize it | ||
57 | * using clock/divider values which OpenBIOS initializes | ||
58 | * for typical configurations at various CPU speeds. | ||
59 | * The base baud is calculated as (FWDA / EXT UART DIV / 16) | ||
60 | */ | ||
61 | #define BASE_BAUD 0 | ||
62 | |||
63 | #define BUBINGA_FPGA_BASE 0xF0300000 | ||
64 | |||
65 | #define PPC4xx_MACHINE_NAME "IBM Bubinga" | ||
66 | |||
67 | #endif /* !__ASSEMBLY__ */ | ||
68 | #endif /* __BUBINGA_H__ */ | ||
69 | #endif /* __KERNEL__ */ | ||
diff --git a/arch/ppc/platforms/4xx/cpci405.c b/arch/ppc/platforms/4xx/cpci405.c new file mode 100644 index 000000000000..ff966773a0bf --- /dev/null +++ b/arch/ppc/platforms/4xx/cpci405.c | |||
@@ -0,0 +1,84 @@ | |||
1 | /* | ||
2 | * arch/ppc/platforms/cpci405.c | ||
3 | * | ||
4 | * Board setup routines for the esd CPCI-405 cPCI Board. | ||
5 | * | ||
6 | * Author: Stefan Roese | ||
7 | * stefan.roese@esd-electronics.com | ||
8 | * | ||
9 | * Copyright 2001 esd electronic system design - hannover germany | ||
10 | * | ||
11 | * This program is free software; you can redistribute it and/or modify it | ||
12 | * under the terms of the GNU General Public License as published by the | ||
13 | * Free Software Foundation; either version 2 of the License, or (at your | ||
14 | * option) any later version. | ||
15 | * | ||
16 | */ | ||
17 | |||
18 | #include <linux/config.h> | ||
19 | #include <linux/init.h> | ||
20 | #include <linux/pci.h> | ||
21 | #include <asm/system.h> | ||
22 | #include <asm/pci-bridge.h> | ||
23 | #include <asm/machdep.h> | ||
24 | #include <asm/todc.h> | ||
25 | #include <asm/ocp.h> | ||
26 | |||
27 | void *cpci405_nvram; | ||
28 | |||
29 | /* | ||
30 | * Some IRQs unique to CPCI-405. | ||
31 | */ | ||
32 | int __init | ||
33 | ppc405_map_irq(struct pci_dev *dev, unsigned char idsel, unsigned char pin) | ||
34 | { | ||
35 | static char pci_irq_table[][4] = | ||
36 | /* | ||
37 | * PCI IDSEL/INTPIN->INTLINE | ||
38 | * A B C D | ||
39 | */ | ||
40 | { | ||
41 | {28, 28, 28, 28}, /* IDSEL 15 - cPCI slot 8 */ | ||
42 | {29, 29, 29, 29}, /* IDSEL 16 - cPCI slot 7 */ | ||
43 | {30, 30, 30, 30}, /* IDSEL 17 - cPCI slot 6 */ | ||
44 | {27, 27, 27, 27}, /* IDSEL 18 - cPCI slot 5 */ | ||
45 | {28, 28, 28, 28}, /* IDSEL 19 - cPCI slot 4 */ | ||
46 | {29, 29, 29, 29}, /* IDSEL 20 - cPCI slot 3 */ | ||
47 | {30, 30, 30, 30}, /* IDSEL 21 - cPCI slot 2 */ | ||
48 | }; | ||
49 | const long min_idsel = 15, max_idsel = 21, irqs_per_slot = 4; | ||
50 | return PCI_IRQ_TABLE_LOOKUP; | ||
51 | }; | ||
52 | |||
53 | void __init | ||
54 | cpci405_setup_arch(void) | ||
55 | { | ||
56 | ppc4xx_setup_arch(); | ||
57 | |||
58 | ibm_ocp_set_emac(0, 0); | ||
59 | |||
60 | TODC_INIT(TODC_TYPE_MK48T35, cpci405_nvram, cpci405_nvram, cpci405_nvram, 8); | ||
61 | } | ||
62 | |||
63 | void __init | ||
64 | cpci405_map_io(void) | ||
65 | { | ||
66 | ppc4xx_map_io(); | ||
67 | cpci405_nvram = ioremap(CPCI405_NVRAM_PADDR, CPCI405_NVRAM_SIZE); | ||
68 | } | ||
69 | |||
70 | void __init | ||
71 | platform_init(unsigned long r3, unsigned long r4, unsigned long r5, | ||
72 | unsigned long r6, unsigned long r7) | ||
73 | { | ||
74 | ppc4xx_init(r3, r4, r5, r6, r7); | ||
75 | |||
76 | ppc_md.setup_arch = cpci405_setup_arch; | ||
77 | ppc_md.setup_io_mappings = cpci405_map_io; | ||
78 | |||
79 | ppc_md.time_init = todc_time_init; | ||
80 | ppc_md.set_rtc_time = todc_set_rtc_time; | ||
81 | ppc_md.get_rtc_time = todc_get_rtc_time; | ||
82 | ppc_md.nvram_read_val = todc_direct_read_val; | ||
83 | ppc_md.nvram_write_val = todc_direct_write_val; | ||
84 | } | ||
diff --git a/arch/ppc/platforms/4xx/cpci405.h b/arch/ppc/platforms/4xx/cpci405.h new file mode 100644 index 000000000000..e27f7cb650d8 --- /dev/null +++ b/arch/ppc/platforms/4xx/cpci405.h | |||
@@ -0,0 +1,37 @@ | |||
1 | /* | ||
2 | * CPCI-405 board specific definitions | ||
3 | * | ||
4 | * Copyright (c) 2001 Stefan Roese (stefan.roese@esd-electronics.com) | ||
5 | */ | ||
6 | |||
7 | #ifdef __KERNEL__ | ||
8 | #ifndef __ASM_CPCI405_H__ | ||
9 | #define __ASM_CPCI405_H__ | ||
10 | |||
11 | #include <linux/config.h> | ||
12 | |||
13 | /* We have a 405GP core */ | ||
14 | #include <platforms/4xx/ibm405gp.h> | ||
15 | |||
16 | #include <asm/ppcboot.h> | ||
17 | |||
18 | #ifndef __ASSEMBLY__ | ||
19 | /* Some 4xx parts use a different timebase frequency from the internal clock. | ||
20 | */ | ||
21 | #define bi_tbfreq bi_intfreq | ||
22 | |||
23 | /* Map for the NVRAM space */ | ||
24 | #define CPCI405_NVRAM_PADDR ((uint)0xf0200000) | ||
25 | #define CPCI405_NVRAM_SIZE ((uint)32*1024) | ||
26 | |||
27 | #ifdef CONFIG_PPC405GP_INTERNAL_CLOCK | ||
28 | #define BASE_BAUD 201600 | ||
29 | #else | ||
30 | #define BASE_BAUD 691200 | ||
31 | #endif | ||
32 | |||
33 | #define PPC4xx_MACHINE_NAME "esd CPCI-405" | ||
34 | |||
35 | #endif /* !__ASSEMBLY__ */ | ||
36 | #endif /* __ASM_CPCI405_H__ */ | ||
37 | #endif /* __KERNEL__ */ | ||
diff --git a/arch/ppc/platforms/4xx/ebony.c b/arch/ppc/platforms/4xx/ebony.c new file mode 100644 index 000000000000..f63bca83e757 --- /dev/null +++ b/arch/ppc/platforms/4xx/ebony.c | |||
@@ -0,0 +1,356 @@ | |||
1 | /* | ||
2 | * arch/ppc/platforms/4xx/ebony.c | ||
3 | * | ||
4 | * Ebony board specific routines | ||
5 | * | ||
6 | * Matt Porter <mporter@kernel.crashing.org> | ||
7 | * Copyright 2002-2005 MontaVista Software Inc. | ||
8 | * | ||
9 | * Eugene Surovegin <eugene.surovegin@zultys.com> or <ebs@ebshome.net> | ||
10 | * Copyright (c) 2003, 2004 Zultys Technologies | ||
11 | * | ||
12 | * This program is free software; you can redistribute it and/or modify it | ||
13 | * under the terms of the GNU General Public License as published by the | ||
14 | * Free Software Foundation; either version 2 of the License, or (at your | ||
15 | * option) any later version. | ||
16 | */ | ||
17 | |||
18 | #include <linux/config.h> | ||
19 | #include <linux/stddef.h> | ||
20 | #include <linux/kernel.h> | ||
21 | #include <linux/init.h> | ||
22 | #include <linux/errno.h> | ||
23 | #include <linux/reboot.h> | ||
24 | #include <linux/pci.h> | ||
25 | #include <linux/kdev_t.h> | ||
26 | #include <linux/types.h> | ||
27 | #include <linux/major.h> | ||
28 | #include <linux/blkdev.h> | ||
29 | #include <linux/console.h> | ||
30 | #include <linux/delay.h> | ||
31 | #include <linux/ide.h> | ||
32 | #include <linux/initrd.h> | ||
33 | #include <linux/irq.h> | ||
34 | #include <linux/seq_file.h> | ||
35 | #include <linux/root_dev.h> | ||
36 | #include <linux/tty.h> | ||
37 | #include <linux/serial.h> | ||
38 | #include <linux/serial_core.h> | ||
39 | |||
40 | #include <asm/system.h> | ||
41 | #include <asm/pgtable.h> | ||
42 | #include <asm/page.h> | ||
43 | #include <asm/dma.h> | ||
44 | #include <asm/io.h> | ||
45 | #include <asm/machdep.h> | ||
46 | #include <asm/ocp.h> | ||
47 | #include <asm/pci-bridge.h> | ||
48 | #include <asm/time.h> | ||
49 | #include <asm/todc.h> | ||
50 | #include <asm/bootinfo.h> | ||
51 | #include <asm/ppc4xx_pic.h> | ||
52 | #include <asm/ppcboot.h> | ||
53 | |||
54 | #include <syslib/gen550.h> | ||
55 | #include <syslib/ibm440gp_common.h> | ||
56 | |||
57 | /* | ||
58 | * This is a horrible kludge, we eventually need to abstract this | ||
59 | * generic PHY stuff, so the standard phy mode defines can be | ||
60 | * easily used from arch code. | ||
61 | */ | ||
62 | #include "../../../../drivers/net/ibm_emac/ibm_emac_phy.h" | ||
63 | |||
64 | bd_t __res; | ||
65 | |||
66 | static struct ibm44x_clocks clocks __initdata; | ||
67 | |||
68 | /* | ||
69 | * Ebony external IRQ triggering/polarity settings | ||
70 | */ | ||
71 | unsigned char ppc4xx_uic_ext_irq_cfg[] __initdata = { | ||
72 | (IRQ_SENSE_LEVEL | IRQ_POLARITY_NEGATIVE), /* IRQ0: PCI slot 0 */ | ||
73 | (IRQ_SENSE_LEVEL | IRQ_POLARITY_NEGATIVE), /* IRQ1: PCI slot 1 */ | ||
74 | (IRQ_SENSE_LEVEL | IRQ_POLARITY_NEGATIVE), /* IRQ2: PCI slot 2 */ | ||
75 | (IRQ_SENSE_LEVEL | IRQ_POLARITY_NEGATIVE), /* IRQ3: PCI slot 3 */ | ||
76 | (IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE), /* IRQ4: IRDA */ | ||
77 | (IRQ_SENSE_EDGE | IRQ_POLARITY_NEGATIVE), /* IRQ5: SMI pushbutton */ | ||
78 | (IRQ_SENSE_LEVEL | IRQ_POLARITY_NEGATIVE), /* IRQ6: PHYs */ | ||
79 | (IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE), /* IRQ7: AUX */ | ||
80 | (IRQ_SENSE_LEVEL | IRQ_POLARITY_NEGATIVE), /* IRQ8: EXT */ | ||
81 | (IRQ_SENSE_LEVEL | IRQ_POLARITY_NEGATIVE), /* IRQ9: EXT */ | ||
82 | (IRQ_SENSE_LEVEL | IRQ_POLARITY_NEGATIVE), /* IRQ10: EXT */ | ||
83 | (IRQ_SENSE_LEVEL | IRQ_POLARITY_NEGATIVE), /* IRQ11: EXT */ | ||
84 | (IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE), /* IRQ12: EXT */ | ||
85 | }; | ||
86 | |||
87 | static void __init | ||
88 | ebony_calibrate_decr(void) | ||
89 | { | ||
90 | unsigned int freq; | ||
91 | |||
92 | /* | ||
93 | * Determine system clock speed | ||
94 | * | ||
95 | * If we are on Rev. B silicon, then use | ||
96 | * default external system clock. If we are | ||
97 | * on Rev. C silicon then errata forces us to | ||
98 | * use the internal clock. | ||
99 | */ | ||
100 | switch (PVR_REV(mfspr(SPRN_PVR))) { | ||
101 | case PVR_REV(PVR_440GP_RB): | ||
102 | freq = EBONY_440GP_RB_SYSCLK; | ||
103 | break; | ||
104 | case PVR_REV(PVR_440GP_RC1): | ||
105 | default: | ||
106 | freq = EBONY_440GP_RC_SYSCLK; | ||
107 | break; | ||
108 | } | ||
109 | |||
110 | ibm44x_calibrate_decr(freq); | ||
111 | } | ||
112 | |||
113 | static int | ||
114 | ebony_show_cpuinfo(struct seq_file *m) | ||
115 | { | ||
116 | seq_printf(m, "vendor\t\t: IBM\n"); | ||
117 | seq_printf(m, "machine\t\t: Ebony\n"); | ||
118 | |||
119 | return 0; | ||
120 | } | ||
121 | |||
122 | static inline int | ||
123 | ebony_map_irq(struct pci_dev *dev, unsigned char idsel, unsigned char pin) | ||
124 | { | ||
125 | static char pci_irq_table[][4] = | ||
126 | /* | ||
127 | * PCI IDSEL/INTPIN->INTLINE | ||
128 | * A B C D | ||
129 | */ | ||
130 | { | ||
131 | { 23, 23, 23, 23 }, /* IDSEL 1 - PCI Slot 0 */ | ||
132 | { 24, 24, 24, 24 }, /* IDSEL 2 - PCI Slot 1 */ | ||
133 | { 25, 25, 25, 25 }, /* IDSEL 3 - PCI Slot 2 */ | ||
134 | { 26, 26, 26, 26 }, /* IDSEL 4 - PCI Slot 3 */ | ||
135 | }; | ||
136 | |||
137 | const long min_idsel = 1, max_idsel = 4, irqs_per_slot = 4; | ||
138 | return PCI_IRQ_TABLE_LOOKUP; | ||
139 | } | ||
140 | |||
141 | #define PCIX_WRITEL(value, offset) \ | ||
142 | (writel(value, pcix_reg_base + offset)) | ||
143 | |||
144 | /* | ||
145 | * FIXME: This is only here to "make it work". This will move | ||
146 | * to a ibm_pcix.c which will contain a generic IBM PCIX bridge | ||
147 | * configuration library. -Matt | ||
148 | */ | ||
149 | static void __init | ||
150 | ebony_setup_pcix(void) | ||
151 | { | ||
152 | void *pcix_reg_base; | ||
153 | |||
154 | pcix_reg_base = ioremap64(PCIX0_REG_BASE, PCIX_REG_SIZE); | ||
155 | |||
156 | /* Disable all windows */ | ||
157 | PCIX_WRITEL(0, PCIX0_POM0SA); | ||
158 | PCIX_WRITEL(0, PCIX0_POM1SA); | ||
159 | PCIX_WRITEL(0, PCIX0_POM2SA); | ||
160 | PCIX_WRITEL(0, PCIX0_PIM0SA); | ||
161 | PCIX_WRITEL(0, PCIX0_PIM1SA); | ||
162 | PCIX_WRITEL(0, PCIX0_PIM2SA); | ||
163 | |||
164 | /* Setup 2GB PLB->PCI outbound mem window (3_8000_0000->0_8000_0000) */ | ||
165 | PCIX_WRITEL(0x00000003, PCIX0_POM0LAH); | ||
166 | PCIX_WRITEL(0x80000000, PCIX0_POM0LAL); | ||
167 | PCIX_WRITEL(0x00000000, PCIX0_POM0PCIAH); | ||
168 | PCIX_WRITEL(0x80000000, PCIX0_POM0PCIAL); | ||
169 | PCIX_WRITEL(0x80000001, PCIX0_POM0SA); | ||
170 | |||
171 | /* Setup 2GB PCI->PLB inbound memory window at 0, enable MSIs */ | ||
172 | PCIX_WRITEL(0x00000000, PCIX0_PIM0LAH); | ||
173 | PCIX_WRITEL(0x00000000, PCIX0_PIM0LAL); | ||
174 | PCIX_WRITEL(0x80000007, PCIX0_PIM0SA); | ||
175 | |||
176 | eieio(); | ||
177 | } | ||
178 | |||
179 | static void __init | ||
180 | ebony_setup_hose(void) | ||
181 | { | ||
182 | struct pci_controller *hose; | ||
183 | |||
184 | /* Configure windows on the PCI-X host bridge */ | ||
185 | ebony_setup_pcix(); | ||
186 | |||
187 | hose = pcibios_alloc_controller(); | ||
188 | |||
189 | if (!hose) | ||
190 | return; | ||
191 | |||
192 | hose->first_busno = 0; | ||
193 | hose->last_busno = 0xff; | ||
194 | |||
195 | hose->pci_mem_offset = EBONY_PCI_MEM_OFFSET; | ||
196 | |||
197 | pci_init_resource(&hose->io_resource, | ||
198 | EBONY_PCI_LOWER_IO, | ||
199 | EBONY_PCI_UPPER_IO, | ||
200 | IORESOURCE_IO, | ||
201 | "PCI host bridge"); | ||
202 | |||
203 | pci_init_resource(&hose->mem_resources[0], | ||
204 | EBONY_PCI_LOWER_MEM, | ||
205 | EBONY_PCI_UPPER_MEM, | ||
206 | IORESOURCE_MEM, | ||
207 | "PCI host bridge"); | ||
208 | |||
209 | hose->io_space.start = EBONY_PCI_LOWER_IO; | ||
210 | hose->io_space.end = EBONY_PCI_UPPER_IO; | ||
211 | hose->mem_space.start = EBONY_PCI_LOWER_MEM; | ||
212 | hose->mem_space.end = EBONY_PCI_UPPER_MEM; | ||
213 | isa_io_base = | ||
214 | (unsigned long)ioremap64(EBONY_PCI_IO_BASE, EBONY_PCI_IO_SIZE); | ||
215 | hose->io_base_virt = (void *)isa_io_base; | ||
216 | |||
217 | setup_indirect_pci(hose, | ||
218 | EBONY_PCI_CFGA_PLB32, | ||
219 | EBONY_PCI_CFGD_PLB32); | ||
220 | hose->set_cfg_type = 1; | ||
221 | |||
222 | hose->last_busno = pciauto_bus_scan(hose, hose->first_busno); | ||
223 | |||
224 | ppc_md.pci_swizzle = common_swizzle; | ||
225 | ppc_md.pci_map_irq = ebony_map_irq; | ||
226 | } | ||
227 | |||
228 | TODC_ALLOC(); | ||
229 | |||
230 | static void __init | ||
231 | ebony_early_serial_map(void) | ||
232 | { | ||
233 | struct uart_port port; | ||
234 | |||
235 | /* Setup ioremapped serial port access */ | ||
236 | memset(&port, 0, sizeof(port)); | ||
237 | port.membase = ioremap64(PPC440GP_UART0_ADDR, 8); | ||
238 | port.irq = 0; | ||
239 | port.uartclk = clocks.uart0; | ||
240 | port.regshift = 0; | ||
241 | port.iotype = SERIAL_IO_MEM; | ||
242 | port.flags = ASYNC_BOOT_AUTOCONF | ASYNC_SKIP_TEST; | ||
243 | port.line = 0; | ||
244 | |||
245 | if (early_serial_setup(&port) != 0) { | ||
246 | printk("Early serial init of port 0 failed\n"); | ||
247 | } | ||
248 | |||
249 | #if defined(CONFIG_SERIAL_TEXT_DEBUG) || defined(CONFIG_KGDB) | ||
250 | /* Configure debug serial access */ | ||
251 | gen550_init(0, &port); | ||
252 | #endif | ||
253 | |||
254 | port.membase = ioremap64(PPC440GP_UART1_ADDR, 8); | ||
255 | port.irq = 1; | ||
256 | port.uartclk = clocks.uart1; | ||
257 | port.line = 1; | ||
258 | |||
259 | if (early_serial_setup(&port) != 0) { | ||
260 | printk("Early serial init of port 1 failed\n"); | ||
261 | } | ||
262 | |||
263 | #if defined(CONFIG_SERIAL_TEXT_DEBUG) || defined(CONFIG_KGDB) | ||
264 | /* Configure debug serial access */ | ||
265 | gen550_init(1, &port); | ||
266 | #endif | ||
267 | } | ||
268 | |||
269 | static void __init | ||
270 | ebony_setup_arch(void) | ||
271 | { | ||
272 | struct ocp_def *def; | ||
273 | struct ocp_func_emac_data *emacdata; | ||
274 | |||
275 | /* Set mac_addr for each EMAC */ | ||
276 | def = ocp_get_one_device(OCP_VENDOR_IBM, OCP_FUNC_EMAC, 0); | ||
277 | emacdata = def->additions; | ||
278 | emacdata->phy_map = 0x00000001; /* Skip 0x00 */ | ||
279 | emacdata->phy_mode = PHY_MODE_RMII; | ||
280 | memcpy(emacdata->mac_addr, __res.bi_enetaddr, 6); | ||
281 | |||
282 | def = ocp_get_one_device(OCP_VENDOR_IBM, OCP_FUNC_EMAC, 1); | ||
283 | emacdata = def->additions; | ||
284 | emacdata->phy_map = 0x00000001; /* Skip 0x00 */ | ||
285 | emacdata->phy_mode = PHY_MODE_RMII; | ||
286 | memcpy(emacdata->mac_addr, __res.bi_enet1addr, 6); | ||
287 | |||
288 | /* | ||
289 | * Determine various clocks. | ||
290 | * To be completely correct we should get SysClk | ||
291 | * from FPGA, because it can be changed by on-board switches | ||
292 | * --ebs | ||
293 | */ | ||
294 | ibm440gp_get_clocks(&clocks, 33333333, 6 * 1843200); | ||
295 | ocp_sys_info.opb_bus_freq = clocks.opb; | ||
296 | |||
297 | /* Setup TODC access */ | ||
298 | TODC_INIT(TODC_TYPE_DS1743, | ||
299 | 0, | ||
300 | 0, | ||
301 | ioremap64(EBONY_RTC_ADDR, EBONY_RTC_SIZE), | ||
302 | 8); | ||
303 | |||
304 | /* init to some ~sane value until calibrate_delay() runs */ | ||
305 | loops_per_jiffy = 50000000/HZ; | ||
306 | |||
307 | /* Setup PCI host bridge */ | ||
308 | ebony_setup_hose(); | ||
309 | |||
310 | #ifdef CONFIG_BLK_DEV_INITRD | ||
311 | if (initrd_start) | ||
312 | ROOT_DEV = Root_RAM0; | ||
313 | else | ||
314 | #endif | ||
315 | #ifdef CONFIG_ROOT_NFS | ||
316 | ROOT_DEV = Root_NFS; | ||
317 | #else | ||
318 | ROOT_DEV = Root_HDA1; | ||
319 | #endif | ||
320 | |||
321 | ebony_early_serial_map(); | ||
322 | |||
323 | /* Identify the system */ | ||
324 | printk("IBM Ebony port (MontaVista Software, Inc. (source@mvista.com))\n"); | ||
325 | } | ||
326 | |||
327 | void __init platform_init(unsigned long r3, unsigned long r4, | ||
328 | unsigned long r5, unsigned long r6, unsigned long r7) | ||
329 | { | ||
330 | parse_bootinfo(find_bootinfo()); | ||
331 | |||
332 | /* | ||
333 | * If we were passed in a board information, copy it into the | ||
334 | * residual data area. | ||
335 | */ | ||
336 | if (r3) | ||
337 | __res = *(bd_t *)(r3 + KERNELBASE); | ||
338 | |||
339 | ibm44x_platform_init(); | ||
340 | |||
341 | ppc_md.setup_arch = ebony_setup_arch; | ||
342 | ppc_md.show_cpuinfo = ebony_show_cpuinfo; | ||
343 | ppc_md.get_irq = NULL; /* Set in ppc4xx_pic_init() */ | ||
344 | |||
345 | ppc_md.calibrate_decr = ebony_calibrate_decr; | ||
346 | ppc_md.time_init = todc_time_init; | ||
347 | ppc_md.set_rtc_time = todc_set_rtc_time; | ||
348 | ppc_md.get_rtc_time = todc_get_rtc_time; | ||
349 | |||
350 | ppc_md.nvram_read_val = todc_direct_read_val; | ||
351 | ppc_md.nvram_write_val = todc_direct_write_val; | ||
352 | #ifdef CONFIG_KGDB | ||
353 | ppc_md.early_serial_map = ebony_early_serial_map; | ||
354 | #endif | ||
355 | } | ||
356 | |||
diff --git a/arch/ppc/platforms/4xx/ebony.h b/arch/ppc/platforms/4xx/ebony.h new file mode 100644 index 000000000000..47c391c9174d --- /dev/null +++ b/arch/ppc/platforms/4xx/ebony.h | |||
@@ -0,0 +1,91 @@ | |||
1 | /* | ||
2 | * arch/ppc/platforms/ebony.h | ||
3 | * | ||
4 | * Ebony board definitions | ||
5 | * | ||
6 | * Matt Porter <mporter@mvista.com> | ||
7 | * | ||
8 | * Copyright 2002 MontaVista Software Inc. | ||
9 | * | ||
10 | * This program is free software; you can redistribute it and/or modify it | ||
11 | * under the terms of the GNU General Public License as published by the | ||
12 | * Free Software Foundation; either version 2 of the License, or (at your | ||
13 | * option) any later version. | ||
14 | */ | ||
15 | |||
16 | #ifdef __KERNEL__ | ||
17 | #ifndef __ASM_EBONY_H__ | ||
18 | #define __ASM_EBONY_H__ | ||
19 | |||
20 | #include <linux/config.h> | ||
21 | #include <platforms/4xx/ibm440gp.h> | ||
22 | |||
23 | /* F/W TLB mapping used in bootloader glue to reset EMAC */ | ||
24 | #define PPC44x_EMAC0_MR0 0xE0000800 | ||
25 | |||
26 | /* Where to find the MAC info */ | ||
27 | #define EBONY_OPENBIOS_MAC_BASE 0xfffffe0c | ||
28 | #define EBONY_OPENBIOS_MAC_OFFSET 0x0c | ||
29 | |||
30 | /* Default clock rates for Rev. B and Rev. C silicon */ | ||
31 | #define EBONY_440GP_RB_SYSCLK 33000000 | ||
32 | #define EBONY_440GP_RC_SYSCLK 400000000 | ||
33 | |||
34 | /* RTC/NVRAM location */ | ||
35 | #define EBONY_RTC_ADDR 0x0000000148000000ULL | ||
36 | #define EBONY_RTC_SIZE 0x2000 | ||
37 | |||
38 | /* Flash */ | ||
39 | #define EBONY_FPGA_ADDR 0x0000000148300000ULL | ||
40 | #define EBONY_BOOT_SMALL_FLASH(x) (x & 0x20) | ||
41 | #define EBONY_ONBRD_FLASH_EN(x) (x & 0x02) | ||
42 | #define EBONY_FLASH_SEL(x) (x & 0x01) | ||
43 | #define EBONY_SMALL_FLASH_LOW1 0x00000001ff800000ULL | ||
44 | #define EBONY_SMALL_FLASH_LOW2 0x00000001ff880000ULL | ||
45 | #define EBONY_SMALL_FLASH_HIGH1 0x00000001fff00000ULL | ||
46 | #define EBONY_SMALL_FLASH_HIGH2 0x00000001fff80000ULL | ||
47 | #define EBONY_SMALL_FLASH_SIZE 0x80000 | ||
48 | #define EBONY_LARGE_FLASH_LOW 0x00000001ff800000ULL | ||
49 | #define EBONY_LARGE_FLASH_HIGH 0x00000001ffc00000ULL | ||
50 | #define EBONY_LARGE_FLASH_SIZE 0x400000 | ||
51 | |||
52 | #define EBONY_SMALL_FLASH_BASE 0x00000001fff80000ULL | ||
53 | #define EBONY_LARGE_FLASH_BASE 0x00000001ff800000ULL | ||
54 | |||
55 | /* | ||
56 | * Serial port defines | ||
57 | */ | ||
58 | |||
59 | /* OpenBIOS defined UART mappings, used before early_serial_setup */ | ||
60 | #define UART0_IO_BASE 0xE0000200 | ||
61 | #define UART1_IO_BASE 0xE0000300 | ||
62 | |||
63 | /* external Epson SG-615P */ | ||
64 | #define BASE_BAUD 691200 | ||
65 | |||
66 | #define STD_UART_OP(num) \ | ||
67 | { 0, BASE_BAUD, 0, UART##num##_INT, \ | ||
68 | (ASYNC_BOOT_AUTOCONF | ASYNC_SKIP_TEST), \ | ||
69 | iomem_base: UART##num##_IO_BASE, \ | ||
70 | io_type: SERIAL_IO_MEM}, | ||
71 | |||
72 | #define SERIAL_PORT_DFNS \ | ||
73 | STD_UART_OP(0) \ | ||
74 | STD_UART_OP(1) | ||
75 | |||
76 | /* PCI support */ | ||
77 | #define EBONY_PCI_LOWER_IO 0x00000000 | ||
78 | #define EBONY_PCI_UPPER_IO 0x0000ffff | ||
79 | #define EBONY_PCI_LOWER_MEM 0x80002000 | ||
80 | #define EBONY_PCI_UPPER_MEM 0xffffefff | ||
81 | |||
82 | #define EBONY_PCI_CFGREGS_BASE 0x000000020ec00000 | ||
83 | #define EBONY_PCI_CFGA_PLB32 0x0ec00000 | ||
84 | #define EBONY_PCI_CFGD_PLB32 0x0ec00004 | ||
85 | |||
86 | #define EBONY_PCI_IO_BASE 0x0000000208000000ULL | ||
87 | #define EBONY_PCI_IO_SIZE 0x00010000 | ||
88 | #define EBONY_PCI_MEM_OFFSET 0x00000000 | ||
89 | |||
90 | #endif /* __ASM_EBONY_H__ */ | ||
91 | #endif /* __KERNEL__ */ | ||
diff --git a/arch/ppc/platforms/4xx/ep405.c b/arch/ppc/platforms/4xx/ep405.c new file mode 100644 index 000000000000..26a07cdb30ec --- /dev/null +++ b/arch/ppc/platforms/4xx/ep405.c | |||
@@ -0,0 +1,197 @@ | |||
1 | /* | ||
2 | * arch/ppc/platforms/4xx/ep405.c | ||
3 | * | ||
4 | * Embedded Planet 405GP board | ||
5 | * http://www.embeddedplanet.com | ||
6 | * | ||
7 | * Author: Matthew Locke <mlocke@mvista.com> | ||
8 | * | ||
9 | * 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 | #include <linux/config.h> | ||
15 | #include <linux/init.h> | ||
16 | #include <linux/pci.h> | ||
17 | #include <asm/system.h> | ||
18 | #include <asm/pci-bridge.h> | ||
19 | #include <asm/machdep.h> | ||
20 | #include <asm/todc.h> | ||
21 | #include <asm/ocp.h> | ||
22 | #include <asm/ibm_ocp_pci.h> | ||
23 | |||
24 | #undef DEBUG | ||
25 | #ifdef DEBUG | ||
26 | #define DBG(x...) printk(x) | ||
27 | #else | ||
28 | #define DBG(x...) | ||
29 | #endif | ||
30 | |||
31 | u8 *ep405_bcsr; | ||
32 | u8 *ep405_nvram; | ||
33 | |||
34 | static struct { | ||
35 | u8 cpld_xirq_select; | ||
36 | int pci_idsel; | ||
37 | int irq; | ||
38 | } ep405_devtable[] = { | ||
39 | #ifdef CONFIG_EP405PC | ||
40 | {0x07, 0x0E, 25}, /* EP405PC: USB */ | ||
41 | #endif | ||
42 | }; | ||
43 | |||
44 | int __init | ||
45 | ppc405_map_irq(struct pci_dev *dev, unsigned char idsel, unsigned char pin) | ||
46 | { | ||
47 | int i; | ||
48 | |||
49 | /* AFAICT this is only called a few times during PCI setup, so | ||
50 | performance is not critical */ | ||
51 | for (i = 0; i < ARRAY_SIZE(ep405_devtable); i++) { | ||
52 | if (idsel == ep405_devtable[i].pci_idsel) | ||
53 | return ep405_devtable[i].irq; | ||
54 | } | ||
55 | return -1; | ||
56 | }; | ||
57 | |||
58 | void __init | ||
59 | ep405_setup_arch(void) | ||
60 | { | ||
61 | ppc4xx_setup_arch(); | ||
62 | |||
63 | ibm_ocp_set_emac(0, 0); | ||
64 | |||
65 | if (__res.bi_nvramsize == 512*1024) { | ||
66 | /* FIXME: we should properly handle NVRTCs of different sizes */ | ||
67 | TODC_INIT(TODC_TYPE_DS1557, ep405_nvram, ep405_nvram, ep405_nvram, 8); | ||
68 | } | ||
69 | } | ||
70 | |||
71 | void __init | ||
72 | bios_fixup(struct pci_controller *hose, struct pcil0_regs *pcip) | ||
73 | { | ||
74 | unsigned int bar_response, bar; | ||
75 | /* | ||
76 | * Expected PCI mapping: | ||
77 | * | ||
78 | * PLB addr PCI memory addr | ||
79 | * --------------------- --------------------- | ||
80 | * 0000'0000 - 7fff'ffff <--- 0000'0000 - 7fff'ffff | ||
81 | * 8000'0000 - Bfff'ffff ---> 8000'0000 - Bfff'ffff | ||
82 | * | ||
83 | * PLB addr PCI io addr | ||
84 | * --------------------- --------------------- | ||
85 | * e800'0000 - e800'ffff ---> 0000'0000 - 0001'0000 | ||
86 | * | ||
87 | */ | ||
88 | |||
89 | /* Disable region zero first */ | ||
90 | out_le32((void *) &(pcip->pmm[0].ma), 0x00000000); | ||
91 | /* PLB starting addr, PCI: 0x80000000 */ | ||
92 | out_le32((void *) &(pcip->pmm[0].la), 0x80000000); | ||
93 | /* PCI start addr, 0x80000000 */ | ||
94 | out_le32((void *) &(pcip->pmm[0].pcila), PPC405_PCI_MEM_BASE); | ||
95 | /* 512MB range of PLB to PCI */ | ||
96 | out_le32((void *) &(pcip->pmm[0].pciha), 0x00000000); | ||
97 | /* Enable no pre-fetch, enable region */ | ||
98 | out_le32((void *) &(pcip->pmm[0].ma), ((0xffffffff - | ||
99 | (PPC405_PCI_UPPER_MEM - | ||
100 | PPC405_PCI_MEM_BASE)) | 0x01)); | ||
101 | |||
102 | /* Disable region one */ | ||
103 | out_le32((void *) &(pcip->pmm[1].ma), 0x00000000); | ||
104 | out_le32((void *) &(pcip->pmm[1].la), 0x00000000); | ||
105 | out_le32((void *) &(pcip->pmm[1].pcila), 0x00000000); | ||
106 | out_le32((void *) &(pcip->pmm[1].pciha), 0x00000000); | ||
107 | out_le32((void *) &(pcip->pmm[1].ma), 0x00000000); | ||
108 | out_le32((void *) &(pcip->ptm1ms), 0x00000000); | ||
109 | |||
110 | /* Disable region two */ | ||
111 | out_le32((void *) &(pcip->pmm[2].ma), 0x00000000); | ||
112 | out_le32((void *) &(pcip->pmm[2].la), 0x00000000); | ||
113 | out_le32((void *) &(pcip->pmm[2].pcila), 0x00000000); | ||
114 | out_le32((void *) &(pcip->pmm[2].pciha), 0x00000000); | ||
115 | out_le32((void *) &(pcip->pmm[2].ma), 0x00000000); | ||
116 | out_le32((void *) &(pcip->ptm2ms), 0x00000000); | ||
117 | |||
118 | /* Configure PTM (PCI->PLB) region 1 */ | ||
119 | out_le32((void *) &(pcip->ptm1la), 0x00000000); /* PLB base address */ | ||
120 | /* Disable PTM region 2 */ | ||
121 | out_le32((void *) &(pcip->ptm2ms), 0x00000000); | ||
122 | |||
123 | /* Zero config bars */ | ||
124 | for (bar = PCI_BASE_ADDRESS_1; bar <= PCI_BASE_ADDRESS_2; bar += 4) { | ||
125 | early_write_config_dword(hose, hose->first_busno, | ||
126 | PCI_FUNC(hose->first_busno), bar, | ||
127 | 0x00000000); | ||
128 | early_read_config_dword(hose, hose->first_busno, | ||
129 | PCI_FUNC(hose->first_busno), bar, | ||
130 | &bar_response); | ||
131 | DBG("BUS %d, device %d, Function %d bar 0x%8.8x is 0x%8.8x\n", | ||
132 | hose->first_busno, PCI_SLOT(hose->first_busno), | ||
133 | PCI_FUNC(hose->first_busno), bar, bar_response); | ||
134 | } | ||
135 | /* end work arround */ | ||
136 | } | ||
137 | |||
138 | void __init | ||
139 | ep405_map_io(void) | ||
140 | { | ||
141 | bd_t *bip = &__res; | ||
142 | |||
143 | ppc4xx_map_io(); | ||
144 | |||
145 | ep405_bcsr = ioremap(EP405_BCSR_PADDR, EP405_BCSR_SIZE); | ||
146 | |||
147 | if (bip->bi_nvramsize > 0) { | ||
148 | ep405_nvram = ioremap(EP405_NVRAM_PADDR, bip->bi_nvramsize); | ||
149 | } | ||
150 | } | ||
151 | |||
152 | void __init | ||
153 | ep405_init_IRQ(void) | ||
154 | { | ||
155 | int i; | ||
156 | |||
157 | ppc4xx_init_IRQ(); | ||
158 | |||
159 | /* Workaround for a bug in the firmware it incorrectly sets | ||
160 | the IRQ polarities for XIRQ0 and XIRQ1 */ | ||
161 | mtdcr(DCRN_UIC_PR(DCRN_UIC0_BASE), 0xffffff80); /* set the polarity */ | ||
162 | mtdcr(DCRN_UIC_SR(DCRN_UIC0_BASE), 0x00000060); /* clear bogus interrupts */ | ||
163 | |||
164 | /* Activate the XIRQs from the CPLD */ | ||
165 | writeb(0xf0, ep405_bcsr+10); | ||
166 | |||
167 | /* Set up IRQ routing */ | ||
168 | for (i = 0; i < ARRAY_SIZE(ep405_devtable); i++) { | ||
169 | if ( (ep405_devtable[i].irq >= 25) | ||
170 | && (ep405_devtable[i].irq) <= 31) { | ||
171 | writeb(ep405_devtable[i].cpld_xirq_select, ep405_bcsr+5); | ||
172 | writeb(ep405_devtable[i].irq - 25, ep405_bcsr+6); | ||
173 | } | ||
174 | } | ||
175 | } | ||
176 | |||
177 | void __init | ||
178 | platform_init(unsigned long r3, unsigned long r4, unsigned long r5, | ||
179 | unsigned long r6, unsigned long r7) | ||
180 | { | ||
181 | ppc4xx_init(r3, r4, r5, r6, r7); | ||
182 | |||
183 | ppc_md.setup_arch = ep405_setup_arch; | ||
184 | ppc_md.setup_io_mappings = ep405_map_io; | ||
185 | ppc_md.init_IRQ = ep405_init_IRQ; | ||
186 | |||
187 | ppc_md.nvram_read_val = todc_direct_read_val; | ||
188 | ppc_md.nvram_write_val = todc_direct_write_val; | ||
189 | |||
190 | if (__res.bi_nvramsize == 512*1024) { | ||
191 | ppc_md.time_init = todc_time_init; | ||
192 | ppc_md.set_rtc_time = todc_set_rtc_time; | ||
193 | ppc_md.get_rtc_time = todc_get_rtc_time; | ||
194 | } else { | ||
195 | printk("EP405: NVRTC size is not 512k (not a DS1557). Not sure what to do with it\n"); | ||
196 | } | ||
197 | } | ||
diff --git a/arch/ppc/platforms/4xx/ep405.h b/arch/ppc/platforms/4xx/ep405.h new file mode 100644 index 000000000000..ea3eb21338fb --- /dev/null +++ b/arch/ppc/platforms/4xx/ep405.h | |||
@@ -0,0 +1,54 @@ | |||
1 | /* | ||
2 | * arch/ppc/platforms/4xx/ep405.h | ||
3 | * | ||
4 | * Embedded Planet 405GP board | ||
5 | * http://www.embeddedplanet.com | ||
6 | * | ||
7 | * Author: Matthew Locke <mlocke@mvista.com> | ||
8 | * | ||
9 | * 2000 (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 | #ifdef __KERNEL__ | ||
16 | #ifndef __ASM_EP405_H__ | ||
17 | #define __ASM_EP405_H__ | ||
18 | |||
19 | /* We have a 405GP core */ | ||
20 | #include <platforms/4xx/ibm405gp.h> | ||
21 | |||
22 | #ifndef __ASSEMBLY__ | ||
23 | |||
24 | #include <linux/types.h> | ||
25 | |||
26 | typedef struct board_info { | ||
27 | unsigned int bi_memsize; /* DRAM installed, in bytes */ | ||
28 | unsigned char bi_enetaddr[6]; /* Local Ethernet MAC address */ | ||
29 | unsigned int bi_intfreq; /* Processor speed, in Hz */ | ||
30 | unsigned int bi_busfreq; /* PLB Bus speed, in Hz */ | ||
31 | unsigned int bi_pci_busfreq; /* PCI Bus speed, in Hz */ | ||
32 | unsigned int bi_nvramsize; /* Size of the NVRAM/RTC */ | ||
33 | } bd_t; | ||
34 | |||
35 | /* Some 4xx parts use a different timebase frequency from the internal clock. | ||
36 | */ | ||
37 | #define bi_tbfreq bi_intfreq | ||
38 | |||
39 | extern u8 *ep405_bcsr; | ||
40 | extern u8 *ep405_nvram; | ||
41 | |||
42 | /* Map for the BCSR and NVRAM space */ | ||
43 | #define EP405_BCSR_PADDR ((uint)0xf4000000) | ||
44 | #define EP405_BCSR_SIZE ((uint)16) | ||
45 | #define EP405_NVRAM_PADDR ((uint)0xf4200000) | ||
46 | |||
47 | /* serial defines */ | ||
48 | #define BASE_BAUD 399193 | ||
49 | |||
50 | #define PPC4xx_MACHINE_NAME "Embedded Planet 405GP" | ||
51 | |||
52 | #endif /* !__ASSEMBLY__ */ | ||
53 | #endif /* __ASM_EP405_H__ */ | ||
54 | #endif /* __KERNEL__ */ | ||
diff --git a/arch/ppc/platforms/4xx/ibm405ep.c b/arch/ppc/platforms/4xx/ibm405ep.c new file mode 100644 index 000000000000..6d44567f4dd2 --- /dev/null +++ b/arch/ppc/platforms/4xx/ibm405ep.c | |||
@@ -0,0 +1,143 @@ | |||
1 | /* | ||
2 | * arch/ppc/platforms/ibm405ep.c | ||
3 | * | ||
4 | * Support for IBM PPC 405EP processors. | ||
5 | * | ||
6 | * Author: SAW (IBM), derived from ibmnp405l.c. | ||
7 | * Maintained by MontaVista Software <source@mvista.com> | ||
8 | * | ||
9 | * 2003 (c) MontaVista Softare Inc. This file is licensed under the | ||
10 | * terms of the GNU General Public License version 2. This program is | ||
11 | * licensed "as is" without any warranty of any kind, whether express | ||
12 | * or implied. | ||
13 | */ | ||
14 | |||
15 | #include <linux/config.h> | ||
16 | #include <linux/init.h> | ||
17 | #include <linux/smp.h> | ||
18 | #include <linux/threads.h> | ||
19 | #include <linux/param.h> | ||
20 | #include <linux/string.h> | ||
21 | |||
22 | #include <asm/ibm4xx.h> | ||
23 | #include <asm/ocp.h> | ||
24 | #include <asm/ppc4xx_pic.h> | ||
25 | |||
26 | #include <platforms/4xx/ibm405ep.h> | ||
27 | |||
28 | static struct ocp_func_mal_data ibm405ep_mal0_def = { | ||
29 | .num_tx_chans = 4, /* Number of TX channels */ | ||
30 | .num_rx_chans = 2, /* Number of RX channels */ | ||
31 | .txeob_irq = 11, /* TX End Of Buffer IRQ */ | ||
32 | .rxeob_irq = 12, /* RX End Of Buffer IRQ */ | ||
33 | .txde_irq = 13, /* TX Descriptor Error IRQ */ | ||
34 | .rxde_irq = 14, /* RX Descriptor Error IRQ */ | ||
35 | .serr_irq = 10, /* MAL System Error IRQ */ | ||
36 | }; | ||
37 | OCP_SYSFS_MAL_DATA() | ||
38 | |||
39 | static struct ocp_func_emac_data ibm405ep_emac0_def = { | ||
40 | .rgmii_idx = -1, /* No RGMII */ | ||
41 | .rgmii_mux = -1, /* No RGMII */ | ||
42 | .zmii_idx = -1, /* ZMII device index */ | ||
43 | .zmii_mux = 0, /* ZMII input of this EMAC */ | ||
44 | .mal_idx = 0, /* MAL device index */ | ||
45 | .mal_rx_chan = 0, /* MAL rx channel number */ | ||
46 | .mal_tx_chan = 0, /* MAL tx channel number */ | ||
47 | .wol_irq = 9, /* WOL interrupt number */ | ||
48 | .mdio_idx = 0, /* MDIO via EMAC0 */ | ||
49 | .tah_idx = -1, /* No TAH */ | ||
50 | }; | ||
51 | |||
52 | static struct ocp_func_emac_data ibm405ep_emac1_def = { | ||
53 | .rgmii_idx = -1, /* No RGMII */ | ||
54 | .rgmii_mux = -1, /* No RGMII */ | ||
55 | .zmii_idx = -1, /* ZMII device index */ | ||
56 | .zmii_mux = 0, /* ZMII input of this EMAC */ | ||
57 | .mal_idx = 0, /* MAL device index */ | ||
58 | .mal_rx_chan = 1, /* MAL rx channel number */ | ||
59 | .mal_tx_chan = 2, /* MAL tx channel number */ | ||
60 | .wol_irq = 9, /* WOL interrupt number */ | ||
61 | .mdio_idx = 0, /* MDIO via EMAC0 */ | ||
62 | .tah_idx = -1, /* No TAH */ | ||
63 | }; | ||
64 | OCP_SYSFS_EMAC_DATA() | ||
65 | |||
66 | static struct ocp_func_iic_data ibm405ep_iic0_def = { | ||
67 | .fast_mode = 0, /* Use standad mode (100Khz) */ | ||
68 | }; | ||
69 | OCP_SYSFS_IIC_DATA() | ||
70 | |||
71 | struct ocp_def core_ocp[] = { | ||
72 | { .vendor = OCP_VENDOR_IBM, | ||
73 | .function = OCP_FUNC_OPB, | ||
74 | .index = 0, | ||
75 | .paddr = 0xEF600000, | ||
76 | .irq = OCP_IRQ_NA, | ||
77 | .pm = OCP_CPM_NA, | ||
78 | }, | ||
79 | { .vendor = OCP_VENDOR_IBM, | ||
80 | .function = OCP_FUNC_16550, | ||
81 | .index = 0, | ||
82 | .paddr = UART0_IO_BASE, | ||
83 | .irq = UART0_INT, | ||
84 | .pm = IBM_CPM_UART0 | ||
85 | }, | ||
86 | { .vendor = OCP_VENDOR_IBM, | ||
87 | .function = OCP_FUNC_16550, | ||
88 | .index = 1, | ||
89 | .paddr = UART1_IO_BASE, | ||
90 | .irq = UART1_INT, | ||
91 | .pm = IBM_CPM_UART1 | ||
92 | }, | ||
93 | { .vendor = OCP_VENDOR_IBM, | ||
94 | .function = OCP_FUNC_IIC, | ||
95 | .paddr = 0xEF600500, | ||
96 | .irq = 2, | ||
97 | .pm = IBM_CPM_IIC0, | ||
98 | .additions = &ibm405ep_iic0_def, | ||
99 | .show = &ocp_show_iic_data | ||
100 | }, | ||
101 | { .vendor = OCP_VENDOR_IBM, | ||
102 | .function = OCP_FUNC_GPIO, | ||
103 | .paddr = 0xEF600700, | ||
104 | .irq = OCP_IRQ_NA, | ||
105 | .pm = IBM_CPM_GPIO0 | ||
106 | }, | ||
107 | { .vendor = OCP_VENDOR_IBM, | ||
108 | .function = OCP_FUNC_MAL, | ||
109 | .paddr = OCP_PADDR_NA, | ||
110 | .irq = OCP_IRQ_NA, | ||
111 | .pm = OCP_CPM_NA, | ||
112 | .additions = &ibm405ep_mal0_def, | ||
113 | .show = &ocp_show_mal_data | ||
114 | }, | ||
115 | { .vendor = OCP_VENDOR_IBM, | ||
116 | .function = OCP_FUNC_EMAC, | ||
117 | .index = 0, | ||
118 | .paddr = EMAC0_BASE, | ||
119 | .irq = 15, | ||
120 | .pm = OCP_CPM_NA, | ||
121 | .additions = &ibm405ep_emac0_def, | ||
122 | .show = &ocp_show_emac_data | ||
123 | }, | ||
124 | { .vendor = OCP_VENDOR_IBM, | ||
125 | .function = OCP_FUNC_EMAC, | ||
126 | .index = 1, | ||
127 | .paddr = 0xEF600900, | ||
128 | .irq = 17, | ||
129 | .pm = OCP_CPM_NA, | ||
130 | .additions = &ibm405ep_emac1_def, | ||
131 | .show = &ocp_show_emac_data | ||
132 | }, | ||
133 | { .vendor = OCP_VENDOR_INVALID | ||
134 | } | ||
135 | }; | ||
136 | |||
137 | /* Polarity and triggering settings for internal interrupt sources */ | ||
138 | struct ppc4xx_uic_settings ppc4xx_core_uic_cfg[] __initdata = { | ||
139 | { .polarity = 0xffff7f80, | ||
140 | .triggering = 0x00000000, | ||
141 | .ext_irq_mask = 0x0000007f, /* IRQ0 - IRQ6 */ | ||
142 | } | ||
143 | }; | ||
diff --git a/arch/ppc/platforms/4xx/ibm405ep.h b/arch/ppc/platforms/4xx/ibm405ep.h new file mode 100644 index 000000000000..e051e3fe8c63 --- /dev/null +++ b/arch/ppc/platforms/4xx/ibm405ep.h | |||
@@ -0,0 +1,148 @@ | |||
1 | /* | ||
2 | * arch/ppc/platforms/4xx/ibm405ep.h | ||
3 | * | ||
4 | * IBM PPC 405EP processor defines. | ||
5 | * | ||
6 | * Author: SAW (IBM), derived from ibm405gp.h. | ||
7 | * Maintained by MontaVista Software <source@mvista.com> | ||
8 | * | ||
9 | * 2003 (c) MontaVista Softare Inc. This file is licensed under the | ||
10 | * terms of the GNU General Public License version 2. This program is | ||
11 | * licensed "as is" without any warranty of any kind, whether express | ||
12 | * or implied. | ||
13 | */ | ||
14 | |||
15 | #ifdef __KERNEL__ | ||
16 | #ifndef __ASM_IBM405EP_H__ | ||
17 | #define __ASM_IBM405EP_H__ | ||
18 | |||
19 | #include <linux/config.h> | ||
20 | |||
21 | /* ibm405.h at bottom of this file */ | ||
22 | |||
23 | /* PCI | ||
24 | * PCI Bridge config reg definitions | ||
25 | * see 17-19 of manual | ||
26 | */ | ||
27 | |||
28 | #define PPC405_PCI_CONFIG_ADDR 0xeec00000 | ||
29 | #define PPC405_PCI_CONFIG_DATA 0xeec00004 | ||
30 | |||
31 | #define PPC405_PCI_PHY_MEM_BASE 0x80000000 /* hose_a->pci_mem_offset */ | ||
32 | /* setbat */ | ||
33 | #define PPC405_PCI_MEM_BASE PPC405_PCI_PHY_MEM_BASE /* setbat */ | ||
34 | #define PPC405_PCI_PHY_IO_BASE 0xe8000000 /* setbat */ | ||
35 | #define PPC405_PCI_IO_BASE PPC405_PCI_PHY_IO_BASE /* setbat */ | ||
36 | |||
37 | #define PPC405_PCI_LOWER_MEM 0x80000000 /* hose_a->mem_space.start */ | ||
38 | #define PPC405_PCI_UPPER_MEM 0xBfffffff /* hose_a->mem_space.end */ | ||
39 | #define PPC405_PCI_LOWER_IO 0x00000000 /* hose_a->io_space.start */ | ||
40 | #define PPC405_PCI_UPPER_IO 0x0000ffff /* hose_a->io_space.end */ | ||
41 | |||
42 | #define PPC405_ISA_IO_BASE PPC405_PCI_IO_BASE | ||
43 | |||
44 | #define PPC4xx_PCI_IO_PADDR ((uint)PPC405_PCI_PHY_IO_BASE) | ||
45 | #define PPC4xx_PCI_IO_VADDR PPC4xx_PCI_IO_PADDR | ||
46 | #define PPC4xx_PCI_IO_SIZE ((uint)64*1024) | ||
47 | #define PPC4xx_PCI_CFG_PADDR ((uint)PPC405_PCI_CONFIG_ADDR) | ||
48 | #define PPC4xx_PCI_CFG_VADDR PPC4xx_PCI_CFG_PADDR | ||
49 | #define PPC4xx_PCI_CFG_SIZE ((uint)4*1024) | ||
50 | #define PPC4xx_PCI_LCFG_PADDR ((uint)0xef400000) | ||
51 | #define PPC4xx_PCI_LCFG_VADDR PPC4xx_PCI_LCFG_PADDR | ||
52 | #define PPC4xx_PCI_LCFG_SIZE ((uint)4*1024) | ||
53 | #define PPC4xx_ONB_IO_PADDR ((uint)0xef600000) | ||
54 | #define PPC4xx_ONB_IO_VADDR PPC4xx_ONB_IO_PADDR | ||
55 | #define PPC4xx_ONB_IO_SIZE ((uint)4*1024) | ||
56 | |||
57 | /* serial port defines */ | ||
58 | #define RS_TABLE_SIZE 2 | ||
59 | |||
60 | #define UART0_INT 0 | ||
61 | #define UART1_INT 1 | ||
62 | |||
63 | #define PCIL0_BASE 0xEF400000 | ||
64 | #define UART0_IO_BASE 0xEF600300 | ||
65 | #define UART1_IO_BASE 0xEF600400 | ||
66 | #define EMAC0_BASE 0xEF600800 | ||
67 | |||
68 | #define BD_EMAC_ADDR(e,i) bi_enetaddr[e][i] | ||
69 | |||
70 | #if defined(CONFIG_UART0_TTYS0) | ||
71 | #define ACTING_UART0_IO_BASE UART0_IO_BASE | ||
72 | #define ACTING_UART1_IO_BASE UART1_IO_BASE | ||
73 | #define ACTING_UART0_INT UART0_INT | ||
74 | #define ACTING_UART1_INT UART1_INT | ||
75 | #else | ||
76 | #define ACTING_UART0_IO_BASE UART1_IO_BASE | ||
77 | #define ACTING_UART1_IO_BASE UART0_IO_BASE | ||
78 | #define ACTING_UART0_INT UART1_INT | ||
79 | #define ACTING_UART1_INT UART0_INT | ||
80 | #endif | ||
81 | |||
82 | #define STD_UART_OP(num) \ | ||
83 | { 0, BASE_BAUD, 0, ACTING_UART##num##_INT, \ | ||
84 | (ASYNC_BOOT_AUTOCONF | ASYNC_SKIP_TEST), \ | ||
85 | iomem_base: (u8 *)ACTING_UART##num##_IO_BASE, \ | ||
86 | io_type: SERIAL_IO_MEM}, | ||
87 | |||
88 | #define SERIAL_DEBUG_IO_BASE ACTING_UART0_IO_BASE | ||
89 | #define SERIAL_PORT_DFNS \ | ||
90 | STD_UART_OP(0) \ | ||
91 | STD_UART_OP(1) | ||
92 | |||
93 | /* DCR defines */ | ||
94 | #define DCRN_CPMSR_BASE 0x0BA | ||
95 | #define DCRN_CPMFR_BASE 0x0B9 | ||
96 | |||
97 | #define DCRN_CPC0_PLLMR0_BASE 0x0F0 | ||
98 | #define DCRN_CPC0_BOOT_BASE 0x0F1 | ||
99 | #define DCRN_CPC0_CR1_BASE 0x0F2 | ||
100 | #define DCRN_CPC0_EPRCSR_BASE 0x0F3 | ||
101 | #define DCRN_CPC0_PLLMR1_BASE 0x0F4 | ||
102 | #define DCRN_CPC0_UCR_BASE 0x0F5 | ||
103 | #define DCRN_CPC0_UCR_U0DIV 0x07F | ||
104 | #define DCRN_CPC0_SRR_BASE 0x0F6 | ||
105 | #define DCRN_CPC0_JTAGID_BASE 0x0F7 | ||
106 | #define DCRN_CPC0_SPARE_BASE 0x0F8 | ||
107 | #define DCRN_CPC0_PCI_BASE 0x0F9 | ||
108 | |||
109 | |||
110 | #define IBM_CPM_GPT 0x80000000 /* GPT interface */ | ||
111 | #define IBM_CPM_PCI 0x40000000 /* PCI bridge */ | ||
112 | #define IBM_CPM_UIC 0x00010000 /* Universal Int Controller */ | ||
113 | #define IBM_CPM_CPU 0x00008000 /* processor core */ | ||
114 | #define IBM_CPM_EBC 0x00002000 /* EBC controller */ | ||
115 | #define IBM_CPM_SDRAM0 0x00004000 /* SDRAM memory controller */ | ||
116 | #define IBM_CPM_GPIO0 0x00001000 /* General Purpose IO */ | ||
117 | #define IBM_CPM_TMRCLK 0x00000400 /* CPU timers */ | ||
118 | #define IBM_CPM_PLB 0x00000100 /* PLB bus arbiter */ | ||
119 | #define IBM_CPM_OPB 0x00000080 /* PLB to OPB bridge */ | ||
120 | #define IBM_CPM_DMA 0x00000040 /* DMA controller */ | ||
121 | #define IBM_CPM_IIC0 0x00000010 /* IIC interface */ | ||
122 | #define IBM_CPM_UART1 0x00000002 /* serial port 0 */ | ||
123 | #define IBM_CPM_UART0 0x00000001 /* serial port 1 */ | ||
124 | #define DFLT_IBM4xx_PM ~(IBM_CPM_PCI | IBM_CPM_CPU | IBM_CPM_DMA \ | ||
125 | | IBM_CPM_OPB | IBM_CPM_EBC \ | ||
126 | | IBM_CPM_SDRAM0 | IBM_CPM_PLB \ | ||
127 | | IBM_CPM_UIC | IBM_CPM_TMRCLK) | ||
128 | #define DCRN_DMA0_BASE 0x100 | ||
129 | #define DCRN_DMA1_BASE 0x108 | ||
130 | #define DCRN_DMA2_BASE 0x110 | ||
131 | #define DCRN_DMA3_BASE 0x118 | ||
132 | #define DCRNCAP_DMA_SG 1 /* have DMA scatter/gather capability */ | ||
133 | #define DCRN_DMASR_BASE 0x120 | ||
134 | #define DCRN_EBC_BASE 0x012 | ||
135 | #define DCRN_DCP0_BASE 0x014 | ||
136 | #define DCRN_MAL_BASE 0x180 | ||
137 | #define DCRN_OCM0_BASE 0x018 | ||
138 | #define DCRN_PLB0_BASE 0x084 | ||
139 | #define DCRN_PLLMR_BASE 0x0B0 | ||
140 | #define DCRN_POB0_BASE 0x0A0 | ||
141 | #define DCRN_SDRAM0_BASE 0x010 | ||
142 | #define DCRN_UIC0_BASE 0x0C0 | ||
143 | #define UIC0 DCRN_UIC0_BASE | ||
144 | |||
145 | #include <asm/ibm405.h> | ||
146 | |||
147 | #endif /* __ASM_IBM405EP_H__ */ | ||
148 | #endif /* __KERNEL__ */ | ||
diff --git a/arch/ppc/platforms/4xx/ibm405gp.c b/arch/ppc/platforms/4xx/ibm405gp.c new file mode 100644 index 000000000000..dfd7ef3ba5f8 --- /dev/null +++ b/arch/ppc/platforms/4xx/ibm405gp.c | |||
@@ -0,0 +1,120 @@ | |||
1 | /* | ||
2 | * | ||
3 | * Copyright 2000-2001 MontaVista Software Inc. | ||
4 | * Original author: Armin Kuster akuster@mvista.com | ||
5 | * | ||
6 | * Module name: ibm405gp.c | ||
7 | * | ||
8 | * | ||
9 | * This program is free software; you can redistribute it and/or modify it | ||
10 | * under the terms of the GNU General Public License as published by the | ||
11 | * Free Software Foundation; either version 2 of the License, or (at your | ||
12 | * option) any later version. | ||
13 | * | ||
14 | */ | ||
15 | |||
16 | #include <linux/config.h> | ||
17 | #include <linux/init.h> | ||
18 | #include <linux/smp.h> | ||
19 | #include <linux/threads.h> | ||
20 | #include <linux/param.h> | ||
21 | #include <linux/string.h> | ||
22 | #include <platforms/4xx/ibm405gp.h> | ||
23 | #include <asm/ibm4xx.h> | ||
24 | #include <asm/ocp.h> | ||
25 | #include <asm/ppc4xx_pic.h> | ||
26 | |||
27 | static struct ocp_func_emac_data ibm405gp_emac0_def = { | ||
28 | .rgmii_idx = -1, /* No RGMII */ | ||
29 | .rgmii_mux = -1, /* No RGMII */ | ||
30 | .zmii_idx = -1, /* ZMII device index */ | ||
31 | .zmii_mux = 0, /* ZMII input of this EMAC */ | ||
32 | .mal_idx = 0, /* MAL device index */ | ||
33 | .mal_rx_chan = 0, /* MAL rx channel number */ | ||
34 | .mal_tx_chan = 0, /* MAL tx channel number */ | ||
35 | .wol_irq = 9, /* WOL interrupt number */ | ||
36 | .mdio_idx = -1, /* No shared MDIO */ | ||
37 | .tah_idx = -1, /* No TAH */ | ||
38 | }; | ||
39 | OCP_SYSFS_EMAC_DATA() | ||
40 | |||
41 | static struct ocp_func_mal_data ibm405gp_mal0_def = { | ||
42 | .num_tx_chans = 1, /* Number of TX channels */ | ||
43 | .num_rx_chans = 1, /* Number of RX channels */ | ||
44 | .txeob_irq = 11, /* TX End Of Buffer IRQ */ | ||
45 | .rxeob_irq = 12, /* RX End Of Buffer IRQ */ | ||
46 | .txde_irq = 13, /* TX Descriptor Error IRQ */ | ||
47 | .rxde_irq = 14, /* RX Descriptor Error IRQ */ | ||
48 | .serr_irq = 10, /* MAL System Error IRQ */ | ||
49 | }; | ||
50 | OCP_SYSFS_MAL_DATA() | ||
51 | |||
52 | static struct ocp_func_iic_data ibm405gp_iic0_def = { | ||
53 | .fast_mode = 0, /* Use standad mode (100Khz) */ | ||
54 | }; | ||
55 | OCP_SYSFS_IIC_DATA() | ||
56 | |||
57 | struct ocp_def core_ocp[] = { | ||
58 | { .vendor = OCP_VENDOR_IBM, | ||
59 | .function = OCP_FUNC_OPB, | ||
60 | .index = 0, | ||
61 | .paddr = 0xEF600000, | ||
62 | .irq = OCP_IRQ_NA, | ||
63 | .pm = OCP_CPM_NA, | ||
64 | }, | ||
65 | { .vendor = OCP_VENDOR_IBM, | ||
66 | .function = OCP_FUNC_16550, | ||
67 | .index = 0, | ||
68 | .paddr = UART0_IO_BASE, | ||
69 | .irq = UART0_INT, | ||
70 | .pm = IBM_CPM_UART0 | ||
71 | }, | ||
72 | { .vendor = OCP_VENDOR_IBM, | ||
73 | .function = OCP_FUNC_16550, | ||
74 | .index = 1, | ||
75 | .paddr = UART1_IO_BASE, | ||
76 | .irq = UART1_INT, | ||
77 | .pm = IBM_CPM_UART1 | ||
78 | }, | ||
79 | { .vendor = OCP_VENDOR_IBM, | ||
80 | .function = OCP_FUNC_IIC, | ||
81 | .paddr = 0xEF600500, | ||
82 | .irq = 2, | ||
83 | .pm = IBM_CPM_IIC0, | ||
84 | .additions = &ibm405gp_iic0_def, | ||
85 | .show = &ocp_show_iic_data, | ||
86 | }, | ||
87 | { .vendor = OCP_VENDOR_IBM, | ||
88 | .function = OCP_FUNC_GPIO, | ||
89 | .paddr = 0xEF600700, | ||
90 | .irq = OCP_IRQ_NA, | ||
91 | .pm = IBM_CPM_GPIO0 | ||
92 | }, | ||
93 | { .vendor = OCP_VENDOR_IBM, | ||
94 | .function = OCP_FUNC_MAL, | ||
95 | .paddr = OCP_PADDR_NA, | ||
96 | .irq = OCP_IRQ_NA, | ||
97 | .pm = OCP_CPM_NA, | ||
98 | .additions = &ibm405gp_mal0_def, | ||
99 | .show = &ocp_show_mal_data, | ||
100 | }, | ||
101 | { .vendor = OCP_VENDOR_IBM, | ||
102 | .function = OCP_FUNC_EMAC, | ||
103 | .index = 0, | ||
104 | .paddr = EMAC0_BASE, | ||
105 | .irq = 15, | ||
106 | .pm = IBM_CPM_EMAC0, | ||
107 | .additions = &ibm405gp_emac0_def, | ||
108 | .show = &ocp_show_emac_data, | ||
109 | }, | ||
110 | { .vendor = OCP_VENDOR_INVALID | ||
111 | } | ||
112 | }; | ||
113 | |||
114 | /* Polarity and triggering settings for internal interrupt sources */ | ||
115 | struct ppc4xx_uic_settings ppc4xx_core_uic_cfg[] __initdata = { | ||
116 | { .polarity = 0xffffff80, | ||
117 | .triggering = 0x10000000, | ||
118 | .ext_irq_mask = 0x0000007f, /* IRQ0 - IRQ6 */ | ||
119 | } | ||
120 | }; | ||
diff --git a/arch/ppc/platforms/4xx/ibm405gp.h b/arch/ppc/platforms/4xx/ibm405gp.h new file mode 100644 index 000000000000..b2b642e81af7 --- /dev/null +++ b/arch/ppc/platforms/4xx/ibm405gp.h | |||
@@ -0,0 +1,151 @@ | |||
1 | /* | ||
2 | * arch/ppc/platforms/4xx/ibm405gp.h | ||
3 | * | ||
4 | * Author: Armin Kuster akuster@mvista.com | ||
5 | * | ||
6 | * 2001 (c) MontaVista, Software, Inc. This file is licensed under | ||
7 | * the terms of the GNU General Public License version 2. This program | ||
8 | * is licensed "as is" without any warranty of any kind, whether express | ||
9 | * or implied. | ||
10 | */ | ||
11 | |||
12 | #ifdef __KERNEL__ | ||
13 | #ifndef __ASM_IBM405GP_H__ | ||
14 | #define __ASM_IBM405GP_H__ | ||
15 | |||
16 | #include <linux/config.h> | ||
17 | |||
18 | /* ibm405.h at bottom of this file */ | ||
19 | |||
20 | /* PCI | ||
21 | * PCI Bridge config reg definitions | ||
22 | * see 17-19 of manual | ||
23 | */ | ||
24 | |||
25 | #define PPC405_PCI_CONFIG_ADDR 0xeec00000 | ||
26 | #define PPC405_PCI_CONFIG_DATA 0xeec00004 | ||
27 | |||
28 | #define PPC405_PCI_PHY_MEM_BASE 0x80000000 /* hose_a->pci_mem_offset */ | ||
29 | /* setbat */ | ||
30 | #define PPC405_PCI_MEM_BASE PPC405_PCI_PHY_MEM_BASE /* setbat */ | ||
31 | #define PPC405_PCI_PHY_IO_BASE 0xe8000000 /* setbat */ | ||
32 | #define PPC405_PCI_IO_BASE PPC405_PCI_PHY_IO_BASE /* setbat */ | ||
33 | |||
34 | #define PPC405_PCI_LOWER_MEM 0x80000000 /* hose_a->mem_space.start */ | ||
35 | #define PPC405_PCI_UPPER_MEM 0xBfffffff /* hose_a->mem_space.end */ | ||
36 | #define PPC405_PCI_LOWER_IO 0x00000000 /* hose_a->io_space.start */ | ||
37 | #define PPC405_PCI_UPPER_IO 0x0000ffff /* hose_a->io_space.end */ | ||
38 | |||
39 | #define PPC405_ISA_IO_BASE PPC405_PCI_IO_BASE | ||
40 | |||
41 | #define PPC4xx_PCI_IO_PADDR ((uint)PPC405_PCI_PHY_IO_BASE) | ||
42 | #define PPC4xx_PCI_IO_VADDR PPC4xx_PCI_IO_PADDR | ||
43 | #define PPC4xx_PCI_IO_SIZE ((uint)64*1024) | ||
44 | #define PPC4xx_PCI_CFG_PADDR ((uint)PPC405_PCI_CONFIG_ADDR) | ||
45 | #define PPC4xx_PCI_CFG_VADDR PPC4xx_PCI_CFG_PADDR | ||
46 | #define PPC4xx_PCI_CFG_SIZE ((uint)4*1024) | ||
47 | #define PPC4xx_PCI_LCFG_PADDR ((uint)0xef400000) | ||
48 | #define PPC4xx_PCI_LCFG_VADDR PPC4xx_PCI_LCFG_PADDR | ||
49 | #define PPC4xx_PCI_LCFG_SIZE ((uint)4*1024) | ||
50 | #define PPC4xx_ONB_IO_PADDR ((uint)0xef600000) | ||
51 | #define PPC4xx_ONB_IO_VADDR PPC4xx_ONB_IO_PADDR | ||
52 | #define PPC4xx_ONB_IO_SIZE ((uint)4*1024) | ||
53 | |||
54 | /* serial port defines */ | ||
55 | #define RS_TABLE_SIZE 2 | ||
56 | |||
57 | #define UART0_INT 0 | ||
58 | #define UART1_INT 1 | ||
59 | |||
60 | #define PCIL0_BASE 0xEF400000 | ||
61 | #define UART0_IO_BASE 0xEF600300 | ||
62 | #define UART1_IO_BASE 0xEF600400 | ||
63 | #define EMAC0_BASE 0xEF600800 | ||
64 | |||
65 | #define BD_EMAC_ADDR(e,i) bi_enetaddr[i] | ||
66 | |||
67 | #define STD_UART_OP(num) \ | ||
68 | { 0, BASE_BAUD, 0, UART##num##_INT, \ | ||
69 | (ASYNC_BOOT_AUTOCONF | ASYNC_SKIP_TEST), \ | ||
70 | iomem_base: (u8 *)UART##num##_IO_BASE, \ | ||
71 | io_type: SERIAL_IO_MEM}, | ||
72 | |||
73 | #if defined(CONFIG_UART0_TTYS0) | ||
74 | #define SERIAL_DEBUG_IO_BASE UART0_IO_BASE | ||
75 | #define SERIAL_PORT_DFNS \ | ||
76 | STD_UART_OP(0) \ | ||
77 | STD_UART_OP(1) | ||
78 | #endif | ||
79 | |||
80 | #if defined(CONFIG_UART0_TTYS1) | ||
81 | #define SERIAL_DEBUG_IO_BASE UART1_IO_BASE | ||
82 | #define SERIAL_PORT_DFNS \ | ||
83 | STD_UART_OP(1) \ | ||
84 | STD_UART_OP(0) | ||
85 | #endif | ||
86 | |||
87 | /* DCR defines */ | ||
88 | #define DCRN_CHCR_BASE 0x0B1 | ||
89 | #define DCRN_CHPSR_BASE 0x0B4 | ||
90 | #define DCRN_CPMSR_BASE 0x0B8 | ||
91 | #define DCRN_CPMFR_BASE 0x0BA | ||
92 | |||
93 | #define CHR0_U0EC 0x00000080 /* Select external clock for UART0 */ | ||
94 | #define CHR0_U1EC 0x00000040 /* Select external clock for UART1 */ | ||
95 | #define CHR0_UDIV 0x0000003E /* UART internal clock divisor */ | ||
96 | #define CHR1_CETE 0x00800000 /* CPU external timer enable */ | ||
97 | |||
98 | #define DCRN_CHPSR_BASE 0x0B4 | ||
99 | #define PSR_PLL_FWD_MASK 0xC0000000 | ||
100 | #define PSR_PLL_FDBACK_MASK 0x30000000 | ||
101 | #define PSR_PLL_TUNING_MASK 0x0E000000 | ||
102 | #define PSR_PLB_CPU_MASK 0x01800000 | ||
103 | #define PSR_OPB_PLB_MASK 0x00600000 | ||
104 | #define PSR_PCI_PLB_MASK 0x00180000 | ||
105 | #define PSR_EB_PLB_MASK 0x00060000 | ||
106 | #define PSR_ROM_WIDTH_MASK 0x00018000 | ||
107 | #define PSR_ROM_LOC 0x00004000 | ||
108 | #define PSR_PCI_ASYNC_EN 0x00001000 | ||
109 | #define PSR_PCI_ARBIT_EN 0x00000400 | ||
110 | |||
111 | #define IBM_CPM_IIC0 0x80000000 /* IIC interface */ | ||
112 | #define IBM_CPM_PCI 0x40000000 /* PCI bridge */ | ||
113 | #define IBM_CPM_CPU 0x20000000 /* processor core */ | ||
114 | #define IBM_CPM_DMA 0x10000000 /* DMA controller */ | ||
115 | #define IBM_CPM_OPB 0x08000000 /* PLB to OPB bridge */ | ||
116 | #define IBM_CPM_DCP 0x04000000 /* CodePack */ | ||
117 | #define IBM_CPM_EBC 0x02000000 /* ROM/SRAM peripheral controller */ | ||
118 | #define IBM_CPM_SDRAM0 0x01000000 /* SDRAM memory controller */ | ||
119 | #define IBM_CPM_PLB 0x00800000 /* PLB bus arbiter */ | ||
120 | #define IBM_CPM_GPIO0 0x00400000 /* General Purpose IO (??) */ | ||
121 | #define IBM_CPM_UART0 0x00200000 /* serial port 0 */ | ||
122 | #define IBM_CPM_UART1 0x00100000 /* serial port 1 */ | ||
123 | #define IBM_CPM_UIC 0x00080000 /* Universal Interrupt Controller */ | ||
124 | #define IBM_CPM_TMRCLK 0x00040000 /* CPU timers */ | ||
125 | #define IBM_CPM_EMAC0 0x00020000 /* on-chip ethernet MM unit */ | ||
126 | #define DFLT_IBM4xx_PM ~(IBM_CPM_PCI | IBM_CPM_CPU | IBM_CPM_DMA \ | ||
127 | | IBM_CPM_OPB | IBM_CPM_EBC \ | ||
128 | | IBM_CPM_SDRAM0 | IBM_CPM_PLB \ | ||
129 | | IBM_CPM_UIC | IBM_CPM_TMRCLK) | ||
130 | |||
131 | #define DCRN_DMA0_BASE 0x100 | ||
132 | #define DCRN_DMA1_BASE 0x108 | ||
133 | #define DCRN_DMA2_BASE 0x110 | ||
134 | #define DCRN_DMA3_BASE 0x118 | ||
135 | #define DCRNCAP_DMA_SG 1 /* have DMA scatter/gather capability */ | ||
136 | #define DCRN_DMASR_BASE 0x120 | ||
137 | #define DCRN_EBC_BASE 0x012 | ||
138 | #define DCRN_DCP0_BASE 0x014 | ||
139 | #define DCRN_MAL_BASE 0x180 | ||
140 | #define DCRN_OCM0_BASE 0x018 | ||
141 | #define DCRN_PLB0_BASE 0x084 | ||
142 | #define DCRN_PLLMR_BASE 0x0B0 | ||
143 | #define DCRN_POB0_BASE 0x0A0 | ||
144 | #define DCRN_SDRAM0_BASE 0x010 | ||
145 | #define DCRN_UIC0_BASE 0x0C0 | ||
146 | #define UIC0 DCRN_UIC0_BASE | ||
147 | |||
148 | #include <asm/ibm405.h> | ||
149 | |||
150 | #endif /* __ASM_IBM405GP_H__ */ | ||
151 | #endif /* __KERNEL__ */ | ||
diff --git a/arch/ppc/platforms/4xx/ibm405gpr.c b/arch/ppc/platforms/4xx/ibm405gpr.c new file mode 100644 index 000000000000..01c8ccbc7214 --- /dev/null +++ b/arch/ppc/platforms/4xx/ibm405gpr.c | |||
@@ -0,0 +1,117 @@ | |||
1 | /* | ||
2 | * arch/ppc/platforms/4xx/ibm405gpr.c | ||
3 | * | ||
4 | * Author: Armin Kuster <akuster@mvista.com> | ||
5 | * | ||
6 | * 2002 (c) MontaVista, Software, Inc. This file is licensed under | ||
7 | * the terms of the GNU General Public License version 2. This program | ||
8 | * is licensed "as is" without any warranty of any kind, whether express | ||
9 | * or implied. | ||
10 | */ | ||
11 | |||
12 | #include <linux/config.h> | ||
13 | #include <linux/init.h> | ||
14 | #include <linux/smp.h> | ||
15 | #include <linux/threads.h> | ||
16 | #include <linux/param.h> | ||
17 | #include <linux/string.h> | ||
18 | #include <platforms/4xx/ibm405gpr.h> | ||
19 | #include <asm/ibm4xx.h> | ||
20 | #include <asm/ocp.h> | ||
21 | #include <asm/ppc4xx_pic.h> | ||
22 | |||
23 | static struct ocp_func_emac_data ibm405gpr_emac0_def = { | ||
24 | .rgmii_idx = -1, /* No RGMII */ | ||
25 | .rgmii_mux = -1, /* No RGMII */ | ||
26 | .zmii_idx = -1, /* ZMII device index */ | ||
27 | .zmii_mux = 0, /* ZMII input of this EMAC */ | ||
28 | .mal_idx = 0, /* MAL device index */ | ||
29 | .mal_rx_chan = 0, /* MAL rx channel number */ | ||
30 | .mal_tx_chan = 0, /* MAL tx channel number */ | ||
31 | .wol_irq = 9, /* WOL interrupt number */ | ||
32 | .mdio_idx = -1, /* No shared MDIO */ | ||
33 | .tah_idx = -1, /* No TAH */ | ||
34 | }; | ||
35 | OCP_SYSFS_EMAC_DATA() | ||
36 | |||
37 | static struct ocp_func_mal_data ibm405gpr_mal0_def = { | ||
38 | .num_tx_chans = 1, /* Number of TX channels */ | ||
39 | .num_rx_chans = 1, /* Number of RX channels */ | ||
40 | .txeob_irq = 11, /* TX End Of Buffer IRQ */ | ||
41 | .rxeob_irq = 12, /* RX End Of Buffer IRQ */ | ||
42 | .txde_irq = 13, /* TX Descriptor Error IRQ */ | ||
43 | .rxde_irq = 14, /* RX Descriptor Error IRQ */ | ||
44 | .serr_irq = 10, /* MAL System Error IRQ */ | ||
45 | }; | ||
46 | OCP_SYSFS_MAL_DATA() | ||
47 | |||
48 | static struct ocp_func_iic_data ibm405gpr_iic0_def = { | ||
49 | .fast_mode = 0, /* Use standad mode (100Khz) */ | ||
50 | }; | ||
51 | |||
52 | OCP_SYSFS_IIC_DATA() | ||
53 | |||
54 | struct ocp_def core_ocp[] = { | ||
55 | { .vendor = OCP_VENDOR_IBM, | ||
56 | .function = OCP_FUNC_OPB, | ||
57 | .index = 0, | ||
58 | .paddr = 0xEF600000, | ||
59 | .irq = OCP_IRQ_NA, | ||
60 | .pm = OCP_CPM_NA, | ||
61 | }, | ||
62 | { .vendor = OCP_VENDOR_IBM, | ||
63 | .function = OCP_FUNC_16550, | ||
64 | .index = 0, | ||
65 | .paddr = UART0_IO_BASE, | ||
66 | .irq = UART0_INT, | ||
67 | .pm = IBM_CPM_UART0 | ||
68 | }, | ||
69 | { .vendor = OCP_VENDOR_IBM, | ||
70 | .function = OCP_FUNC_16550, | ||
71 | .index = 1, | ||
72 | .paddr = UART1_IO_BASE, | ||
73 | .irq = UART1_INT, | ||
74 | .pm = IBM_CPM_UART1 | ||
75 | }, | ||
76 | { .vendor = OCP_VENDOR_IBM, | ||
77 | .function = OCP_FUNC_IIC, | ||
78 | .paddr = 0xEF600500, | ||
79 | .irq = 2, | ||
80 | .pm = IBM_CPM_IIC0, | ||
81 | .additions = &ibm405gpr_iic0_def, | ||
82 | .show = &ocp_show_iic_data, | ||
83 | }, | ||
84 | { .vendor = OCP_VENDOR_IBM, | ||
85 | .function = OCP_FUNC_GPIO, | ||
86 | .paddr = 0xEF600700, | ||
87 | .irq = OCP_IRQ_NA, | ||
88 | .pm = IBM_CPM_GPIO0 | ||
89 | }, | ||
90 | { .vendor = OCP_VENDOR_IBM, | ||
91 | .function = OCP_FUNC_MAL, | ||
92 | .paddr = OCP_PADDR_NA, | ||
93 | .irq = OCP_IRQ_NA, | ||
94 | .pm = OCP_CPM_NA, | ||
95 | .additions = &ibm405gpr_mal0_def, | ||
96 | .show = &ocp_show_mal_data, | ||
97 | }, | ||
98 | { .vendor = OCP_VENDOR_IBM, | ||
99 | .function = OCP_FUNC_EMAC, | ||
100 | .index = 0, | ||
101 | .paddr = EMAC0_BASE, | ||
102 | .irq = 15, | ||
103 | .pm = IBM_CPM_EMAC0, | ||
104 | .additions = &ibm405gpr_emac0_def, | ||
105 | .show = &ocp_show_emac_data, | ||
106 | }, | ||
107 | { .vendor = OCP_VENDOR_INVALID | ||
108 | } | ||
109 | }; | ||
110 | |||
111 | /* Polarity and triggering settings for internal interrupt sources */ | ||
112 | struct ppc4xx_uic_settings ppc4xx_core_uic_cfg[] __initdata = { | ||
113 | { .polarity = 0xffffe000, | ||
114 | .triggering = 0x10000000, | ||
115 | .ext_irq_mask = 0x00001fff, /* IRQ7 - IRQ12, IRQ0 - IRQ6 */ | ||
116 | } | ||
117 | }; | ||
diff --git a/arch/ppc/platforms/4xx/ibm405gpr.h b/arch/ppc/platforms/4xx/ibm405gpr.h new file mode 100644 index 000000000000..45412fb4368f --- /dev/null +++ b/arch/ppc/platforms/4xx/ibm405gpr.h | |||
@@ -0,0 +1,151 @@ | |||
1 | /* | ||
2 | * arch/ppc/platforms/4xx/ibm405gpr.h | ||
3 | * | ||
4 | * Author: Armin Kuster <akuster@mvista.com> | ||
5 | * | ||
6 | * 2002 (c) MontaVista, Software, Inc. This file is licensed under | ||
7 | * the terms of the GNU General Public License version 2. This program | ||
8 | * is licensed "as is" without any warranty of any kind, whether express | ||
9 | * or implied. | ||
10 | */ | ||
11 | |||
12 | #ifdef __KERNEL__ | ||
13 | #ifndef __ASM_IBM405GPR_H__ | ||
14 | #define __ASM_IBM405GPR_H__ | ||
15 | |||
16 | #include <linux/config.h> | ||
17 | |||
18 | /* ibm405.h at bottom of this file */ | ||
19 | |||
20 | /* PCI | ||
21 | * PCI Bridge config reg definitions | ||
22 | * see 17-19 of manual | ||
23 | */ | ||
24 | |||
25 | #define PPC405_PCI_CONFIG_ADDR 0xeec00000 | ||
26 | #define PPC405_PCI_CONFIG_DATA 0xeec00004 | ||
27 | |||
28 | #define PPC405_PCI_PHY_MEM_BASE 0x80000000 /* hose_a->pci_mem_offset */ | ||
29 | /* setbat */ | ||
30 | #define PPC405_PCI_MEM_BASE PPC405_PCI_PHY_MEM_BASE /* setbat */ | ||
31 | #define PPC405_PCI_PHY_IO_BASE 0xe8000000 /* setbat */ | ||
32 | #define PPC405_PCI_IO_BASE PPC405_PCI_PHY_IO_BASE /* setbat */ | ||
33 | |||
34 | #define PPC405_PCI_LOWER_MEM 0x80000000 /* hose_a->mem_space.start */ | ||
35 | #define PPC405_PCI_UPPER_MEM 0xBfffffff /* hose_a->mem_space.end */ | ||
36 | #define PPC405_PCI_LOWER_IO 0x00000000 /* hose_a->io_space.start */ | ||
37 | #define PPC405_PCI_UPPER_IO 0x0000ffff /* hose_a->io_space.end */ | ||
38 | |||
39 | #define PPC405_ISA_IO_BASE PPC405_PCI_IO_BASE | ||
40 | |||
41 | #define PPC4xx_PCI_IO_PADDR ((uint)PPC405_PCI_PHY_IO_BASE) | ||
42 | #define PPC4xx_PCI_IO_VADDR PPC4xx_PCI_IO_PADDR | ||
43 | #define PPC4xx_PCI_IO_SIZE ((uint)64*1024) | ||
44 | #define PPC4xx_PCI_CFG_PADDR ((uint)PPC405_PCI_CONFIG_ADDR) | ||
45 | #define PPC4xx_PCI_CFG_VADDR PPC4xx_PCI_CFG_PADDR | ||
46 | #define PPC4xx_PCI_CFG_SIZE ((uint)4*1024) | ||
47 | #define PPC4xx_PCI_LCFG_PADDR ((uint)0xef400000) | ||
48 | #define PPC4xx_PCI_LCFG_VADDR PPC4xx_PCI_LCFG_PADDR | ||
49 | #define PPC4xx_PCI_LCFG_SIZE ((uint)4*1024) | ||
50 | #define PPC4xx_ONB_IO_PADDR ((uint)0xef600000) | ||
51 | #define PPC4xx_ONB_IO_VADDR PPC4xx_ONB_IO_PADDR | ||
52 | #define PPC4xx_ONB_IO_SIZE ((uint)4*1024) | ||
53 | |||
54 | /* serial port defines */ | ||
55 | #define RS_TABLE_SIZE 2 | ||
56 | |||
57 | #define UART0_INT 0 | ||
58 | #define UART1_INT 1 | ||
59 | |||
60 | #define PCIL0_BASE 0xEF400000 | ||
61 | #define UART0_IO_BASE 0xEF600300 | ||
62 | #define UART1_IO_BASE 0xEF600400 | ||
63 | #define EMAC0_BASE 0xEF600800 | ||
64 | |||
65 | #define BD_EMAC_ADDR(e,i) bi_enetaddr[i] | ||
66 | |||
67 | #define STD_UART_OP(num) \ | ||
68 | { 0, BASE_BAUD, 0, UART##num##_INT, \ | ||
69 | (ASYNC_BOOT_AUTOCONF | ASYNC_SKIP_TEST), \ | ||
70 | iomem_base: (u8 *)UART##num##_IO_BASE, \ | ||
71 | io_type: SERIAL_IO_MEM}, | ||
72 | |||
73 | #if defined(CONFIG_UART0_TTYS0) | ||
74 | #define SERIAL_DEBUG_IO_BASE UART0_IO_BASE | ||
75 | #define SERIAL_PORT_DFNS \ | ||
76 | STD_UART_OP(0) \ | ||
77 | STD_UART_OP(1) | ||
78 | #endif | ||
79 | |||
80 | #if defined(CONFIG_UART0_TTYS1) | ||
81 | #define SERIAL_DEBUG_IO_BASE UART1_IO_BASE | ||
82 | #define SERIAL_PORT_DFNS \ | ||
83 | STD_UART_OP(1) \ | ||
84 | STD_UART_OP(0) | ||
85 | #endif | ||
86 | |||
87 | /* DCR defines */ | ||
88 | #define DCRN_CHCR_BASE 0x0B1 | ||
89 | #define DCRN_CHPSR_BASE 0x0B4 | ||
90 | #define DCRN_CPMSR_BASE 0x0B8 | ||
91 | #define DCRN_CPMFR_BASE 0x0BA | ||
92 | |||
93 | #define CHR0_U0EC 0x00000080 /* Select external clock for UART0 */ | ||
94 | #define CHR0_U1EC 0x00000040 /* Select external clock for UART1 */ | ||
95 | #define CHR0_UDIV 0x0000003E /* UART internal clock divisor */ | ||
96 | #define CHR1_CETE 0x00800000 /* CPU external timer enable */ | ||
97 | |||
98 | #define DCRN_CHPSR_BASE 0x0B4 | ||
99 | #define PSR_PLL_FWD_MASK 0xC0000000 | ||
100 | #define PSR_PLL_FDBACK_MASK 0x30000000 | ||
101 | #define PSR_PLL_TUNING_MASK 0x0E000000 | ||
102 | #define PSR_PLB_CPU_MASK 0x01800000 | ||
103 | #define PSR_OPB_PLB_MASK 0x00600000 | ||
104 | #define PSR_PCI_PLB_MASK 0x00180000 | ||
105 | #define PSR_EB_PLB_MASK 0x00060000 | ||
106 | #define PSR_ROM_WIDTH_MASK 0x00018000 | ||
107 | #define PSR_ROM_LOC 0x00004000 | ||
108 | #define PSR_PCI_ASYNC_EN 0x00001000 | ||
109 | #define PSR_PCI_ARBIT_EN 0x00000400 | ||
110 | |||
111 | #define IBM_CPM_IIC0 0x80000000 /* IIC interface */ | ||
112 | #define IBM_CPM_PCI 0x40000000 /* PCI bridge */ | ||
113 | #define IBM_CPM_CPU 0x20000000 /* processor core */ | ||
114 | #define IBM_CPM_DMA 0x10000000 /* DMA controller */ | ||
115 | #define IBM_CPM_OPB 0x08000000 /* PLB to OPB bridge */ | ||
116 | #define IBM_CPM_DCP 0x04000000 /* CodePack */ | ||
117 | #define IBM_CPM_EBC 0x02000000 /* ROM/SRAM peripheral controller */ | ||
118 | #define IBM_CPM_SDRAM0 0x01000000 /* SDRAM memory controller */ | ||
119 | #define IBM_CPM_PLB 0x00800000 /* PLB bus arbiter */ | ||
120 | #define IBM_CPM_GPIO0 0x00400000 /* General Purpose IO (??) */ | ||
121 | #define IBM_CPM_UART0 0x00200000 /* serial port 0 */ | ||
122 | #define IBM_CPM_UART1 0x00100000 /* serial port 1 */ | ||
123 | #define IBM_CPM_UIC 0x00080000 /* Universal Interrupt Controller */ | ||
124 | #define IBM_CPM_TMRCLK 0x00040000 /* CPU timers */ | ||
125 | #define IBM_CPM_EMAC0 0x00020000 /* on-chip ethernet MM unit */ | ||
126 | #define DFLT_IBM4xx_PM ~(IBM_CPM_PCI | IBM_CPM_CPU | IBM_CPM_DMA \ | ||
127 | | IBM_CPM_OPB | IBM_CPM_EBC \ | ||
128 | | IBM_CPM_SDRAM0 | IBM_CPM_PLB \ | ||
129 | | IBM_CPM_UIC | IBM_CPM_TMRCLK) | ||
130 | |||
131 | #define DCRN_DMA0_BASE 0x100 | ||
132 | #define DCRN_DMA1_BASE 0x108 | ||
133 | #define DCRN_DMA2_BASE 0x110 | ||
134 | #define DCRN_DMA3_BASE 0x118 | ||
135 | #define DCRNCAP_DMA_SG 1 /* have DMA scatter/gather capability */ | ||
136 | #define DCRN_DMASR_BASE 0x120 | ||
137 | #define DCRN_EBC_BASE 0x012 | ||
138 | #define DCRN_DCP0_BASE 0x014 | ||
139 | #define DCRN_MAL_BASE 0x180 | ||
140 | #define DCRN_OCM0_BASE 0x018 | ||
141 | #define DCRN_PLB0_BASE 0x084 | ||
142 | #define DCRN_PLLMR_BASE 0x0B0 | ||
143 | #define DCRN_POB0_BASE 0x0A0 | ||
144 | #define DCRN_SDRAM0_BASE 0x010 | ||
145 | #define DCRN_UIC0_BASE 0x0C0 | ||
146 | #define UIC0 DCRN_UIC0_BASE | ||
147 | |||
148 | #include <asm/ibm405.h> | ||
149 | |||
150 | #endif /* __ASM_IBM405GPR_H__ */ | ||
151 | #endif /* __KERNEL__ */ | ||
diff --git a/arch/ppc/platforms/4xx/ibm440gp.c b/arch/ppc/platforms/4xx/ibm440gp.c new file mode 100644 index 000000000000..27615ef8309c --- /dev/null +++ b/arch/ppc/platforms/4xx/ibm440gp.c | |||
@@ -0,0 +1,164 @@ | |||
1 | /* | ||
2 | * arch/ppc/platforms/4xx/ibm440gp.c | ||
3 | * | ||
4 | * PPC440GP I/O descriptions | ||
5 | * | ||
6 | * Matt Porter <mporter@mvista.com> | ||
7 | * Copyright 2002-2004 MontaVista Software Inc. | ||
8 | * | ||
9 | * Eugene Surovegin <eugene.surovegin@zultys.com> or <ebs@ebshome.net> | ||
10 | * Copyright (c) 2003, 2004 Zultys Technologies | ||
11 | * | ||
12 | * This program is free software; you can redistribute it and/or modify it | ||
13 | * under the terms of the GNU General Public License as published by the | ||
14 | * Free Software Foundation; either version 2 of the License, or (at your | ||
15 | * option) any later version. | ||
16 | * | ||
17 | */ | ||
18 | #include <linux/init.h> | ||
19 | #include <linux/module.h> | ||
20 | #include <platforms/4xx/ibm440gp.h> | ||
21 | #include <asm/ocp.h> | ||
22 | #include <asm/ppc4xx_pic.h> | ||
23 | |||
24 | static struct ocp_func_emac_data ibm440gp_emac0_def = { | ||
25 | .rgmii_idx = -1, /* No RGMII */ | ||
26 | .rgmii_mux = -1, /* No RGMII */ | ||
27 | .zmii_idx = 0, /* ZMII device index */ | ||
28 | .zmii_mux = 0, /* ZMII input of this EMAC */ | ||
29 | .mal_idx = 0, /* MAL device index */ | ||
30 | .mal_rx_chan = 0, /* MAL rx channel number */ | ||
31 | .mal_tx_chan = 0, /* MAL tx channel number */ | ||
32 | .wol_irq = 61, /* WOL interrupt number */ | ||
33 | .mdio_idx = -1, /* No shared MDIO */ | ||
34 | .tah_idx = -1, /* No TAH */ | ||
35 | }; | ||
36 | |||
37 | static struct ocp_func_emac_data ibm440gp_emac1_def = { | ||
38 | .rgmii_idx = -1, /* No RGMII */ | ||
39 | .rgmii_mux = -1, /* No RGMII */ | ||
40 | .zmii_idx = 0, /* ZMII device index */ | ||
41 | .zmii_mux = 1, /* ZMII input of this EMAC */ | ||
42 | .mal_idx = 0, /* MAL device index */ | ||
43 | .mal_rx_chan = 1, /* MAL rx channel number */ | ||
44 | .mal_tx_chan = 2, /* MAL tx channel number */ | ||
45 | .wol_irq = 63, /* WOL interrupt number */ | ||
46 | .mdio_idx = -1, /* No shared MDIO */ | ||
47 | .tah_idx = -1, /* No TAH */ | ||
48 | }; | ||
49 | OCP_SYSFS_EMAC_DATA() | ||
50 | |||
51 | static struct ocp_func_mal_data ibm440gp_mal0_def = { | ||
52 | .num_tx_chans = 4, /* Number of TX channels */ | ||
53 | .num_rx_chans = 2, /* Number of RX channels */ | ||
54 | .txeob_irq = 10, /* TX End Of Buffer IRQ */ | ||
55 | .rxeob_irq = 11, /* RX End Of Buffer IRQ */ | ||
56 | .txde_irq = 33, /* TX Descriptor Error IRQ */ | ||
57 | .rxde_irq = 34, /* RX Descriptor Error IRQ */ | ||
58 | .serr_irq = 32, /* MAL System Error IRQ */ | ||
59 | }; | ||
60 | OCP_SYSFS_MAL_DATA() | ||
61 | |||
62 | static struct ocp_func_iic_data ibm440gp_iic0_def = { | ||
63 | .fast_mode = 0, /* Use standad mode (100Khz) */ | ||
64 | }; | ||
65 | |||
66 | static struct ocp_func_iic_data ibm440gp_iic1_def = { | ||
67 | .fast_mode = 0, /* Use standad mode (100Khz) */ | ||
68 | }; | ||
69 | OCP_SYSFS_IIC_DATA() | ||
70 | |||
71 | struct ocp_def core_ocp[] = { | ||
72 | { .vendor = OCP_VENDOR_IBM, | ||
73 | .function = OCP_FUNC_OPB, | ||
74 | .index = 0, | ||
75 | .paddr = 0x0000000140000000ULL, | ||
76 | .irq = OCP_IRQ_NA, | ||
77 | .pm = OCP_CPM_NA, | ||
78 | }, | ||
79 | { .vendor = OCP_VENDOR_IBM, | ||
80 | .function = OCP_FUNC_16550, | ||
81 | .index = 0, | ||
82 | .paddr = PPC440GP_UART0_ADDR, | ||
83 | .irq = UART0_INT, | ||
84 | .pm = IBM_CPM_UART0, | ||
85 | }, | ||
86 | { .vendor = OCP_VENDOR_IBM, | ||
87 | .function = OCP_FUNC_16550, | ||
88 | .index = 1, | ||
89 | .paddr = PPC440GP_UART1_ADDR, | ||
90 | .irq = UART1_INT, | ||
91 | .pm = IBM_CPM_UART1, | ||
92 | }, | ||
93 | { .vendor = OCP_VENDOR_IBM, | ||
94 | .function = OCP_FUNC_IIC, | ||
95 | .index = 0, | ||
96 | .paddr = 0x0000000140000400ULL, | ||
97 | .irq = 2, | ||
98 | .pm = IBM_CPM_IIC0, | ||
99 | .additions = &ibm440gp_iic0_def, | ||
100 | .show = &ocp_show_iic_data | ||
101 | }, | ||
102 | { .vendor = OCP_VENDOR_IBM, | ||
103 | .function = OCP_FUNC_IIC, | ||
104 | .index = 1, | ||
105 | .paddr = 0x0000000140000500ULL, | ||
106 | .irq = 3, | ||
107 | .pm = IBM_CPM_IIC1, | ||
108 | .additions = &ibm440gp_iic1_def, | ||
109 | .show = &ocp_show_iic_data | ||
110 | }, | ||
111 | { .vendor = OCP_VENDOR_IBM, | ||
112 | .function = OCP_FUNC_GPIO, | ||
113 | .index = 0, | ||
114 | .paddr = 0x0000000140000700ULL, | ||
115 | .irq = OCP_IRQ_NA, | ||
116 | .pm = IBM_CPM_GPIO0, | ||
117 | }, | ||
118 | { .vendor = OCP_VENDOR_IBM, | ||
119 | .function = OCP_FUNC_MAL, | ||
120 | .paddr = OCP_PADDR_NA, | ||
121 | .irq = OCP_IRQ_NA, | ||
122 | .pm = OCP_CPM_NA, | ||
123 | .additions = &ibm440gp_mal0_def, | ||
124 | .show = &ocp_show_mal_data, | ||
125 | }, | ||
126 | { .vendor = OCP_VENDOR_IBM, | ||
127 | .function = OCP_FUNC_EMAC, | ||
128 | .index = 0, | ||
129 | .paddr = 0x0000000140000800ULL, | ||
130 | .irq = 60, | ||
131 | .pm = OCP_CPM_NA, | ||
132 | .additions = &ibm440gp_emac0_def, | ||
133 | .show = &ocp_show_emac_data, | ||
134 | }, | ||
135 | { .vendor = OCP_VENDOR_IBM, | ||
136 | .function = OCP_FUNC_EMAC, | ||
137 | .index = 1, | ||
138 | .paddr = 0x0000000140000900ULL, | ||
139 | .irq = 62, | ||
140 | .pm = OCP_CPM_NA, | ||
141 | .additions = &ibm440gp_emac1_def, | ||
142 | .show = &ocp_show_emac_data, | ||
143 | }, | ||
144 | { .vendor = OCP_VENDOR_IBM, | ||
145 | .function = OCP_FUNC_ZMII, | ||
146 | .paddr = 0x0000000140000780ULL, | ||
147 | .irq = OCP_IRQ_NA, | ||
148 | .pm = OCP_CPM_NA, | ||
149 | }, | ||
150 | { .vendor = OCP_VENDOR_INVALID | ||
151 | } | ||
152 | }; | ||
153 | |||
154 | /* Polarity and triggering settings for internal interrupt sources */ | ||
155 | struct ppc4xx_uic_settings ppc4xx_core_uic_cfg[] __initdata = { | ||
156 | { .polarity = 0xfffffe03, | ||
157 | .triggering = 0x01c00000, | ||
158 | .ext_irq_mask = 0x000001fc, /* IRQ0 - IRQ6 */ | ||
159 | }, | ||
160 | { .polarity = 0xffffc0ff, | ||
161 | .triggering = 0x00ff8000, | ||
162 | .ext_irq_mask = 0x00003f00, /* IRQ7 - IRQ12 */ | ||
163 | }, | ||
164 | }; | ||
diff --git a/arch/ppc/platforms/4xx/ibm440gp.h b/arch/ppc/platforms/4xx/ibm440gp.h new file mode 100644 index 000000000000..ae1efc03b295 --- /dev/null +++ b/arch/ppc/platforms/4xx/ibm440gp.h | |||
@@ -0,0 +1,66 @@ | |||
1 | /* | ||
2 | * arch/ppc/platforms/4xx/ibm440gp.h | ||
3 | * | ||
4 | * PPC440GP definitions | ||
5 | * | ||
6 | * Roland Dreier <roland@digitalvampire.org> | ||
7 | * | ||
8 | * Copyright 2002 Roland Dreier | ||
9 | * | ||
10 | * This program is free software; you can redistribute it and/or modify it | ||
11 | * under the terms of the GNU General Public License as published by the | ||
12 | * Free Software Foundation; either version 2 of the License, or (at your | ||
13 | * option) any later version. | ||
14 | * | ||
15 | * This file contains code that was originally in the files ibm44x.h | ||
16 | * and ebony.h, which were written by Matt Porter of MontaVista Software Inc. | ||
17 | */ | ||
18 | |||
19 | #ifdef __KERNEL__ | ||
20 | #ifndef __PPC_PLATFORMS_IBM440GP_H | ||
21 | #define __PPC_PLATFORMS_IBM440GP_H | ||
22 | |||
23 | #include <linux/config.h> | ||
24 | |||
25 | /* UART */ | ||
26 | #define PPC440GP_UART0_ADDR 0x0000000140000200ULL | ||
27 | #define PPC440GP_UART1_ADDR 0x0000000140000300ULL | ||
28 | #define UART0_INT 0 | ||
29 | #define UART1_INT 1 | ||
30 | |||
31 | /* Clock and Power Management */ | ||
32 | #define IBM_CPM_IIC0 0x80000000 /* IIC interface */ | ||
33 | #define IBM_CPM_IIC1 0x40000000 /* IIC interface */ | ||
34 | #define IBM_CPM_PCI 0x20000000 /* PCI bridge */ | ||
35 | #define IBM_CPM_CPU 0x02000000 /* processor core */ | ||
36 | #define IBM_CPM_DMA 0x01000000 /* DMA controller */ | ||
37 | #define IBM_CPM_BGO 0x00800000 /* PLB to OPB bus arbiter */ | ||
38 | #define IBM_CPM_BGI 0x00400000 /* OPB to PLB bridge */ | ||
39 | #define IBM_CPM_EBC 0x00200000 /* External Bux Controller */ | ||
40 | #define IBM_CPM_EBM 0x00100000 /* Ext Bus Master Interface */ | ||
41 | #define IBM_CPM_DMC 0x00080000 /* SDRAM peripheral controller */ | ||
42 | #define IBM_CPM_PLB 0x00040000 /* PLB bus arbiter */ | ||
43 | #define IBM_CPM_SRAM 0x00020000 /* SRAM memory controller */ | ||
44 | #define IBM_CPM_PPM 0x00002000 /* PLB Performance Monitor */ | ||
45 | #define IBM_CPM_UIC1 0x00001000 /* Universal Interrupt Controller */ | ||
46 | #define IBM_CPM_GPIO0 0x00000800 /* General Purpose IO (??) */ | ||
47 | #define IBM_CPM_GPT 0x00000400 /* General Purpose Timers */ | ||
48 | #define IBM_CPM_UART0 0x00000200 /* serial port 0 */ | ||
49 | #define IBM_CPM_UART1 0x00000100 /* serial port 1 */ | ||
50 | #define IBM_CPM_UIC0 0x00000080 /* Universal Interrupt Controller */ | ||
51 | #define IBM_CPM_TMRCLK 0x00000040 /* CPU timers */ | ||
52 | |||
53 | #define DFLT_IBM4xx_PM ~(IBM_CPM_UIC | IBM_CPM_UIC1 | IBM_CPM_CPU \ | ||
54 | | IBM_CPM_EBC | IBM_CPM_SRAM | IBM_CPM_BGO \ | ||
55 | | IBM_CPM_EBM | IBM_CPM_PLB | IBM_CPM_OPB \ | ||
56 | | IBM_CPM_TMRCLK | IBM_CPM_DMA | IBM_CPM_PCI) | ||
57 | /* | ||
58 | * Serial port defines | ||
59 | */ | ||
60 | #define RS_TABLE_SIZE 2 | ||
61 | |||
62 | #include <asm/ibm44x.h> | ||
63 | #include <syslib/ibm440gp_common.h> | ||
64 | |||
65 | #endif /* __PPC_PLATFORMS_IBM440GP_H */ | ||
66 | #endif /* __KERNEL__ */ | ||
diff --git a/arch/ppc/platforms/4xx/ibm440gx.c b/arch/ppc/platforms/4xx/ibm440gx.c new file mode 100644 index 000000000000..1f38f42835b4 --- /dev/null +++ b/arch/ppc/platforms/4xx/ibm440gx.c | |||
@@ -0,0 +1,234 @@ | |||
1 | /* | ||
2 | * arch/ppc/platforms/4xx/ibm440gx.c | ||
3 | * | ||
4 | * PPC440GX I/O descriptions | ||
5 | * | ||
6 | * Matt Porter <mporter@mvista.com> | ||
7 | * Copyright 2002-2004 MontaVista Software Inc. | ||
8 | * | ||
9 | * Eugene Surovegin <eugene.surovegin@zultys.com> or <ebs@ebshome.net> | ||
10 | * Copyright (c) 2003, 2004 Zultys Technologies | ||
11 | * | ||
12 | * This program is free software; you can redistribute it and/or modify it | ||
13 | * under the terms of the GNU General Public License as published by the | ||
14 | * Free Software Foundation; either version 2 of the License, or (at your | ||
15 | * option) any later version. | ||
16 | * | ||
17 | */ | ||
18 | #include <linux/init.h> | ||
19 | #include <linux/module.h> | ||
20 | #include <platforms/4xx/ibm440gx.h> | ||
21 | #include <asm/ocp.h> | ||
22 | #include <asm/ppc4xx_pic.h> | ||
23 | |||
24 | static struct ocp_func_emac_data ibm440gx_emac0_def = { | ||
25 | .rgmii_idx = -1, /* No RGMII */ | ||
26 | .rgmii_mux = -1, /* No RGMII */ | ||
27 | .zmii_idx = 0, /* ZMII device index */ | ||
28 | .zmii_mux = 0, /* ZMII input of this EMAC */ | ||
29 | .mal_idx = 0, /* MAL device index */ | ||
30 | .mal_rx_chan = 0, /* MAL rx channel number */ | ||
31 | .mal_tx_chan = 0, /* MAL tx channel number */ | ||
32 | .wol_irq = 61, /* WOL interrupt number */ | ||
33 | .mdio_idx = -1, /* No shared MDIO */ | ||
34 | .tah_idx = -1, /* No TAH */ | ||
35 | }; | ||
36 | |||
37 | static struct ocp_func_emac_data ibm440gx_emac1_def = { | ||
38 | .rgmii_idx = -1, /* No RGMII */ | ||
39 | .rgmii_mux = -1, /* No RGMII */ | ||
40 | .zmii_idx = 0, /* ZMII device index */ | ||
41 | .zmii_mux = 1, /* ZMII input of this EMAC */ | ||
42 | .mal_idx = 0, /* MAL device index */ | ||
43 | .mal_rx_chan = 1, /* MAL rx channel number */ | ||
44 | .mal_tx_chan = 1, /* MAL tx channel number */ | ||
45 | .wol_irq = 63, /* WOL interrupt number */ | ||
46 | .mdio_idx = -1, /* No shared MDIO */ | ||
47 | .tah_idx = -1, /* No TAH */ | ||
48 | }; | ||
49 | |||
50 | static struct ocp_func_emac_data ibm440gx_emac2_def = { | ||
51 | .rgmii_idx = 0, /* RGMII device index */ | ||
52 | .rgmii_mux = 0, /* RGMII input of this EMAC */ | ||
53 | .zmii_idx = 0, /* ZMII device index */ | ||
54 | .zmii_mux = 2, /* ZMII input of this EMAC */ | ||
55 | .mal_idx = 0, /* MAL device index */ | ||
56 | .mal_rx_chan = 2, /* MAL rx channel number */ | ||
57 | .mal_tx_chan = 2, /* MAL tx channel number */ | ||
58 | .wol_irq = 65, /* WOL interrupt number */ | ||
59 | .mdio_idx = -1, /* No shared MDIO */ | ||
60 | .tah_idx = 0, /* TAH device index */ | ||
61 | .jumbo = 1, /* Jumbo frames supported */ | ||
62 | }; | ||
63 | |||
64 | static struct ocp_func_emac_data ibm440gx_emac3_def = { | ||
65 | .rgmii_idx = 0, /* RGMII device index */ | ||
66 | .rgmii_mux = 1, /* RGMII input of this EMAC */ | ||
67 | .zmii_idx = 0, /* ZMII device index */ | ||
68 | .zmii_mux = 3, /* ZMII input of this EMAC */ | ||
69 | .mal_idx = 0, /* MAL device index */ | ||
70 | .mal_rx_chan = 3, /* MAL rx channel number */ | ||
71 | .mal_tx_chan = 3, /* MAL tx channel number */ | ||
72 | .wol_irq = 67, /* WOL interrupt number */ | ||
73 | .mdio_idx = -1, /* No shared MDIO */ | ||
74 | .tah_idx = 1, /* TAH device index */ | ||
75 | .jumbo = 1, /* Jumbo frames supported */ | ||
76 | }; | ||
77 | OCP_SYSFS_EMAC_DATA() | ||
78 | |||
79 | static struct ocp_func_mal_data ibm440gx_mal0_def = { | ||
80 | .num_tx_chans = 4, /* Number of TX channels */ | ||
81 | .num_rx_chans = 4, /* Number of RX channels */ | ||
82 | .txeob_irq = 10, /* TX End Of Buffer IRQ */ | ||
83 | .rxeob_irq = 11, /* RX End Of Buffer IRQ */ | ||
84 | .txde_irq = 33, /* TX Descriptor Error IRQ */ | ||
85 | .rxde_irq = 34, /* RX Descriptor Error IRQ */ | ||
86 | .serr_irq = 32, /* MAL System Error IRQ */ | ||
87 | }; | ||
88 | OCP_SYSFS_MAL_DATA() | ||
89 | |||
90 | static struct ocp_func_iic_data ibm440gx_iic0_def = { | ||
91 | .fast_mode = 0, /* Use standad mode (100Khz) */ | ||
92 | }; | ||
93 | |||
94 | static struct ocp_func_iic_data ibm440gx_iic1_def = { | ||
95 | .fast_mode = 0, /* Use standad mode (100Khz) */ | ||
96 | }; | ||
97 | OCP_SYSFS_IIC_DATA() | ||
98 | |||
99 | struct ocp_def core_ocp[] = { | ||
100 | { .vendor = OCP_VENDOR_IBM, | ||
101 | .function = OCP_FUNC_OPB, | ||
102 | .index = 0, | ||
103 | .paddr = 0x0000000140000000ULL, | ||
104 | .irq = OCP_IRQ_NA, | ||
105 | .pm = OCP_CPM_NA, | ||
106 | }, | ||
107 | { .vendor = OCP_VENDOR_IBM, | ||
108 | .function = OCP_FUNC_16550, | ||
109 | .index = 0, | ||
110 | .paddr = PPC440GX_UART0_ADDR, | ||
111 | .irq = UART0_INT, | ||
112 | .pm = IBM_CPM_UART0, | ||
113 | }, | ||
114 | { .vendor = OCP_VENDOR_IBM, | ||
115 | .function = OCP_FUNC_16550, | ||
116 | .index = 1, | ||
117 | .paddr = PPC440GX_UART1_ADDR, | ||
118 | .irq = UART1_INT, | ||
119 | .pm = IBM_CPM_UART1, | ||
120 | }, | ||
121 | { .vendor = OCP_VENDOR_IBM, | ||
122 | .function = OCP_FUNC_IIC, | ||
123 | .index = 0, | ||
124 | .paddr = 0x0000000140000400ULL, | ||
125 | .irq = 2, | ||
126 | .pm = IBM_CPM_IIC0, | ||
127 | .additions = &ibm440gx_iic0_def, | ||
128 | .show = &ocp_show_iic_data | ||
129 | }, | ||
130 | { .vendor = OCP_VENDOR_IBM, | ||
131 | .function = OCP_FUNC_IIC, | ||
132 | .index = 1, | ||
133 | .paddr = 0x0000000140000500ULL, | ||
134 | .irq = 3, | ||
135 | .pm = IBM_CPM_IIC1, | ||
136 | .additions = &ibm440gx_iic1_def, | ||
137 | .show = &ocp_show_iic_data | ||
138 | }, | ||
139 | { .vendor = OCP_VENDOR_IBM, | ||
140 | .function = OCP_FUNC_GPIO, | ||
141 | .index = 0, | ||
142 | .paddr = 0x0000000140000700ULL, | ||
143 | .irq = OCP_IRQ_NA, | ||
144 | .pm = IBM_CPM_GPIO0, | ||
145 | }, | ||
146 | { .vendor = OCP_VENDOR_IBM, | ||
147 | .function = OCP_FUNC_MAL, | ||
148 | .paddr = OCP_PADDR_NA, | ||
149 | .irq = OCP_IRQ_NA, | ||
150 | .pm = OCP_CPM_NA, | ||
151 | .additions = &ibm440gx_mal0_def, | ||
152 | .show = &ocp_show_mal_data, | ||
153 | }, | ||
154 | { .vendor = OCP_VENDOR_IBM, | ||
155 | .function = OCP_FUNC_EMAC, | ||
156 | .index = 0, | ||
157 | .paddr = 0x0000000140000800ULL, | ||
158 | .irq = 60, | ||
159 | .pm = OCP_CPM_NA, | ||
160 | .additions = &ibm440gx_emac0_def, | ||
161 | .show = &ocp_show_emac_data, | ||
162 | }, | ||
163 | { .vendor = OCP_VENDOR_IBM, | ||
164 | .function = OCP_FUNC_EMAC, | ||
165 | .index = 1, | ||
166 | .paddr = 0x0000000140000900ULL, | ||
167 | .irq = 62, | ||
168 | .pm = OCP_CPM_NA, | ||
169 | .additions = &ibm440gx_emac1_def, | ||
170 | .show = &ocp_show_emac_data, | ||
171 | }, | ||
172 | { .vendor = OCP_VENDOR_IBM, | ||
173 | .function = OCP_FUNC_EMAC, | ||
174 | .index = 2, | ||
175 | .paddr = 0x0000000140000C00ULL, | ||
176 | .irq = 64, | ||
177 | .pm = OCP_CPM_NA, | ||
178 | .additions = &ibm440gx_emac2_def, | ||
179 | .show = &ocp_show_emac_data, | ||
180 | }, | ||
181 | { .vendor = OCP_VENDOR_IBM, | ||
182 | .function = OCP_FUNC_EMAC, | ||
183 | .index = 3, | ||
184 | .paddr = 0x0000000140000E00ULL, | ||
185 | .irq = 66, | ||
186 | .pm = OCP_CPM_NA, | ||
187 | .additions = &ibm440gx_emac3_def, | ||
188 | .show = &ocp_show_emac_data, | ||
189 | }, | ||
190 | { .vendor = OCP_VENDOR_IBM, | ||
191 | .function = OCP_FUNC_RGMII, | ||
192 | .paddr = 0x0000000140000790ULL, | ||
193 | .irq = OCP_IRQ_NA, | ||
194 | .pm = OCP_CPM_NA, | ||
195 | }, | ||
196 | { .vendor = OCP_VENDOR_IBM, | ||
197 | .function = OCP_FUNC_ZMII, | ||
198 | .paddr = 0x0000000140000780ULL, | ||
199 | .irq = OCP_IRQ_NA, | ||
200 | .pm = OCP_CPM_NA, | ||
201 | }, | ||
202 | { .vendor = OCP_VENDOR_IBM, | ||
203 | .function = OCP_FUNC_TAH, | ||
204 | .index = 0, | ||
205 | .paddr = 0x0000000140000b50ULL, | ||
206 | .irq = 68, | ||
207 | .pm = OCP_CPM_NA, | ||
208 | }, | ||
209 | { .vendor = OCP_VENDOR_IBM, | ||
210 | .function = OCP_FUNC_TAH, | ||
211 | .index = 1, | ||
212 | .paddr = 0x0000000140000d50ULL, | ||
213 | .irq = 69, | ||
214 | .pm = OCP_CPM_NA, | ||
215 | }, | ||
216 | { .vendor = OCP_VENDOR_INVALID | ||
217 | } | ||
218 | }; | ||
219 | |||
220 | /* Polarity and triggering settings for internal interrupt sources */ | ||
221 | struct ppc4xx_uic_settings ppc4xx_core_uic_cfg[] __initdata = { | ||
222 | { .polarity = 0xfffffe03, | ||
223 | .triggering = 0x01c00000, | ||
224 | .ext_irq_mask = 0x000001fc, /* IRQ0 - IRQ6 */ | ||
225 | }, | ||
226 | { .polarity = 0xffffc0ff, | ||
227 | .triggering = 0x00ff8000, | ||
228 | .ext_irq_mask = 0x00003f00, /* IRQ7 - IRQ12 */ | ||
229 | }, | ||
230 | { .polarity = 0xffff83ff, | ||
231 | .triggering = 0x000f83c0, | ||
232 | .ext_irq_mask = 0x00007c00, /* IRQ13 - IRQ17 */ | ||
233 | }, | ||
234 | }; | ||
diff --git a/arch/ppc/platforms/4xx/ibm440gx.h b/arch/ppc/platforms/4xx/ibm440gx.h new file mode 100644 index 000000000000..0b59d8dcd03c --- /dev/null +++ b/arch/ppc/platforms/4xx/ibm440gx.h | |||
@@ -0,0 +1,74 @@ | |||
1 | /* | ||
2 | * arch/ppc/platforms/ibm440gx.h | ||
3 | * | ||
4 | * PPC440GX definitions | ||
5 | * | ||
6 | * Matt Porter <mporter@mvista.com> | ||
7 | * | ||
8 | * Copyright 2002 Roland Dreier | ||
9 | * Copyright 2003 MontaVista Software, Inc. | ||
10 | * | ||
11 | * This program is free software; you can redistribute it and/or modify it | ||
12 | * under the terms of the GNU General Public License as published by the | ||
13 | * Free Software Foundation; either version 2 of the License, or (at your | ||
14 | * option) any later version. | ||
15 | * | ||
16 | */ | ||
17 | |||
18 | #ifdef __KERNEL__ | ||
19 | #ifndef __PPC_PLATFORMS_IBM440GX_H | ||
20 | #define __PPC_PLATFORMS_IBM440GX_H | ||
21 | |||
22 | #include <linux/config.h> | ||
23 | |||
24 | #include <asm/ibm44x.h> | ||
25 | |||
26 | /* UART */ | ||
27 | #define PPC440GX_UART0_ADDR 0x0000000140000200ULL | ||
28 | #define PPC440GX_UART1_ADDR 0x0000000140000300ULL | ||
29 | #define UART0_INT 0 | ||
30 | #define UART1_INT 1 | ||
31 | |||
32 | /* Clock and Power Management */ | ||
33 | #define IBM_CPM_IIC0 0x80000000 /* IIC interface */ | ||
34 | #define IBM_CPM_IIC1 0x40000000 /* IIC interface */ | ||
35 | #define IBM_CPM_PCI 0x20000000 /* PCI bridge */ | ||
36 | #define IBM_CPM_RGMII 0x10000000 /* RGMII */ | ||
37 | #define IBM_CPM_TAHOE0 0x08000000 /* TAHOE 0 */ | ||
38 | #define IBM_CPM_TAHOE1 0x04000000 /* TAHOE 1 */ | ||
39 | #define IBM_CPM_CPU 0x02000000 /* processor core */ | ||
40 | #define IBM_CPM_DMA 0x01000000 /* DMA controller */ | ||
41 | #define IBM_CPM_BGO 0x00800000 /* PLB to OPB bus arbiter */ | ||
42 | #define IBM_CPM_BGI 0x00400000 /* OPB to PLB bridge */ | ||
43 | #define IBM_CPM_EBC 0x00200000 /* External Bux Controller */ | ||
44 | #define IBM_CPM_EBM 0x00100000 /* Ext Bus Master Interface */ | ||
45 | #define IBM_CPM_DMC 0x00080000 /* SDRAM peripheral controller */ | ||
46 | #define IBM_CPM_PLB 0x00040000 /* PLB bus arbiter */ | ||
47 | #define IBM_CPM_SRAM 0x00020000 /* SRAM memory controller */ | ||
48 | #define IBM_CPM_PPM 0x00002000 /* PLB Performance Monitor */ | ||
49 | #define IBM_CPM_UIC1 0x00001000 /* Universal Interrupt Controller */ | ||
50 | #define IBM_CPM_GPIO0 0x00000800 /* General Purpose IO (??) */ | ||
51 | #define IBM_CPM_GPT 0x00000400 /* General Purpose Timers */ | ||
52 | #define IBM_CPM_UART0 0x00000200 /* serial port 0 */ | ||
53 | #define IBM_CPM_UART1 0x00000100 /* serial port 1 */ | ||
54 | #define IBM_CPM_UIC0 0x00000080 /* Universal Interrupt Controller */ | ||
55 | #define IBM_CPM_TMRCLK 0x00000040 /* CPU timers */ | ||
56 | #define IBM_CPM_EMAC0 0x00000020 /* EMAC 0 */ | ||
57 | #define IBM_CPM_EMAC1 0x00000010 /* EMAC 1 */ | ||
58 | #define IBM_CPM_EMAC2 0x00000008 /* EMAC 2 */ | ||
59 | #define IBM_CPM_EMAC3 0x00000004 /* EMAC 3 */ | ||
60 | |||
61 | #define DFLT_IBM4xx_PM ~(IBM_CPM_UIC | IBM_CPM_UIC1 | IBM_CPM_CPU \ | ||
62 | | IBM_CPM_EBC | IBM_CPM_SRAM | IBM_CPM_BGO \ | ||
63 | | IBM_CPM_EBM | IBM_CPM_PLB | IBM_CPM_OPB \ | ||
64 | | IBM_CPM_TMRCLK | IBM_CPM_DMA | IBM_CPM_PCI \ | ||
65 | | IBM_CPM_TAHOE0 | IBM_CPM_TAHOE1 \ | ||
66 | | IBM_CPM_EMAC0 | IBM_CPM_EMAC1 \ | ||
67 | | IBM_CPM_EMAC2 | IBM_CPM_EMAC3 ) | ||
68 | /* | ||
69 | * Serial port defines | ||
70 | */ | ||
71 | #define RS_TABLE_SIZE 2 | ||
72 | |||
73 | #endif /* __PPC_PLATFORMS_IBM440GX_H */ | ||
74 | #endif /* __KERNEL__ */ | ||
diff --git a/arch/ppc/platforms/4xx/ibm440sp.c b/arch/ppc/platforms/4xx/ibm440sp.c new file mode 100644 index 000000000000..a203efb47aba --- /dev/null +++ b/arch/ppc/platforms/4xx/ibm440sp.c | |||
@@ -0,0 +1,131 @@ | |||
1 | /* | ||
2 | * arch/ppc/platforms/4xx/ibm440sp.c | ||
3 | * | ||
4 | * PPC440SP I/O descriptions | ||
5 | * | ||
6 | * Matt Porter <mporter@kernel.crashing.org> | ||
7 | * Copyright 2002-2005 MontaVista Software Inc. | ||
8 | * | ||
9 | * Eugene Surovegin <eugene.surovegin@zultys.com> or <ebs@ebshome.net> | ||
10 | * Copyright (c) 2003, 2004 Zultys Technologies | ||
11 | * | ||
12 | * This program is free software; you can redistribute it and/or modify it | ||
13 | * under the terms of the GNU General Public License as published by the | ||
14 | * Free Software Foundation; either version 2 of the License, or (at your | ||
15 | * option) any later version. | ||
16 | * | ||
17 | */ | ||
18 | #include <linux/init.h> | ||
19 | #include <linux/module.h> | ||
20 | #include <platforms/4xx/ibm440sp.h> | ||
21 | #include <asm/ocp.h> | ||
22 | |||
23 | static struct ocp_func_emac_data ibm440sp_emac0_def = { | ||
24 | .rgmii_idx = -1, /* No RGMII */ | ||
25 | .rgmii_mux = -1, /* No RGMII */ | ||
26 | .zmii_idx = -1, /* No ZMII */ | ||
27 | .zmii_mux = -1, /* No ZMII */ | ||
28 | .mal_idx = 0, /* MAL device index */ | ||
29 | .mal_rx_chan = 0, /* MAL rx channel number */ | ||
30 | .mal_tx_chan = 0, /* MAL tx channel number */ | ||
31 | .wol_irq = 61, /* WOL interrupt number */ | ||
32 | .mdio_idx = -1, /* No shared MDIO */ | ||
33 | .tah_idx = -1, /* No TAH */ | ||
34 | .jumbo = 1, /* Jumbo frames supported */ | ||
35 | }; | ||
36 | OCP_SYSFS_EMAC_DATA() | ||
37 | |||
38 | static struct ocp_func_mal_data ibm440sp_mal0_def = { | ||
39 | .num_tx_chans = 4, /* Number of TX channels */ | ||
40 | .num_rx_chans = 4, /* Number of RX channels */ | ||
41 | .txeob_irq = 38, /* TX End Of Buffer IRQ */ | ||
42 | .rxeob_irq = 39, /* RX End Of Buffer IRQ */ | ||
43 | .txde_irq = 34, /* TX Descriptor Error IRQ */ | ||
44 | .rxde_irq = 35, /* RX Descriptor Error IRQ */ | ||
45 | .serr_irq = 33, /* MAL System Error IRQ */ | ||
46 | }; | ||
47 | OCP_SYSFS_MAL_DATA() | ||
48 | |||
49 | static struct ocp_func_iic_data ibm440sp_iic0_def = { | ||
50 | .fast_mode = 0, /* Use standad mode (100Khz) */ | ||
51 | }; | ||
52 | |||
53 | static struct ocp_func_iic_data ibm440sp_iic1_def = { | ||
54 | .fast_mode = 0, /* Use standad mode (100Khz) */ | ||
55 | }; | ||
56 | OCP_SYSFS_IIC_DATA() | ||
57 | |||
58 | struct ocp_def core_ocp[] = { | ||
59 | { .vendor = OCP_VENDOR_IBM, | ||
60 | .function = OCP_FUNC_OPB, | ||
61 | .index = 0, | ||
62 | .paddr = 0x0000000140000000ULL, | ||
63 | .irq = OCP_IRQ_NA, | ||
64 | .pm = OCP_CPM_NA, | ||
65 | }, | ||
66 | { .vendor = OCP_VENDOR_IBM, | ||
67 | .function = OCP_FUNC_16550, | ||
68 | .index = 0, | ||
69 | .paddr = PPC440SP_UART0_ADDR, | ||
70 | .irq = UART0_INT, | ||
71 | .pm = IBM_CPM_UART0, | ||
72 | }, | ||
73 | { .vendor = OCP_VENDOR_IBM, | ||
74 | .function = OCP_FUNC_16550, | ||
75 | .index = 1, | ||
76 | .paddr = PPC440SP_UART1_ADDR, | ||
77 | .irq = UART1_INT, | ||
78 | .pm = IBM_CPM_UART1, | ||
79 | }, | ||
80 | { .vendor = OCP_VENDOR_IBM, | ||
81 | .function = OCP_FUNC_16550, | ||
82 | .index = 2, | ||
83 | .paddr = PPC440SP_UART2_ADDR, | ||
84 | .irq = UART2_INT, | ||
85 | .pm = IBM_CPM_UART2, | ||
86 | }, | ||
87 | { .vendor = OCP_VENDOR_IBM, | ||
88 | .function = OCP_FUNC_IIC, | ||
89 | .index = 0, | ||
90 | .paddr = 0x00000001f0000400ULL, | ||
91 | .irq = 2, | ||
92 | .pm = IBM_CPM_IIC0, | ||
93 | .additions = &ibm440sp_iic0_def, | ||
94 | .show = &ocp_show_iic_data | ||
95 | }, | ||
96 | { .vendor = OCP_VENDOR_IBM, | ||
97 | .function = OCP_FUNC_IIC, | ||
98 | .index = 1, | ||
99 | .paddr = 0x00000001f0000500ULL, | ||
100 | .irq = 3, | ||
101 | .pm = IBM_CPM_IIC1, | ||
102 | .additions = &ibm440sp_iic1_def, | ||
103 | .show = &ocp_show_iic_data | ||
104 | }, | ||
105 | { .vendor = OCP_VENDOR_IBM, | ||
106 | .function = OCP_FUNC_GPIO, | ||
107 | .index = 0, | ||
108 | .paddr = 0x00000001f0000700ULL, | ||
109 | .irq = OCP_IRQ_NA, | ||
110 | .pm = IBM_CPM_GPIO0, | ||
111 | }, | ||
112 | { .vendor = OCP_VENDOR_IBM, | ||
113 | .function = OCP_FUNC_MAL, | ||
114 | .paddr = OCP_PADDR_NA, | ||
115 | .irq = OCP_IRQ_NA, | ||
116 | .pm = OCP_CPM_NA, | ||
117 | .additions = &ibm440sp_mal0_def, | ||
118 | .show = &ocp_show_mal_data, | ||
119 | }, | ||
120 | { .vendor = OCP_VENDOR_IBM, | ||
121 | .function = OCP_FUNC_EMAC, | ||
122 | .index = 0, | ||
123 | .paddr = 0x00000001f0000800ULL, | ||
124 | .irq = 60, | ||
125 | .pm = OCP_CPM_NA, | ||
126 | .additions = &ibm440sp_emac0_def, | ||
127 | .show = &ocp_show_emac_data, | ||
128 | }, | ||
129 | { .vendor = OCP_VENDOR_INVALID | ||
130 | } | ||
131 | }; | ||
diff --git a/arch/ppc/platforms/4xx/ibm440sp.h b/arch/ppc/platforms/4xx/ibm440sp.h new file mode 100644 index 000000000000..c71e46a18b9e --- /dev/null +++ b/arch/ppc/platforms/4xx/ibm440sp.h | |||
@@ -0,0 +1,64 @@ | |||
1 | /* | ||
2 | * arch/ppc/platforms/4xx/ibm440sp.h | ||
3 | * | ||
4 | * PPC440SP definitions | ||
5 | * | ||
6 | * Matt Porter <mporter@kernel.crashing.org> | ||
7 | * | ||
8 | * Copyright 2004-2005 MontaVista Software, Inc. | ||
9 | * | ||
10 | * This program is free software; you can redistribute it and/or modify it | ||
11 | * under the terms of the GNU General Public License as published by the | ||
12 | * Free Software Foundation; either version 2 of the License, or (at your | ||
13 | * option) any later version. | ||
14 | */ | ||
15 | |||
16 | #ifdef __KERNEL__ | ||
17 | #ifndef __PPC_PLATFORMS_IBM440SP_H | ||
18 | #define __PPC_PLATFORMS_IBM440SP_H | ||
19 | |||
20 | #include <linux/config.h> | ||
21 | |||
22 | #include <asm/ibm44x.h> | ||
23 | |||
24 | /* UART */ | ||
25 | #define PPC440SP_UART0_ADDR 0x00000001f0000200ULL | ||
26 | #define PPC440SP_UART1_ADDR 0x00000001f0000300ULL | ||
27 | #define PPC440SP_UART2_ADDR 0x00000001f0000600ULL | ||
28 | #define UART0_INT 0 | ||
29 | #define UART1_INT 1 | ||
30 | #define UART2_INT 2 | ||
31 | |||
32 | /* Clock and Power Management */ | ||
33 | #define IBM_CPM_IIC0 0x80000000 /* IIC interface */ | ||
34 | #define IBM_CPM_IIC1 0x40000000 /* IIC interface */ | ||
35 | #define IBM_CPM_PCI 0x20000000 /* PCI bridge */ | ||
36 | #define IBM_CPM_CPU 0x02000000 /* processor core */ | ||
37 | #define IBM_CPM_DMA 0x01000000 /* DMA controller */ | ||
38 | #define IBM_CPM_BGO 0x00800000 /* PLB to OPB bus arbiter */ | ||
39 | #define IBM_CPM_BGI 0x00400000 /* OPB to PLB bridge */ | ||
40 | #define IBM_CPM_EBC 0x00200000 /* External Bux Controller */ | ||
41 | #define IBM_CPM_EBM 0x00100000 /* Ext Bus Master Interface */ | ||
42 | #define IBM_CPM_DMC 0x00080000 /* SDRAM peripheral controller */ | ||
43 | #define IBM_CPM_PLB 0x00040000 /* PLB bus arbiter */ | ||
44 | #define IBM_CPM_SRAM 0x00020000 /* SRAM memory controller */ | ||
45 | #define IBM_CPM_PPM 0x00002000 /* PLB Performance Monitor */ | ||
46 | #define IBM_CPM_UIC1 0x00001000 /* Universal Interrupt Controller */ | ||
47 | #define IBM_CPM_GPIO0 0x00000800 /* General Purpose IO (??) */ | ||
48 | #define IBM_CPM_GPT 0x00000400 /* General Purpose Timers */ | ||
49 | #define IBM_CPM_UART0 0x00000200 /* serial port 0 */ | ||
50 | #define IBM_CPM_UART1 0x00000100 /* serial port 1 */ | ||
51 | #define IBM_CPM_UART2 0x00000100 /* serial port 1 */ | ||
52 | #define IBM_CPM_UIC0 0x00000080 /* Universal Interrupt Controller */ | ||
53 | #define IBM_CPM_TMRCLK 0x00000040 /* CPU timers */ | ||
54 | #define IBM_CPM_EMAC0 0x00000020 /* EMAC 0 */ | ||
55 | |||
56 | #define DFLT_IBM4xx_PM ~(IBM_CPM_UIC | IBM_CPM_UIC1 | IBM_CPM_CPU \ | ||
57 | | IBM_CPM_EBC | IBM_CPM_SRAM | IBM_CPM_BGO \ | ||
58 | | IBM_CPM_EBM | IBM_CPM_PLB | IBM_CPM_OPB \ | ||
59 | | IBM_CPM_TMRCLK | IBM_CPM_DMA | IBM_CPM_PCI \ | ||
60 | | IBM_CPM_TAHOE0 | IBM_CPM_TAHOE1 \ | ||
61 | | IBM_CPM_EMAC0 | IBM_CPM_EMAC1 \ | ||
62 | | IBM_CPM_EMAC2 | IBM_CPM_EMAC3 ) | ||
63 | #endif /* __PPC_PLATFORMS_IBM440SP_H */ | ||
64 | #endif /* __KERNEL__ */ | ||
diff --git a/arch/ppc/platforms/4xx/ibmnp405h.c b/arch/ppc/platforms/4xx/ibmnp405h.c new file mode 100644 index 000000000000..ecdc5be6ae28 --- /dev/null +++ b/arch/ppc/platforms/4xx/ibmnp405h.c | |||
@@ -0,0 +1,172 @@ | |||
1 | /* | ||
2 | * arch/ppc/platforms/4xx/ibmnp405h.c | ||
3 | * | ||
4 | * Author: Armin Kuster <akuster@mvista.com> | ||
5 | * | ||
6 | * 2000-2002 (c) MontaVista, Software, Inc. This file is licensed under | ||
7 | * the terms of the GNU General Public License version 2. This program | ||
8 | * is licensed "as is" without any warranty of any kind, whether express | ||
9 | * or implied. | ||
10 | */ | ||
11 | |||
12 | #include <linux/config.h> | ||
13 | #include <linux/init.h> | ||
14 | #include <asm/ocp.h> | ||
15 | #include <platforms/4xx/ibmnp405h.h> | ||
16 | |||
17 | static struct ocp_func_emac_data ibmnp405h_emac0_def = { | ||
18 | .rgmii_idx = -1, /* No RGMII */ | ||
19 | .rgmii_mux = -1, /* No RGMII */ | ||
20 | .zmii_idx = 0, /* ZMII device index */ | ||
21 | .zmii_mux = 0, /* ZMII input of this EMAC */ | ||
22 | .mal_idx = 0, /* MAL device index */ | ||
23 | .mal_rx_chan = 0, /* MAL rx channel number */ | ||
24 | .mal_tx_chan = 0, /* MAL tx channel number */ | ||
25 | .wol_irq = 41, /* WOL interrupt number */ | ||
26 | .mdio_idx = -1, /* No shared MDIO */ | ||
27 | .tah_idx = -1, /* No TAH */ | ||
28 | }; | ||
29 | |||
30 | static struct ocp_func_emac_data ibmnp405h_emac1_def = { | ||
31 | .rgmii_idx = -1, /* No RGMII */ | ||
32 | .rgmii_mux = -1, /* No RGMII */ | ||
33 | .zmii_idx = 0, /* ZMII device index */ | ||
34 | .zmii_mux = 1, /* ZMII input of this EMAC */ | ||
35 | .mal_idx = 0, /* MAL device index */ | ||
36 | .mal_rx_chan = 1, /* MAL rx channel number */ | ||
37 | .mal_tx_chan = 1, /* MAL tx channel number */ | ||
38 | .wol_irq = 41, /* WOL interrupt number */ | ||
39 | .mdio_idx = -1, /* No shared MDIO */ | ||
40 | .tah_idx = -1, /* No TAH */ | ||
41 | }; | ||
42 | static struct ocp_func_emac_data ibmnp405h_emac2_def = { | ||
43 | .rgmii_idx = -1, /* No RGMII */ | ||
44 | .rgmii_mux = -1, /* No RGMII */ | ||
45 | .zmii_idx = 0, /* ZMII device index */ | ||
46 | .zmii_mux = 2, /* ZMII input of this EMAC */ | ||
47 | .mal_idx = 0, /* MAL device index */ | ||
48 | .mal_rx_chan = 2, /* MAL rx channel number */ | ||
49 | .mal_tx_chan = 2, /* MAL tx channel number */ | ||
50 | .wol_irq = 41, /* WOL interrupt number */ | ||
51 | .mdio_idx = -1, /* No shared MDIO */ | ||
52 | .tah_idx = -1, /* No TAH */ | ||
53 | }; | ||
54 | static struct ocp_func_emac_data ibmnp405h_emac3_def = { | ||
55 | .rgmii_idx = -1, /* No RGMII */ | ||
56 | .rgmii_mux = -1, /* No RGMII */ | ||
57 | .zmii_idx = 0, /* ZMII device index */ | ||
58 | .zmii_mux = 3, /* ZMII input of this EMAC */ | ||
59 | .mal_idx = 0, /* MAL device index */ | ||
60 | .mal_rx_chan = 3, /* MAL rx channel number */ | ||
61 | .mal_tx_chan = 3, /* MAL tx channel number */ | ||
62 | .wol_irq = 41, /* WOL interrupt number */ | ||
63 | .mdio_idx = -1, /* No shared MDIO */ | ||
64 | .tah_idx = -1, /* No TAH */ | ||
65 | }; | ||
66 | OCP_SYSFS_EMAC_DATA() | ||
67 | |||
68 | static struct ocp_func_mal_data ibmnp405h_mal0_def = { | ||
69 | .num_tx_chans = 8, /* Number of TX channels */ | ||
70 | .num_rx_chans = 4, /* Number of RX channels */ | ||
71 | .txeob_irq = 17, /* TX End Of Buffer IRQ */ | ||
72 | .rxeob_irq = 18, /* RX End Of Buffer IRQ */ | ||
73 | .txde_irq = 46, /* TX Descriptor Error IRQ */ | ||
74 | .rxde_irq = 47, /* RX Descriptor Error IRQ */ | ||
75 | .serr_irq = 45, /* MAL System Error IRQ */ | ||
76 | }; | ||
77 | OCP_SYSFS_MAL_DATA() | ||
78 | |||
79 | static struct ocp_func_iic_data ibmnp405h_iic0_def = { | ||
80 | .fast_mode = 0, /* Use standad mode (100Khz) */ | ||
81 | }; | ||
82 | OCP_SYSFS_IIC_DATA() | ||
83 | |||
84 | struct ocp_def core_ocp[] = { | ||
85 | { .vendor = OCP_VENDOR_IBM, | ||
86 | .function = OCP_FUNC_OPB, | ||
87 | .index = 0, | ||
88 | .paddr = 0xEF600000, | ||
89 | .irq = OCP_IRQ_NA, | ||
90 | .pm = OCP_CPM_NA, | ||
91 | }, | ||
92 | { .vendor = OCP_VENDOR_IBM, | ||
93 | .function = OCP_FUNC_16550, | ||
94 | .index = 0, | ||
95 | .paddr = UART0_IO_BASE, | ||
96 | .irq = UART0_INT, | ||
97 | .pm = IBM_CPM_UART0 | ||
98 | }, | ||
99 | { .vendor = OCP_VENDOR_IBM, | ||
100 | .function = OCP_FUNC_16550, | ||
101 | .index = 1, | ||
102 | .paddr = UART1_IO_BASE, | ||
103 | .irq = UART1_INT, | ||
104 | .pm = IBM_CPM_UART1 | ||
105 | }, | ||
106 | { .vendor = OCP_VENDOR_IBM, | ||
107 | .function = OCP_FUNC_IIC, | ||
108 | .paddr = 0xEF600500, | ||
109 | .irq = 2, | ||
110 | .pm = IBM_CPM_IIC0, | ||
111 | .additions = &ibmnp405h_iic0_def, | ||
112 | .show = &ocp_show_iic_data | ||
113 | }, | ||
114 | { .vendor = OCP_VENDOR_IBM, | ||
115 | .function = OCP_FUNC_GPIO, | ||
116 | .paddr = 0xEF600700, | ||
117 | .irq = OCP_IRQ_NA, | ||
118 | .pm = IBM_CPM_GPIO0 | ||
119 | }, | ||
120 | { .vendor = OCP_VENDOR_IBM, | ||
121 | .function = OCP_FUNC_MAL, | ||
122 | .paddr = OCP_PADDR_NA, | ||
123 | .irq = OCP_IRQ_NA, | ||
124 | .pm = OCP_CPM_NA, | ||
125 | .additions = &ibmnp405h_mal0_def, | ||
126 | .show = &ocp_show_mal_data, | ||
127 | }, | ||
128 | { .vendor = OCP_VENDOR_IBM, | ||
129 | .function = OCP_FUNC_EMAC, | ||
130 | .index = 0, | ||
131 | .paddr = EMAC0_BASE, | ||
132 | .irq = 37, | ||
133 | .pm = IBM_CPM_EMAC0, | ||
134 | .additions = &ibmnp405h_emac0_def, | ||
135 | .show = &ocp_show_emac_data, | ||
136 | }, | ||
137 | { .vendor = OCP_VENDOR_IBM, | ||
138 | .function = OCP_FUNC_EMAC, | ||
139 | .index = 1, | ||
140 | .paddr = 0xEF600900, | ||
141 | .irq = 38, | ||
142 | .pm = IBM_CPM_EMAC1, | ||
143 | .additions = &ibmnp405h_emac1_def, | ||
144 | .show = &ocp_show_emac_data, | ||
145 | }, | ||
146 | { .vendor = OCP_VENDOR_IBM, | ||
147 | .function = OCP_FUNC_EMAC, | ||
148 | .index = 2, | ||
149 | .paddr = 0xEF600a00, | ||
150 | .irq = 39, | ||
151 | .pm = IBM_CPM_EMAC2, | ||
152 | .additions = &ibmnp405h_emac2_def, | ||
153 | .show = &ocp_show_emac_data, | ||
154 | }, | ||
155 | { .vendor = OCP_VENDOR_IBM, | ||
156 | .function = OCP_FUNC_EMAC, | ||
157 | .index = 3, | ||
158 | .paddr = 0xEF600b00, | ||
159 | .irq = 40, | ||
160 | .pm = IBM_CPM_EMAC3, | ||
161 | .additions = &ibmnp405h_emac3_def, | ||
162 | .show = &ocp_show_emac_data, | ||
163 | }, | ||
164 | { .vendor = OCP_VENDOR_IBM, | ||
165 | .function = OCP_FUNC_ZMII, | ||
166 | .paddr = 0xEF600C10, | ||
167 | .irq = OCP_IRQ_NA, | ||
168 | .pm = OCP_CPM_NA, | ||
169 | }, | ||
170 | { .vendor = OCP_VENDOR_INVALID | ||
171 | } | ||
172 | }; | ||
diff --git a/arch/ppc/platforms/4xx/ibmnp405h.h b/arch/ppc/platforms/4xx/ibmnp405h.h new file mode 100644 index 000000000000..e2c2b06128c8 --- /dev/null +++ b/arch/ppc/platforms/4xx/ibmnp405h.h | |||
@@ -0,0 +1,157 @@ | |||
1 | /* | ||
2 | * arch/ppc/platforms/4xx/ibmnp405h.h | ||
3 | * | ||
4 | * Author: Armin Kuster <akuster@mvista.com> | ||
5 | * | ||
6 | * 2002 (c) MontaVista, Software, Inc. This file is licensed under | ||
7 | * the terms of the GNU General Public License version 2. This program | ||
8 | * is licensed "as is" without any warranty of any kind, whether express | ||
9 | * or implied. | ||
10 | */ | ||
11 | |||
12 | #ifdef __KERNEL__ | ||
13 | #ifndef __ASM_IBMNP405H_H__ | ||
14 | #define __ASM_IBMNP405H_H__ | ||
15 | |||
16 | #include <linux/config.h> | ||
17 | |||
18 | /* ibm405.h at bottom of this file */ | ||
19 | |||
20 | #define PPC405_PCI_CONFIG_ADDR 0xeec00000 | ||
21 | #define PPC405_PCI_CONFIG_DATA 0xeec00004 | ||
22 | #define PPC405_PCI_PHY_MEM_BASE 0x80000000 /* hose_a->pci_mem_offset */ | ||
23 | /* setbat */ | ||
24 | #define PPC405_PCI_MEM_BASE PPC405_PCI_PHY_MEM_BASE /* setbat */ | ||
25 | #define PPC405_PCI_PHY_IO_BASE 0xe8000000 /* setbat */ | ||
26 | #define PPC405_PCI_IO_BASE PPC405_PCI_PHY_IO_BASE /* setbat */ | ||
27 | |||
28 | #define PPC405_PCI_LOWER_MEM 0x00000000 /* hose_a->mem_space.start */ | ||
29 | #define PPC405_PCI_UPPER_MEM 0xBfffffff /* hose_a->mem_space.end */ | ||
30 | #define PPC405_PCI_LOWER_IO 0x00000000 /* hose_a->io_space.start */ | ||
31 | #define PPC405_PCI_UPPER_IO 0x0000ffff /* hose_a->io_space.end */ | ||
32 | |||
33 | #define PPC405_ISA_IO_BASE PPC405_PCI_IO_BASE | ||
34 | |||
35 | #define PPC4xx_PCI_IO_ADDR ((uint)PPC405_PCI_PHY_IO_BASE) | ||
36 | #define PPC4xx_PCI_IO_SIZE ((uint)64*1024) | ||
37 | #define PPC4xx_PCI_CFG_ADDR ((uint)PPC405_PCI_CONFIG_ADDR) | ||
38 | #define PPC4xx_PCI_CFG_SIZE ((uint)4*1024) | ||
39 | #define PPC4xx_PCI_LCFG_ADDR ((uint)0xef400000) | ||
40 | #define PPC4xx_PCI_LCFG_SIZE ((uint)4*1024) | ||
41 | #define PPC4xx_ONB_IO_ADDR ((uint)0xef600000) | ||
42 | #define PPC4xx_ONB_IO_SIZE ((uint)4*1024) | ||
43 | |||
44 | /* serial port defines */ | ||
45 | #define RS_TABLE_SIZE 4 | ||
46 | |||
47 | #define UART0_INT 0 | ||
48 | #define UART1_INT 1 | ||
49 | #define PCIL0_BASE 0xEF400000 | ||
50 | #define UART0_IO_BASE 0xEF600300 | ||
51 | #define UART1_IO_BASE 0xEF600400 | ||
52 | #define OPB0_BASE 0xEF600600 | ||
53 | #define EMAC0_BASE 0xEF600800 | ||
54 | |||
55 | #define BD_EMAC_ADDR(e,i) bi_enetaddr[e][i] | ||
56 | |||
57 | #define STD_UART_OP(num) \ | ||
58 | { 0, BASE_BAUD, 0, UART##num##_INT, \ | ||
59 | (ASYNC_BOOT_AUTOCONF | ASYNC_SKIP_TEST), \ | ||
60 | iomem_base:(u8 *) UART##num##_IO_BASE, \ | ||
61 | io_type: SERIAL_IO_MEM}, | ||
62 | |||
63 | #if defined(CONFIG_UART0_TTYS0) | ||
64 | #define SERIAL_DEBUG_IO_BASE UART0_IO_BASE | ||
65 | #define SERIAL_PORT_DFNS \ | ||
66 | STD_UART_OP(0) \ | ||
67 | STD_UART_OP(1) | ||
68 | #endif | ||
69 | |||
70 | #if defined(CONFIG_UART0_TTYS1) | ||
71 | #define SERIAL_DEBUG_IO_BASE UART0_IO_BASE | ||
72 | #define SERIAL_PORT_DFNS \ | ||
73 | STD_UART_OP(1) \ | ||
74 | STD_UART_OP(0) | ||
75 | #endif | ||
76 | |||
77 | /* DCR defines */ | ||
78 | /* ------------------------------------------------------------------------- */ | ||
79 | |||
80 | #define DCRN_CHCR_BASE 0x0F1 | ||
81 | #define DCRN_CHPSR_BASE 0x0B4 | ||
82 | #define DCRN_CPMSR_BASE 0x0BA | ||
83 | #define DCRN_CPMFR_BASE 0x0B9 | ||
84 | #define DCRN_CPMER_BASE 0x0B8 | ||
85 | |||
86 | /* CPM Clocking & Power Mangement defines */ | ||
87 | #define IBM_CPM_PCI 0x40000000 /* PCI */ | ||
88 | #define IBM_CPM_EMAC2 0x20000000 /* EMAC 2 MII */ | ||
89 | #define IBM_CPM_EMAC3 0x04000000 /* EMAC 3 MII */ | ||
90 | #define IBM_CPM_EMAC0 0x00800000 /* EMAC 0 MII */ | ||
91 | #define IBM_CPM_EMAC1 0x00100000 /* EMAC 1 MII */ | ||
92 | #define IBM_CPM_EMMII 0 /* Shift value for MII */ | ||
93 | #define IBM_CPM_EMRX 1 /* Shift value for recv */ | ||
94 | #define IBM_CPM_EMTX 2 /* Shift value for MAC */ | ||
95 | #define IBM_CPM_UIC1 0x00020000 /* Universal Interrupt Controller */ | ||
96 | #define IBM_CPM_UIC0 0x00010000 /* Universal Interrupt Controller */ | ||
97 | #define IBM_CPM_CPU 0x00008000 /* processor core */ | ||
98 | #define IBM_CPM_EBC 0x00004000 /* ROM/SRAM peripheral controller */ | ||
99 | #define IBM_CPM_SDRAM0 0x00002000 /* SDRAM memory controller */ | ||
100 | #define IBM_CPM_GPIO0 0x00001000 /* General Purpose IO (??) */ | ||
101 | #define IBM_CPM_HDLC 0x00000800 /* HDCL */ | ||
102 | #define IBM_CPM_TMRCLK 0x00000400 /* CPU timers */ | ||
103 | #define IBM_CPM_PLB 0x00000100 /* PLB bus arbiter */ | ||
104 | #define IBM_CPM_OPB 0x00000080 /* PLB to OPB bridge */ | ||
105 | #define IBM_CPM_DMA 0x00000040 /* DMA controller */ | ||
106 | #define IBM_CPM_IIC0 0x00000010 /* IIC interface */ | ||
107 | #define IBM_CPM_UART0 0x00000002 /* serial port 0 */ | ||
108 | #define IBM_CPM_UART1 0x00000001 /* serial port 1 */ | ||
109 | /* this is the default setting for devices put to sleep when booting */ | ||
110 | |||
111 | #define DFLT_IBM4xx_PM ~(IBM_CPM_UIC0 | IBM_CPM_UIC1 | IBM_CPM_CPU \ | ||
112 | | IBM_CPM_EBC | IBM_CPM_SDRAM0 | IBM_CPM_PLB \ | ||
113 | | IBM_CPM_OPB | IBM_CPM_TMRCLK | IBM_CPM_DMA \ | ||
114 | | IBM_CPM_EMAC0 | IBM_CPM_EMAC1 | IBM_CPM_EMAC2 \ | ||
115 | | IBM_CPM_EMAC3 | IBM_CPM_PCI) | ||
116 | |||
117 | #define DCRN_DMA0_BASE 0x100 | ||
118 | #define DCRN_DMA1_BASE 0x108 | ||
119 | #define DCRN_DMA2_BASE 0x110 | ||
120 | #define DCRN_DMA3_BASE 0x118 | ||
121 | #define DCRNCAP_DMA_SG 1 /* have DMA scatter/gather capability */ | ||
122 | #define DCRN_DMASR_BASE 0x120 | ||
123 | #define DCRN_EBC_BASE 0x012 | ||
124 | #define DCRN_DCP0_BASE 0x014 | ||
125 | #define DCRN_MAL_BASE 0x180 | ||
126 | #define DCRN_OCM0_BASE 0x018 | ||
127 | #define DCRN_PLB0_BASE 0x084 | ||
128 | #define DCRN_PLLMR_BASE 0x0B0 | ||
129 | #define DCRN_POB0_BASE 0x0A0 | ||
130 | #define DCRN_SDRAM0_BASE 0x010 | ||
131 | #define DCRN_UIC0_BASE 0x0C0 | ||
132 | #define DCRN_UIC1_BASE 0x0D0 | ||
133 | #define DCRN_CPC0_EPRCSR 0x0F3 | ||
134 | |||
135 | #define UIC0_UIC1NC 0x00000002 | ||
136 | |||
137 | #define CHR1_CETE 0x00000004 /* CPU external timer enable */ | ||
138 | #define UIC0 DCRN_UIC0_BASE | ||
139 | #define UIC1 DCRN_UIC1_BASE | ||
140 | |||
141 | #undef NR_UICS | ||
142 | #define NR_UICS 2 | ||
143 | |||
144 | /* EMAC DCRN's FIXME: armin */ | ||
145 | #define DCRN_MALRXCTP2R(base) ((base) + 0x42) /* Channel Rx 2 Channel Table Pointer */ | ||
146 | #define DCRN_MALRXCTP3R(base) ((base) + 0x43) /* Channel Rx 3 Channel Table Pointer */ | ||
147 | #define DCRN_MALTXCTP4R(base) ((base) + 0x24) /* Channel Tx 4 Channel Table Pointer */ | ||
148 | #define DCRN_MALTXCTP5R(base) ((base) + 0x25) /* Channel Tx 5 Channel Table Pointer */ | ||
149 | #define DCRN_MALTXCTP6R(base) ((base) + 0x26) /* Channel Tx 6 Channel Table Pointer */ | ||
150 | #define DCRN_MALTXCTP7R(base) ((base) + 0x27) /* Channel Tx 7 Channel Table Pointer */ | ||
151 | #define DCRN_MALRCBS2(base) ((base) + 0x62) /* Channel Rx 2 Channel Buffer Size */ | ||
152 | #define DCRN_MALRCBS3(base) ((base) + 0x63) /* Channel Rx 3 Channel Buffer Size */ | ||
153 | |||
154 | #include <asm/ibm405.h> | ||
155 | |||
156 | #endif /* __ASM_IBMNP405H_H__ */ | ||
157 | #endif /* __KERNEL__ */ | ||
diff --git a/arch/ppc/platforms/4xx/ibmstb4.c b/arch/ppc/platforms/4xx/ibmstb4.c new file mode 100644 index 000000000000..874d16bab73c --- /dev/null +++ b/arch/ppc/platforms/4xx/ibmstb4.c | |||
@@ -0,0 +1,83 @@ | |||
1 | /* | ||
2 | * arch/ppc/platforms/4xx/ibmstb4.c | ||
3 | * | ||
4 | * Author: Armin Kuster <akuster@mvista.com> | ||
5 | * | ||
6 | * 2000-2001 (c) MontaVista, Software, Inc. This file is licensed under | ||
7 | * the terms of the GNU General Public License version 2. This program | ||
8 | * is licensed "as is" without any warranty of any kind, whether express | ||
9 | * or implied. | ||
10 | */ | ||
11 | |||
12 | #include <linux/init.h> | ||
13 | #include <asm/ocp.h> | ||
14 | #include <platforms/4xx/ibmstb4.h> | ||
15 | |||
16 | static struct ocp_func_iic_data ibmstb4_iic0_def = { | ||
17 | .fast_mode = 0, /* Use standad mode (100Khz) */ | ||
18 | }; | ||
19 | |||
20 | static struct ocp_func_iic_data ibmstb4_iic1_def = { | ||
21 | .fast_mode = 0, /* Use standad mode (100Khz) */ | ||
22 | }; | ||
23 | OCP_SYSFS_IIC_DATA() | ||
24 | |||
25 | struct ocp_def core_ocp[] __initdata = { | ||
26 | { .vendor = OCP_VENDOR_IBM, | ||
27 | .function = OCP_FUNC_16550, | ||
28 | .index = 0, | ||
29 | .paddr = UART0_IO_BASE, | ||
30 | .irq = UART0_INT, | ||
31 | .pm = IBM_CPM_UART0, | ||
32 | }, | ||
33 | { .vendor = OCP_VENDOR_IBM, | ||
34 | .function = OCP_FUNC_16550, | ||
35 | .index = 1, | ||
36 | .paddr = UART1_IO_BASE, | ||
37 | .irq = UART1_INT, | ||
38 | .pm = IBM_CPM_UART1, | ||
39 | }, | ||
40 | { .vendor = OCP_VENDOR_IBM, | ||
41 | .function = OCP_FUNC_16550, | ||
42 | .index = 2, | ||
43 | .paddr = UART2_IO_BASE, | ||
44 | .irq = UART2_INT, | ||
45 | .pm = IBM_CPM_UART2, | ||
46 | }, | ||
47 | { .vendor = OCP_VENDOR_IBM, | ||
48 | .function = OCP_FUNC_IIC, | ||
49 | .paddr = IIC0_BASE, | ||
50 | .irq = IIC0_IRQ, | ||
51 | .pm = IBM_CPM_IIC0, | ||
52 | .additions = &ibmstb4_iic0_def, | ||
53 | .show = &ocp_show_iic_data | ||
54 | }, | ||
55 | { .vendor = OCP_VENDOR_IBM, | ||
56 | .function = OCP_FUNC_IIC, | ||
57 | .paddr = IIC1_BASE, | ||
58 | .irq = IIC1_IRQ, | ||
59 | .pm = IBM_CPM_IIC1, | ||
60 | .additions = &ibmstb4_iic1_def, | ||
61 | .show = &ocp_show_iic_data | ||
62 | }, | ||
63 | { .vendor = OCP_VENDOR_IBM, | ||
64 | .function = OCP_FUNC_GPIO, | ||
65 | .paddr = GPIO0_BASE, | ||
66 | .irq = OCP_IRQ_NA, | ||
67 | .pm = IBM_CPM_GPIO0, | ||
68 | }, | ||
69 | { .vendor = OCP_VENDOR_IBM, | ||
70 | .function = OCP_FUNC_IDE, | ||
71 | .paddr = IDE0_BASE, | ||
72 | .irq = IDE0_IRQ, | ||
73 | .pm = OCP_CPM_NA, | ||
74 | }, | ||
75 | { .vendor = OCP_VENDOR_IBM, | ||
76 | .function = OCP_FUNC_USB, | ||
77 | .paddr = USB0_BASE, | ||
78 | .irq = USB0_IRQ, | ||
79 | .pm = OCP_CPM_NA, | ||
80 | }, | ||
81 | { .vendor = OCP_VENDOR_INVALID, | ||
82 | } | ||
83 | }; | ||
diff --git a/arch/ppc/platforms/4xx/ibmstb4.h b/arch/ppc/platforms/4xx/ibmstb4.h new file mode 100644 index 000000000000..bcb4b1ee71f2 --- /dev/null +++ b/arch/ppc/platforms/4xx/ibmstb4.h | |||
@@ -0,0 +1,238 @@ | |||
1 | /* | ||
2 | * arch/ppc/platforms/4xx/ibmstb4.h | ||
3 | * | ||
4 | * Author: Armin Kuster <akuster@mvista.com> | ||
5 | * | ||
6 | * 2001 (c) MontaVista, Software, Inc. This file is licensed under | ||
7 | * the terms of the GNU General Public License version 2. This program | ||
8 | * is licensed "as is" without any warranty of any kind, whether express | ||
9 | * or implied. | ||
10 | */ | ||
11 | |||
12 | #ifdef __KERNEL__ | ||
13 | #ifndef __ASM_IBMSTB4_H__ | ||
14 | #define __ASM_IBMSTB4_H__ | ||
15 | |||
16 | #include <linux/config.h> | ||
17 | |||
18 | /* serial port defines */ | ||
19 | #define STB04xxx_IO_BASE ((uint)0xe0000000) | ||
20 | #define PPC4xx_PCI_IO_ADDR STB04xxx_IO_BASE | ||
21 | #define PPC4xx_ONB_IO_PADDR STB04xxx_IO_BASE | ||
22 | #define PPC4xx_ONB_IO_VADDR ((uint)0xe0000000) | ||
23 | #define PPC4xx_ONB_IO_SIZE ((uint)14*64*1024) | ||
24 | |||
25 | /* | ||
26 | * map STB04xxx internal i/o address (0x400x00xx) to an address | ||
27 | * which is below the 2GB limit... | ||
28 | * | ||
29 | * 4000 000x uart1 -> 0xe000 000x | ||
30 | * 4001 00xx ppu | ||
31 | * 4002 00xx smart card | ||
32 | * 4003 000x iic | ||
33 | * 4004 000x uart0 | ||
34 | * 4005 0xxx timer | ||
35 | * 4006 00xx gpio | ||
36 | * 4007 00xx smart card | ||
37 | * 400b 000x iic | ||
38 | * 400c 000x scp | ||
39 | * 400d 000x modem | ||
40 | * 400e 000x uart2 | ||
41 | */ | ||
42 | #define STB04xxx_MAP_IO_ADDR(a) (((uint)(a)) + (STB04xxx_IO_BASE - 0x40000000)) | ||
43 | |||
44 | #define RS_TABLE_SIZE 3 | ||
45 | #define UART0_INT 20 | ||
46 | |||
47 | #ifdef __BOOTER__ | ||
48 | #define UART0_IO_BASE 0x40040000 | ||
49 | #else | ||
50 | #define UART0_IO_BASE 0xe0040000 | ||
51 | #endif | ||
52 | |||
53 | #define UART1_INT 21 | ||
54 | |||
55 | #ifdef __BOOTER__ | ||
56 | #define UART1_IO_BASE 0x40000000 | ||
57 | #else | ||
58 | #define UART1_IO_BASE 0xe0000000 | ||
59 | #endif | ||
60 | |||
61 | #define UART2_INT 31 | ||
62 | #ifdef __BOOTER__ | ||
63 | #define UART2_IO_BASE 0x400e0000 | ||
64 | #else | ||
65 | #define UART2_IO_BASE 0xe00e0000 | ||
66 | #endif | ||
67 | |||
68 | #define IDE0_BASE 0x400F0000 | ||
69 | #define IDE0_SIZE 0x200 | ||
70 | #define IDE0_IRQ 25 | ||
71 | #define IIC0_BASE 0x40030000 | ||
72 | #define IIC1_BASE 0x400b0000 | ||
73 | #define OPB0_BASE 0x40000000 | ||
74 | #define GPIO0_BASE 0x40060000 | ||
75 | |||
76 | #define USB0_IRQ 18 | ||
77 | #define USB0_BASE STB04xxx_MAP_IO_ADDR(0x40010000) | ||
78 | #define USB0_EXTENT 4096 | ||
79 | |||
80 | #define IIC_NUMS 2 | ||
81 | #define UART_NUMS 3 | ||
82 | #define IIC0_IRQ 9 | ||
83 | #define IIC1_IRQ 10 | ||
84 | #define IIC_OWN 0x55 | ||
85 | #define IIC_CLOCK 50 | ||
86 | |||
87 | #define BD_EMAC_ADDR(e,i) bi_enetaddr[i] | ||
88 | |||
89 | #define STD_UART_OP(num) \ | ||
90 | { 0, BASE_BAUD, 0, UART##num##_INT, \ | ||
91 | (ASYNC_BOOT_AUTOCONF | ASYNC_SKIP_TEST), \ | ||
92 | iomem_base: (u8 *)UART##num##_IO_BASE, \ | ||
93 | io_type: SERIAL_IO_MEM}, | ||
94 | |||
95 | #if defined(CONFIG_UART0_TTYS0) | ||
96 | #define SERIAL_DEBUG_IO_BASE UART0_IO_BASE | ||
97 | #define SERIAL_PORT_DFNS \ | ||
98 | STD_UART_OP(0) \ | ||
99 | STD_UART_OP(1) \ | ||
100 | STD_UART_OP(2) | ||
101 | #endif | ||
102 | |||
103 | #if defined(CONFIG_UART0_TTYS1) | ||
104 | #define SERIAL_DEBUG_IO_BASE UART2_IO_BASE | ||
105 | #define SERIAL_PORT_DFNS \ | ||
106 | STD_UART_OP(1) \ | ||
107 | STD_UART_OP(0) \ | ||
108 | STD_UART_OP(2) | ||
109 | #endif | ||
110 | |||
111 | #if defined(CONFIG_UART0_TTYS2) | ||
112 | #define SERIAL_DEBUG_IO_BASE UART2_IO_BASE | ||
113 | #define SERIAL_PORT_DFNS \ | ||
114 | STD_UART_OP(2) \ | ||
115 | STD_UART_OP(0) \ | ||
116 | STD_UART_OP(1) | ||
117 | #endif | ||
118 | |||
119 | #define DCRN_BE_BASE 0x090 | ||
120 | #define DCRN_DMA0_BASE 0x0C0 | ||
121 | #define DCRN_DMA1_BASE 0x0C8 | ||
122 | #define DCRN_DMA2_BASE 0x0D0 | ||
123 | #define DCRN_DMA3_BASE 0x0D8 | ||
124 | #define DCRNCAP_DMA_CC 1 /* have DMA chained count capability */ | ||
125 | #define DCRN_DMASR_BASE 0x0E0 | ||
126 | #define DCRN_PLB0_BASE 0x054 | ||
127 | #define DCRN_PLB1_BASE 0x064 | ||
128 | #define DCRN_POB0_BASE 0x0B0 | ||
129 | #define DCRN_SCCR_BASE 0x120 | ||
130 | #define DCRN_UIC0_BASE 0x040 | ||
131 | #define DCRN_BE_BASE 0x090 | ||
132 | #define DCRN_DMA0_BASE 0x0C0 | ||
133 | #define DCRN_DMA1_BASE 0x0C8 | ||
134 | #define DCRN_DMA2_BASE 0x0D0 | ||
135 | #define DCRN_DMA3_BASE 0x0D8 | ||
136 | #define DCRN_CIC_BASE 0x030 | ||
137 | #define DCRN_DMASR_BASE 0x0E0 | ||
138 | #define DCRN_EBIMC_BASE 0x070 | ||
139 | #define DCRN_DCRX_BASE 0x020 | ||
140 | #define DCRN_CPMFR_BASE 0x102 | ||
141 | #define DCRN_SCCR_BASE 0x120 | ||
142 | #define UIC0 DCRN_UIC0_BASE | ||
143 | |||
144 | #define IBM_CPM_IIC0 0x80000000 /* IIC 0 interface */ | ||
145 | #define IBM_CPM_USB0 0x40000000 /* IEEE-1284 */ | ||
146 | #define IBM_CPM_IIC1 0x20000000 /* IIC 1 interface */ | ||
147 | #define IBM_CPM_CPU 0x10000000 /* PPC405B3 clock control */ | ||
148 | #define IBM_CPM_AUD 0x08000000 /* Audio Decoder */ | ||
149 | #define IBM_CPM_EBIU 0x04000000 /* External Bus Interface Unit */ | ||
150 | #define IBM_CPM_SDRAM1 0x02000000 /* SDRAM 1 memory controller */ | ||
151 | #define IBM_CPM_DMA 0x01000000 /* DMA controller */ | ||
152 | #define IBM_CPM_DMA1 0x00800000 /* reserved */ | ||
153 | #define IBM_CPM_XPT1 0x00400000 /* reserved */ | ||
154 | #define IBM_CPM_XPT2 0x00200000 /* reserved */ | ||
155 | #define IBM_CPM_UART1 0x00100000 /* Serial 1 / Infrared */ | ||
156 | #define IBM_CPM_UART0 0x00080000 /* Serial 0 / 16550 */ | ||
157 | #define IBM_CPM_EPI 0x00040000 /* DCR Extension */ | ||
158 | #define IBM_CPM_SC0 0x00020000 /* Smart Card 0 */ | ||
159 | #define IBM_CPM_VID 0x00010000 /* reserved */ | ||
160 | #define IBM_CPM_SC1 0x00008000 /* Smart Card 1 */ | ||
161 | #define IBM_CPM_USBSDRA 0x00004000 /* SDRAM 0 memory controller */ | ||
162 | #define IBM_CPM_XPT0 0x00002000 /* Transport - 54 Mhz */ | ||
163 | #define IBM_CPM_CBS 0x00001000 /* Cross Bar Switch */ | ||
164 | #define IBM_CPM_GPT 0x00000800 /* GPTPWM */ | ||
165 | #define IBM_CPM_GPIO0 0x00000400 /* General Purpose IO 0 */ | ||
166 | #define IBM_CPM_DENC 0x00000200 /* Digital video Encoder */ | ||
167 | #define IBM_CPM_TMRCLK 0x00000100 /* CPU timers */ | ||
168 | #define IBM_CPM_XPT27 0x00000080 /* Transport - 27 Mhz */ | ||
169 | #define IBM_CPM_UIC 0x00000040 /* Universal Interrupt Controller */ | ||
170 | #define IBM_CPM_SSP 0x00000010 /* Modem Serial Interface (SSP) */ | ||
171 | #define IBM_CPM_UART2 0x00000008 /* Serial Control Port */ | ||
172 | #define IBM_CPM_DDIO 0x00000004 /* Descrambler */ | ||
173 | #define IBM_CPM_VID2 0x00000002 /* Video Decoder clock domain 2 */ | ||
174 | |||
175 | #define DFLT_IBM4xx_PM ~(IBM_CPM_CPU | IBM_CPM_EBIU | IBM_CPM_SDRAM1 \ | ||
176 | | IBM_CPM_DMA | IBM_CPM_DMA1 | IBM_CPM_CBS \ | ||
177 | | IBM_CPM_USBSDRA | IBM_CPM_XPT0 | IBM_CPM_TMRCLK \ | ||
178 | | IBM_CPM_XPT27 | IBM_CPM_UIC ) | ||
179 | |||
180 | #define DCRN_BEAR (DCRN_BE_BASE + 0x0) /* Bus Error Address Register */ | ||
181 | #define DCRN_BESR (DCRN_BE_BASE + 0x1) /* Bus Error Syndrome Register */ | ||
182 | /* DCRN_BESR */ | ||
183 | #define BESR_DSES 0x80000000 /* Data-Side Error Status */ | ||
184 | #define BESR_DMES 0x40000000 /* DMA Error Status */ | ||
185 | #define BESR_RWS 0x20000000 /* Read/Write Status */ | ||
186 | #define BESR_ETMASK 0x1C000000 /* Error Type */ | ||
187 | #define ET_PROT 0 | ||
188 | #define ET_PARITY 1 | ||
189 | #define ET_NCFG 2 | ||
190 | #define ET_BUSERR 4 | ||
191 | #define ET_BUSTO 6 | ||
192 | |||
193 | #define CHR1_CETE 0x00800000 /* CPU external timer enable */ | ||
194 | #define CHR1_PCIPW 0x00008000 /* PCI Int enable/Peripheral Write enable */ | ||
195 | |||
196 | #define DCRN_CICCR (DCRN_CIC_BASE + 0x0) /* CIC Control Register */ | ||
197 | #define DCRN_DMAS1 (DCRN_CIC_BASE + 0x1) /* DMA Select1 Register */ | ||
198 | #define DCRN_DMAS2 (DCRN_CIC_BASE + 0x2) /* DMA Select2 Register */ | ||
199 | #define DCRN_CICVCR (DCRN_CIC_BASE + 0x3) /* CIC Video COntro Register */ | ||
200 | #define DCRN_CICSEL3 (DCRN_CIC_BASE + 0x5) /* CIC Select 3 Register */ | ||
201 | #define DCRN_SGPO (DCRN_CIC_BASE + 0x6) /* CIC GPIO Output Register */ | ||
202 | #define DCRN_SGPOD (DCRN_CIC_BASE + 0x7) /* CIC GPIO OD Register */ | ||
203 | #define DCRN_SGPTC (DCRN_CIC_BASE + 0x8) /* CIC GPIO Tristate Ctrl Reg */ | ||
204 | #define DCRN_SGPI (DCRN_CIC_BASE + 0x9) /* CIC GPIO Input Reg */ | ||
205 | |||
206 | #define DCRN_DCRXICR (DCRN_DCRX_BASE + 0x0) /* Internal Control Register */ | ||
207 | #define DCRN_DCRXISR (DCRN_DCRX_BASE + 0x1) /* Internal Status Register */ | ||
208 | #define DCRN_DCRXECR (DCRN_DCRX_BASE + 0x2) /* External Control Register */ | ||
209 | #define DCRN_DCRXESR (DCRN_DCRX_BASE + 0x3) /* External Status Register */ | ||
210 | #define DCRN_DCRXTAR (DCRN_DCRX_BASE + 0x4) /* Target Address Register */ | ||
211 | #define DCRN_DCRXTDR (DCRN_DCRX_BASE + 0x5) /* Target Data Register */ | ||
212 | #define DCRN_DCRXIGR (DCRN_DCRX_BASE + 0x6) /* Interrupt Generation Register */ | ||
213 | #define DCRN_DCRXBCR (DCRN_DCRX_BASE + 0x7) /* Line Buffer Control Register */ | ||
214 | |||
215 | #define DCRN_BRCRH0 (DCRN_EBIMC_BASE + 0x0) /* Bus Region Config High 0 */ | ||
216 | #define DCRN_BRCRH1 (DCRN_EBIMC_BASE + 0x1) /* Bus Region Config High 1 */ | ||
217 | #define DCRN_BRCRH2 (DCRN_EBIMC_BASE + 0x2) /* Bus Region Config High 2 */ | ||
218 | #define DCRN_BRCRH3 (DCRN_EBIMC_BASE + 0x3) /* Bus Region Config High 3 */ | ||
219 | #define DCRN_BRCRH4 (DCRN_EBIMC_BASE + 0x4) /* Bus Region Config High 4 */ | ||
220 | #define DCRN_BRCRH5 (DCRN_EBIMC_BASE + 0x5) /* Bus Region Config High 5 */ | ||
221 | #define DCRN_BRCRH6 (DCRN_EBIMC_BASE + 0x6) /* Bus Region Config High 6 */ | ||
222 | #define DCRN_BRCRH7 (DCRN_EBIMC_BASE + 0x7) /* Bus Region Config High 7 */ | ||
223 | #define DCRN_BRCR0 (DCRN_EBIMC_BASE + 0x10) /* BRC 0 */ | ||
224 | #define DCRN_BRCR1 (DCRN_EBIMC_BASE + 0x11) /* BRC 1 */ | ||
225 | #define DCRN_BRCR2 (DCRN_EBIMC_BASE + 0x12) /* BRC 2 */ | ||
226 | #define DCRN_BRCR3 (DCRN_EBIMC_BASE + 0x13) /* BRC 3 */ | ||
227 | #define DCRN_BRCR4 (DCRN_EBIMC_BASE + 0x14) /* BRC 4 */ | ||
228 | #define DCRN_BRCR5 (DCRN_EBIMC_BASE + 0x15) /* BRC 5 */ | ||
229 | #define DCRN_BRCR6 (DCRN_EBIMC_BASE + 0x16) /* BRC 6 */ | ||
230 | #define DCRN_BRCR7 (DCRN_EBIMC_BASE + 0x17) /* BRC 7 */ | ||
231 | #define DCRN_BEAR0 (DCRN_EBIMC_BASE + 0x20) /* Bus Error Address Register */ | ||
232 | #define DCRN_BESR0 (DCRN_EBIMC_BASE + 0x21) /* Bus Error Status Register */ | ||
233 | #define DCRN_BIUCR (DCRN_EBIMC_BASE + 0x2A) /* Bus Interfac Unit Ctrl Reg */ | ||
234 | |||
235 | #include <asm/ibm405.h> | ||
236 | |||
237 | #endif /* __ASM_IBMSTB4_H__ */ | ||
238 | #endif /* __KERNEL__ */ | ||
diff --git a/arch/ppc/platforms/4xx/ibmstbx25.c b/arch/ppc/platforms/4xx/ibmstbx25.c new file mode 100644 index 000000000000..b895b9cca57d --- /dev/null +++ b/arch/ppc/platforms/4xx/ibmstbx25.c | |||
@@ -0,0 +1,68 @@ | |||
1 | /* | ||
2 | * arch/ppc/platforms/4xx/ibmstbx25.c | ||
3 | * | ||
4 | * Author: Armin Kuster <akuster@mvista.com> | ||
5 | * | ||
6 | * 2000-2002 (c) MontaVista, Software, Inc. This file is licensed under | ||
7 | * the terms of the GNU General Public License version 2. This program | ||
8 | * is licensed "as is" without any warranty of any kind, whether express | ||
9 | * or implied. | ||
10 | */ | ||
11 | |||
12 | #include <linux/init.h> | ||
13 | #include <asm/ocp.h> | ||
14 | #include <platforms/4xx/ibmstbx25.h> | ||
15 | #include <asm/ppc4xx_pic.h> | ||
16 | |||
17 | static struct ocp_func_iic_data ibmstbx25_iic0_def = { | ||
18 | .fast_mode = 0, /* Use standad mode (100Khz) */ | ||
19 | }; | ||
20 | OCP_SYSFS_IIC_DATA() | ||
21 | |||
22 | struct ocp_def core_ocp[] __initdata = { | ||
23 | { .vendor = OCP_VENDOR_IBM, | ||
24 | .function = OCP_FUNC_16550, | ||
25 | .index = 0, | ||
26 | .paddr = UART0_IO_BASE, | ||
27 | .irq = UART0_INT, | ||
28 | .pm = IBM_CPM_UART0, | ||
29 | }, | ||
30 | { .vendor = OCP_VENDOR_IBM, | ||
31 | .function = OCP_FUNC_16550, | ||
32 | .index = 1, | ||
33 | .paddr = UART1_IO_BASE, | ||
34 | .irq = UART1_INT, | ||
35 | .pm = IBM_CPM_UART1, | ||
36 | }, | ||
37 | { .vendor = OCP_VENDOR_IBM, | ||
38 | .function = OCP_FUNC_16550, | ||
39 | .index = 2, | ||
40 | .paddr = UART2_IO_BASE, | ||
41 | .irq = UART2_INT, | ||
42 | .pm = IBM_CPM_UART2, | ||
43 | }, | ||
44 | { .vendor = OCP_VENDOR_IBM, | ||
45 | .function = OCP_FUNC_IIC, | ||
46 | .paddr = IIC0_BASE, | ||
47 | .irq = IIC0_IRQ, | ||
48 | .pm = IBM_CPM_IIC0, | ||
49 | .additions = &ibmstbx25_iic0_def, | ||
50 | .show = &ocp_show_iic_data | ||
51 | }, | ||
52 | { .vendor = OCP_VENDOR_IBM, | ||
53 | .function = OCP_FUNC_GPIO, | ||
54 | .paddr = GPIO0_BASE, | ||
55 | .irq = OCP_IRQ_NA, | ||
56 | .pm = IBM_CPM_GPIO0, | ||
57 | }, | ||
58 | { .vendor = OCP_VENDOR_INVALID | ||
59 | } | ||
60 | }; | ||
61 | |||
62 | /* Polarity and triggering settings for internal interrupt sources */ | ||
63 | struct ppc4xx_uic_settings ppc4xx_core_uic_cfg[] __initdata = { | ||
64 | { .polarity = 0xffff8f80, | ||
65 | .triggering = 0x00000000, | ||
66 | .ext_irq_mask = 0x0000707f, /* IRQ7 - IRQ9, IRQ0 - IRQ6 */ | ||
67 | } | ||
68 | }; | ||
diff --git a/arch/ppc/platforms/4xx/ibmstbx25.h b/arch/ppc/platforms/4xx/ibmstbx25.h new file mode 100644 index 000000000000..9a2efc366e9c --- /dev/null +++ b/arch/ppc/platforms/4xx/ibmstbx25.h | |||
@@ -0,0 +1,261 @@ | |||
1 | /* | ||
2 | * arch/ppc/platforms/4xx/ibmstbx25.h | ||
3 | * | ||
4 | * Author: Armin Kuster <akuster@mvista.com> | ||
5 | * | ||
6 | * 2002 (c) MontaVista, Software, Inc. This file is licensed under | ||
7 | * the terms of the GNU General Public License version 2. This program | ||
8 | * is licensed "as is" without any warranty of any kind, whether express | ||
9 | * or implied. | ||
10 | */ | ||
11 | |||
12 | #ifdef __KERNEL__ | ||
13 | #ifndef __ASM_IBMSTBX25_H__ | ||
14 | #define __ASM_IBMSTBX25_H__ | ||
15 | |||
16 | #include <linux/config.h> | ||
17 | |||
18 | /* serial port defines */ | ||
19 | #define STBx25xx_IO_BASE ((uint)0xe0000000) | ||
20 | #define PPC4xx_ONB_IO_PADDR STBx25xx_IO_BASE | ||
21 | #define PPC4xx_ONB_IO_VADDR ((uint)0xe0000000) | ||
22 | #define PPC4xx_ONB_IO_SIZE ((uint)14*64*1024) | ||
23 | |||
24 | /* | ||
25 | * map STBxxxx internal i/o address (0x400x00xx) to an address | ||
26 | * which is below the 2GB limit... | ||
27 | * | ||
28 | * 4000 000x uart1 -> 0xe000 000x | ||
29 | * 4001 00xx uart2 | ||
30 | * 4002 00xx smart card | ||
31 | * 4003 000x iic | ||
32 | * 4004 000x uart0 | ||
33 | * 4005 0xxx timer | ||
34 | * 4006 00xx gpio | ||
35 | * 4007 00xx smart card | ||
36 | * 400b 000x iic | ||
37 | * 400c 000x scp | ||
38 | * 400d 000x modem | ||
39 | * 400e 000x uart2 | ||
40 | */ | ||
41 | #define STBx25xx_MAP_IO_ADDR(a) (((uint)(a)) + (STBx25xx_IO_BASE - 0x40000000)) | ||
42 | |||
43 | #define RS_TABLE_SIZE 3 | ||
44 | |||
45 | #define OPB_BASE_START 0x40000000 | ||
46 | #define EBIU_BASE_START 0xF0100000 | ||
47 | #define DCR_BASE_START 0x0000 | ||
48 | |||
49 | #ifdef __BOOTER__ | ||
50 | #define UART1_IO_BASE 0x40000000 | ||
51 | #define UART2_IO_BASE 0x40010000 | ||
52 | #else | ||
53 | #define UART1_IO_BASE 0xe0000000 | ||
54 | #define UART2_IO_BASE 0xe0010000 | ||
55 | #endif | ||
56 | #define SC0_BASE 0x40020000 /* smart card #0 */ | ||
57 | #define IIC0_BASE 0x40030000 | ||
58 | #ifdef __BOOTER__ | ||
59 | #define UART0_IO_BASE 0x40040000 | ||
60 | #else | ||
61 | #define UART0_IO_BASE 0xe0040000 | ||
62 | #endif | ||
63 | #define SCC0_BASE 0x40040000 /* Serial 0 controller IrdA */ | ||
64 | #define GPT0_BASE 0x40050000 /* General purpose timers */ | ||
65 | #define GPIO0_BASE 0x40060000 | ||
66 | #define SC1_BASE 0x40070000 /* smart card #1 */ | ||
67 | #define SCP0_BASE 0x400C0000 /* Serial Controller Port */ | ||
68 | #define SSP0_BASE 0x400D0000 /* Sync serial port */ | ||
69 | |||
70 | #define IDE0_BASE 0xf0100000 | ||
71 | #define REDWOOD_IDE_CTRL 0xf1100000 | ||
72 | |||
73 | #define RTCFPC_IRQ 0 | ||
74 | #define XPORT_IRQ 1 | ||
75 | #define AUD_IRQ 2 | ||
76 | #define AID_IRQ 3 | ||
77 | #define DMA0 4 | ||
78 | #define DMA1_IRQ 5 | ||
79 | #define DMA2_IRQ 6 | ||
80 | #define DMA3_IRQ 7 | ||
81 | #define SC0_IRQ 8 | ||
82 | #define IIC0_IRQ 9 | ||
83 | #define IIR0_IRQ 10 | ||
84 | #define GPT0_IRQ 11 | ||
85 | #define GPT1_IRQ 12 | ||
86 | #define SCP0_IRQ 13 | ||
87 | #define SSP0_IRQ 14 | ||
88 | #define GPT2_IRQ 15 /* count down timer */ | ||
89 | #define SC1_IRQ 16 | ||
90 | /* IRQ 17 - 19 external */ | ||
91 | #define UART0_INT 20 | ||
92 | #define UART1_INT 21 | ||
93 | #define UART2_INT 22 | ||
94 | #define XPTDMA_IRQ 23 | ||
95 | #define DCRIDE_IRQ 24 | ||
96 | /* IRQ 25 - 30 external */ | ||
97 | #define IDE0_IRQ 26 | ||
98 | |||
99 | #define IIC_NUMS 1 | ||
100 | #define UART_NUMS 3 | ||
101 | #define IIC_OWN 0x55 | ||
102 | #define IIC_CLOCK 50 | ||
103 | |||
104 | #define BD_EMAC_ADDR(e,i) bi_enetaddr[i] | ||
105 | |||
106 | #define STD_UART_OP(num) \ | ||
107 | { 0, BASE_BAUD, 0, UART##num##_INT, \ | ||
108 | (ASYNC_BOOT_AUTOCONF | ASYNC_SKIP_TEST), \ | ||
109 | iomem_base: (u8 *)UART##num##_IO_BASE, \ | ||
110 | io_type: SERIAL_IO_MEM}, | ||
111 | |||
112 | #if defined(CONFIG_UART0_TTYS0) | ||
113 | #define SERIAL_DEBUG_IO_BASE UART0_IO_BASE | ||
114 | #define SERIAL_PORT_DFNS \ | ||
115 | STD_UART_OP(0) \ | ||
116 | STD_UART_OP(1) \ | ||
117 | STD_UART_OP(2) | ||
118 | #endif | ||
119 | |||
120 | #if defined(CONFIG_UART0_TTYS1) | ||
121 | #define SERIAL_DEBUG_IO_BASE UART2_IO_BASE | ||
122 | #define SERIAL_PORT_DFNS \ | ||
123 | STD_UART_OP(1) \ | ||
124 | STD_UART_OP(0) \ | ||
125 | STD_UART_OP(2) | ||
126 | #endif | ||
127 | |||
128 | #if defined(CONFIG_UART0_TTYS2) | ||
129 | #define SERIAL_DEBUG_IO_BASE UART2_IO_BASE | ||
130 | #define SERIAL_PORT_DFNS \ | ||
131 | STD_UART_OP(2) \ | ||
132 | STD_UART_OP(0) \ | ||
133 | STD_UART_OP(1) | ||
134 | #endif | ||
135 | |||
136 | #define DCRN_BE_BASE 0x090 | ||
137 | #define DCRN_DMA0_BASE 0x0C0 | ||
138 | #define DCRN_DMA1_BASE 0x0C8 | ||
139 | #define DCRN_DMA2_BASE 0x0D0 | ||
140 | #define DCRN_DMA3_BASE 0x0D8 | ||
141 | #define DCRNCAP_DMA_CC 1 /* have DMA chained count capability */ | ||
142 | #define DCRN_DMASR_BASE 0x0E0 | ||
143 | #define DCRN_PLB0_BASE 0x054 | ||
144 | #define DCRN_PLB1_BASE 0x064 | ||
145 | #define DCRN_POB0_BASE 0x0B0 | ||
146 | #define DCRN_SCCR_BASE 0x120 | ||
147 | #define DCRN_UIC0_BASE 0x040 | ||
148 | #define DCRN_BE_BASE 0x090 | ||
149 | #define DCRN_DMA0_BASE 0x0C0 | ||
150 | #define DCRN_DMA1_BASE 0x0C8 | ||
151 | #define DCRN_DMA2_BASE 0x0D0 | ||
152 | #define DCRN_DMA3_BASE 0x0D8 | ||
153 | #define DCRN_CIC_BASE 0x030 | ||
154 | #define DCRN_DMASR_BASE 0x0E0 | ||
155 | #define DCRN_EBIMC_BASE 0x070 | ||
156 | #define DCRN_DCRX_BASE 0x020 | ||
157 | #define DCRN_CPMFR_BASE 0x102 | ||
158 | #define DCRN_SCCR_BASE 0x120 | ||
159 | #define DCRN_RTCFP_BASE 0x310 | ||
160 | |||
161 | #define UIC0 DCRN_UIC0_BASE | ||
162 | |||
163 | #define IBM_CPM_IIC0 0x80000000 /* IIC 0 interface */ | ||
164 | #define IBM_CPM_CPU 0x10000000 /* PPC405B3 clock control */ | ||
165 | #define IBM_CPM_AUD 0x08000000 /* Audio Decoder */ | ||
166 | #define IBM_CPM_EBIU 0x04000000 /* External Bus Interface Unit */ | ||
167 | #define IBM_CPM_IRR 0x02000000 /* Infrared receiver */ | ||
168 | #define IBM_CPM_DMA 0x01000000 /* DMA controller */ | ||
169 | #define IBM_CPM_UART2 0x00200000 /* Serial Control Port */ | ||
170 | #define IBM_CPM_UART1 0x00100000 /* Serial 1 / Infrared */ | ||
171 | #define IBM_CPM_UART0 0x00080000 /* Serial 0 / 16550 */ | ||
172 | #define IBM_PM_DCRIDE 0x00040000 /* DCR timeout & IDE line Mode clock */ | ||
173 | #define IBM_CPM_SC0 0x00020000 /* Smart Card 0 */ | ||
174 | #define IBM_CPM_VID 0x00010000 /* reserved */ | ||
175 | #define IBM_CPM_SC1 0x00008000 /* Smart Card 0 */ | ||
176 | #define IBM_CPM_XPT0 0x00002000 /* Transport - 54 Mhz */ | ||
177 | #define IBM_CPM_CBS 0x00001000 /* Cross Bar Switch */ | ||
178 | #define IBM_CPM_GPT 0x00000800 /* GPTPWM */ | ||
179 | #define IBM_CPM_GPIO0 0x00000400 /* General Purpose IO 0 */ | ||
180 | #define IBM_CPM_DENC 0x00000200 /* Digital video Encoder */ | ||
181 | #define IBM_CPM_C405T 0x00000100 /* CPU timers */ | ||
182 | #define IBM_CPM_XPT27 0x00000080 /* Transport - 27 Mhz */ | ||
183 | #define IBM_CPM_UIC 0x00000040 /* Universal Interrupt Controller */ | ||
184 | #define IBM_CPM_RTCFPC 0x00000020 /* Realtime clock and front panel */ | ||
185 | #define IBM_CPM_SSP 0x00000010 /* Modem Serial Interface (SSP) */ | ||
186 | #define IBM_CPM_VID2 0x00000002 /* Video Decoder clock domain 2 */ | ||
187 | #define DFLT_IBM4xx_PM ~(IBM_CPM_CPU | IBM_CPM_EBIU | IBM_CPM_DMA \ | ||
188 | | IBM_CPM_CBS | IBM_CPM_XPT0 | IBM_CPM_C405T \ | ||
189 | | IBM_CPM_XPT27 | IBM_CPM_UIC) | ||
190 | |||
191 | #define DCRN_BEAR (DCRN_BE_BASE + 0x0) /* Bus Error Address Register */ | ||
192 | #define DCRN_BESR (DCRN_BE_BASE + 0x1) /* Bus Error Syndrome Register */ | ||
193 | /* DCRN_BESR */ | ||
194 | #define BESR_DSES 0x80000000 /* Data-Side Error Status */ | ||
195 | #define BESR_DMES 0x40000000 /* DMA Error Status */ | ||
196 | #define BESR_RWS 0x20000000 /* Read/Write Status */ | ||
197 | #define BESR_ETMASK 0x1C000000 /* Error Type */ | ||
198 | #define ET_PROT 0 | ||
199 | #define ET_PARITY 1 | ||
200 | #define ET_NCFG 2 | ||
201 | #define ET_BUSERR 4 | ||
202 | #define ET_BUSTO 6 | ||
203 | |||
204 | #define CHR1_CETE 0x00800000 /* CPU external timer enable */ | ||
205 | #define CHR1_PCIPW 0x00008000 /* PCI Int enable/Peripheral Write enable */ | ||
206 | |||
207 | #define DCRN_CICCR (DCRN_CIC_BASE + 0x0) /* CIC Control Register */ | ||
208 | #define DCRN_DMAS1 (DCRN_CIC_BASE + 0x1) /* DMA Select1 Register */ | ||
209 | #define DCRN_DMAS2 (DCRN_CIC_BASE + 0x2) /* DMA Select2 Register */ | ||
210 | #define DCRN_CICVCR (DCRN_CIC_BASE + 0x3) /* CIC Video COntro Register */ | ||
211 | #define DCRN_CICSEL3 (DCRN_CIC_BASE + 0x5) /* CIC Select 3 Register */ | ||
212 | #define DCRN_SGPO (DCRN_CIC_BASE + 0x6) /* CIC GPIO Output Register */ | ||
213 | #define DCRN_SGPOD (DCRN_CIC_BASE + 0x7) /* CIC GPIO OD Register */ | ||
214 | #define DCRN_SGPTC (DCRN_CIC_BASE + 0x8) /* CIC GPIO Tristate Ctrl Reg */ | ||
215 | #define DCRN_SGPI (DCRN_CIC_BASE + 0x9) /* CIC GPIO Input Reg */ | ||
216 | |||
217 | #define DCRN_DCRXICR (DCRN_DCRX_BASE + 0x0) /* Internal Control Register */ | ||
218 | #define DCRN_DCRXISR (DCRN_DCRX_BASE + 0x1) /* Internal Status Register */ | ||
219 | #define DCRN_DCRXECR (DCRN_DCRX_BASE + 0x2) /* External Control Register */ | ||
220 | #define DCRN_DCRXESR (DCRN_DCRX_BASE + 0x3) /* External Status Register */ | ||
221 | #define DCRN_DCRXTAR (DCRN_DCRX_BASE + 0x4) /* Target Address Register */ | ||
222 | #define DCRN_DCRXTDR (DCRN_DCRX_BASE + 0x5) /* Target Data Register */ | ||
223 | #define DCRN_DCRXIGR (DCRN_DCRX_BASE + 0x6) /* Interrupt Generation Register */ | ||
224 | #define DCRN_DCRXBCR (DCRN_DCRX_BASE + 0x7) /* Line Buffer Control Register */ | ||
225 | |||
226 | #define DCRN_BRCRH0 (DCRN_EBIMC_BASE + 0x0) /* Bus Region Config High 0 */ | ||
227 | #define DCRN_BRCRH1 (DCRN_EBIMC_BASE + 0x1) /* Bus Region Config High 1 */ | ||
228 | #define DCRN_BRCRH2 (DCRN_EBIMC_BASE + 0x2) /* Bus Region Config High 2 */ | ||
229 | #define DCRN_BRCRH3 (DCRN_EBIMC_BASE + 0x3) /* Bus Region Config High 3 */ | ||
230 | #define DCRN_BRCRH4 (DCRN_EBIMC_BASE + 0x4) /* Bus Region Config High 4 */ | ||
231 | #define DCRN_BRCRH5 (DCRN_EBIMC_BASE + 0x5) /* Bus Region Config High 5 */ | ||
232 | #define DCRN_BRCRH6 (DCRN_EBIMC_BASE + 0x6) /* Bus Region Config High 6 */ | ||
233 | #define DCRN_BRCRH7 (DCRN_EBIMC_BASE + 0x7) /* Bus Region Config High 7 */ | ||
234 | #define DCRN_BRCR0 (DCRN_EBIMC_BASE + 0x10) /* BRC 0 */ | ||
235 | #define DCRN_BRCR1 (DCRN_EBIMC_BASE + 0x11) /* BRC 1 */ | ||
236 | #define DCRN_BRCR2 (DCRN_EBIMC_BASE + 0x12) /* BRC 2 */ | ||
237 | #define DCRN_BRCR3 (DCRN_EBIMC_BASE + 0x13) /* BRC 3 */ | ||
238 | #define DCRN_BRCR4 (DCRN_EBIMC_BASE + 0x14) /* BRC 4 */ | ||
239 | #define DCRN_BRCR5 (DCRN_EBIMC_BASE + 0x15) /* BRC 5 */ | ||
240 | #define DCRN_BRCR6 (DCRN_EBIMC_BASE + 0x16) /* BRC 6 */ | ||
241 | #define DCRN_BRCR7 (DCRN_EBIMC_BASE + 0x17) /* BRC 7 */ | ||
242 | #define DCRN_BEAR0 (DCRN_EBIMC_BASE + 0x20) /* Bus Error Address Register */ | ||
243 | #define DCRN_BESR0 (DCRN_EBIMC_BASE + 0x21) /* Bus Error Status Register */ | ||
244 | #define DCRN_BIUCR (DCRN_EBIMC_BASE + 0x2A) /* Bus Interfac Unit Ctrl Reg */ | ||
245 | |||
246 | #define DCRN_RTC_FPC0_CNTL (DCRN_RTCFP_BASE + 0x00) /* RTC cntl */ | ||
247 | #define DCRN_RTC_FPC0_INT (DCRN_RTCFP_BASE + 0x01) /* RTC Interrupt */ | ||
248 | #define DCRN_RTC_FPC0_TIME (DCRN_RTCFP_BASE + 0x02) /* RTC time reg */ | ||
249 | #define DCRN_RTC_FPC0_ALRM (DCRN_RTCFP_BASE + 0x03) /* RTC Alarm reg */ | ||
250 | #define DCRN_RTC_FPC0_D1 (DCRN_RTCFP_BASE + 0x04) /* LED Data 1 */ | ||
251 | #define DCRN_RTC_FPC0_D2 (DCRN_RTCFP_BASE + 0x05) /* LED Data 2 */ | ||
252 | #define DCRN_RTC_FPC0_D3 (DCRN_RTCFP_BASE + 0x06) /* LED Data 3 */ | ||
253 | #define DCRN_RTC_FPC0_D4 (DCRN_RTCFP_BASE + 0x07) /* LED Data 4 */ | ||
254 | #define DCRN_RTC_FPC0_D5 (DCRN_RTCFP_BASE + 0x08) /* LED Data 5 */ | ||
255 | #define DCRN_RTC_FPC0_FCNTL (DCRN_RTCFP_BASE + 0x09) /* LED control */ | ||
256 | #define DCRN_RTC_FPC0_BRT (DCRN_RTCFP_BASE + 0x0A) /* Brightness cntl */ | ||
257 | |||
258 | #include <asm/ibm405.h> | ||
259 | |||
260 | #endif /* __ASM_IBMSTBX25_H__ */ | ||
261 | #endif /* __KERNEL__ */ | ||
diff --git a/arch/ppc/platforms/4xx/luan.c b/arch/ppc/platforms/4xx/luan.c new file mode 100644 index 000000000000..1df2339f1f6c --- /dev/null +++ b/arch/ppc/platforms/4xx/luan.c | |||
@@ -0,0 +1,387 @@ | |||
1 | /* | ||
2 | * arch/ppc/platforms/4xx/luan.c | ||
3 | * | ||
4 | * Luan board specific routines | ||
5 | * | ||
6 | * Matt Porter <mporter@kernel.crashing.org> | ||
7 | * | ||
8 | * Copyright 2004-2005 MontaVista Software Inc. | ||
9 | * | ||
10 | * This program is free software; you can redistribute it and/or modify it | ||
11 | * under the terms of the GNU General Public License as published by the | ||
12 | * Free Software Foundation; either version 2 of the License, or (at your | ||
13 | * option) any later version. | ||
14 | */ | ||
15 | |||
16 | #include <linux/config.h> | ||
17 | #include <linux/stddef.h> | ||
18 | #include <linux/kernel.h> | ||
19 | #include <linux/init.h> | ||
20 | #include <linux/errno.h> | ||
21 | #include <linux/reboot.h> | ||
22 | #include <linux/pci.h> | ||
23 | #include <linux/kdev_t.h> | ||
24 | #include <linux/types.h> | ||
25 | #include <linux/major.h> | ||
26 | #include <linux/blkdev.h> | ||
27 | #include <linux/console.h> | ||
28 | #include <linux/delay.h> | ||
29 | #include <linux/ide.h> | ||
30 | #include <linux/initrd.h> | ||
31 | #include <linux/irq.h> | ||
32 | #include <linux/seq_file.h> | ||
33 | #include <linux/root_dev.h> | ||
34 | #include <linux/tty.h> | ||
35 | #include <linux/serial.h> | ||
36 | #include <linux/serial_core.h> | ||
37 | |||
38 | #include <asm/system.h> | ||
39 | #include <asm/pgtable.h> | ||
40 | #include <asm/page.h> | ||
41 | #include <asm/dma.h> | ||
42 | #include <asm/io.h> | ||
43 | #include <asm/machdep.h> | ||
44 | #include <asm/ocp.h> | ||
45 | #include <asm/pci-bridge.h> | ||
46 | #include <asm/time.h> | ||
47 | #include <asm/todc.h> | ||
48 | #include <asm/bootinfo.h> | ||
49 | #include <asm/ppc4xx_pic.h> | ||
50 | #include <asm/ppcboot.h> | ||
51 | |||
52 | #include <syslib/ibm44x_common.h> | ||
53 | #include <syslib/ibm440gx_common.h> | ||
54 | #include <syslib/ibm440sp_common.h> | ||
55 | |||
56 | /* | ||
57 | * This is a horrible kludge, we eventually need to abstract this | ||
58 | * generic PHY stuff, so the standard phy mode defines can be | ||
59 | * easily used from arch code. | ||
60 | */ | ||
61 | #include "../../../../drivers/net/ibm_emac/ibm_emac_phy.h" | ||
62 | |||
63 | bd_t __res; | ||
64 | |||
65 | static struct ibm44x_clocks clocks __initdata; | ||
66 | |||
67 | static void __init | ||
68 | luan_calibrate_decr(void) | ||
69 | { | ||
70 | unsigned int freq; | ||
71 | |||
72 | if (mfspr(SPRN_CCR1) & CCR1_TCS) | ||
73 | freq = LUAN_TMR_CLK; | ||
74 | else | ||
75 | freq = clocks.cpu; | ||
76 | |||
77 | ibm44x_calibrate_decr(freq); | ||
78 | } | ||
79 | |||
80 | static int | ||
81 | luan_show_cpuinfo(struct seq_file *m) | ||
82 | { | ||
83 | seq_printf(m, "vendor\t\t: IBM\n"); | ||
84 | seq_printf(m, "machine\t\t: PPC440SP EVB (Luan)\n"); | ||
85 | |||
86 | return 0; | ||
87 | } | ||
88 | |||
89 | static inline int | ||
90 | luan_map_irq(struct pci_dev *dev, unsigned char idsel, unsigned char pin) | ||
91 | { | ||
92 | struct pci_controller *hose = pci_bus_to_hose(dev->bus->number); | ||
93 | |||
94 | /* PCIX0 in adapter mode, no host interrupt routing */ | ||
95 | |||
96 | /* PCIX1 */ | ||
97 | if (hose->index == 0) { | ||
98 | static char pci_irq_table[][4] = | ||
99 | /* | ||
100 | * PCI IDSEL/INTPIN->INTLINE | ||
101 | * A B C D | ||
102 | */ | ||
103 | { | ||
104 | { 49, 49, 49, 49 }, /* IDSEL 1 - PCIX1 Slot 0 */ | ||
105 | { 49, 49, 49, 49 }, /* IDSEL 2 - PCIX1 Slot 1 */ | ||
106 | { 49, 49, 49, 49 }, /* IDSEL 3 - PCIX1 Slot 2 */ | ||
107 | { 49, 49, 49, 49 }, /* IDSEL 4 - PCIX1 Slot 3 */ | ||
108 | }; | ||
109 | const long min_idsel = 1, max_idsel = 4, irqs_per_slot = 4; | ||
110 | return PCI_IRQ_TABLE_LOOKUP; | ||
111 | /* PCIX2 */ | ||
112 | } else if (hose->index == 1) { | ||
113 | static char pci_irq_table[][4] = | ||
114 | /* | ||
115 | * PCI IDSEL/INTPIN->INTLINE | ||
116 | * A B C D | ||
117 | */ | ||
118 | { | ||
119 | { 50, 50, 50, 50 }, /* IDSEL 1 - PCIX2 Slot 0 */ | ||
120 | { 50, 50, 50, 50 }, /* IDSEL 2 - PCIX2 Slot 1 */ | ||
121 | { 50, 50, 50, 50 }, /* IDSEL 3 - PCIX2 Slot 2 */ | ||
122 | { 50, 50, 50, 50 }, /* IDSEL 4 - PCIX2 Slot 3 */ | ||
123 | }; | ||
124 | const long min_idsel = 1, max_idsel = 4, irqs_per_slot = 4; | ||
125 | return PCI_IRQ_TABLE_LOOKUP; | ||
126 | } | ||
127 | return -1; | ||
128 | } | ||
129 | |||
130 | static void __init luan_set_emacdata(void) | ||
131 | { | ||
132 | struct ocp_def *def; | ||
133 | struct ocp_func_emac_data *emacdata; | ||
134 | |||
135 | /* Set phy_map, phy_mode, and mac_addr for the EMAC */ | ||
136 | def = ocp_get_one_device(OCP_VENDOR_IBM, OCP_FUNC_EMAC, 0); | ||
137 | emacdata = def->additions; | ||
138 | emacdata->phy_map = 0x00000001; /* Skip 0x00 */ | ||
139 | emacdata->phy_mode = PHY_MODE_GMII; | ||
140 | memcpy(emacdata->mac_addr, __res.bi_enetaddr, 6); | ||
141 | } | ||
142 | |||
143 | #define PCIX_READW(offset) \ | ||
144 | (readw((void *)((u32)pcix_reg_base+offset))) | ||
145 | |||
146 | #define PCIX_WRITEW(value, offset) \ | ||
147 | (writew(value, (void *)((u32)pcix_reg_base+offset))) | ||
148 | |||
149 | #define PCIX_WRITEL(value, offset) \ | ||
150 | (writel(value, (void *)((u32)pcix_reg_base+offset))) | ||
151 | |||
152 | static void __init | ||
153 | luan_setup_pcix(void) | ||
154 | { | ||
155 | int i; | ||
156 | void *pcix_reg_base; | ||
157 | |||
158 | for (i=0;i<3;i++) { | ||
159 | pcix_reg_base = ioremap64(PCIX0_REG_BASE + i*PCIX_REG_OFFSET, PCIX_REG_SIZE); | ||
160 | |||
161 | /* Enable PCIX0 I/O, Mem, and Busmaster cycles */ | ||
162 | PCIX_WRITEW(PCIX_READW(PCIX0_COMMAND) | PCI_COMMAND_IO | PCI_COMMAND_MEMORY | PCI_COMMAND_MASTER, PCIX0_COMMAND); | ||
163 | |||
164 | /* Disable all windows */ | ||
165 | PCIX_WRITEL(0, PCIX0_POM0SA); | ||
166 | PCIX_WRITEL(0, PCIX0_POM1SA); | ||
167 | PCIX_WRITEL(0, PCIX0_POM2SA); | ||
168 | PCIX_WRITEL(0, PCIX0_PIM0SA); | ||
169 | PCIX_WRITEL(0, PCIX0_PIM0SAH); | ||
170 | PCIX_WRITEL(0, PCIX0_PIM1SA); | ||
171 | PCIX_WRITEL(0, PCIX0_PIM2SA); | ||
172 | PCIX_WRITEL(0, PCIX0_PIM2SAH); | ||
173 | |||
174 | /* | ||
175 | * Setup 512MB PLB->PCI outbound mem window | ||
176 | * (a_n000_0000->0_n000_0000) | ||
177 | * */ | ||
178 | PCIX_WRITEL(0x0000000a, PCIX0_POM0LAH); | ||
179 | PCIX_WRITEL(0x80000000 | i*LUAN_PCIX_MEM_SIZE, PCIX0_POM0LAL); | ||
180 | PCIX_WRITEL(0x00000000, PCIX0_POM0PCIAH); | ||
181 | PCIX_WRITEL(0x80000000 | i*LUAN_PCIX_MEM_SIZE, PCIX0_POM0PCIAL); | ||
182 | PCIX_WRITEL(0xe0000001, PCIX0_POM0SA); | ||
183 | |||
184 | /* Setup 2GB PCI->PLB inbound memory window at 0, enable MSIs */ | ||
185 | PCIX_WRITEL(0x00000000, PCIX0_PIM0LAH); | ||
186 | PCIX_WRITEL(0x00000000, PCIX0_PIM0LAL); | ||
187 | PCIX_WRITEL(0xe0000007, PCIX0_PIM0SA); | ||
188 | PCIX_WRITEL(0xffffffff, PCIX0_PIM0SAH); | ||
189 | |||
190 | iounmap(pcix_reg_base); | ||
191 | } | ||
192 | |||
193 | eieio(); | ||
194 | } | ||
195 | |||
196 | static void __init | ||
197 | luan_setup_hose(struct pci_controller *hose, | ||
198 | int lower_mem, | ||
199 | int upper_mem, | ||
200 | int cfga, | ||
201 | int cfgd, | ||
202 | u64 pcix_io_base) | ||
203 | { | ||
204 | char name[20]; | ||
205 | |||
206 | sprintf(name, "PCIX%d host bridge", hose->index); | ||
207 | |||
208 | hose->pci_mem_offset = LUAN_PCIX_MEM_OFFSET; | ||
209 | |||
210 | pci_init_resource(&hose->io_resource, | ||
211 | LUAN_PCIX_LOWER_IO, | ||
212 | LUAN_PCIX_UPPER_IO, | ||
213 | IORESOURCE_IO, | ||
214 | name); | ||
215 | |||
216 | pci_init_resource(&hose->mem_resources[0], | ||
217 | lower_mem, | ||
218 | upper_mem, | ||
219 | IORESOURCE_MEM, | ||
220 | name); | ||
221 | |||
222 | hose->io_space.start = LUAN_PCIX_LOWER_IO; | ||
223 | hose->io_space.end = LUAN_PCIX_UPPER_IO; | ||
224 | hose->mem_space.start = lower_mem; | ||
225 | hose->mem_space.end = upper_mem; | ||
226 | isa_io_base = | ||
227 | (unsigned long)ioremap64(pcix_io_base, PCIX_IO_SIZE); | ||
228 | hose->io_base_virt = (void *)isa_io_base; | ||
229 | |||
230 | setup_indirect_pci(hose, cfga, cfgd); | ||
231 | hose->set_cfg_type = 1; | ||
232 | } | ||
233 | |||
234 | static void __init | ||
235 | luan_setup_hoses(void) | ||
236 | { | ||
237 | struct pci_controller *hose1, *hose2; | ||
238 | |||
239 | /* Configure windows on the PCI-X host bridge */ | ||
240 | luan_setup_pcix(); | ||
241 | |||
242 | /* Allocate hoses for PCIX1 and PCIX2 */ | ||
243 | hose1 = pcibios_alloc_controller(); | ||
244 | hose2 = pcibios_alloc_controller(); | ||
245 | if (!hose1 || !hose2) | ||
246 | return; | ||
247 | |||
248 | /* Setup PCIX1 */ | ||
249 | hose1->first_busno = 0; | ||
250 | hose1->last_busno = 0xff; | ||
251 | |||
252 | luan_setup_hose(hose1, | ||
253 | LUAN_PCIX1_LOWER_MEM, | ||
254 | LUAN_PCIX1_UPPER_MEM, | ||
255 | PCIX1_CFGA, | ||
256 | PCIX1_CFGD, | ||
257 | PCIX1_IO_BASE); | ||
258 | |||
259 | hose1->last_busno = pciauto_bus_scan(hose1, hose1->first_busno); | ||
260 | |||
261 | /* Setup PCIX2 */ | ||
262 | hose2->first_busno = hose1->last_busno + 1; | ||
263 | hose2->last_busno = 0xff; | ||
264 | |||
265 | luan_setup_hose(hose2, | ||
266 | LUAN_PCIX2_LOWER_MEM, | ||
267 | LUAN_PCIX2_UPPER_MEM, | ||
268 | PCIX2_CFGA, | ||
269 | PCIX2_CFGD, | ||
270 | PCIX2_IO_BASE); | ||
271 | |||
272 | hose2->last_busno = pciauto_bus_scan(hose2, hose2->first_busno); | ||
273 | |||
274 | ppc_md.pci_swizzle = common_swizzle; | ||
275 | ppc_md.pci_map_irq = luan_map_irq; | ||
276 | } | ||
277 | |||
278 | TODC_ALLOC(); | ||
279 | |||
280 | static void __init | ||
281 | luan_early_serial_map(void) | ||
282 | { | ||
283 | struct uart_port port; | ||
284 | |||
285 | /* Setup ioremapped serial port access */ | ||
286 | memset(&port, 0, sizeof(port)); | ||
287 | port.membase = ioremap64(PPC440SP_UART0_ADDR, 8); | ||
288 | port.irq = UART0_INT; | ||
289 | port.uartclk = clocks.uart0; | ||
290 | port.regshift = 0; | ||
291 | port.iotype = SERIAL_IO_MEM; | ||
292 | port.flags = ASYNC_BOOT_AUTOCONF | ASYNC_SKIP_TEST; | ||
293 | port.line = 0; | ||
294 | |||
295 | if (early_serial_setup(&port) != 0) { | ||
296 | printk("Early serial init of port 0 failed\n"); | ||
297 | } | ||
298 | |||
299 | port.membase = ioremap64(PPC440SP_UART1_ADDR, 8); | ||
300 | port.irq = UART1_INT; | ||
301 | port.uartclk = clocks.uart1; | ||
302 | port.line = 1; | ||
303 | |||
304 | if (early_serial_setup(&port) != 0) { | ||
305 | printk("Early serial init of port 1 failed\n"); | ||
306 | } | ||
307 | |||
308 | port.membase = ioremap64(PPC440SP_UART2_ADDR, 8); | ||
309 | port.irq = UART2_INT; | ||
310 | port.uartclk = BASE_BAUD; | ||
311 | port.line = 2; | ||
312 | |||
313 | if (early_serial_setup(&port) != 0) { | ||
314 | printk("Early serial init of port 2 failed\n"); | ||
315 | } | ||
316 | } | ||
317 | |||
318 | static void __init | ||
319 | luan_setup_arch(void) | ||
320 | { | ||
321 | luan_set_emacdata(); | ||
322 | |||
323 | #if !defined(CONFIG_BDI_SWITCH) | ||
324 | /* | ||
325 | * The Abatron BDI JTAG debugger does not tolerate others | ||
326 | * mucking with the debug registers. | ||
327 | */ | ||
328 | mtspr(SPRN_DBCR0, (DBCR0_TDE | DBCR0_IDM)); | ||
329 | #endif | ||
330 | |||
331 | /* | ||
332 | * Determine various clocks. | ||
333 | * To be completely correct we should get SysClk | ||
334 | * from FPGA, because it can be changed by on-board switches | ||
335 | * --ebs | ||
336 | */ | ||
337 | /* 440GX and 440SP clocking is the same -mdp */ | ||
338 | ibm440gx_get_clocks(&clocks, 33333333, 6 * 1843200); | ||
339 | ocp_sys_info.opb_bus_freq = clocks.opb; | ||
340 | |||
341 | /* init to some ~sane value until calibrate_delay() runs */ | ||
342 | loops_per_jiffy = 50000000/HZ; | ||
343 | |||
344 | /* Setup PCIXn host bridges */ | ||
345 | luan_setup_hoses(); | ||
346 | |||
347 | #ifdef CONFIG_BLK_DEV_INITRD | ||
348 | if (initrd_start) | ||
349 | ROOT_DEV = Root_RAM0; | ||
350 | else | ||
351 | #endif | ||
352 | #ifdef CONFIG_ROOT_NFS | ||
353 | ROOT_DEV = Root_NFS; | ||
354 | #else | ||
355 | ROOT_DEV = Root_HDA1; | ||
356 | #endif | ||
357 | |||
358 | luan_early_serial_map(); | ||
359 | |||
360 | /* Identify the system */ | ||
361 | printk("Luan port (MontaVista Software, Inc. <source@mvista.com>)\n"); | ||
362 | } | ||
363 | |||
364 | void __init platform_init(unsigned long r3, unsigned long r4, | ||
365 | unsigned long r5, unsigned long r6, unsigned long r7) | ||
366 | { | ||
367 | parse_bootinfo(find_bootinfo()); | ||
368 | |||
369 | /* | ||
370 | * If we were passed in a board information, copy it into the | ||
371 | * residual data area. | ||
372 | */ | ||
373 | if (r3) | ||
374 | __res = *(bd_t *)(r3 + KERNELBASE); | ||
375 | |||
376 | ibm44x_platform_init(); | ||
377 | |||
378 | ppc_md.setup_arch = luan_setup_arch; | ||
379 | ppc_md.show_cpuinfo = luan_show_cpuinfo; | ||
380 | ppc_md.find_end_of_memory = ibm440sp_find_end_of_memory; | ||
381 | ppc_md.get_irq = NULL; /* Set in ppc4xx_pic_init() */ | ||
382 | |||
383 | ppc_md.calibrate_decr = luan_calibrate_decr; | ||
384 | #ifdef CONFIG_KGDB | ||
385 | ppc_md.early_serial_map = luan_early_serial_map; | ||
386 | #endif | ||
387 | } | ||
diff --git a/arch/ppc/platforms/4xx/luan.h b/arch/ppc/platforms/4xx/luan.h new file mode 100644 index 000000000000..09b444c87816 --- /dev/null +++ b/arch/ppc/platforms/4xx/luan.h | |||
@@ -0,0 +1,80 @@ | |||
1 | /* | ||
2 | * arch/ppc/platforms/4xx/luan.h | ||
3 | * | ||
4 | * Luan board definitions | ||
5 | * | ||
6 | * Matt Porter <mporter@kernel.crashing.org> | ||
7 | * | ||
8 | * Copyright 2004-2005 MontaVista Software Inc. | ||
9 | * | ||
10 | * This program is free software; you can redistribute it and/or modify it | ||
11 | * under the terms of the GNU General Public License as published by the | ||
12 | * Free Software Foundation; either version 2 of the License, or (at your | ||
13 | * option) any later version. | ||
14 | * | ||
15 | */ | ||
16 | |||
17 | #ifdef __KERNEL__ | ||
18 | #ifndef __ASM_LUAN_H__ | ||
19 | #define __ASM_LUAN_H__ | ||
20 | |||
21 | #include <linux/config.h> | ||
22 | #include <platforms/4xx/ibm440sp.h> | ||
23 | |||
24 | /* F/W TLB mapping used in bootloader glue to reset EMAC */ | ||
25 | #define PPC44x_EMAC0_MR0 0xa0000800 | ||
26 | |||
27 | /* Location of MAC addresses in PIBS image */ | ||
28 | #define PIBS_FLASH_BASE 0xffe00000 | ||
29 | #define PIBS_MAC_BASE (PIBS_FLASH_BASE+0x1b0400) | ||
30 | |||
31 | /* External timer clock frequency */ | ||
32 | #define LUAN_TMR_CLK 25000000 | ||
33 | |||
34 | /* Flash */ | ||
35 | #define LUAN_FPGA_REG_0 0x0000000148300000ULL | ||
36 | #define LUAN_BOOT_LARGE_FLASH(x) (x & 0x40) | ||
37 | #define LUAN_SMALL_FLASH_LOW 0x00000001ff900000ULL | ||
38 | #define LUAN_SMALL_FLASH_HIGH 0x00000001ffe00000ULL | ||
39 | #define LUAN_SMALL_FLASH_SIZE 0x100000 | ||
40 | #define LUAN_LARGE_FLASH_LOW 0x00000001ff800000ULL | ||
41 | #define LUAN_LARGE_FLASH_HIGH 0x00000001ffc00000ULL | ||
42 | #define LUAN_LARGE_FLASH_SIZE 0x400000 | ||
43 | |||
44 | /* | ||
45 | * Serial port defines | ||
46 | */ | ||
47 | #define RS_TABLE_SIZE 3 | ||
48 | |||
49 | /* PIBS defined UART mappings, used before early_serial_setup */ | ||
50 | #define UART0_IO_BASE 0xa0000200 | ||
51 | #define UART1_IO_BASE 0xa0000300 | ||
52 | #define UART2_IO_BASE 0xa0000600 | ||
53 | |||
54 | #define BASE_BAUD 11059200 | ||
55 | #define STD_UART_OP(num) \ | ||
56 | { 0, BASE_BAUD, 0, UART##num##_INT, \ | ||
57 | (ASYNC_BOOT_AUTOCONF | ASYNC_SKIP_TEST), \ | ||
58 | iomem_base: UART##num##_IO_BASE, \ | ||
59 | io_type: SERIAL_IO_MEM}, | ||
60 | |||
61 | #define SERIAL_PORT_DFNS \ | ||
62 | STD_UART_OP(0) \ | ||
63 | STD_UART_OP(1) \ | ||
64 | STD_UART_OP(2) | ||
65 | |||
66 | /* PCI support */ | ||
67 | #define LUAN_PCIX_LOWER_IO 0x00000000 | ||
68 | #define LUAN_PCIX_UPPER_IO 0x0000ffff | ||
69 | #define LUAN_PCIX0_LOWER_MEM 0x80000000 | ||
70 | #define LUAN_PCIX0_UPPER_MEM 0x9fffffff | ||
71 | #define LUAN_PCIX1_LOWER_MEM 0xa0000000 | ||
72 | #define LUAN_PCIX1_UPPER_MEM 0xbfffffff | ||
73 | #define LUAN_PCIX2_LOWER_MEM 0xc0000000 | ||
74 | #define LUAN_PCIX2_UPPER_MEM 0xdfffffff | ||
75 | |||
76 | #define LUAN_PCIX_MEM_SIZE 0x20000000 | ||
77 | #define LUAN_PCIX_MEM_OFFSET 0x00000000 | ||
78 | |||
79 | #endif /* __ASM_LUAN_H__ */ | ||
80 | #endif /* __KERNEL__ */ | ||
diff --git a/arch/ppc/platforms/4xx/oak.c b/arch/ppc/platforms/4xx/oak.c new file mode 100644 index 000000000000..fa25ee1fa733 --- /dev/null +++ b/arch/ppc/platforms/4xx/oak.c | |||
@@ -0,0 +1,255 @@ | |||
1 | /* | ||
2 | * | ||
3 | * Copyright (c) 1999-2000 Grant Erickson <grant@lcse.umn.edu> | ||
4 | * | ||
5 | * Module name: oak.c | ||
6 | * | ||
7 | * Description: | ||
8 | * Architecture- / platform-specific boot-time initialization code for | ||
9 | * the IBM PowerPC 403GCX "Oak" evaluation board. Adapted from original | ||
10 | * code by Gary Thomas, Cort Dougan <cort@fsmlabs.com>, and Dan Malek | ||
11 | * <dan@net4x.com>. | ||
12 | * | ||
13 | */ | ||
14 | |||
15 | #include <linux/config.h> | ||
16 | #include <linux/init.h> | ||
17 | #include <linux/smp.h> | ||
18 | #include <linux/threads.h> | ||
19 | #include <linux/param.h> | ||
20 | #include <linux/string.h> | ||
21 | #include <linux/initrd.h> | ||
22 | #include <linux/irq.h> | ||
23 | #include <linux/seq_file.h> | ||
24 | |||
25 | #include <asm/board.h> | ||
26 | #include <asm/machdep.h> | ||
27 | #include <asm/page.h> | ||
28 | #include <asm/bootinfo.h> | ||
29 | #include <asm/ppc4xx_pic.h> | ||
30 | #include <asm/time.h> | ||
31 | |||
32 | #include "oak.h" | ||
33 | |||
34 | /* Function Prototypes */ | ||
35 | |||
36 | extern void abort(void); | ||
37 | |||
38 | /* Global Variables */ | ||
39 | |||
40 | unsigned char __res[sizeof(bd_t)]; | ||
41 | |||
42 | |||
43 | /* | ||
44 | * void __init oak_init() | ||
45 | * | ||
46 | * Description: | ||
47 | * This routine... | ||
48 | * | ||
49 | * Input(s): | ||
50 | * r3 - Optional pointer to a board information structure. | ||
51 | * r4 - Optional pointer to the physical starting address of the init RAM | ||
52 | * disk. | ||
53 | * r5 - Optional pointer to the physical ending address of the init RAM | ||
54 | * disk. | ||
55 | * r6 - Optional pointer to the physical starting address of any kernel | ||
56 | * command-line parameters. | ||
57 | * r7 - Optional pointer to the physical ending address of any kernel | ||
58 | * command-line parameters. | ||
59 | * | ||
60 | * Output(s): | ||
61 | * N/A | ||
62 | * | ||
63 | * Returns: | ||
64 | * N/A | ||
65 | * | ||
66 | */ | ||
67 | void __init | ||
68 | platform_init(unsigned long r3, unsigned long r4, unsigned long r5, | ||
69 | unsigned long r6, unsigned long r7) | ||
70 | { | ||
71 | parse_bootinfo(find_bootinfo()); | ||
72 | |||
73 | /* | ||
74 | * If we were passed in a board information, copy it into the | ||
75 | * residual data area. | ||
76 | */ | ||
77 | if (r3) { | ||
78 | memcpy((void *)__res, (void *)(r3 + KERNELBASE), sizeof(bd_t)); | ||
79 | } | ||
80 | |||
81 | #if defined(CONFIG_BLK_DEV_INITRD) | ||
82 | /* | ||
83 | * If the init RAM disk has been configured in, and there's a valid | ||
84 | * starting address for it, set it up. | ||
85 | */ | ||
86 | if (r4) { | ||
87 | initrd_start = r4 + KERNELBASE; | ||
88 | initrd_end = r5 + KERNELBASE; | ||
89 | } | ||
90 | #endif /* CONFIG_BLK_DEV_INITRD */ | ||
91 | |||
92 | /* Copy the kernel command line arguments to a safe place. */ | ||
93 | |||
94 | if (r6) { | ||
95 | *(char *)(r7 + KERNELBASE) = 0; | ||
96 | strcpy(cmd_line, (char *)(r6 + KERNELBASE)); | ||
97 | } | ||
98 | |||
99 | /* Initialize machine-dependency vectors */ | ||
100 | |||
101 | ppc_md.setup_arch = oak_setup_arch; | ||
102 | ppc_md.show_percpuinfo = oak_show_percpuinfo; | ||
103 | ppc_md.irq_canonicalize = NULL; | ||
104 | ppc_md.init_IRQ = ppc4xx_pic_init; | ||
105 | ppc_md.get_irq = NULL; /* Set in ppc4xx_pic_init() */ | ||
106 | ppc_md.init = NULL; | ||
107 | |||
108 | ppc_md.restart = oak_restart; | ||
109 | ppc_md.power_off = oak_power_off; | ||
110 | ppc_md.halt = oak_halt; | ||
111 | |||
112 | ppc_md.time_init = oak_time_init; | ||
113 | ppc_md.set_rtc_time = oak_set_rtc_time; | ||
114 | ppc_md.get_rtc_time = oak_get_rtc_time; | ||
115 | ppc_md.calibrate_decr = oak_calibrate_decr; | ||
116 | } | ||
117 | |||
118 | /* | ||
119 | * Document me. | ||
120 | */ | ||
121 | void __init | ||
122 | oak_setup_arch(void) | ||
123 | { | ||
124 | /* XXX - Implement me */ | ||
125 | } | ||
126 | |||
127 | /* | ||
128 | * int oak_show_percpuinfo() | ||
129 | * | ||
130 | * Description: | ||
131 | * This routine pretty-prints the platform's internal CPU and bus clock | ||
132 | * frequencies into the buffer for usage in /proc/cpuinfo. | ||
133 | * | ||
134 | * Input(s): | ||
135 | * *buffer - Buffer into which CPU and bus clock frequencies are to be | ||
136 | * printed. | ||
137 | * | ||
138 | * Output(s): | ||
139 | * *buffer - Buffer with the CPU and bus clock frequencies. | ||
140 | * | ||
141 | * Returns: | ||
142 | * The number of bytes copied into 'buffer' if OK, otherwise zero or less | ||
143 | * on error. | ||
144 | */ | ||
145 | int | ||
146 | oak_show_percpuinfo(struct seq_file *m, int i) | ||
147 | { | ||
148 | bd_t *bp = (bd_t *)__res; | ||
149 | |||
150 | seq_printf(m, "clock\t\t: %dMHz\n" | ||
151 | "bus clock\t\t: %dMHz\n", | ||
152 | bp->bi_intfreq / 1000000, | ||
153 | bp->bi_busfreq / 1000000); | ||
154 | |||
155 | return 0; | ||
156 | } | ||
157 | |||
158 | /* | ||
159 | * Document me. | ||
160 | */ | ||
161 | void | ||
162 | oak_restart(char *cmd) | ||
163 | { | ||
164 | abort(); | ||
165 | } | ||
166 | |||
167 | /* | ||
168 | * Document me. | ||
169 | */ | ||
170 | void | ||
171 | oak_power_off(void) | ||
172 | { | ||
173 | oak_restart(NULL); | ||
174 | } | ||
175 | |||
176 | /* | ||
177 | * Document me. | ||
178 | */ | ||
179 | void | ||
180 | oak_halt(void) | ||
181 | { | ||
182 | oak_restart(NULL); | ||
183 | } | ||
184 | |||
185 | /* | ||
186 | * Document me. | ||
187 | */ | ||
188 | long __init | ||
189 | oak_time_init(void) | ||
190 | { | ||
191 | /* XXX - Implement me */ | ||
192 | return 0; | ||
193 | } | ||
194 | |||
195 | /* | ||
196 | * Document me. | ||
197 | */ | ||
198 | int __init | ||
199 | oak_set_rtc_time(unsigned long time) | ||
200 | { | ||
201 | /* XXX - Implement me */ | ||
202 | |||
203 | return (0); | ||
204 | } | ||
205 | |||
206 | /* | ||
207 | * Document me. | ||
208 | */ | ||
209 | unsigned long __init | ||
210 | oak_get_rtc_time(void) | ||
211 | { | ||
212 | /* XXX - Implement me */ | ||
213 | |||
214 | return (0); | ||
215 | } | ||
216 | |||
217 | /* | ||
218 | * void __init oak_calibrate_decr() | ||
219 | * | ||
220 | * Description: | ||
221 | * This routine retrieves the internal processor frequency from the board | ||
222 | * information structure, sets up the kernel timer decrementer based on | ||
223 | * that value, enables the 403 programmable interval timer (PIT) and sets | ||
224 | * it up for auto-reload. | ||
225 | * | ||
226 | * Input(s): | ||
227 | * N/A | ||
228 | * | ||
229 | * Output(s): | ||
230 | * N/A | ||
231 | * | ||
232 | * Returns: | ||
233 | * N/A | ||
234 | * | ||
235 | */ | ||
236 | void __init | ||
237 | oak_calibrate_decr(void) | ||
238 | { | ||
239 | unsigned int freq; | ||
240 | bd_t *bip = (bd_t *)__res; | ||
241 | |||
242 | freq = bip->bi_intfreq; | ||
243 | |||
244 | decrementer_count = freq / HZ; | ||
245 | count_period_num = 1; | ||
246 | count_period_den = freq; | ||
247 | |||
248 | /* Enable the PIT and set auto-reload of its value */ | ||
249 | |||
250 | mtspr(SPRN_TCR, TCR_PIE | TCR_ARE); | ||
251 | |||
252 | /* Clear any pending timer interrupts */ | ||
253 | |||
254 | mtspr(SPRN_TSR, TSR_ENW | TSR_WIS | TSR_PIS | TSR_FIS); | ||
255 | } | ||
diff --git a/arch/ppc/platforms/4xx/oak.h b/arch/ppc/platforms/4xx/oak.h new file mode 100644 index 000000000000..1b86a4c66b04 --- /dev/null +++ b/arch/ppc/platforms/4xx/oak.h | |||
@@ -0,0 +1,96 @@ | |||
1 | /* | ||
2 | * | ||
3 | * Copyright (c) 1999 Grant Erickson <grant@lcse.umn.edu> | ||
4 | * | ||
5 | * Module name: oak.h | ||
6 | * | ||
7 | * Description: | ||
8 | * Macros, definitions, and data structures specific to the IBM PowerPC | ||
9 | * 403G{A,B,C,CX} "Oak" evaluation board. Anything specific to the pro- | ||
10 | * cessor itself is defined elsewhere. | ||
11 | * | ||
12 | */ | ||
13 | |||
14 | #ifdef __KERNEL__ | ||
15 | #ifndef __ASM_OAK_H__ | ||
16 | #define __ASM_OAK_H__ | ||
17 | |||
18 | /* We have an IBM 403G{A,B,C,CX} core */ | ||
19 | #include <asm/ibm403.h> | ||
20 | |||
21 | #define _IO_BASE 0 | ||
22 | #define _ISA_MEM_BASE 0 | ||
23 | #define PCI_DRAM_OFFSET 0 | ||
24 | |||
25 | /* Memory map for the "Oak" evaluation board */ | ||
26 | |||
27 | #define PPC403SPU_IO_BASE 0x40000000 /* 403 On-chip serial port */ | ||
28 | #define PPC403SPU_IO_SIZE 0x00000008 | ||
29 | #define OAKSERIAL_IO_BASE 0x7E000000 /* NS16550DV serial port */ | ||
30 | #define OAKSERIAL_IO_SIZE 0x00000008 | ||
31 | #define OAKNET_IO_BASE 0xF4000000 /* NS83902AV Ethernet */ | ||
32 | #define OAKNET_IO_SIZE 0x00000040 | ||
33 | #define OAKPROM_IO_BASE 0xFFFE0000 /* AMD 29F010 Flash ROM */ | ||
34 | #define OAKPROM_IO_SIZE 0x00020000 | ||
35 | |||
36 | |||
37 | /* Interrupt assignments fixed by the hardware implementation */ | ||
38 | |||
39 | /* This is annoying kbuild-2.4 problem. -- Tom */ | ||
40 | |||
41 | #define PPC403SPU_RX_INT 4 /* AIC_INT4 */ | ||
42 | #define PPC403SPU_TX_INT 5 /* AIC_INT5 */ | ||
43 | #define OAKNET_INT 27 /* AIC_INT27 */ | ||
44 | #define OAKSERIAL_INT 28 /* AIC_INT28 */ | ||
45 | |||
46 | #ifndef __ASSEMBLY__ | ||
47 | /* | ||
48 | * Data structure defining board information maintained by the boot | ||
49 | * ROM on IBM's "Oak" evaluation board. An effort has been made to | ||
50 | * keep the field names consistent with the 8xx 'bd_t' board info | ||
51 | * structures. | ||
52 | */ | ||
53 | |||
54 | typedef struct board_info { | ||
55 | unsigned char bi_s_version[4]; /* Version of this structure */ | ||
56 | unsigned char bi_r_version[30]; /* Version of the IBM ROM */ | ||
57 | unsigned int bi_memsize; /* DRAM installed, in bytes */ | ||
58 | unsigned char bi_enetaddr[6]; /* Ethernet MAC address */ | ||
59 | unsigned int bi_intfreq; /* Processor speed, in Hz */ | ||
60 | unsigned int bi_busfreq; /* Bus speed, in Hz */ | ||
61 | } bd_t; | ||
62 | |||
63 | #ifdef __cplusplus | ||
64 | extern "C" { | ||
65 | #endif | ||
66 | |||
67 | extern void oak_init(unsigned long r3, | ||
68 | unsigned long ird_start, | ||
69 | unsigned long ird_end, | ||
70 | unsigned long cline_start, | ||
71 | unsigned long cline_end); | ||
72 | extern void oak_setup_arch(void); | ||
73 | extern int oak_setup_residual(char *buffer); | ||
74 | extern void oak_init_IRQ(void); | ||
75 | extern int oak_get_irq(struct pt_regs *regs); | ||
76 | extern void oak_restart(char *cmd); | ||
77 | extern void oak_power_off(void); | ||
78 | extern void oak_halt(void); | ||
79 | extern void oak_time_init(void); | ||
80 | extern int oak_set_rtc_time(unsigned long now); | ||
81 | extern unsigned long oak_get_rtc_time(void); | ||
82 | extern void oak_calibrate_decr(void); | ||
83 | |||
84 | #ifdef __cplusplus | ||
85 | } | ||
86 | #endif | ||
87 | |||
88 | /* Some 4xx parts use a different timebase frequency from the internal clock. | ||
89 | */ | ||
90 | #define bi_tbfreq bi_intfreq | ||
91 | |||
92 | #define PPC4xx_MACHINE_NAME "IBM Oak" | ||
93 | |||
94 | #endif /* !__ASSEMBLY__ */ | ||
95 | #endif /* __ASM_OAK_H__ */ | ||
96 | #endif /* __KERNEL__ */ | ||
diff --git a/arch/ppc/platforms/4xx/oak_setup.h b/arch/ppc/platforms/4xx/oak_setup.h new file mode 100644 index 000000000000..8648bd084df8 --- /dev/null +++ b/arch/ppc/platforms/4xx/oak_setup.h | |||
@@ -0,0 +1,50 @@ | |||
1 | /* | ||
2 | * | ||
3 | * Copyright (c) 1999-2000 Grant Erickson <grant@lcse.umn.edu> | ||
4 | * | ||
5 | * Module name: oak_setup.h | ||
6 | * | ||
7 | * Description: | ||
8 | * Architecture- / platform-specific boot-time initialization code for | ||
9 | * the IBM PowerPC 403GCX "Oak" evaluation board. Adapted from original | ||
10 | * code by Gary Thomas, Cort Dougan <cort@cs.nmt.edu>, and Dan Malek | ||
11 | * <dan@netx4.com>. | ||
12 | * | ||
13 | */ | ||
14 | |||
15 | #ifndef __OAK_SETUP_H__ | ||
16 | #define __OAK_SETUP_H__ | ||
17 | |||
18 | #include <asm/ptrace.h> | ||
19 | #include <asm/board.h> | ||
20 | |||
21 | |||
22 | #ifdef __cplusplus | ||
23 | extern "C" { | ||
24 | #endif | ||
25 | |||
26 | extern unsigned char __res[sizeof(bd_t)]; | ||
27 | |||
28 | extern void oak_init(unsigned long r3, | ||
29 | unsigned long ird_start, | ||
30 | unsigned long ird_end, | ||
31 | unsigned long cline_start, | ||
32 | unsigned long cline_end); | ||
33 | extern void oak_setup_arch(void); | ||
34 | extern int oak_setup_residual(char *buffer); | ||
35 | extern void oak_init_IRQ(void); | ||
36 | extern int oak_get_irq(struct pt_regs *regs); | ||
37 | extern void oak_restart(char *cmd); | ||
38 | extern void oak_power_off(void); | ||
39 | extern void oak_halt(void); | ||
40 | extern void oak_time_init(void); | ||
41 | extern int oak_set_rtc_time(unsigned long now); | ||
42 | extern unsigned long oak_get_rtc_time(void); | ||
43 | extern void oak_calibrate_decr(void); | ||
44 | |||
45 | |||
46 | #ifdef __cplusplus | ||
47 | } | ||
48 | #endif | ||
49 | |||
50 | #endif /* __OAK_SETUP_H__ */ | ||
diff --git a/arch/ppc/platforms/4xx/ocotea.c b/arch/ppc/platforms/4xx/ocotea.c new file mode 100644 index 000000000000..28de707434f1 --- /dev/null +++ b/arch/ppc/platforms/4xx/ocotea.c | |||
@@ -0,0 +1,367 @@ | |||
1 | /* | ||
2 | * arch/ppc/platforms/4xx/ocotea.c | ||
3 | * | ||
4 | * Ocotea board specific routines | ||
5 | * | ||
6 | * Matt Porter <mporter@kernel.crashing.org> | ||
7 | * | ||
8 | * Copyright 2003-2005 MontaVista Software Inc. | ||
9 | * | ||
10 | * This program is free software; you can redistribute it and/or modify it | ||
11 | * under the terms of the GNU General Public License as published by the | ||
12 | * Free Software Foundation; either version 2 of the License, or (at your | ||
13 | * option) any later version. | ||
14 | */ | ||
15 | |||
16 | #include <linux/config.h> | ||
17 | #include <linux/stddef.h> | ||
18 | #include <linux/kernel.h> | ||
19 | #include <linux/init.h> | ||
20 | #include <linux/errno.h> | ||
21 | #include <linux/reboot.h> | ||
22 | #include <linux/pci.h> | ||
23 | #include <linux/kdev_t.h> | ||
24 | #include <linux/types.h> | ||
25 | #include <linux/major.h> | ||
26 | #include <linux/blkdev.h> | ||
27 | #include <linux/console.h> | ||
28 | #include <linux/delay.h> | ||
29 | #include <linux/ide.h> | ||
30 | #include <linux/initrd.h> | ||
31 | #include <linux/irq.h> | ||
32 | #include <linux/seq_file.h> | ||
33 | #include <linux/root_dev.h> | ||
34 | #include <linux/tty.h> | ||
35 | #include <linux/serial.h> | ||
36 | #include <linux/serial_core.h> | ||
37 | |||
38 | #include <asm/system.h> | ||
39 | #include <asm/pgtable.h> | ||
40 | #include <asm/page.h> | ||
41 | #include <asm/dma.h> | ||
42 | #include <asm/io.h> | ||
43 | #include <asm/machdep.h> | ||
44 | #include <asm/ocp.h> | ||
45 | #include <asm/pci-bridge.h> | ||
46 | #include <asm/time.h> | ||
47 | #include <asm/todc.h> | ||
48 | #include <asm/bootinfo.h> | ||
49 | #include <asm/ppc4xx_pic.h> | ||
50 | #include <asm/ppcboot.h> | ||
51 | |||
52 | #include <syslib/gen550.h> | ||
53 | #include <syslib/ibm440gx_common.h> | ||
54 | |||
55 | /* | ||
56 | * This is a horrible kludge, we eventually need to abstract this | ||
57 | * generic PHY stuff, so the standard phy mode defines can be | ||
58 | * easily used from arch code. | ||
59 | */ | ||
60 | #include "../../../../drivers/net/ibm_emac/ibm_emac_phy.h" | ||
61 | |||
62 | bd_t __res; | ||
63 | |||
64 | static struct ibm44x_clocks clocks __initdata; | ||
65 | |||
66 | static void __init | ||
67 | ocotea_calibrate_decr(void) | ||
68 | { | ||
69 | unsigned int freq; | ||
70 | |||
71 | if (mfspr(SPRN_CCR1) & CCR1_TCS) | ||
72 | freq = OCOTEA_TMR_CLK; | ||
73 | else | ||
74 | freq = clocks.cpu; | ||
75 | |||
76 | ibm44x_calibrate_decr(freq); | ||
77 | } | ||
78 | |||
79 | static int | ||
80 | ocotea_show_cpuinfo(struct seq_file *m) | ||
81 | { | ||
82 | seq_printf(m, "vendor\t\t: IBM\n"); | ||
83 | seq_printf(m, "machine\t\t: PPC440GX EVB (Ocotea)\n"); | ||
84 | ibm440gx_show_cpuinfo(m); | ||
85 | return 0; | ||
86 | } | ||
87 | |||
88 | static inline int | ||
89 | ocotea_map_irq(struct pci_dev *dev, unsigned char idsel, unsigned char pin) | ||
90 | { | ||
91 | static char pci_irq_table[][4] = | ||
92 | /* | ||
93 | * PCI IDSEL/INTPIN->INTLINE | ||
94 | * A B C D | ||
95 | */ | ||
96 | { | ||
97 | { 23, 23, 23, 23 }, /* IDSEL 1 - PCI Slot 0 */ | ||
98 | { 24, 24, 24, 24 }, /* IDSEL 2 - PCI Slot 1 */ | ||
99 | { 25, 25, 25, 25 }, /* IDSEL 3 - PCI Slot 2 */ | ||
100 | { 26, 26, 26, 26 }, /* IDSEL 4 - PCI Slot 3 */ | ||
101 | }; | ||
102 | |||
103 | const long min_idsel = 1, max_idsel = 4, irqs_per_slot = 4; | ||
104 | return PCI_IRQ_TABLE_LOOKUP; | ||
105 | } | ||
106 | |||
107 | static void __init ocotea_set_emacdata(void) | ||
108 | { | ||
109 | struct ocp_def *def; | ||
110 | struct ocp_func_emac_data *emacdata; | ||
111 | int i; | ||
112 | |||
113 | /* | ||
114 | * Note: Current rev. board only operates in Group 4a | ||
115 | * mode, so we always set EMAC0-1 for SMII and EMAC2-3 | ||
116 | * for RGMII (though these could run in RTBI just the same). | ||
117 | * | ||
118 | * The FPGA reg 3 information isn't even suitable for | ||
119 | * determining the phy_mode, so if the board becomes | ||
120 | * usable in !4a, it will be necessary to parse an environment | ||
121 | * variable from the firmware or similar to properly configure | ||
122 | * the phy_map/phy_mode. | ||
123 | */ | ||
124 | /* Set phy_map, phy_mode, and mac_addr for each EMAC */ | ||
125 | for (i=0; i<4; i++) { | ||
126 | def = ocp_get_one_device(OCP_VENDOR_IBM, OCP_FUNC_EMAC, i); | ||
127 | emacdata = def->additions; | ||
128 | if (i < 2) { | ||
129 | emacdata->phy_map = 0x00000001; /* Skip 0x00 */ | ||
130 | emacdata->phy_mode = PHY_MODE_SMII; | ||
131 | } | ||
132 | else { | ||
133 | emacdata->phy_map = 0x0000ffff; /* Skip 0x00-0x0f */ | ||
134 | emacdata->phy_mode = PHY_MODE_RGMII; | ||
135 | } | ||
136 | if (i == 0) | ||
137 | memcpy(emacdata->mac_addr, __res.bi_enetaddr, 6); | ||
138 | else if (i == 1) | ||
139 | memcpy(emacdata->mac_addr, __res.bi_enet1addr, 6); | ||
140 | else if (i == 2) | ||
141 | memcpy(emacdata->mac_addr, __res.bi_enet2addr, 6); | ||
142 | else if (i == 3) | ||
143 | memcpy(emacdata->mac_addr, __res.bi_enet3addr, 6); | ||
144 | } | ||
145 | } | ||
146 | |||
147 | #define PCIX_READW(offset) \ | ||
148 | (readw(pcix_reg_base+offset)) | ||
149 | |||
150 | #define PCIX_WRITEW(value, offset) \ | ||
151 | (writew(value, pcix_reg_base+offset)) | ||
152 | |||
153 | #define PCIX_WRITEL(value, offset) \ | ||
154 | (writel(value, pcix_reg_base+offset)) | ||
155 | |||
156 | /* | ||
157 | * FIXME: This is only here to "make it work". This will move | ||
158 | * to a ibm_pcix.c which will contain a generic IBM PCIX bridge | ||
159 | * configuration library. -Matt | ||
160 | */ | ||
161 | static void __init | ||
162 | ocotea_setup_pcix(void) | ||
163 | { | ||
164 | void *pcix_reg_base; | ||
165 | |||
166 | pcix_reg_base = ioremap64(PCIX0_REG_BASE, PCIX_REG_SIZE); | ||
167 | |||
168 | /* Enable PCIX0 I/O, Mem, and Busmaster cycles */ | ||
169 | PCIX_WRITEW(PCIX_READW(PCIX0_COMMAND) | PCI_COMMAND_IO | PCI_COMMAND_MEMORY | PCI_COMMAND_MASTER, PCIX0_COMMAND); | ||
170 | |||
171 | /* Disable all windows */ | ||
172 | PCIX_WRITEL(0, PCIX0_POM0SA); | ||
173 | PCIX_WRITEL(0, PCIX0_POM1SA); | ||
174 | PCIX_WRITEL(0, PCIX0_POM2SA); | ||
175 | PCIX_WRITEL(0, PCIX0_PIM0SA); | ||
176 | PCIX_WRITEL(0, PCIX0_PIM0SAH); | ||
177 | PCIX_WRITEL(0, PCIX0_PIM1SA); | ||
178 | PCIX_WRITEL(0, PCIX0_PIM2SA); | ||
179 | PCIX_WRITEL(0, PCIX0_PIM2SAH); | ||
180 | |||
181 | /* Setup 2GB PLB->PCI outbound mem window (3_8000_0000->0_8000_0000) */ | ||
182 | PCIX_WRITEL(0x00000003, PCIX0_POM0LAH); | ||
183 | PCIX_WRITEL(0x80000000, PCIX0_POM0LAL); | ||
184 | PCIX_WRITEL(0x00000000, PCIX0_POM0PCIAH); | ||
185 | PCIX_WRITEL(0x80000000, PCIX0_POM0PCIAL); | ||
186 | PCIX_WRITEL(0x80000001, PCIX0_POM0SA); | ||
187 | |||
188 | /* Setup 2GB PCI->PLB inbound memory window at 0, enable MSIs */ | ||
189 | PCIX_WRITEL(0x00000000, PCIX0_PIM0LAH); | ||
190 | PCIX_WRITEL(0x00000000, PCIX0_PIM0LAL); | ||
191 | PCIX_WRITEL(0xe0000007, PCIX0_PIM0SA); | ||
192 | |||
193 | eieio(); | ||
194 | } | ||
195 | |||
196 | static void __init | ||
197 | ocotea_setup_hose(void) | ||
198 | { | ||
199 | struct pci_controller *hose; | ||
200 | |||
201 | /* Configure windows on the PCI-X host bridge */ | ||
202 | ocotea_setup_pcix(); | ||
203 | |||
204 | hose = pcibios_alloc_controller(); | ||
205 | |||
206 | if (!hose) | ||
207 | return; | ||
208 | |||
209 | hose->first_busno = 0; | ||
210 | hose->last_busno = 0xff; | ||
211 | |||
212 | hose->pci_mem_offset = OCOTEA_PCI_MEM_OFFSET; | ||
213 | |||
214 | pci_init_resource(&hose->io_resource, | ||
215 | OCOTEA_PCI_LOWER_IO, | ||
216 | OCOTEA_PCI_UPPER_IO, | ||
217 | IORESOURCE_IO, | ||
218 | "PCI host bridge"); | ||
219 | |||
220 | pci_init_resource(&hose->mem_resources[0], | ||
221 | OCOTEA_PCI_LOWER_MEM, | ||
222 | OCOTEA_PCI_UPPER_MEM, | ||
223 | IORESOURCE_MEM, | ||
224 | "PCI host bridge"); | ||
225 | |||
226 | hose->io_space.start = OCOTEA_PCI_LOWER_IO; | ||
227 | hose->io_space.end = OCOTEA_PCI_UPPER_IO; | ||
228 | hose->mem_space.start = OCOTEA_PCI_LOWER_MEM; | ||
229 | hose->mem_space.end = OCOTEA_PCI_UPPER_MEM; | ||
230 | isa_io_base = | ||
231 | (unsigned long)ioremap64(OCOTEA_PCI_IO_BASE, OCOTEA_PCI_IO_SIZE); | ||
232 | hose->io_base_virt = (void *)isa_io_base; | ||
233 | |||
234 | setup_indirect_pci(hose, | ||
235 | OCOTEA_PCI_CFGA_PLB32, | ||
236 | OCOTEA_PCI_CFGD_PLB32); | ||
237 | hose->set_cfg_type = 1; | ||
238 | |||
239 | hose->last_busno = pciauto_bus_scan(hose, hose->first_busno); | ||
240 | |||
241 | ppc_md.pci_swizzle = common_swizzle; | ||
242 | ppc_md.pci_map_irq = ocotea_map_irq; | ||
243 | } | ||
244 | |||
245 | |||
246 | TODC_ALLOC(); | ||
247 | |||
248 | static void __init | ||
249 | ocotea_early_serial_map(void) | ||
250 | { | ||
251 | struct uart_port port; | ||
252 | |||
253 | /* Setup ioremapped serial port access */ | ||
254 | memset(&port, 0, sizeof(port)); | ||
255 | port.membase = ioremap64(PPC440GX_UART0_ADDR, 8); | ||
256 | port.irq = UART0_INT; | ||
257 | port.uartclk = clocks.uart0; | ||
258 | port.regshift = 0; | ||
259 | port.iotype = SERIAL_IO_MEM; | ||
260 | port.flags = ASYNC_BOOT_AUTOCONF | ASYNC_SKIP_TEST; | ||
261 | port.line = 0; | ||
262 | |||
263 | if (early_serial_setup(&port) != 0) { | ||
264 | printk("Early serial init of port 0 failed\n"); | ||
265 | } | ||
266 | |||
267 | #if defined(CONFIG_SERIAL_TEXT_DEBUG) || defined(CONFIG_KGDB) | ||
268 | /* Configure debug serial access */ | ||
269 | gen550_init(0, &port); | ||
270 | #endif | ||
271 | |||
272 | port.membase = ioremap64(PPC440GX_UART1_ADDR, 8); | ||
273 | port.irq = UART1_INT; | ||
274 | port.uartclk = clocks.uart1; | ||
275 | port.line = 1; | ||
276 | |||
277 | if (early_serial_setup(&port) != 0) { | ||
278 | printk("Early serial init of port 1 failed\n"); | ||
279 | } | ||
280 | |||
281 | #if defined(CONFIG_SERIAL_TEXT_DEBUG) || defined(CONFIG_KGDB) | ||
282 | /* Configure debug serial access */ | ||
283 | gen550_init(1, &port); | ||
284 | #endif | ||
285 | } | ||
286 | |||
287 | static void __init | ||
288 | ocotea_setup_arch(void) | ||
289 | { | ||
290 | ocotea_set_emacdata(); | ||
291 | |||
292 | ibm440gx_tah_enable(); | ||
293 | |||
294 | /* Setup TODC access */ | ||
295 | TODC_INIT(TODC_TYPE_DS1743, | ||
296 | 0, | ||
297 | 0, | ||
298 | ioremap64(OCOTEA_RTC_ADDR, OCOTEA_RTC_SIZE), | ||
299 | 8); | ||
300 | |||
301 | /* init to some ~sane value until calibrate_delay() runs */ | ||
302 | loops_per_jiffy = 50000000/HZ; | ||
303 | |||
304 | /* Setup PCI host bridge */ | ||
305 | ocotea_setup_hose(); | ||
306 | |||
307 | #ifdef CONFIG_BLK_DEV_INITRD | ||
308 | if (initrd_start) | ||
309 | ROOT_DEV = Root_RAM0; | ||
310 | else | ||
311 | #endif | ||
312 | #ifdef CONFIG_ROOT_NFS | ||
313 | ROOT_DEV = Root_NFS; | ||
314 | #else | ||
315 | ROOT_DEV = Root_HDA1; | ||
316 | #endif | ||
317 | |||
318 | ocotea_early_serial_map(); | ||
319 | |||
320 | /* Identify the system */ | ||
321 | printk("IBM Ocotea port (MontaVista Software, Inc. <source@mvista.com>)\n"); | ||
322 | } | ||
323 | |||
324 | static void __init ocotea_init(void) | ||
325 | { | ||
326 | ibm440gx_l2c_setup(&clocks); | ||
327 | } | ||
328 | |||
329 | void __init platform_init(unsigned long r3, unsigned long r4, | ||
330 | unsigned long r5, unsigned long r6, unsigned long r7) | ||
331 | { | ||
332 | parse_bootinfo(find_bootinfo()); | ||
333 | |||
334 | /* | ||
335 | * If we were passed in a board information, copy it into the | ||
336 | * residual data area. | ||
337 | */ | ||
338 | if (r3) | ||
339 | __res = *(bd_t *)(r3 + KERNELBASE); | ||
340 | |||
341 | /* | ||
342 | * Determine various clocks. | ||
343 | * To be completely correct we should get SysClk | ||
344 | * from FPGA, because it can be changed by on-board switches | ||
345 | * --ebs | ||
346 | */ | ||
347 | ibm440gx_get_clocks(&clocks, 33333333, 6 * 1843200); | ||
348 | ocp_sys_info.opb_bus_freq = clocks.opb; | ||
349 | |||
350 | ibm44x_platform_init(); | ||
351 | |||
352 | ppc_md.setup_arch = ocotea_setup_arch; | ||
353 | ppc_md.show_cpuinfo = ocotea_show_cpuinfo; | ||
354 | ppc_md.get_irq = NULL; /* Set in ppc4xx_pic_init() */ | ||
355 | |||
356 | ppc_md.calibrate_decr = ocotea_calibrate_decr; | ||
357 | ppc_md.time_init = todc_time_init; | ||
358 | ppc_md.set_rtc_time = todc_set_rtc_time; | ||
359 | ppc_md.get_rtc_time = todc_get_rtc_time; | ||
360 | |||
361 | ppc_md.nvram_read_val = todc_direct_read_val; | ||
362 | ppc_md.nvram_write_val = todc_direct_write_val; | ||
363 | #ifdef CONFIG_KGDB | ||
364 | ppc_md.early_serial_map = ocotea_early_serial_map; | ||
365 | #endif | ||
366 | ppc_md.init = ocotea_init; | ||
367 | } | ||
diff --git a/arch/ppc/platforms/4xx/ocotea.h b/arch/ppc/platforms/4xx/ocotea.h new file mode 100644 index 000000000000..202dc8251190 --- /dev/null +++ b/arch/ppc/platforms/4xx/ocotea.h | |||
@@ -0,0 +1,88 @@ | |||
1 | /* | ||
2 | * arch/ppc/platforms/ocotea.h | ||
3 | * | ||
4 | * Ocotea board definitions | ||
5 | * | ||
6 | * Matt Porter <mporter@kernel.crashing.org> | ||
7 | * | ||
8 | * Copyright 2003-2005 MontaVista Software Inc. | ||
9 | * | ||
10 | * This program is free software; you can redistribute it and/or modify it | ||
11 | * under the terms of the GNU General Public License as published by the | ||
12 | * Free Software Foundation; either version 2 of the License, or (at your | ||
13 | * option) any later version. | ||
14 | * | ||
15 | */ | ||
16 | |||
17 | #ifdef __KERNEL__ | ||
18 | #ifndef __ASM_OCOTEA_H__ | ||
19 | #define __ASM_OCOTEA_H__ | ||
20 | |||
21 | #include <linux/config.h> | ||
22 | #include <platforms/4xx/ibm440gx.h> | ||
23 | |||
24 | /* F/W TLB mapping used in bootloader glue to reset EMAC */ | ||
25 | #define PPC44x_EMAC0_MR0 0xe0000800 | ||
26 | |||
27 | /* Location of MAC addresses in PIBS image */ | ||
28 | #define PIBS_FLASH_BASE 0xfff00000 | ||
29 | #define PIBS_MAC_BASE (PIBS_FLASH_BASE+0xb0500) | ||
30 | #define PIBS_MAC_SIZE 0x200 | ||
31 | #define PIBS_MAC_OFFSET 0x100 | ||
32 | |||
33 | /* External timer clock frequency */ | ||
34 | #define OCOTEA_TMR_CLK 25000000 | ||
35 | |||
36 | /* RTC/NVRAM location */ | ||
37 | #define OCOTEA_RTC_ADDR 0x0000000148000000ULL | ||
38 | #define OCOTEA_RTC_SIZE 0x2000 | ||
39 | |||
40 | /* Flash */ | ||
41 | #define OCOTEA_FPGA_REG_0 0x0000000148300000ULL | ||
42 | #define OCOTEA_BOOT_LARGE_FLASH(x) (x & 0x40) | ||
43 | #define OCOTEA_SMALL_FLASH_LOW 0x00000001ff900000ULL | ||
44 | #define OCOTEA_SMALL_FLASH_HIGH 0x00000001fff00000ULL | ||
45 | #define OCOTEA_SMALL_FLASH_SIZE 0x100000 | ||
46 | #define OCOTEA_LARGE_FLASH_LOW 0x00000001ff800000ULL | ||
47 | #define OCOTEA_LARGE_FLASH_HIGH 0x00000001ffc00000ULL | ||
48 | #define OCOTEA_LARGE_FLASH_SIZE 0x400000 | ||
49 | |||
50 | /* FPGA_REG_3 (Ethernet Groups) */ | ||
51 | #define OCOTEA_FPGA_REG_3 0x0000000148300003ULL | ||
52 | |||
53 | /* | ||
54 | * Serial port defines | ||
55 | */ | ||
56 | #define RS_TABLE_SIZE 2 | ||
57 | |||
58 | /* OpenBIOS defined UART mappings, used before early_serial_setup */ | ||
59 | #define UART0_IO_BASE 0xE0000200 | ||
60 | #define UART1_IO_BASE 0xE0000300 | ||
61 | |||
62 | #define BASE_BAUD 11059200/16 | ||
63 | #define STD_UART_OP(num) \ | ||
64 | { 0, BASE_BAUD, 0, UART##num##_INT, \ | ||
65 | (ASYNC_BOOT_AUTOCONF | ASYNC_SKIP_TEST), \ | ||
66 | iomem_base: UART##num##_IO_BASE, \ | ||
67 | io_type: SERIAL_IO_MEM}, | ||
68 | |||
69 | #define SERIAL_PORT_DFNS \ | ||
70 | STD_UART_OP(0) \ | ||
71 | STD_UART_OP(1) | ||
72 | |||
73 | /* PCI support */ | ||
74 | #define OCOTEA_PCI_LOWER_IO 0x00000000 | ||
75 | #define OCOTEA_PCI_UPPER_IO 0x0000ffff | ||
76 | #define OCOTEA_PCI_LOWER_MEM 0x80000000 | ||
77 | #define OCOTEA_PCI_UPPER_MEM 0xffffefff | ||
78 | |||
79 | #define OCOTEA_PCI_CFGREGS_BASE 0x000000020ec00000ULL | ||
80 | #define OCOTEA_PCI_CFGA_PLB32 0x0ec00000 | ||
81 | #define OCOTEA_PCI_CFGD_PLB32 0x0ec00004 | ||
82 | |||
83 | #define OCOTEA_PCI_IO_BASE 0x0000000208000000ULL | ||
84 | #define OCOTEA_PCI_IO_SIZE 0x00010000 | ||
85 | #define OCOTEA_PCI_MEM_OFFSET 0x00000000 | ||
86 | |||
87 | #endif /* __ASM_OCOTEA_H__ */ | ||
88 | #endif /* __KERNEL__ */ | ||
diff --git a/arch/ppc/platforms/4xx/redwood5.c b/arch/ppc/platforms/4xx/redwood5.c new file mode 100644 index 000000000000..2f5e410afbc5 --- /dev/null +++ b/arch/ppc/platforms/4xx/redwood5.c | |||
@@ -0,0 +1,110 @@ | |||
1 | /* | ||
2 | * arch/ppc/platforms/4xx/redwood5.c | ||
3 | * | ||
4 | * Support for the IBM redwood5 eval board file | ||
5 | * | ||
6 | * Author: Armin Kuster <akuster@mvista.com> | ||
7 | * | ||
8 | * 2000-2001 (c) MontaVista, Software, Inc. This file is licensed under | ||
9 | * the terms of the GNU General Public License version 2. This program | ||
10 | * is licensed "as is" without any warranty of any kind, whether express | ||
11 | * or implied. | ||
12 | */ | ||
13 | |||
14 | #include <linux/config.h> | ||
15 | #include <linux/init.h> | ||
16 | #include <linux/pagemap.h> | ||
17 | #include <linux/device.h> | ||
18 | #include <linux/ioport.h> | ||
19 | #include <asm/io.h> | ||
20 | #include <asm/machdep.h> | ||
21 | |||
22 | static struct resource smc91x_resources[] = { | ||
23 | [0] = { | ||
24 | .start = SMC91111_BASE_ADDR, | ||
25 | .end = SMC91111_BASE_ADDR + SMC91111_REG_SIZE - 1, | ||
26 | .flags = IORESOURCE_MEM, | ||
27 | }, | ||
28 | [1] = { | ||
29 | .start = SMC91111_IRQ, | ||
30 | .end = SMC91111_IRQ, | ||
31 | .flags = IORESOURCE_IRQ, | ||
32 | }, | ||
33 | }; | ||
34 | |||
35 | static struct platform_device smc91x_device = { | ||
36 | .name = "smc91x", | ||
37 | .id = 0, | ||
38 | .num_resources = ARRAY_SIZE(smc91x_resources), | ||
39 | .resource = smc91x_resources, | ||
40 | }; | ||
41 | |||
42 | static struct platform_device *redwood5_devs[] __initdata = { | ||
43 | &smc91x_device, | ||
44 | }; | ||
45 | |||
46 | static int __init | ||
47 | redwood5_platform_add_devices(void) | ||
48 | { | ||
49 | return platform_add_devices(redwood5_devs, ARRAY_SIZE(redwood5_devs)); | ||
50 | } | ||
51 | |||
52 | void __init | ||
53 | redwood5_setup_arch(void) | ||
54 | { | ||
55 | ppc4xx_setup_arch(); | ||
56 | |||
57 | #ifdef CONFIG_DEBUG_BRINGUP | ||
58 | printk("\n"); | ||
59 | printk("machine\t: %s\n", PPC4xx_MACHINE_NAME); | ||
60 | printk("\n"); | ||
61 | printk("bi_s_version\t %s\n", bip->bi_s_version); | ||
62 | printk("bi_r_version\t %s\n", bip->bi_r_version); | ||
63 | printk("bi_memsize\t 0x%8.8x\t %dMBytes\n", bip->bi_memsize,bip->bi_memsize/(1024*1000)); | ||
64 | printk("bi_enetaddr %d\t %2.2x%2.2x%2.2x-%2.2x%2.2x%2.2x\n", 0, | ||
65 | bip->bi_enetaddr[0], bip->bi_enetaddr[1], | ||
66 | bip->bi_enetaddr[2], bip->bi_enetaddr[3], | ||
67 | bip->bi_enetaddr[4], bip->bi_enetaddr[5]); | ||
68 | |||
69 | printk("bi_intfreq\t 0x%8.8x\t clock:\t %dMhz\n", | ||
70 | bip->bi_intfreq, bip->bi_intfreq/ 1000000); | ||
71 | |||
72 | printk("bi_busfreq\t 0x%8.8x\t plb bus clock:\t %dMHz\n", | ||
73 | bip->bi_busfreq, bip->bi_busfreq / 1000000 ); | ||
74 | printk("bi_tbfreq\t 0x%8.8x\t TB freq:\t %dMHz\n", | ||
75 | bip->bi_tbfreq, bip->bi_tbfreq/1000000); | ||
76 | |||
77 | printk("\n"); | ||
78 | #endif | ||
79 | device_initcall(redwood5_platform_add_devices); | ||
80 | } | ||
81 | |||
82 | void __init | ||
83 | redwood5_map_io(void) | ||
84 | { | ||
85 | int i; | ||
86 | |||
87 | ppc4xx_map_io(); | ||
88 | for (i = 0; i < 16; i++) { | ||
89 | unsigned long v, p; | ||
90 | |||
91 | /* 0x400x0000 -> 0xe00x0000 */ | ||
92 | p = 0x40000000 | (i << 16); | ||
93 | v = STB04xxx_IO_BASE | (i << 16); | ||
94 | |||
95 | io_block_mapping(v, p, PAGE_SIZE, | ||
96 | _PAGE_NO_CACHE | pgprot_val(PAGE_KERNEL) | _PAGE_GUARDED); | ||
97 | } | ||
98 | |||
99 | |||
100 | } | ||
101 | |||
102 | void __init | ||
103 | platform_init(unsigned long r3, unsigned long r4, unsigned long r5, | ||
104 | unsigned long r6, unsigned long r7) | ||
105 | { | ||
106 | ppc4xx_init(r3, r4, r5, r6, r7); | ||
107 | |||
108 | ppc_md.setup_arch = redwood5_setup_arch; | ||
109 | ppc_md.setup_io_mappings = redwood5_map_io; | ||
110 | } | ||
diff --git a/arch/ppc/platforms/4xx/redwood5.h b/arch/ppc/platforms/4xx/redwood5.h new file mode 100644 index 000000000000..264e34fb3fbd --- /dev/null +++ b/arch/ppc/platforms/4xx/redwood5.h | |||
@@ -0,0 +1,54 @@ | |||
1 | /* | ||
2 | * arch/ppc/platforms/4xx/redwood5.h | ||
3 | * | ||
4 | * Macros, definitions, and data structures specific to the IBM PowerPC | ||
5 | * STB03xxx "Redwood" evaluation board. | ||
6 | * | ||
7 | * Author: Armin Kuster <akuster@mvista.com> | ||
8 | * | ||
9 | * 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 | #ifdef __KERNEL__ | ||
16 | #ifndef __ASM_REDWOOD5_H__ | ||
17 | #define __ASM_REDWOOD5_H__ | ||
18 | |||
19 | /* Redwood5 has an STB04xxx core */ | ||
20 | #include <platforms/4xx/ibmstb4.h> | ||
21 | |||
22 | #ifndef __ASSEMBLY__ | ||
23 | typedef struct board_info { | ||
24 | unsigned char bi_s_version[4]; /* Version of this structure */ | ||
25 | unsigned char bi_r_version[30]; /* Version of the IBM ROM */ | ||
26 | unsigned int bi_memsize; /* DRAM installed, in bytes */ | ||
27 | unsigned int bi_dummy; /* field shouldn't exist */ | ||
28 | unsigned char bi_enetaddr[6]; /* Ethernet MAC address */ | ||
29 | unsigned int bi_intfreq; /* Processor speed, in Hz */ | ||
30 | unsigned int bi_busfreq; /* Bus speed, in Hz */ | ||
31 | unsigned int bi_tbfreq; /* Software timebase freq */ | ||
32 | } bd_t; | ||
33 | #endif /* !__ASSEMBLY__ */ | ||
34 | |||
35 | |||
36 | #define SMC91111_BASE_ADDR 0xf2000300 | ||
37 | #define SMC91111_REG_SIZE 16 | ||
38 | #define SMC91111_IRQ 28 | ||
39 | |||
40 | #ifdef MAX_HWIFS | ||
41 | #undef MAX_HWIFS | ||
42 | #endif | ||
43 | #define MAX_HWIFS 1 | ||
44 | |||
45 | #define _IO_BASE 0 | ||
46 | #define _ISA_MEM_BASE 0 | ||
47 | #define PCI_DRAM_OFFSET 0 | ||
48 | |||
49 | #define BASE_BAUD (378000000 / 18 / 16) | ||
50 | |||
51 | #define PPC4xx_MACHINE_NAME "IBM Redwood5" | ||
52 | |||
53 | #endif /* __ASM_REDWOOD5_H__ */ | ||
54 | #endif /* __KERNEL__ */ | ||
diff --git a/arch/ppc/platforms/4xx/redwood6.c b/arch/ppc/platforms/4xx/redwood6.c new file mode 100644 index 000000000000..8b1012994dfc --- /dev/null +++ b/arch/ppc/platforms/4xx/redwood6.c | |||
@@ -0,0 +1,159 @@ | |||
1 | /* | ||
2 | * arch/ppc/platforms/4xx/redwood6.c | ||
3 | * | ||
4 | * Author: Armin Kuster <akuster@mvista.com> | ||
5 | * | ||
6 | * 2002 (c) MontaVista, Software, Inc. This file is licensed under | ||
7 | * the terms of the GNU General Public License version 2. This program | ||
8 | * is licensed "as is" without any warranty of any kind, whether express | ||
9 | * or implied. | ||
10 | */ | ||
11 | |||
12 | #include <linux/config.h> | ||
13 | #include <linux/init.h> | ||
14 | #include <linux/pagemap.h> | ||
15 | #include <linux/device.h> | ||
16 | #include <linux/ioport.h> | ||
17 | #include <asm/io.h> | ||
18 | #include <asm/ppc4xx_pic.h> | ||
19 | #include <linux/delay.h> | ||
20 | #include <asm/machdep.h> | ||
21 | |||
22 | /* | ||
23 | * Define external IRQ senses and polarities. | ||
24 | */ | ||
25 | unsigned char ppc4xx_uic_ext_irq_cfg[] __initdata = { | ||
26 | (IRQ_SENSE_LEVEL | IRQ_POLARITY_NEGATIVE), /* Ext Int 7 */ | ||
27 | (IRQ_SENSE_LEVEL | IRQ_POLARITY_NEGATIVE), /* Ext Int 8 */ | ||
28 | (IRQ_SENSE_LEVEL | IRQ_POLARITY_NEGATIVE), /* Ext Int 9 */ | ||
29 | (IRQ_SENSE_LEVEL | IRQ_POLARITY_NEGATIVE), /* Ext Int 0 */ | ||
30 | (IRQ_SENSE_LEVEL | IRQ_POLARITY_NEGATIVE), /* Ext Int 1 */ | ||
31 | (IRQ_SENSE_LEVEL | IRQ_POLARITY_NEGATIVE), /* Ext Int 2 */ | ||
32 | (IRQ_SENSE_LEVEL | IRQ_POLARITY_NEGATIVE), /* Ext Int 3 */ | ||
33 | (IRQ_SENSE_LEVEL | IRQ_POLARITY_NEGATIVE), /* Ext Int 4 */ | ||
34 | (IRQ_SENSE_LEVEL | IRQ_POLARITY_NEGATIVE), /* Ext Int 5 */ | ||
35 | (IRQ_SENSE_LEVEL | IRQ_POLARITY_NEGATIVE), /* Ext Int 6 */ | ||
36 | }; | ||
37 | |||
38 | static struct resource smc91x_resources[] = { | ||
39 | [0] = { | ||
40 | .start = SMC91111_BASE_ADDR, | ||
41 | .end = SMC91111_BASE_ADDR + SMC91111_REG_SIZE - 1, | ||
42 | .flags = IORESOURCE_MEM, | ||
43 | }, | ||
44 | [1] = { | ||
45 | .start = SMC91111_IRQ, | ||
46 | .end = SMC91111_IRQ, | ||
47 | .flags = IORESOURCE_IRQ, | ||
48 | }, | ||
49 | }; | ||
50 | |||
51 | static struct platform_device smc91x_device = { | ||
52 | .name = "smc91x", | ||
53 | .id = 0, | ||
54 | .num_resources = ARRAY_SIZE(smc91x_resources), | ||
55 | .resource = smc91x_resources, | ||
56 | }; | ||
57 | |||
58 | static struct platform_device *redwood6_devs[] __initdata = { | ||
59 | &smc91x_device, | ||
60 | }; | ||
61 | |||
62 | static int __init | ||
63 | redwood6_platform_add_devices(void) | ||
64 | { | ||
65 | return platform_add_devices(redwood6_devs, ARRAY_SIZE(redwood6_devs)); | ||
66 | } | ||
67 | |||
68 | |||
69 | void __init | ||
70 | redwood6_setup_arch(void) | ||
71 | { | ||
72 | #ifdef CONFIG_IDE | ||
73 | void *xilinx, *xilinx_1, *xilinx_2; | ||
74 | unsigned short us_reg5; | ||
75 | #endif | ||
76 | |||
77 | ppc4xx_setup_arch(); | ||
78 | |||
79 | #ifdef CONFIG_IDE | ||
80 | xilinx = (unsigned long) ioremap(IDE_XLINUX_MUX_BASE, 0x10); | ||
81 | /* init xilinx control registers - enable ide mux, clear reset bit */ | ||
82 | if (!xilinx) { | ||
83 | printk(KERN_CRIT | ||
84 | "redwood6_setup_arch() xilinxi ioremap failed\n"); | ||
85 | return; | ||
86 | } | ||
87 | xilinx_1 = xilinx + 0xa; | ||
88 | xilinx_2 = xilinx + 0xe; | ||
89 | |||
90 | us_reg5 = readb(xilinx_1); | ||
91 | writeb(0x01d1, xilinx_1); | ||
92 | writeb(0x0008, xilinx_2); | ||
93 | |||
94 | udelay(10 * 1000); | ||
95 | |||
96 | writeb(0x01d1, xilinx_1); | ||
97 | writeb(0x0008, xilinx_2); | ||
98 | #endif | ||
99 | |||
100 | #ifdef DEBUG_BRINGUP | ||
101 | bd_t *bip = (bd_t *) __res; | ||
102 | printk("\n"); | ||
103 | printk("machine\t: %s\n", PPC4xx_MACHINE_NAME); | ||
104 | printk("\n"); | ||
105 | printk("bi_s_version\t %s\n", bip->bi_s_version); | ||
106 | printk("bi_r_version\t %s\n", bip->bi_r_version); | ||
107 | printk("bi_memsize\t 0x%8.8x\t %dMBytes\n", bip->bi_memsize, | ||
108 | bip->bi_memsize / (1024 * 1000)); | ||
109 | printk("bi_enetaddr %d\t %2.2x%2.2x%2.2x-%2.2x%2.2x%2.2x\n", 0, | ||
110 | bip->bi_enetaddr[0], bip->bi_enetaddr[1], bip->bi_enetaddr[2], | ||
111 | bip->bi_enetaddr[3], bip->bi_enetaddr[4], bip->bi_enetaddr[5]); | ||
112 | |||
113 | printk("bi_intfreq\t 0x%8.8x\t clock:\t %dMhz\n", | ||
114 | bip->bi_intfreq, bip->bi_intfreq / 1000000); | ||
115 | |||
116 | printk("bi_busfreq\t 0x%8.8x\t plb bus clock:\t %dMHz\n", | ||
117 | bip->bi_busfreq, bip->bi_busfreq / 1000000); | ||
118 | printk("bi_tbfreq\t 0x%8.8x\t TB freq:\t %dMHz\n", | ||
119 | bip->bi_tbfreq, bip->bi_tbfreq / 1000000); | ||
120 | |||
121 | printk("\n"); | ||
122 | #endif | ||
123 | |||
124 | /* Identify the system */ | ||
125 | printk(KERN_INFO "IBM Redwood6 (STBx25XX) Platform\n"); | ||
126 | printk(KERN_INFO | ||
127 | "Port by MontaVista Software, Inc. (source@mvista.com)\n"); | ||
128 | |||
129 | device_initcall(redwood6_platform_add_devices); | ||
130 | } | ||
131 | |||
132 | void __init | ||
133 | redwood6_map_io(void) | ||
134 | { | ||
135 | int i; | ||
136 | |||
137 | ppc4xx_map_io(); | ||
138 | for (i = 0; i < 16; i++) { | ||
139 | unsigned long v, p; | ||
140 | |||
141 | /* 0x400x0000 -> 0xe00x0000 */ | ||
142 | p = 0x40000000 | (i << 16); | ||
143 | v = STBx25xx_IO_BASE | (i << 16); | ||
144 | |||
145 | io_block_mapping(v, p, PAGE_SIZE, | ||
146 | _PAGE_NO_CACHE | pgprot_val(PAGE_KERNEL) | | ||
147 | _PAGE_GUARDED); | ||
148 | } | ||
149 | } | ||
150 | |||
151 | void __init | ||
152 | platform_init(unsigned long r3, unsigned long r4, unsigned long r5, | ||
153 | unsigned long r6, unsigned long r7) | ||
154 | { | ||
155 | ppc4xx_init(r3, r4, r5, r6, r7); | ||
156 | |||
157 | ppc_md.setup_arch = redwood6_setup_arch; | ||
158 | ppc_md.setup_io_mappings = redwood6_map_io; | ||
159 | } | ||
diff --git a/arch/ppc/platforms/4xx/redwood6.h b/arch/ppc/platforms/4xx/redwood6.h new file mode 100644 index 000000000000..1814b9f5fc3a --- /dev/null +++ b/arch/ppc/platforms/4xx/redwood6.h | |||
@@ -0,0 +1,55 @@ | |||
1 | /* | ||
2 | * arch/ppc/platforms/4xx/redwood6.h | ||
3 | * | ||
4 | * Macros, definitions, and data structures specific to the IBM PowerPC | ||
5 | * STBx25xx "Redwood6" evaluation board. | ||
6 | * | ||
7 | * Author: Armin Kuster <akuster@mvista.com> | ||
8 | * | ||
9 | * 2002 (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 | #ifdef __KERNEL__ | ||
16 | #ifndef __ASM_REDWOOD5_H__ | ||
17 | #define __ASM_REDWOOD5_H__ | ||
18 | |||
19 | /* Redwood6 has an STBx25xx core */ | ||
20 | #include <platforms/4xx/ibmstbx25.h> | ||
21 | |||
22 | #ifndef __ASSEMBLY__ | ||
23 | typedef struct board_info { | ||
24 | unsigned char bi_s_version[4]; /* Version of this structure */ | ||
25 | unsigned char bi_r_version[30]; /* Version of the IBM ROM */ | ||
26 | unsigned int bi_memsize; /* DRAM installed, in bytes */ | ||
27 | unsigned int bi_dummy; /* field shouldn't exist */ | ||
28 | unsigned char bi_enetaddr[6]; /* Ethernet MAC address */ | ||
29 | unsigned int bi_intfreq; /* Processor speed, in Hz */ | ||
30 | unsigned int bi_busfreq; /* Bus speed, in Hz */ | ||
31 | unsigned int bi_tbfreq; /* Software timebase freq */ | ||
32 | } bd_t; | ||
33 | #endif /* !__ASSEMBLY__ */ | ||
34 | |||
35 | #define SMC91111_BASE_ADDR 0xf2030300 | ||
36 | #define SMC91111_REG_SIZE 16 | ||
37 | #define SMC91111_IRQ 27 | ||
38 | #define IDE_XLINUX_MUX_BASE 0xf2040000 | ||
39 | #define IDE_DMA_ADDR 0xfce00000 | ||
40 | |||
41 | #ifdef MAX_HWIFS | ||
42 | #undef MAX_HWIFS | ||
43 | #endif | ||
44 | #define MAX_HWIFS 1 | ||
45 | |||
46 | #define _IO_BASE 0 | ||
47 | #define _ISA_MEM_BASE 0 | ||
48 | #define PCI_DRAM_OFFSET 0 | ||
49 | |||
50 | #define BASE_BAUD (378000000 / 18 / 16) | ||
51 | |||
52 | #define PPC4xx_MACHINE_NAME "IBM Redwood6" | ||
53 | |||
54 | #endif /* __ASM_REDWOOD5_H__ */ | ||
55 | #endif /* __KERNEL__ */ | ||
diff --git a/arch/ppc/platforms/4xx/sycamore.c b/arch/ppc/platforms/4xx/sycamore.c new file mode 100644 index 000000000000..d8019eec4704 --- /dev/null +++ b/arch/ppc/platforms/4xx/sycamore.c | |||
@@ -0,0 +1,278 @@ | |||
1 | /* | ||
2 | * arch/ppc/platforms/4xx/sycamore.c | ||
3 | * | ||
4 | * Architecture- / platform-specific boot-time initialization code for | ||
5 | * IBM PowerPC 4xx based boards. | ||
6 | * | ||
7 | * Author: Armin Kuster <akuster@mvista.com> | ||
8 | * | ||
9 | * 2000-2002 (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 | #include <linux/config.h> | ||
15 | #include <linux/init.h> | ||
16 | #include <linux/smp.h> | ||
17 | #include <linux/threads.h> | ||
18 | #include <linux/param.h> | ||
19 | #include <linux/string.h> | ||
20 | #include <linux/pci.h> | ||
21 | #include <linux/rtc.h> | ||
22 | |||
23 | #include <asm/ocp.h> | ||
24 | #include <asm/ppc4xx_pic.h> | ||
25 | #include <asm/system.h> | ||
26 | #include <asm/pci-bridge.h> | ||
27 | #include <asm/machdep.h> | ||
28 | #include <asm/page.h> | ||
29 | #include <asm/time.h> | ||
30 | #include <asm/io.h> | ||
31 | #include <asm/ibm_ocp_pci.h> | ||
32 | #include <asm/todc.h> | ||
33 | |||
34 | #undef DEBUG | ||
35 | |||
36 | #ifdef DEBUG | ||
37 | #define DBG(x...) printk(x) | ||
38 | #else | ||
39 | #define DBG(x...) | ||
40 | #endif | ||
41 | |||
42 | void *kb_cs; | ||
43 | void *kb_data; | ||
44 | void *sycamore_rtc_base; | ||
45 | |||
46 | /* | ||
47 | * Define external IRQ senses and polarities. | ||
48 | */ | ||
49 | unsigned char ppc4xx_uic_ext_irq_cfg[] __initdata = { | ||
50 | (IRQ_SENSE_LEVEL | IRQ_POLARITY_NEGATIVE), /* Ext Int 7 */ | ||
51 | (IRQ_SENSE_LEVEL | IRQ_POLARITY_NEGATIVE), /* Ext Int 8 */ | ||
52 | (IRQ_SENSE_LEVEL | IRQ_POLARITY_NEGATIVE), /* Ext Int 9 */ | ||
53 | (IRQ_SENSE_LEVEL | IRQ_POLARITY_NEGATIVE), /* Ext Int 10 */ | ||
54 | (IRQ_SENSE_LEVEL | IRQ_POLARITY_NEGATIVE), /* Ext Int 11 */ | ||
55 | (IRQ_SENSE_LEVEL | IRQ_POLARITY_NEGATIVE), /* Ext Int 12 */ | ||
56 | (IRQ_SENSE_LEVEL | IRQ_POLARITY_NEGATIVE), /* Ext Int 0 */ | ||
57 | (IRQ_SENSE_LEVEL | IRQ_POLARITY_NEGATIVE), /* Ext Int 1 */ | ||
58 | (IRQ_SENSE_LEVEL | IRQ_POLARITY_NEGATIVE), /* Ext Int 2 */ | ||
59 | (IRQ_SENSE_LEVEL | IRQ_POLARITY_NEGATIVE), /* Ext Int 3 */ | ||
60 | (IRQ_SENSE_LEVEL | IRQ_POLARITY_NEGATIVE), /* Ext Int 4 */ | ||
61 | (IRQ_SENSE_LEVEL | IRQ_POLARITY_NEGATIVE), /* Ext Int 5 */ | ||
62 | (IRQ_SENSE_LEVEL | IRQ_POLARITY_NEGATIVE), /* Ext Int 6 */ | ||
63 | }; | ||
64 | |||
65 | |||
66 | /* Some IRQs unique to Sycamore. | ||
67 | * Used by the generic 405 PCI setup functions in ppc4xx_pci.c | ||
68 | */ | ||
69 | int __init | ||
70 | ppc405_map_irq(struct pci_dev *dev, unsigned char idsel, unsigned char pin) | ||
71 | { | ||
72 | static char pci_irq_table[][4] = | ||
73 | /* | ||
74 | * PCI IDSEL/INTPIN->INTLINE | ||
75 | * A B C D | ||
76 | */ | ||
77 | { | ||
78 | {28, 28, 28, 28}, /* IDSEL 1 - PCI slot 1 */ | ||
79 | {29, 29, 29, 29}, /* IDSEL 2 - PCI slot 2 */ | ||
80 | {30, 30, 30, 30}, /* IDSEL 3 - PCI slot 3 */ | ||
81 | {31, 31, 31, 31}, /* IDSEL 4 - PCI slot 4 */ | ||
82 | }; | ||
83 | |||
84 | const long min_idsel = 1, max_idsel = 4, irqs_per_slot = 4; | ||
85 | return PCI_IRQ_TABLE_LOOKUP; | ||
86 | }; | ||
87 | |||
88 | void __init | ||
89 | sycamore_setup_arch(void) | ||
90 | { | ||
91 | #define SYCAMORE_PS2_BASE 0xF0100000 | ||
92 | #define SYCAMORE_FPGA_BASE 0xF0300000 | ||
93 | |||
94 | void *fpga_brdc; | ||
95 | unsigned char fpga_brdc_data; | ||
96 | void *fpga_enable; | ||
97 | void *fpga_polarity; | ||
98 | void *fpga_status; | ||
99 | void *fpga_trigger; | ||
100 | |||
101 | ppc4xx_setup_arch(); | ||
102 | |||
103 | ibm_ocp_set_emac(0, 1); | ||
104 | |||
105 | kb_data = ioremap(SYCAMORE_PS2_BASE, 8); | ||
106 | if (!kb_data) { | ||
107 | printk(KERN_CRIT | ||
108 | "sycamore_setup_arch() kb_data ioremap failed\n"); | ||
109 | return; | ||
110 | } | ||
111 | |||
112 | kb_cs = kb_data + 1; | ||
113 | |||
114 | fpga_status = ioremap(SYCAMORE_FPGA_BASE, 8); | ||
115 | if (!fpga_status) { | ||
116 | printk(KERN_CRIT | ||
117 | "sycamore_setup_arch() fpga_status ioremap failed\n"); | ||
118 | return; | ||
119 | } | ||
120 | |||
121 | fpga_enable = fpga_status + 1; | ||
122 | fpga_polarity = fpga_status + 2; | ||
123 | fpga_trigger = fpga_status + 3; | ||
124 | fpga_brdc = fpga_status + 4; | ||
125 | |||
126 | /* split the keyboard and mouse interrupts */ | ||
127 | fpga_brdc_data = readb(fpga_brdc); | ||
128 | fpga_brdc_data |= 0x80; | ||
129 | writeb(fpga_brdc_data, fpga_brdc); | ||
130 | |||
131 | writeb(0x3, fpga_enable); | ||
132 | |||
133 | writeb(0x3, fpga_polarity); | ||
134 | |||
135 | writeb(0x3, fpga_trigger); | ||
136 | |||
137 | /* RTC step for the sycamore */ | ||
138 | sycamore_rtc_base = (void *) SYCAMORE_RTC_VADDR; | ||
139 | TODC_INIT(TODC_TYPE_DS1743, sycamore_rtc_base, sycamore_rtc_base, | ||
140 | sycamore_rtc_base, 8); | ||
141 | |||
142 | /* Identify the system */ | ||
143 | printk(KERN_INFO "IBM Sycamore (IBM405GPr) Platform\n"); | ||
144 | printk(KERN_INFO | ||
145 | "Port by MontaVista Software, Inc. (source@mvista.com)\n"); | ||
146 | } | ||
147 | |||
148 | void __init | ||
149 | bios_fixup(struct pci_controller *hose, struct pcil0_regs *pcip) | ||
150 | { | ||
151 | #ifdef CONFIG_PCI | ||
152 | unsigned int bar_response, bar; | ||
153 | /* | ||
154 | * Expected PCI mapping: | ||
155 | * | ||
156 | * PLB addr PCI memory addr | ||
157 | * --------------------- --------------------- | ||
158 | * 0000'0000 - 7fff'ffff <--- 0000'0000 - 7fff'ffff | ||
159 | * 8000'0000 - Bfff'ffff ---> 8000'0000 - Bfff'ffff | ||
160 | * | ||
161 | * PLB addr PCI io addr | ||
162 | * --------------------- --------------------- | ||
163 | * e800'0000 - e800'ffff ---> 0000'0000 - 0001'0000 | ||
164 | * | ||
165 | * The following code is simplified by assuming that the bootrom | ||
166 | * has been well behaved in following this mapping. | ||
167 | */ | ||
168 | |||
169 | #ifdef DEBUG | ||
170 | int i; | ||
171 | |||
172 | printk("ioremap PCLIO_BASE = 0x%x\n", pcip); | ||
173 | printk("PCI bridge regs before fixup \n"); | ||
174 | for (i = 0; i <= 3; i++) { | ||
175 | printk(" pmm%dma\t0x%x\n", i, in_le32(&(pcip->pmm[i].ma))); | ||
176 | printk(" pmm%dma\t0x%x\n", i, in_le32(&(pcip->pmm[i].la))); | ||
177 | printk(" pmm%dma\t0x%x\n", i, in_le32(&(pcip->pmm[i].pcila))); | ||
178 | printk(" pmm%dma\t0x%x\n", i, in_le32(&(pcip->pmm[i].pciha))); | ||
179 | } | ||
180 | printk(" ptm1ms\t0x%x\n", in_le32(&(pcip->ptm1ms))); | ||
181 | printk(" ptm1la\t0x%x\n", in_le32(&(pcip->ptm1la))); | ||
182 | printk(" ptm2ms\t0x%x\n", in_le32(&(pcip->ptm2ms))); | ||
183 | printk(" ptm2la\t0x%x\n", in_le32(&(pcip->ptm2la))); | ||
184 | |||
185 | #endif | ||
186 | |||
187 | /* added for IBM boot rom version 1.15 bios bar changes -AK */ | ||
188 | |||
189 | /* Disable region first */ | ||
190 | out_le32((void *) &(pcip->pmm[0].ma), 0x00000000); | ||
191 | /* PLB starting addr, PCI: 0x80000000 */ | ||
192 | out_le32((void *) &(pcip->pmm[0].la), 0x80000000); | ||
193 | /* PCI start addr, 0x80000000 */ | ||
194 | out_le32((void *) &(pcip->pmm[0].pcila), PPC405_PCI_MEM_BASE); | ||
195 | /* 512MB range of PLB to PCI */ | ||
196 | out_le32((void *) &(pcip->pmm[0].pciha), 0x00000000); | ||
197 | /* Enable no pre-fetch, enable region */ | ||
198 | out_le32((void *) &(pcip->pmm[0].ma), ((0xffffffff - | ||
199 | (PPC405_PCI_UPPER_MEM - | ||
200 | PPC405_PCI_MEM_BASE)) | 0x01)); | ||
201 | |||
202 | /* Enable inbound region one - 1GB size */ | ||
203 | out_le32((void *) &(pcip->ptm1ms), 0xc0000001); | ||
204 | |||
205 | /* Disable outbound region one */ | ||
206 | out_le32((void *) &(pcip->pmm[1].ma), 0x00000000); | ||
207 | out_le32((void *) &(pcip->pmm[1].la), 0x00000000); | ||
208 | out_le32((void *) &(pcip->pmm[1].pcila), 0x00000000); | ||
209 | out_le32((void *) &(pcip->pmm[1].pciha), 0x00000000); | ||
210 | out_le32((void *) &(pcip->pmm[1].ma), 0x00000000); | ||
211 | |||
212 | /* Disable inbound region two */ | ||
213 | out_le32((void *) &(pcip->ptm2ms), 0x00000000); | ||
214 | |||
215 | /* Disable outbound region two */ | ||
216 | out_le32((void *) &(pcip->pmm[2].ma), 0x00000000); | ||
217 | out_le32((void *) &(pcip->pmm[2].la), 0x00000000); | ||
218 | out_le32((void *) &(pcip->pmm[2].pcila), 0x00000000); | ||
219 | out_le32((void *) &(pcip->pmm[2].pciha), 0x00000000); | ||
220 | out_le32((void *) &(pcip->pmm[2].ma), 0x00000000); | ||
221 | |||
222 | /* Zero config bars */ | ||
223 | for (bar = PCI_BASE_ADDRESS_1; bar <= PCI_BASE_ADDRESS_2; bar += 4) { | ||
224 | early_write_config_dword(hose, hose->first_busno, | ||
225 | PCI_FUNC(hose->first_busno), bar, | ||
226 | 0x00000000); | ||
227 | early_read_config_dword(hose, hose->first_busno, | ||
228 | PCI_FUNC(hose->first_busno), bar, | ||
229 | &bar_response); | ||
230 | DBG("BUS %d, device %d, Function %d bar 0x%8.8x is 0x%8.8x\n", | ||
231 | hose->first_busno, PCI_SLOT(hose->first_busno), | ||
232 | PCI_FUNC(hose->first_busno), bar, bar_response); | ||
233 | } | ||
234 | /* end work arround */ | ||
235 | |||
236 | #ifdef DEBUG | ||
237 | printk("PCI bridge regs after fixup \n"); | ||
238 | for (i = 0; i <= 3; i++) { | ||
239 | printk(" pmm%dma\t0x%x\n", i, in_le32(&(pcip->pmm[i].ma))); | ||
240 | printk(" pmm%dma\t0x%x\n", i, in_le32(&(pcip->pmm[i].la))); | ||
241 | printk(" pmm%dma\t0x%x\n", i, in_le32(&(pcip->pmm[i].pcila))); | ||
242 | printk(" pmm%dma\t0x%x\n", i, in_le32(&(pcip->pmm[i].pciha))); | ||
243 | } | ||
244 | printk(" ptm1ms\t0x%x\n", in_le32(&(pcip->ptm1ms))); | ||
245 | printk(" ptm1la\t0x%x\n", in_le32(&(pcip->ptm1la))); | ||
246 | printk(" ptm2ms\t0x%x\n", in_le32(&(pcip->ptm2ms))); | ||
247 | printk(" ptm2la\t0x%x\n", in_le32(&(pcip->ptm2la))); | ||
248 | |||
249 | #endif | ||
250 | #endif | ||
251 | |||
252 | } | ||
253 | |||
254 | void __init | ||
255 | sycamore_map_io(void) | ||
256 | { | ||
257 | ppc4xx_map_io(); | ||
258 | io_block_mapping(SYCAMORE_RTC_VADDR, | ||
259 | SYCAMORE_RTC_PADDR, SYCAMORE_RTC_SIZE, _PAGE_IO); | ||
260 | } | ||
261 | |||
262 | void __init | ||
263 | platform_init(unsigned long r3, unsigned long r4, unsigned long r5, | ||
264 | unsigned long r6, unsigned long r7) | ||
265 | { | ||
266 | ppc4xx_init(r3, r4, r5, r6, r7); | ||
267 | |||
268 | ppc_md.setup_arch = sycamore_setup_arch; | ||
269 | ppc_md.setup_io_mappings = sycamore_map_io; | ||
270 | |||
271 | #ifdef CONFIG_GEN_RTC | ||
272 | ppc_md.time_init = todc_time_init; | ||
273 | ppc_md.set_rtc_time = todc_set_rtc_time; | ||
274 | ppc_md.get_rtc_time = todc_get_rtc_time; | ||
275 | ppc_md.nvram_read_val = todc_direct_read_val; | ||
276 | ppc_md.nvram_write_val = todc_direct_write_val; | ||
277 | #endif | ||
278 | } | ||
diff --git a/arch/ppc/platforms/4xx/sycamore.h b/arch/ppc/platforms/4xx/sycamore.h new file mode 100644 index 000000000000..3e7b4e2c8c57 --- /dev/null +++ b/arch/ppc/platforms/4xx/sycamore.h | |||
@@ -0,0 +1,67 @@ | |||
1 | /* | ||
2 | * arch/ppc/platforms/4xx/sycamore.h | ||
3 | * | ||
4 | * Macros, definitions, and data structures specific to the IBM PowerPC | ||
5 | * 405GPr "Sycamore" evaluation board. | ||
6 | * | ||
7 | * Author: Armin Kuster <akuster@mvista.com> | ||
8 | * | ||
9 | * 2000 (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 | #ifdef __KERNEL__ | ||
16 | #ifndef __ASM_SYCAMORE_H__ | ||
17 | #define __ASM_SYCAMORE_H__ | ||
18 | |||
19 | #include <platforms/4xx/ibm405gpr.h> | ||
20 | |||
21 | #ifndef __ASSEMBLY__ | ||
22 | /* | ||
23 | * Data structure defining board information maintained by the boot | ||
24 | * ROM on IBM's "Sycamore" evaluation board. An effort has been made to | ||
25 | * keep the field names consistent with the 8xx 'bd_t' board info | ||
26 | * structures. | ||
27 | */ | ||
28 | |||
29 | typedef struct board_info { | ||
30 | unsigned char bi_s_version[4]; /* Version of this structure */ | ||
31 | unsigned char bi_r_version[30]; /* Version of the IBM ROM */ | ||
32 | unsigned int bi_memsize; /* DRAM installed, in bytes */ | ||
33 | unsigned char bi_enetaddr[6]; /* Local Ethernet MAC address */ | ||
34 | unsigned char bi_pci_enetaddr[6]; /* PCI Ethernet MAC address */ | ||
35 | unsigned int bi_intfreq; /* Processor speed, in Hz */ | ||
36 | unsigned int bi_busfreq; /* PLB Bus speed, in Hz */ | ||
37 | unsigned int bi_pci_busfreq; /* PCI Bus speed, in Hz */ | ||
38 | } bd_t; | ||
39 | |||
40 | /* Some 4xx parts use a different timebase frequency from the internal clock. | ||
41 | */ | ||
42 | #define bi_tbfreq bi_intfreq | ||
43 | |||
44 | |||
45 | /* Memory map for the IBM "Sycamore" 405GP evaluation board. | ||
46 | * Generic 4xx plus RTC. | ||
47 | */ | ||
48 | |||
49 | extern void *sycamore_rtc_base; | ||
50 | #define SYCAMORE_RTC_PADDR ((uint)0xf0000000) | ||
51 | #define SYCAMORE_RTC_VADDR SYCAMORE_RTC_PADDR | ||
52 | #define SYCAMORE_RTC_SIZE ((uint)8*1024) | ||
53 | |||
54 | #ifdef CONFIG_PPC405GP_INTERNAL_CLOCK | ||
55 | #define BASE_BAUD 201600 | ||
56 | #else | ||
57 | #define BASE_BAUD 691200 | ||
58 | #endif | ||
59 | |||
60 | #define SYCAMORE_PS2_BASE 0xF0100000 | ||
61 | #define SYCAMORE_FPGA_BASE 0xF0300000 | ||
62 | |||
63 | #define PPC4xx_MACHINE_NAME "IBM Sycamore" | ||
64 | |||
65 | #endif /* !__ASSEMBLY__ */ | ||
66 | #endif /* __ASM_SYCAMORE_H__ */ | ||
67 | #endif /* __KERNEL__ */ | ||
diff --git a/arch/ppc/platforms/4xx/virtex-ii_pro.c b/arch/ppc/platforms/4xx/virtex-ii_pro.c new file mode 100644 index 000000000000..097cc9d5aca0 --- /dev/null +++ b/arch/ppc/platforms/4xx/virtex-ii_pro.c | |||
@@ -0,0 +1,60 @@ | |||
1 | /* | ||
2 | * arch/ppc/platforms/4xx/virtex-ii_pro.c | ||
3 | * | ||
4 | * Author: MontaVista Software, Inc. | ||
5 | * source@mvista.com | ||
6 | * | ||
7 | * 2002-2004 (c) MontaVista Software, Inc. This file is licensed under the | ||
8 | * terms of the GNU General Public License version 2. This program is licensed | ||
9 | * "as is" without any warranty of any kind, whether express or implied. | ||
10 | */ | ||
11 | |||
12 | #include <linux/config.h> | ||
13 | #include <linux/init.h> | ||
14 | #include <asm/ocp.h> | ||
15 | #include "virtex-ii_pro.h" | ||
16 | |||
17 | /* Have OCP take care of the serial ports. */ | ||
18 | struct ocp_def core_ocp[] = { | ||
19 | #ifdef XPAR_UARTNS550_0_BASEADDR | ||
20 | { .vendor = OCP_VENDOR_XILINX, | ||
21 | .function = OCP_FUNC_16550, | ||
22 | .index = 0, | ||
23 | .paddr = XPAR_UARTNS550_0_BASEADDR, | ||
24 | .irq = XPAR_INTC_0_UARTNS550_0_VEC_ID, | ||
25 | .pm = OCP_CPM_NA | ||
26 | }, | ||
27 | #ifdef XPAR_UARTNS550_1_BASEADDR | ||
28 | { .vendor = OCP_VENDOR_XILINX, | ||
29 | .function = OCP_FUNC_16550, | ||
30 | .index = 1, | ||
31 | .paddr = XPAR_UARTNS550_1_BASEADDR, | ||
32 | .irq = XPAR_INTC_0_UARTNS550_1_VEC_ID, | ||
33 | .pm = OCP_CPM_NA | ||
34 | }, | ||
35 | #ifdef XPAR_UARTNS550_2_BASEADDR | ||
36 | { .vendor = OCP_VENDOR_XILINX, | ||
37 | .function = OCP_FUNC_16550, | ||
38 | .index = 2, | ||
39 | .paddr = XPAR_UARTNS550_2_BASEADDR, | ||
40 | .irq = XPAR_INTC_0_UARTNS550_2_VEC_ID, | ||
41 | .pm = OCP_CPM_NA | ||
42 | }, | ||
43 | #ifdef XPAR_UARTNS550_3_BASEADDR | ||
44 | { .vendor = OCP_VENDOR_XILINX, | ||
45 | .function = OCP_FUNC_16550, | ||
46 | .index = 3, | ||
47 | .paddr = XPAR_UARTNS550_3_BASEADDR, | ||
48 | .irq = XPAR_INTC_0_UARTNS550_3_VEC_ID, | ||
49 | .pm = OCP_CPM_NA | ||
50 | }, | ||
51 | #ifdef XPAR_UARTNS550_4_BASEADDR | ||
52 | #error Edit this file to add more devices. | ||
53 | #endif /* 4 */ | ||
54 | #endif /* 3 */ | ||
55 | #endif /* 2 */ | ||
56 | #endif /* 1 */ | ||
57 | #endif /* 0 */ | ||
58 | { .vendor = OCP_VENDOR_INVALID | ||
59 | } | ||
60 | }; | ||
diff --git a/arch/ppc/platforms/4xx/virtex-ii_pro.h b/arch/ppc/platforms/4xx/virtex-ii_pro.h new file mode 100644 index 000000000000..9014c4887339 --- /dev/null +++ b/arch/ppc/platforms/4xx/virtex-ii_pro.h | |||
@@ -0,0 +1,99 @@ | |||
1 | /* | ||
2 | * arch/ppc/platforms/4xx/virtex-ii_pro.h | ||
3 | * | ||
4 | * Include file that defines the Xilinx Virtex-II Pro processor | ||
5 | * | ||
6 | * Author: MontaVista Software, Inc. | ||
7 | * source@mvista.com | ||
8 | * | ||
9 | * 2002-2004 (c) MontaVista Software, Inc. This file is licensed under the | ||
10 | * terms of the GNU General Public License version 2. This program is licensed | ||
11 | * "as is" without any warranty of any kind, whether express or implied. | ||
12 | */ | ||
13 | |||
14 | #ifdef __KERNEL__ | ||
15 | #ifndef __ASM_VIRTEXIIPRO_H__ | ||
16 | #define __ASM_VIRTEXIIPRO_H__ | ||
17 | |||
18 | #include <linux/config.h> | ||
19 | #include <asm/xparameters.h> | ||
20 | |||
21 | /* serial defines */ | ||
22 | |||
23 | #define RS_TABLE_SIZE 4 /* change this and add more devices below | ||
24 | if you have more then 4 16x50 UARTs */ | ||
25 | |||
26 | #define BASE_BAUD (XPAR_UARTNS550_0_CLOCK_FREQ_HZ/16) | ||
27 | |||
28 | /* The serial ports in the Virtex-II Pro have each I/O byte in the | ||
29 | * LSByte of a word. This means that iomem_reg_shift needs to be 2 to | ||
30 | * change the byte offsets into word offsets. In addition the base | ||
31 | * addresses need to have 3 added to them to get to the LSByte. | ||
32 | */ | ||
33 | #define STD_UART_OP(num) \ | ||
34 | { 0, BASE_BAUD, 0, XPAR_INTC_0_UARTNS550_##num##_VEC_ID, \ | ||
35 | ASYNC_BOOT_AUTOCONF, \ | ||
36 | .iomem_base = (u8 *)XPAR_UARTNS550_##num##_BASEADDR + 3, \ | ||
37 | .iomem_reg_shift = 2, \ | ||
38 | .io_type = SERIAL_IO_MEM}, | ||
39 | |||
40 | #if defined(XPAR_INTC_0_UARTNS550_0_VEC_ID) | ||
41 | #define ML300_UART0 STD_UART_OP(0) | ||
42 | #else | ||
43 | #define ML300_UART0 | ||
44 | #endif | ||
45 | |||
46 | #if defined(XPAR_INTC_0_UARTNS550_1_VEC_ID) | ||
47 | #define ML300_UART1 STD_UART_OP(1) | ||
48 | #else | ||
49 | #define ML300_UART1 | ||
50 | #endif | ||
51 | |||
52 | #if defined(XPAR_INTC_0_UARTNS550_2_VEC_ID) | ||
53 | #define ML300_UART2 STD_UART_OP(2) | ||
54 | #else | ||
55 | #define ML300_UART2 | ||
56 | #endif | ||
57 | |||
58 | #if defined(XPAR_INTC_0_UARTNS550_3_VEC_ID) | ||
59 | #define ML300_UART3 STD_UART_OP(3) | ||
60 | #else | ||
61 | #define ML300_UART3 | ||
62 | #endif | ||
63 | |||
64 | #if defined(XPAR_INTC_0_UARTNS550_4_VEC_ID) | ||
65 | #error Edit this file to add more devices. | ||
66 | #elif defined(XPAR_INTC_0_UARTNS550_3_VEC_ID) | ||
67 | #define NR_SER_PORTS 4 | ||
68 | #elif defined(XPAR_INTC_0_UARTNS550_2_VEC_ID) | ||
69 | #define NR_SER_PORTS 3 | ||
70 | #elif defined(XPAR_INTC_0_UARTNS550_1_VEC_ID) | ||
71 | #define NR_SER_PORTS 2 | ||
72 | #elif defined(XPAR_INTC_0_UARTNS550_0_VEC_ID) | ||
73 | #define NR_SER_PORTS 1 | ||
74 | #else | ||
75 | #define NR_SER_PORTS 0 | ||
76 | #endif | ||
77 | |||
78 | #if defined(CONFIG_UART0_TTYS0) | ||
79 | #define SERIAL_PORT_DFNS \ | ||
80 | ML300_UART0 \ | ||
81 | ML300_UART1 \ | ||
82 | ML300_UART2 \ | ||
83 | ML300_UART3 | ||
84 | #endif | ||
85 | |||
86 | #if defined(CONFIG_UART0_TTYS1) | ||
87 | #define SERIAL_PORT_DFNS \ | ||
88 | ML300_UART1 \ | ||
89 | ML300_UART0 \ | ||
90 | ML300_UART2 \ | ||
91 | ML300_UART3 | ||
92 | #endif | ||
93 | |||
94 | #define DCRN_CPMFR_BASE 0 | ||
95 | |||
96 | #include <asm/ibm405.h> | ||
97 | |||
98 | #endif /* __ASM_VIRTEXIIPRO_H__ */ | ||
99 | #endif /* __KERNEL__ */ | ||
diff --git a/arch/ppc/platforms/4xx/walnut.c b/arch/ppc/platforms/4xx/walnut.c new file mode 100644 index 000000000000..a33eda4b7489 --- /dev/null +++ b/arch/ppc/platforms/4xx/walnut.c | |||
@@ -0,0 +1,249 @@ | |||
1 | /* | ||
2 | * arch/ppc/platforms/4xx/walnut.c | ||
3 | * | ||
4 | * Architecture- / platform-specific boot-time initialization code for | ||
5 | * IBM PowerPC 4xx based boards. Adapted from original | ||
6 | * code by Gary Thomas, Cort Dougan <cort@fsmlabs.com>, and Dan Malek | ||
7 | * <dan@net4x.com>. | ||
8 | * | ||
9 | * Copyright(c) 1999-2000 Grant Erickson <grant@lcse.umn.edu> | ||
10 | * | ||
11 | * 2002 (c) MontaVista, Software, Inc. This file is licensed under | ||
12 | * the terms of the GNU General Public License version 2. This program | ||
13 | * is licensed "as is" without any warranty of any kind, whether express | ||
14 | * or implied. | ||
15 | */ | ||
16 | #include <linux/config.h> | ||
17 | #include <linux/init.h> | ||
18 | #include <linux/smp.h> | ||
19 | #include <linux/threads.h> | ||
20 | #include <linux/param.h> | ||
21 | #include <linux/string.h> | ||
22 | #include <linux/pci.h> | ||
23 | #include <linux/rtc.h> | ||
24 | |||
25 | #include <asm/system.h> | ||
26 | #include <asm/pci-bridge.h> | ||
27 | #include <asm/machdep.h> | ||
28 | #include <asm/page.h> | ||
29 | #include <asm/time.h> | ||
30 | #include <asm/io.h> | ||
31 | #include <asm/ocp.h> | ||
32 | #include <asm/ibm_ocp_pci.h> | ||
33 | #include <asm/todc.h> | ||
34 | |||
35 | #undef DEBUG | ||
36 | |||
37 | #ifdef DEBUG | ||
38 | #define DBG(x...) printk(x) | ||
39 | #else | ||
40 | #define DBG(x...) | ||
41 | #endif | ||
42 | |||
43 | void *kb_cs; | ||
44 | void *kb_data; | ||
45 | void *walnut_rtc_base; | ||
46 | |||
47 | /* Some IRQs unique to Walnut. | ||
48 | * Used by the generic 405 PCI setup functions in ppc4xx_pci.c | ||
49 | */ | ||
50 | int __init | ||
51 | ppc405_map_irq(struct pci_dev *dev, unsigned char idsel, unsigned char pin) | ||
52 | { | ||
53 | static char pci_irq_table[][4] = | ||
54 | /* | ||
55 | * PCI IDSEL/INTPIN->INTLINE | ||
56 | * A B C D | ||
57 | */ | ||
58 | { | ||
59 | {28, 28, 28, 28}, /* IDSEL 1 - PCI slot 1 */ | ||
60 | {29, 29, 29, 29}, /* IDSEL 2 - PCI slot 2 */ | ||
61 | {30, 30, 30, 30}, /* IDSEL 3 - PCI slot 3 */ | ||
62 | {31, 31, 31, 31}, /* IDSEL 4 - PCI slot 4 */ | ||
63 | }; | ||
64 | |||
65 | const long min_idsel = 1, max_idsel = 4, irqs_per_slot = 4; | ||
66 | return PCI_IRQ_TABLE_LOOKUP; | ||
67 | }; | ||
68 | |||
69 | void __init | ||
70 | walnut_setup_arch(void) | ||
71 | { | ||
72 | |||
73 | void *fpga_brdc; | ||
74 | unsigned char fpga_brdc_data; | ||
75 | void *fpga_enable; | ||
76 | void *fpga_polarity; | ||
77 | void *fpga_status; | ||
78 | void *fpga_trigger; | ||
79 | |||
80 | ppc4xx_setup_arch(); | ||
81 | |||
82 | ibm_ocp_set_emac(0, 0); | ||
83 | |||
84 | kb_data = ioremap(WALNUT_PS2_BASE, 8); | ||
85 | if (!kb_data) { | ||
86 | printk(KERN_CRIT | ||
87 | "walnut_setup_arch() kb_data ioremap failed\n"); | ||
88 | return; | ||
89 | } | ||
90 | |||
91 | kb_cs = kb_data + 1; | ||
92 | |||
93 | fpga_status = ioremap(WALNUT_FPGA_BASE, 8); | ||
94 | if (!fpga_status) { | ||
95 | printk(KERN_CRIT | ||
96 | "walnut_setup_arch() fpga_status ioremap failed\n"); | ||
97 | return; | ||
98 | } | ||
99 | |||
100 | fpga_enable = fpga_status + 1; | ||
101 | fpga_polarity = fpga_status + 2; | ||
102 | fpga_trigger = fpga_status + 3; | ||
103 | fpga_brdc = fpga_status + 4; | ||
104 | |||
105 | /* split the keyboard and mouse interrupts */ | ||
106 | fpga_brdc_data = readb(fpga_brdc); | ||
107 | fpga_brdc_data |= 0x80; | ||
108 | writeb(fpga_brdc_data, fpga_brdc); | ||
109 | |||
110 | writeb(0x3, fpga_enable); | ||
111 | |||
112 | writeb(0x3, fpga_polarity); | ||
113 | |||
114 | writeb(0x3, fpga_trigger); | ||
115 | |||
116 | /* RTC step for the walnut */ | ||
117 | walnut_rtc_base = (void *) WALNUT_RTC_VADDR; | ||
118 | TODC_INIT(TODC_TYPE_DS1743, walnut_rtc_base, walnut_rtc_base, | ||
119 | walnut_rtc_base, 8); | ||
120 | /* Identify the system */ | ||
121 | printk("IBM Walnut port (C) 2000-2002 MontaVista Software, Inc. (source@mvista.com)\n"); | ||
122 | } | ||
123 | |||
124 | void __init | ||
125 | bios_fixup(struct pci_controller *hose, struct pcil0_regs *pcip) | ||
126 | { | ||
127 | #ifdef CONFIG_PCI | ||
128 | unsigned int bar_response, bar; | ||
129 | /* | ||
130 | * Expected PCI mapping: | ||
131 | * | ||
132 | * PLB addr PCI memory addr | ||
133 | * --------------------- --------------------- | ||
134 | * 0000'0000 - 7fff'ffff <--- 0000'0000 - 7fff'ffff | ||
135 | * 8000'0000 - Bfff'ffff ---> 8000'0000 - Bfff'ffff | ||
136 | * | ||
137 | * PLB addr PCI io addr | ||
138 | * --------------------- --------------------- | ||
139 | * e800'0000 - e800'ffff ---> 0000'0000 - 0001'0000 | ||
140 | * | ||
141 | * The following code is simplified by assuming that the bootrom | ||
142 | * has been well behaved in following this mapping. | ||
143 | */ | ||
144 | |||
145 | #ifdef DEBUG | ||
146 | int i; | ||
147 | |||
148 | printk("ioremap PCLIO_BASE = 0x%x\n", pcip); | ||
149 | printk("PCI bridge regs before fixup \n"); | ||
150 | for (i = 0; i <= 3; i++) { | ||
151 | printk(" pmm%dma\t0x%x\n", i, in_le32(&(pcip->pmm[i].ma))); | ||
152 | printk(" pmm%dma\t0x%x\n", i, in_le32(&(pcip->pmm[i].la))); | ||
153 | printk(" pmm%dma\t0x%x\n", i, in_le32(&(pcip->pmm[i].pcila))); | ||
154 | printk(" pmm%dma\t0x%x\n", i, in_le32(&(pcip->pmm[i].pciha))); | ||
155 | } | ||
156 | printk(" ptm1ms\t0x%x\n", in_le32(&(pcip->ptm1ms))); | ||
157 | printk(" ptm1la\t0x%x\n", in_le32(&(pcip->ptm1la))); | ||
158 | printk(" ptm2ms\t0x%x\n", in_le32(&(pcip->ptm2ms))); | ||
159 | printk(" ptm2la\t0x%x\n", in_le32(&(pcip->ptm2la))); | ||
160 | |||
161 | #endif | ||
162 | |||
163 | /* added for IBM boot rom version 1.15 bios bar changes -AK */ | ||
164 | |||
165 | /* Disable region first */ | ||
166 | out_le32((void *) &(pcip->pmm[0].ma), 0x00000000); | ||
167 | /* PLB starting addr, PCI: 0x80000000 */ | ||
168 | out_le32((void *) &(pcip->pmm[0].la), 0x80000000); | ||
169 | /* PCI start addr, 0x80000000 */ | ||
170 | out_le32((void *) &(pcip->pmm[0].pcila), PPC405_PCI_MEM_BASE); | ||
171 | /* 512MB range of PLB to PCI */ | ||
172 | out_le32((void *) &(pcip->pmm[0].pciha), 0x00000000); | ||
173 | /* Enable no pre-fetch, enable region */ | ||
174 | out_le32((void *) &(pcip->pmm[0].ma), ((0xffffffff - | ||
175 | (PPC405_PCI_UPPER_MEM - | ||
176 | PPC405_PCI_MEM_BASE)) | 0x01)); | ||
177 | |||
178 | /* Disable region one */ | ||
179 | out_le32((void *) &(pcip->pmm[1].ma), 0x00000000); | ||
180 | out_le32((void *) &(pcip->pmm[1].la), 0x00000000); | ||
181 | out_le32((void *) &(pcip->pmm[1].pcila), 0x00000000); | ||
182 | out_le32((void *) &(pcip->pmm[1].pciha), 0x00000000); | ||
183 | out_le32((void *) &(pcip->pmm[1].ma), 0x00000000); | ||
184 | out_le32((void *) &(pcip->ptm1ms), 0x00000000); | ||
185 | |||
186 | /* Disable region two */ | ||
187 | out_le32((void *) &(pcip->pmm[2].ma), 0x00000000); | ||
188 | out_le32((void *) &(pcip->pmm[2].la), 0x00000000); | ||
189 | out_le32((void *) &(pcip->pmm[2].pcila), 0x00000000); | ||
190 | out_le32((void *) &(pcip->pmm[2].pciha), 0x00000000); | ||
191 | out_le32((void *) &(pcip->pmm[2].ma), 0x00000000); | ||
192 | out_le32((void *) &(pcip->ptm2ms), 0x00000000); | ||
193 | |||
194 | /* Zero config bars */ | ||
195 | for (bar = PCI_BASE_ADDRESS_1; bar <= PCI_BASE_ADDRESS_2; bar += 4) { | ||
196 | early_write_config_dword(hose, hose->first_busno, | ||
197 | PCI_FUNC(hose->first_busno), bar, | ||
198 | 0x00000000); | ||
199 | early_read_config_dword(hose, hose->first_busno, | ||
200 | PCI_FUNC(hose->first_busno), bar, | ||
201 | &bar_response); | ||
202 | DBG("BUS %d, device %d, Function %d bar 0x%8.8x is 0x%8.8x\n", | ||
203 | hose->first_busno, PCI_SLOT(hose->first_busno), | ||
204 | PCI_FUNC(hose->first_busno), bar, bar_response); | ||
205 | } | ||
206 | /* end work arround */ | ||
207 | |||
208 | #ifdef DEBUG | ||
209 | printk("PCI bridge regs after fixup \n"); | ||
210 | for (i = 0; i <= 3; i++) { | ||
211 | printk(" pmm%dma\t0x%x\n", i, in_le32(&(pcip->pmm[i].ma))); | ||
212 | printk(" pmm%dma\t0x%x\n", i, in_le32(&(pcip->pmm[i].la))); | ||
213 | printk(" pmm%dma\t0x%x\n", i, in_le32(&(pcip->pmm[i].pcila))); | ||
214 | printk(" pmm%dma\t0x%x\n", i, in_le32(&(pcip->pmm[i].pciha))); | ||
215 | } | ||
216 | printk(" ptm1ms\t0x%x\n", in_le32(&(pcip->ptm1ms))); | ||
217 | printk(" ptm1la\t0x%x\n", in_le32(&(pcip->ptm1la))); | ||
218 | printk(" ptm2ms\t0x%x\n", in_le32(&(pcip->ptm2ms))); | ||
219 | printk(" ptm2la\t0x%x\n", in_le32(&(pcip->ptm2la))); | ||
220 | |||
221 | #endif | ||
222 | #endif | ||
223 | } | ||
224 | |||
225 | void __init | ||
226 | walnut_map_io(void) | ||
227 | { | ||
228 | ppc4xx_map_io(); | ||
229 | io_block_mapping(WALNUT_RTC_VADDR, | ||
230 | WALNUT_RTC_PADDR, WALNUT_RTC_SIZE, _PAGE_IO); | ||
231 | } | ||
232 | |||
233 | void __init | ||
234 | platform_init(unsigned long r3, unsigned long r4, unsigned long r5, | ||
235 | unsigned long r6, unsigned long r7) | ||
236 | { | ||
237 | ppc4xx_init(r3, r4, r5, r6, r7); | ||
238 | |||
239 | ppc_md.setup_arch = walnut_setup_arch; | ||
240 | ppc_md.setup_io_mappings = walnut_map_io; | ||
241 | |||
242 | #ifdef CONFIG_GEN_RTC | ||
243 | ppc_md.time_init = todc_time_init; | ||
244 | ppc_md.set_rtc_time = todc_set_rtc_time; | ||
245 | ppc_md.get_rtc_time = todc_get_rtc_time; | ||
246 | ppc_md.nvram_read_val = todc_direct_read_val; | ||
247 | ppc_md.nvram_write_val = todc_direct_write_val; | ||
248 | #endif | ||
249 | } | ||
diff --git a/arch/ppc/platforms/4xx/walnut.h b/arch/ppc/platforms/4xx/walnut.h new file mode 100644 index 000000000000..04cfbf3696b9 --- /dev/null +++ b/arch/ppc/platforms/4xx/walnut.h | |||
@@ -0,0 +1,72 @@ | |||
1 | /* | ||
2 | * arch/ppc/platforms/4xx/walnut.h | ||
3 | * | ||
4 | * Macros, definitions, and data structures specific to the IBM PowerPC | ||
5 | * 405GP "Walnut" evaluation board. | ||
6 | * | ||
7 | * Authors: Grant Erickson <grant@lcse.umn.edu>, Frank Rowand | ||
8 | * <frank_rowand@mvista.com>, Debbie Chu <debbie_chu@mvista.com> or | ||
9 | * source@mvista.com | ||
10 | * | ||
11 | * Copyright (c) 1999 Grant Erickson <grant@lcse.umn.edu> | ||
12 | * | ||
13 | * 2000 (c) MontaVista, Software, Inc. This file is licensed under | ||
14 | * the terms of the GNU General Public License version 2. This program | ||
15 | * is licensed "as is" without any warranty of any kind, whether express | ||
16 | * or implied. | ||
17 | */ | ||
18 | |||
19 | #ifdef __KERNEL__ | ||
20 | #ifndef __ASM_WALNUT_H__ | ||
21 | #define __ASM_WALNUT_H__ | ||
22 | |||
23 | /* We have a 405GP core */ | ||
24 | #include <platforms/4xx/ibm405gp.h> | ||
25 | |||
26 | #ifndef __ASSEMBLY__ | ||
27 | /* | ||
28 | * Data structure defining board information maintained by the boot | ||
29 | * ROM on IBM's "Walnut" evaluation board. An effort has been made to | ||
30 | * keep the field names consistent with the 8xx 'bd_t' board info | ||
31 | * structures. | ||
32 | */ | ||
33 | |||
34 | typedef struct board_info { | ||
35 | unsigned char bi_s_version[4]; /* Version of this structure */ | ||
36 | unsigned char bi_r_version[30]; /* Version of the IBM ROM */ | ||
37 | unsigned int bi_memsize; /* DRAM installed, in bytes */ | ||
38 | unsigned char bi_enetaddr[6]; /* Local Ethernet MAC address */ | ||
39 | unsigned char bi_pci_enetaddr[6]; /* PCI Ethernet MAC address */ | ||
40 | unsigned int bi_intfreq; /* Processor speed, in Hz */ | ||
41 | unsigned int bi_busfreq; /* PLB Bus speed, in Hz */ | ||
42 | unsigned int bi_pci_busfreq; /* PCI Bus speed, in Hz */ | ||
43 | } bd_t; | ||
44 | |||
45 | /* Some 4xx parts use a different timebase frequency from the internal clock. | ||
46 | */ | ||
47 | #define bi_tbfreq bi_intfreq | ||
48 | |||
49 | |||
50 | /* Memory map for the IBM "Walnut" 405GP evaluation board. | ||
51 | * Generic 4xx plus RTC. | ||
52 | */ | ||
53 | |||
54 | extern void *walnut_rtc_base; | ||
55 | #define WALNUT_RTC_PADDR ((uint)0xf0000000) | ||
56 | #define WALNUT_RTC_VADDR WALNUT_RTC_PADDR | ||
57 | #define WALNUT_RTC_SIZE ((uint)8*1024) | ||
58 | |||
59 | #ifdef CONFIG_PPC405GP_INTERNAL_CLOCK | ||
60 | #define BASE_BAUD 201600 | ||
61 | #else | ||
62 | #define BASE_BAUD 691200 | ||
63 | #endif | ||
64 | |||
65 | #define WALNUT_PS2_BASE 0xF0100000 | ||
66 | #define WALNUT_FPGA_BASE 0xF0300000 | ||
67 | |||
68 | #define PPC4xx_MACHINE_NAME "IBM Walnut" | ||
69 | |||
70 | #endif /* !__ASSEMBLY__ */ | ||
71 | #endif /* __ASM_WALNUT_H__ */ | ||
72 | #endif /* __KERNEL__ */ | ||
diff --git a/arch/ppc/platforms/4xx/xilinx_ml300.c b/arch/ppc/platforms/4xx/xilinx_ml300.c new file mode 100644 index 000000000000..0b1b77d986bf --- /dev/null +++ b/arch/ppc/platforms/4xx/xilinx_ml300.c | |||
@@ -0,0 +1,146 @@ | |||
1 | /* | ||
2 | * arch/ppc/platforms/4xx/xilinx_ml300.c | ||
3 | * | ||
4 | * Xilinx ML300 evaluation board initialization | ||
5 | * | ||
6 | * Author: MontaVista Software, Inc. | ||
7 | * source@mvista.com | ||
8 | * | ||
9 | * 2002-2004 (c) MontaVista Software, Inc. This file is licensed under the | ||
10 | * terms of the GNU General Public License version 2. This program is licensed | ||
11 | * "as is" without any warranty of any kind, whether express or implied. | ||
12 | */ | ||
13 | |||
14 | #include <linux/config.h> | ||
15 | #include <linux/init.h> | ||
16 | #include <linux/irq.h> | ||
17 | #include <linux/tty.h> | ||
18 | #include <linux/serial.h> | ||
19 | #include <linux/serial_core.h> | ||
20 | #include <linux/serialP.h> | ||
21 | #include <asm/io.h> | ||
22 | #include <asm/machdep.h> | ||
23 | #include <asm/ocp.h> | ||
24 | |||
25 | #include <platforms/4xx/virtex-ii_pro.h> /* for NR_SER_PORTS */ | ||
26 | |||
27 | /* | ||
28 | * As an overview of how the following functions (platform_init, | ||
29 | * ml300_map_io, ml300_setup_arch and ml300_init_IRQ) fit into the | ||
30 | * kernel startup procedure, here's a call tree: | ||
31 | * | ||
32 | * start_here arch/ppc/kernel/head_4xx.S | ||
33 | * early_init arch/ppc/kernel/setup.c | ||
34 | * machine_init arch/ppc/kernel/setup.c | ||
35 | * platform_init this file | ||
36 | * ppc4xx_init arch/ppc/syslib/ppc4xx_setup.c | ||
37 | * parse_bootinfo | ||
38 | * find_bootinfo | ||
39 | * "setup some default ppc_md pointers" | ||
40 | * MMU_init arch/ppc/mm/init.c | ||
41 | * *ppc_md.setup_io_mappings == ml300_map_io this file | ||
42 | * ppc4xx_map_io arch/ppc/syslib/ppc4xx_setup.c | ||
43 | * start_kernel init/main.c | ||
44 | * setup_arch arch/ppc/kernel/setup.c | ||
45 | * #if defined(CONFIG_KGDB) | ||
46 | * *ppc_md.kgdb_map_scc() == gen550_kgdb_map_scc | ||
47 | * #endif | ||
48 | * *ppc_md.setup_arch == ml300_setup_arch this file | ||
49 | * ppc4xx_setup_arch arch/ppc/syslib/ppc4xx_setup.c | ||
50 | * ppc4xx_find_bridges arch/ppc/syslib/ppc405_pci.c | ||
51 | * init_IRQ arch/ppc/kernel/irq.c | ||
52 | * *ppc_md.init_IRQ == ml300_init_IRQ this file | ||
53 | * ppc4xx_init_IRQ arch/ppc/syslib/ppc4xx_setup.c | ||
54 | * ppc4xx_pic_init arch/ppc/syslib/xilinx_pic.c | ||
55 | */ | ||
56 | |||
57 | #if defined(XPAR_POWER_0_POWERDOWN_BASEADDR) | ||
58 | |||
59 | static volatile unsigned *powerdown_base = | ||
60 | (volatile unsigned *) XPAR_POWER_0_POWERDOWN_BASEADDR; | ||
61 | |||
62 | static void | ||
63 | xilinx_power_off(void) | ||
64 | { | ||
65 | local_irq_disable(); | ||
66 | out_be32(powerdown_base, XPAR_POWER_0_POWERDOWN_VALUE); | ||
67 | while (1) ; | ||
68 | } | ||
69 | #endif | ||
70 | |||
71 | void __init | ||
72 | ml300_map_io(void) | ||
73 | { | ||
74 | ppc4xx_map_io(); | ||
75 | |||
76 | #if defined(XPAR_POWER_0_POWERDOWN_BASEADDR) | ||
77 | powerdown_base = ioremap((unsigned long) powerdown_base, | ||
78 | XPAR_POWER_0_POWERDOWN_HIGHADDR - | ||
79 | XPAR_POWER_0_POWERDOWN_BASEADDR + 1); | ||
80 | #endif | ||
81 | } | ||
82 | |||
83 | static void __init | ||
84 | ml300_early_serial_map(void) | ||
85 | { | ||
86 | #ifdef CONFIG_SERIAL_8250 | ||
87 | struct serial_state old_ports[] = { SERIAL_PORT_DFNS }; | ||
88 | struct uart_port port; | ||
89 | int i; | ||
90 | |||
91 | /* Setup ioremapped serial port access */ | ||
92 | for (i = 0; i < ARRAY_SIZE(old_ports); i++ ) { | ||
93 | memset(&port, 0, sizeof(port)); | ||
94 | port.membase = ioremap((phys_addr_t)(old_ports[i].iomem_base), 16); | ||
95 | port.irq = old_ports[i].irq; | ||
96 | port.uartclk = old_ports[i].baud_base * 16; | ||
97 | port.regshift = old_ports[i].iomem_reg_shift; | ||
98 | port.iotype = SERIAL_IO_MEM; | ||
99 | port.flags = ASYNC_BOOT_AUTOCONF | ASYNC_SKIP_TEST; | ||
100 | port.line = i; | ||
101 | |||
102 | if (early_serial_setup(&port) != 0) { | ||
103 | printk("Early serial init of port %d failed\n", i); | ||
104 | } | ||
105 | } | ||
106 | #endif /* CONFIG_SERIAL_8250 */ | ||
107 | } | ||
108 | |||
109 | void __init | ||
110 | ml300_setup_arch(void) | ||
111 | { | ||
112 | ppc4xx_setup_arch(); /* calls ppc4xx_find_bridges() */ | ||
113 | |||
114 | ml300_early_serial_map(); | ||
115 | |||
116 | /* Identify the system */ | ||
117 | printk(KERN_INFO "Xilinx Virtex-II Pro port\n"); | ||
118 | printk(KERN_INFO "Port by MontaVista Software, Inc. (source@mvista.com)\n"); | ||
119 | } | ||
120 | |||
121 | /* Called after board_setup_irq from ppc4xx_init_IRQ(). */ | ||
122 | void __init | ||
123 | ml300_init_irq(void) | ||
124 | { | ||
125 | ppc4xx_init_IRQ(); | ||
126 | } | ||
127 | |||
128 | void __init | ||
129 | platform_init(unsigned long r3, unsigned long r4, unsigned long r5, | ||
130 | unsigned long r6, unsigned long r7) | ||
131 | { | ||
132 | ppc4xx_init(r3, r4, r5, r6, r7); | ||
133 | |||
134 | ppc_md.setup_arch = ml300_setup_arch; | ||
135 | ppc_md.setup_io_mappings = ml300_map_io; | ||
136 | ppc_md.init_IRQ = ml300_init_irq; | ||
137 | |||
138 | #if defined(XPAR_POWER_0_POWERDOWN_BASEADDR) | ||
139 | ppc_md.power_off = xilinx_power_off; | ||
140 | #endif | ||
141 | |||
142 | #ifdef CONFIG_KGDB | ||
143 | ppc_md.early_serial_map = ml300_early_serial_map; | ||
144 | #endif | ||
145 | } | ||
146 | |||
diff --git a/arch/ppc/platforms/4xx/xilinx_ml300.h b/arch/ppc/platforms/4xx/xilinx_ml300.h new file mode 100644 index 000000000000..f8c588412336 --- /dev/null +++ b/arch/ppc/platforms/4xx/xilinx_ml300.h | |||
@@ -0,0 +1,47 @@ | |||
1 | /* | ||
2 | * arch/ppc/platforms/4xx/xilinx_ml300.h | ||
3 | * | ||
4 | * Include file that defines the Xilinx ML300 evaluation board | ||
5 | * | ||
6 | * Author: MontaVista Software, Inc. | ||
7 | * source@mvista.com | ||
8 | * | ||
9 | * 2002-2004 (c) MontaVista Software, Inc. This file is licensed under the | ||
10 | * terms of the GNU General Public License version 2. This program is licensed | ||
11 | * "as is" without any warranty of any kind, whether express or implied. | ||
12 | */ | ||
13 | |||
14 | #ifdef __KERNEL__ | ||
15 | #ifndef __ASM_XILINX_ML300_H__ | ||
16 | #define __ASM_XILINX_ML300_H__ | ||
17 | |||
18 | /* ML300 has a Xilinx Virtex-II Pro processor */ | ||
19 | #include <platforms/4xx/virtex-ii_pro.h> | ||
20 | |||
21 | #ifndef __ASSEMBLY__ | ||
22 | |||
23 | #include <linux/types.h> | ||
24 | |||
25 | typedef struct board_info { | ||
26 | unsigned int bi_memsize; /* DRAM installed, in bytes */ | ||
27 | unsigned char bi_enetaddr[6]; /* Local Ethernet MAC address */ | ||
28 | unsigned int bi_intfreq; /* Processor speed, in Hz */ | ||
29 | unsigned int bi_busfreq; /* PLB Bus speed, in Hz */ | ||
30 | unsigned int bi_pci_busfreq; /* PCI Bus speed, in Hz */ | ||
31 | } bd_t; | ||
32 | |||
33 | /* Some 4xx parts use a different timebase frequency from the internal clock. | ||
34 | */ | ||
35 | #define bi_tbfreq bi_intfreq | ||
36 | |||
37 | #endif /* !__ASSEMBLY__ */ | ||
38 | |||
39 | /* We don't need anything mapped. Size of zero will accomplish that. */ | ||
40 | #define PPC4xx_ONB_IO_PADDR 0u | ||
41 | #define PPC4xx_ONB_IO_VADDR 0u | ||
42 | #define PPC4xx_ONB_IO_SIZE 0u | ||
43 | |||
44 | #define PPC4xx_MACHINE_NAME "Xilinx ML300" | ||
45 | |||
46 | #endif /* __ASM_XILINX_ML300_H__ */ | ||
47 | #endif /* __KERNEL__ */ | ||
diff --git a/arch/ppc/platforms/4xx/xparameters/xparameters_ml300.h b/arch/ppc/platforms/4xx/xparameters/xparameters_ml300.h new file mode 100644 index 000000000000..97e3f4d4bd54 --- /dev/null +++ b/arch/ppc/platforms/4xx/xparameters/xparameters_ml300.h | |||
@@ -0,0 +1,310 @@ | |||
1 | /******************************************************************* | ||
2 | * | ||
3 | * Author: Xilinx, Inc. | ||
4 | * | ||
5 | * | ||
6 | * This program is free software; you can redistribute it and/or modify it | ||
7 | * under the terms of the GNU General Public License as published by the | ||
8 | * Free Software Foundation; either version 2 of the License, or (at your | ||
9 | * option) any later version. | ||
10 | * | ||
11 | * | ||
12 | * XILINX IS PROVIDING THIS DESIGN, CODE, OR INFORMATION "AS IS" AS A | ||
13 | * COURTESY TO YOU. BY PROVIDING THIS DESIGN, CODE, OR INFORMATION AS | ||
14 | * ONE POSSIBLE IMPLEMENTATION OF THIS FEATURE, APPLICATION OR STANDARD, | ||
15 | * XILINX IS MAKING NO REPRESENTATION THAT THIS IMPLEMENTATION IS FREE | ||
16 | * FROM ANY CLAIMS OF INFRINGEMENT, AND YOU ARE RESPONSIBLE FOR OBTAINING | ||
17 | * ANY THIRD PARTY RIGHTS YOU MAY REQUIRE FOR YOUR IMPLEMENTATION. | ||
18 | * XILINX EXPRESSLY DISCLAIMS ANY WARRANTY WHATSOEVER WITH RESPECT TO | ||
19 | * THE ADEQUACY OF THE IMPLEMENTATION, INCLUDING BUT NOT LIMITED TO ANY | ||
20 | * WARRANTIES OR REPRESENTATIONS THAT THIS IMPLEMENTATION IS FREE FROM | ||
21 | * CLAIMS OF INFRINGEMENT, IMPLIED WARRANTIES OF MERCHANTABILITY AND | ||
22 | * FITNESS FOR A PARTICULAR PURPOSE. | ||
23 | * | ||
24 | * | ||
25 | * Xilinx hardware products are not intended for use in life support | ||
26 | * appliances, devices, or systems. Use in such applications is | ||
27 | * expressly prohibited. | ||
28 | * | ||
29 | * | ||
30 | * (c) Copyright 2002-2004 Xilinx Inc. | ||
31 | * All rights reserved. | ||
32 | * | ||
33 | * | ||
34 | * You should have received a copy of the GNU General Public License along | ||
35 | * with this program; if not, write to the Free Software Foundation, Inc., | ||
36 | * 675 Mass Ave, Cambridge, MA 02139, USA. | ||
37 | * | ||
38 | * Description: Driver parameters | ||
39 | * | ||
40 | *******************************************************************/ | ||
41 | |||
42 | #define XPAR_XPCI_NUM_INSTANCES 1 | ||
43 | #define XPAR_XPCI_CLOCK_HZ 33333333 | ||
44 | #define XPAR_OPB_PCI_REF_0_DEVICE_ID 0 | ||
45 | #define XPAR_OPB_PCI_REF_0_BASEADDR 0x20000000 | ||
46 | #define XPAR_OPB_PCI_REF_0_HIGHADDR 0x3FFFFFFF | ||
47 | #define XPAR_OPB_PCI_REF_0_CONFIG_ADDR 0x3C000000 | ||
48 | #define XPAR_OPB_PCI_REF_0_CONFIG_DATA 0x3C000004 | ||
49 | #define XPAR_OPB_PCI_REF_0_LCONFIG_ADDR 0x3E000000 | ||
50 | #define XPAR_OPB_PCI_REF_0_MEM_BASEADDR 0x20000000 | ||
51 | #define XPAR_OPB_PCI_REF_0_MEM_HIGHADDR 0x37FFFFFF | ||
52 | #define XPAR_OPB_PCI_REF_0_IO_BASEADDR 0x38000000 | ||
53 | #define XPAR_OPB_PCI_REF_0_IO_HIGHADDR 0x3BFFFFFF | ||
54 | |||
55 | /******************************************************************/ | ||
56 | |||
57 | #define XPAR_XEMAC_NUM_INSTANCES 1 | ||
58 | #define XPAR_OPB_ETHERNET_0_BASEADDR 0x60000000 | ||
59 | #define XPAR_OPB_ETHERNET_0_HIGHADDR 0x60003FFF | ||
60 | #define XPAR_OPB_ETHERNET_0_DEVICE_ID 0 | ||
61 | #define XPAR_OPB_ETHERNET_0_ERR_COUNT_EXIST 1 | ||
62 | #define XPAR_OPB_ETHERNET_0_DMA_PRESENT 1 | ||
63 | #define XPAR_OPB_ETHERNET_0_MII_EXIST 1 | ||
64 | |||
65 | /******************************************************************/ | ||
66 | |||
67 | #define XPAR_MY_OPB_GPIO_0_DEVICE_ID_0 0 | ||
68 | #define XPAR_MY_OPB_GPIO_0_BASEADDR_0 0x90000000 | ||
69 | #define XPAR_MY_OPB_GPIO_0_HIGHADDR_0 (0x90000000+0x7) | ||
70 | #define XPAR_MY_OPB_GPIO_0_DEVICE_ID_1 1 | ||
71 | #define XPAR_MY_OPB_GPIO_0_BASEADDR_1 (0x90000000+0x8) | ||
72 | #define XPAR_MY_OPB_GPIO_0_HIGHADDR_1 (0x90000000+0x1F) | ||
73 | #define XPAR_XGPIO_NUM_INSTANCES 2 | ||
74 | |||
75 | /******************************************************************/ | ||
76 | |||
77 | #define XPAR_XIIC_NUM_INSTANCES 1 | ||
78 | #define XPAR_OPB_IIC_0_BASEADDR 0xA8000000 | ||
79 | #define XPAR_OPB_IIC_0_HIGHADDR 0xA80001FF | ||
80 | #define XPAR_OPB_IIC_0_DEVICE_ID 0 | ||
81 | #define XPAR_OPB_IIC_0_TEN_BIT_ADR 0 | ||
82 | |||
83 | /******************************************************************/ | ||
84 | |||
85 | #define XPAR_XUARTNS550_NUM_INSTANCES 2 | ||
86 | #define XPAR_XUARTNS550_CLOCK_HZ 100000000 | ||
87 | #define XPAR_OPB_UART16550_0_BASEADDR 0xA0000000 | ||
88 | #define XPAR_OPB_UART16550_0_HIGHADDR 0xA0001FFF | ||
89 | #define XPAR_OPB_UART16550_0_DEVICE_ID 0 | ||
90 | #define XPAR_OPB_UART16550_1_BASEADDR 0xA0010000 | ||
91 | #define XPAR_OPB_UART16550_1_HIGHADDR 0xA0011FFF | ||
92 | #define XPAR_OPB_UART16550_1_DEVICE_ID 1 | ||
93 | |||
94 | /******************************************************************/ | ||
95 | |||
96 | #define XPAR_XSPI_NUM_INSTANCES 1 | ||
97 | #define XPAR_OPB_SPI_0_BASEADDR 0xA4000000 | ||
98 | #define XPAR_OPB_SPI_0_HIGHADDR 0xA400007F | ||
99 | #define XPAR_OPB_SPI_0_DEVICE_ID 0 | ||
100 | #define XPAR_OPB_SPI_0_FIFO_EXIST 1 | ||
101 | #define XPAR_OPB_SPI_0_SPI_SLAVE_ONLY 0 | ||
102 | #define XPAR_OPB_SPI_0_NUM_SS_BITS 1 | ||
103 | |||
104 | /******************************************************************/ | ||
105 | |||
106 | #define XPAR_XPS2_NUM_INSTANCES 2 | ||
107 | #define XPAR_OPB_PS2_DUAL_REF_0_DEVICE_ID_0 0 | ||
108 | #define XPAR_OPB_PS2_DUAL_REF_0_BASEADDR_0 0xA9000000 | ||
109 | #define XPAR_OPB_PS2_DUAL_REF_0_HIGHADDR_0 (0xA9000000+0x3F) | ||
110 | #define XPAR_OPB_PS2_DUAL_REF_0_DEVICE_ID_1 1 | ||
111 | #define XPAR_OPB_PS2_DUAL_REF_0_BASEADDR_1 (0xA9000000+0x1000) | ||
112 | #define XPAR_OPB_PS2_DUAL_REF_0_HIGHADDR_1 (0xA9000000+0x103F) | ||
113 | |||
114 | /******************************************************************/ | ||
115 | |||
116 | #define XPAR_XTOUCHSCREEN_NUM_INSTANCES 1 | ||
117 | #define XPAR_OPB_TSD_REF_0_BASEADDR 0xAA000000 | ||
118 | #define XPAR_OPB_TSD_REF_0_HIGHADDR 0xAA000007 | ||
119 | #define XPAR_OPB_TSD_REF_0_DEVICE_ID 0 | ||
120 | |||
121 | /******************************************************************/ | ||
122 | |||
123 | #define XPAR_OPB_AC97_CONTROLLER_REF_0_BASEADDR 0xA6000000 | ||
124 | #define XPAR_OPB_AC97_CONTROLLER_REF_0_HIGHADDR 0xA60000FF | ||
125 | #define XPAR_OPB_PAR_PORT_REF_0_BASEADDR 0x90010000 | ||
126 | #define XPAR_OPB_PAR_PORT_REF_0_HIGHADDR 0x900100FF | ||
127 | #define XPAR_PLB_DDR_0_BASEADDR 0x00000000 | ||
128 | #define XPAR_PLB_DDR_0_HIGHADDR 0x0FFFFFFF | ||
129 | |||
130 | /******************************************************************/ | ||
131 | |||
132 | #define XPAR_XINTC_HAS_IPR 1 | ||
133 | #define XPAR_INTC_MAX_NUM_INTR_INPUTS 18 | ||
134 | #define XPAR_XINTC_USE_DCR 0 | ||
135 | #define XPAR_XINTC_NUM_INSTANCES 1 | ||
136 | #define XPAR_DCR_INTC_0_BASEADDR 0xD0000FC0 | ||
137 | #define XPAR_DCR_INTC_0_HIGHADDR 0xD0000FDF | ||
138 | #define XPAR_DCR_INTC_0_DEVICE_ID 0 | ||
139 | #define XPAR_DCR_INTC_0_KIND_OF_INTR 0x00038000 | ||
140 | |||
141 | /******************************************************************/ | ||
142 | |||
143 | #define XPAR_DCR_INTC_0_MISC_LOGIC_0_PHY_MII_INT_INTR 0 | ||
144 | #define XPAR_DCR_INTC_0_OPB_ETHERNET_0_IP2INTC_IRPT_INTR 1 | ||
145 | #define XPAR_DCR_INTC_0_MISC_LOGIC_0_IIC_TEMP_CRIT_INTR 2 | ||
146 | #define XPAR_DCR_INTC_0_MISC_LOGIC_0_IIC_IRQ_INTR 3 | ||
147 | #define XPAR_DCR_INTC_0_OPB_IIC_0_IP2INTC_IRPT_INTR 4 | ||
148 | #define XPAR_DCR_INTC_0_OPB_SYSACE_0_SYSACE_IRQ_INTR 5 | ||
149 | #define XPAR_DCR_INTC_0_OPB_UART16550_0_IP2INTC_IRPT_INTR 6 | ||
150 | #define XPAR_DCR_INTC_0_OPB_UART16550_1_IP2INTC_IRPT_INTR 7 | ||
151 | #define XPAR_DCR_INTC_0_OPB_PS2_DUAL_REF_0_SYS_INTR1_INTR 8 | ||
152 | #define XPAR_DCR_INTC_0_OPB_PS2_DUAL_REF_0_SYS_INTR2_INTR 9 | ||
153 | #define XPAR_DCR_INTC_0_OPB_SPI_0_IP2INTC_IRPT_INTR 10 | ||
154 | #define XPAR_DCR_INTC_0_OPB_TSD_REF_0_INTR_INTR 11 | ||
155 | #define XPAR_DCR_INTC_0_OPB_AC97_CONTROLLER_REF_0_PLAYBACK_INTERRUPT_INTR 12 | ||
156 | #define XPAR_DCR_INTC_0_OPB_AC97_CONTROLLER_REF_0_RECORD_INTERRUPT_INTR 13 | ||
157 | #define XPAR_DCR_INTC_0_OPB_PCI_REF_0_INTR_OUT_INTR 14 | ||
158 | #define XPAR_DCR_INTC_0_PLB2OPB_BRIDGE_0_BUS_ERROR_DET_INTR 15 | ||
159 | #define XPAR_DCR_INTC_0_PLB_V34_0_BUS_ERROR_DET_INTR 16 | ||
160 | #define XPAR_DCR_INTC_0_OPB2PLB_BRIDGE_0_BUS_ERROR_DET_INTR 17 | ||
161 | |||
162 | /******************************************************************/ | ||
163 | |||
164 | #define XPAR_XTFT_NUM_INSTANCES 1 | ||
165 | #define XPAR_PLB_TFT_CNTLR_REF_0_DCR_BASEADDR 0xD0000200 | ||
166 | #define XPAR_PLB_TFT_CNTLR_REF_0_DCR_HIGHADDR 0xD0000207 | ||
167 | #define XPAR_PLB_TFT_CNTLR_REF_0_DEVICE_ID 0 | ||
168 | |||
169 | /******************************************************************/ | ||
170 | |||
171 | #define XPAR_XSYSACE_MEM_WIDTH 8 | ||
172 | #define XPAR_XSYSACE_NUM_INSTANCES 1 | ||
173 | #define XPAR_OPB_SYSACE_0_BASEADDR 0xCF000000 | ||
174 | #define XPAR_OPB_SYSACE_0_HIGHADDR 0xCF0001FF | ||
175 | #define XPAR_OPB_SYSACE_0_DEVICE_ID 0 | ||
176 | #define XPAR_OPB_SYSACE_0_MEM_WIDTH 8 | ||
177 | |||
178 | /******************************************************************/ | ||
179 | |||
180 | #define XPAR_CPU_PPC405_CORE_CLOCK_FREQ_HZ 300000000 | ||
181 | |||
182 | /******************************************************************/ | ||
183 | |||
184 | /******************************************************************/ | ||
185 | |||
186 | /* Linux Redefines */ | ||
187 | |||
188 | /******************************************************************/ | ||
189 | |||
190 | #define XPAR_UARTNS550_0_BASEADDR (XPAR_OPB_UART16550_0_BASEADDR+0x1000) | ||
191 | #define XPAR_UARTNS550_0_HIGHADDR XPAR_OPB_UART16550_0_HIGHADDR | ||
192 | #define XPAR_UARTNS550_0_CLOCK_FREQ_HZ XPAR_XUARTNS550_CLOCK_HZ | ||
193 | #define XPAR_UARTNS550_0_DEVICE_ID XPAR_OPB_UART16550_0_DEVICE_ID | ||
194 | #define XPAR_UARTNS550_1_BASEADDR (XPAR_OPB_UART16550_1_BASEADDR+0x1000) | ||
195 | #define XPAR_UARTNS550_1_HIGHADDR XPAR_OPB_UART16550_1_HIGHADDR | ||
196 | #define XPAR_UARTNS550_1_CLOCK_FREQ_HZ XPAR_XUARTNS550_CLOCK_HZ | ||
197 | #define XPAR_UARTNS550_1_DEVICE_ID XPAR_OPB_UART16550_1_DEVICE_ID | ||
198 | |||
199 | /******************************************************************/ | ||
200 | |||
201 | #define XPAR_GPIO_0_BASEADDR XPAR_MY_OPB_GPIO_0_BASEADDR_0 | ||
202 | #define XPAR_GPIO_0_HIGHADDR XPAR_MY_OPB_GPIO_0_HIGHADDR_0 | ||
203 | #define XPAR_GPIO_0_DEVICE_ID XPAR_MY_OPB_GPIO_0_DEVICE_ID_0 | ||
204 | #define XPAR_GPIO_1_BASEADDR XPAR_MY_OPB_GPIO_0_BASEADDR_1 | ||
205 | #define XPAR_GPIO_1_HIGHADDR XPAR_MY_OPB_GPIO_0_HIGHADDR_1 | ||
206 | #define XPAR_GPIO_1_DEVICE_ID XPAR_MY_OPB_GPIO_0_DEVICE_ID_1 | ||
207 | |||
208 | /******************************************************************/ | ||
209 | |||
210 | #define XPAR_IIC_0_BASEADDR XPAR_OPB_IIC_0_BASEADDR | ||
211 | #define XPAR_IIC_0_HIGHADDR XPAR_OPB_IIC_0_HIGHADDR | ||
212 | #define XPAR_IIC_0_TEN_BIT_ADR XPAR_OPB_IIC_0_TEN_BIT_ADR | ||
213 | #define XPAR_IIC_0_DEVICE_ID XPAR_OPB_IIC_0_DEVICE_ID | ||
214 | |||
215 | /******************************************************************/ | ||
216 | |||
217 | #define XPAR_SYSACE_0_BASEADDR XPAR_OPB_SYSACE_0_BASEADDR | ||
218 | #define XPAR_SYSACE_0_HIGHADDR XPAR_OPB_SYSACE_0_HIGHADDR | ||
219 | #define XPAR_SYSACE_0_DEVICE_ID XPAR_OPB_SYSACE_0_DEVICE_ID | ||
220 | |||
221 | /******************************************************************/ | ||
222 | |||
223 | #define XPAR_INTC_0_BASEADDR XPAR_DCR_INTC_0_BASEADDR | ||
224 | #define XPAR_INTC_0_HIGHADDR XPAR_DCR_INTC_0_HIGHADDR | ||
225 | #define XPAR_INTC_0_KIND_OF_INTR XPAR_DCR_INTC_0_KIND_OF_INTR | ||
226 | #define XPAR_INTC_0_DEVICE_ID XPAR_DCR_INTC_0_DEVICE_ID | ||
227 | |||
228 | /******************************************************************/ | ||
229 | |||
230 | #define XPAR_INTC_0_EMAC_0_VEC_ID XPAR_DCR_INTC_0_OPB_ETHERNET_0_IP2INTC_IRPT_INTR | ||
231 | #define XPAR_INTC_0_IIC_0_VEC_ID XPAR_DCR_INTC_0_OPB_IIC_0_IP2INTC_IRPT_INTR | ||
232 | #define XPAR_INTC_0_SYSACE_0_VEC_ID XPAR_DCR_INTC_0_OPB_SYSACE_0_SYSACE_IRQ_INTR | ||
233 | #define XPAR_INTC_0_UARTNS550_0_VEC_ID XPAR_DCR_INTC_0_OPB_UART16550_0_IP2INTC_IRPT_INTR | ||
234 | #define XPAR_INTC_0_UARTNS550_1_VEC_ID XPAR_DCR_INTC_0_OPB_UART16550_1_IP2INTC_IRPT_INTR | ||
235 | #define XPAR_INTC_0_PS2_0_VEC_ID XPAR_DCR_INTC_0_OPB_PS2_DUAL_REF_0_SYS_INTR1_INTR | ||
236 | #define XPAR_INTC_0_PS2_1_VEC_ID XPAR_DCR_INTC_0_OPB_PS2_DUAL_REF_0_SYS_INTR2_INTR | ||
237 | #define XPAR_INTC_0_SPI_0_VEC_ID XPAR_DCR_INTC_0_OPB_SPI_0_IP2INTC_IRPT_INTR | ||
238 | #define XPAR_INTC_0_TOUCHSCREEN_0_VEC_ID XPAR_DCR_INTC_0_OPB_TSD_REF_0_INTR_INTR | ||
239 | #define XPAR_INTC_0_PCI_0_VEC_ID_A XPAR_DCR_INTC_0_OPB_PCI_REF_0_INTR_OUT_INTR | ||
240 | #define XPAR_INTC_0_PCI_0_VEC_ID_B XPAR_DCR_INTC_0_OPB_PCI_REF_0_INTR_OUT_INTR | ||
241 | #define XPAR_INTC_0_PCI_0_VEC_ID_C XPAR_DCR_INTC_0_OPB_PCI_REF_0_INTR_OUT_INTR | ||
242 | #define XPAR_INTC_0_PCI_0_VEC_ID_D XPAR_DCR_INTC_0_OPB_PCI_REF_0_INTR_OUT_INTR | ||
243 | |||
244 | /******************************************************************/ | ||
245 | |||
246 | #define XPAR_EMAC_0_BASEADDR XPAR_OPB_ETHERNET_0_BASEADDR | ||
247 | #define XPAR_EMAC_0_HIGHADDR XPAR_OPB_ETHERNET_0_HIGHADDR | ||
248 | #define XPAR_EMAC_0_DMA_PRESENT XPAR_OPB_ETHERNET_0_DMA_PRESENT | ||
249 | #define XPAR_EMAC_0_MII_EXIST XPAR_OPB_ETHERNET_0_MII_EXIST | ||
250 | #define XPAR_EMAC_0_ERR_COUNT_EXIST XPAR_OPB_ETHERNET_0_ERR_COUNT_EXIST | ||
251 | #define XPAR_EMAC_0_DEVICE_ID XPAR_OPB_ETHERNET_0_DEVICE_ID | ||
252 | |||
253 | /******************************************************************/ | ||
254 | |||
255 | #define XPAR_SPI_0_BASEADDR XPAR_OPB_SPI_0_BASEADDR | ||
256 | #define XPAR_SPI_0_HIGHADDR XPAR_OPB_SPI_0_HIGHADDR | ||
257 | #define XPAR_SPI_0_DEVICE_ID XPAR_OPB_SPI_0_DEVICE_ID | ||
258 | |||
259 | /******************************************************************/ | ||
260 | |||
261 | #define XPAR_TOUCHSCREEN_0_BASEADDR XPAR_OPB_TSD_REF_0_BASEADDR | ||
262 | #define XPAR_TOUCHSCREEN_0_HIGHADDR XPAR_OPB_TSD_REF_0_HIGHADDR | ||
263 | #define XPAR_TOUCHSCREEN_0_DEVICE_ID XPAR_OPB_TSD_REF_0_DEVICE_ID | ||
264 | |||
265 | /******************************************************************/ | ||
266 | |||
267 | #define XPAR_TFT_0_BASEADDR XPAR_PLB_TFT_CNTLR_REF_0_DCR_BASEADDR | ||
268 | |||
269 | /******************************************************************/ | ||
270 | |||
271 | #define XPAR_PCI_0_BASEADDR XPAR_OPB_PCI_REF_0_BASEADDR | ||
272 | #define XPAR_PCI_0_HIGHADDR XPAR_OPB_PCI_REF_0_HIGHADDR | ||
273 | #define XPAR_PCI_0_CONFIG_ADDR XPAR_OPB_PCI_REF_0_CONFIG_ADDR | ||
274 | #define XPAR_PCI_0_CONFIG_DATA XPAR_OPB_PCI_REF_0_CONFIG_DATA | ||
275 | #define XPAR_PCI_0_LCONFIG_ADDR XPAR_OPB_PCI_REF_0_LCONFIG_ADDR | ||
276 | #define XPAR_PCI_0_MEM_BASEADDR XPAR_OPB_PCI_REF_0_MEM_BASEADDR | ||
277 | #define XPAR_PCI_0_MEM_HIGHADDR XPAR_OPB_PCI_REF_0_MEM_HIGHADDR | ||
278 | #define XPAR_PCI_0_IO_BASEADDR XPAR_OPB_PCI_REF_0_IO_BASEADDR | ||
279 | #define XPAR_PCI_0_IO_HIGHADDR XPAR_OPB_PCI_REF_0_IO_HIGHADDR | ||
280 | #define XPAR_PCI_0_CLOCK_FREQ_HZ XPAR_XPCI_CLOCK_HZ | ||
281 | #define XPAR_PCI_0_DEVICE_ID XPAR_OPB_PCI_REF_0_DEVICE_ID | ||
282 | |||
283 | /******************************************************************/ | ||
284 | |||
285 | #define XPAR_PS2_0_BASEADDR XPAR_OPB_PS2_DUAL_REF_0_BASEADDR_0 | ||
286 | #define XPAR_PS2_0_HIGHADDR XPAR_OPB_PS2_DUAL_REF_0_HIGHADDR_0 | ||
287 | #define XPAR_PS2_0_DEVICE_ID XPAR_OPB_PS2_DUAL_REF_0_DEVICE_ID_0 | ||
288 | #define XPAR_PS2_1_BASEADDR XPAR_OPB_PS2_DUAL_REF_0_BASEADDR_1 | ||
289 | #define XPAR_PS2_1_HIGHADDR XPAR_OPB_PS2_DUAL_REF_0_HIGHADDR_1 | ||
290 | #define XPAR_PS2_1_DEVICE_ID XPAR_OPB_PS2_DUAL_REF_0_DEVICE_ID_1 | ||
291 | |||
292 | /******************************************************************/ | ||
293 | |||
294 | #define XPAR_PLB_CLOCK_FREQ_HZ 100000000 | ||
295 | #define XPAR_CORE_CLOCK_FREQ_HZ XPAR_CPU_PPC405_CORE_CLOCK_FREQ_HZ | ||
296 | #define XPAR_DDR_0_SIZE 0x08000000 | ||
297 | |||
298 | /******************************************************************/ | ||
299 | |||
300 | #define XPAR_PERSISTENT_0_IIC_0_BASEADDR 0x00000400 | ||
301 | #define XPAR_PERSISTENT_0_IIC_0_HIGHADDR 0x000007FF | ||
302 | #define XPAR_PERSISTENT_0_IIC_0_EEPROMADDR 0xA0 | ||
303 | |||
304 | /******************************************************************/ | ||
305 | |||
306 | #define XPAR_POWER_0_POWERDOWN_BASEADDR 0x90000004 | ||
307 | #define XPAR_POWER_0_POWERDOWN_HIGHADDR 0x90000007 | ||
308 | #define XPAR_POWER_0_POWERDOWN_VALUE 0xFF | ||
309 | |||
310 | /******************************************************************/ | ||
diff --git a/arch/ppc/platforms/83xx/Makefile b/arch/ppc/platforms/83xx/Makefile new file mode 100644 index 000000000000..eb55341d6a17 --- /dev/null +++ b/arch/ppc/platforms/83xx/Makefile | |||
@@ -0,0 +1,4 @@ | |||
1 | # | ||
2 | # Makefile for the PowerPC 83xx linux kernel. | ||
3 | # | ||
4 | obj-$(CONFIG_MPC834x_SYS) += mpc834x_sys.o | ||
diff --git a/arch/ppc/platforms/83xx/mpc834x_sys.c b/arch/ppc/platforms/83xx/mpc834x_sys.c new file mode 100644 index 000000000000..b3b0f51979d2 --- /dev/null +++ b/arch/ppc/platforms/83xx/mpc834x_sys.c | |||
@@ -0,0 +1,289 @@ | |||
1 | /* | ||
2 | * arch/ppc/platforms/83xx/mpc834x_sys.c | ||
3 | * | ||
4 | * MPC834x SYS board specific routines | ||
5 | * | ||
6 | * Maintainer: Kumar Gala <kumar.gala@freescale.com> | ||
7 | * | ||
8 | * Copyright 2005 Freescale Semiconductor Inc. | ||
9 | * | ||
10 | * This program is free software; you can redistribute it and/or modify it | ||
11 | * under the terms of the GNU General Public License as published by the | ||
12 | * Free Software Foundation; either version 2 of the License, or (at your | ||
13 | * option) any later version. | ||
14 | */ | ||
15 | |||
16 | #include <linux/config.h> | ||
17 | #include <linux/stddef.h> | ||
18 | #include <linux/kernel.h> | ||
19 | #include <linux/init.h> | ||
20 | #include <linux/errno.h> | ||
21 | #include <linux/reboot.h> | ||
22 | #include <linux/pci.h> | ||
23 | #include <linux/kdev_t.h> | ||
24 | #include <linux/major.h> | ||
25 | #include <linux/console.h> | ||
26 | #include <linux/delay.h> | ||
27 | #include <linux/irq.h> | ||
28 | #include <linux/seq_file.h> | ||
29 | #include <linux/root_dev.h> | ||
30 | #include <linux/serial.h> | ||
31 | #include <linux/tty.h> /* for linux/serial_core.h */ | ||
32 | #include <linux/serial_core.h> | ||
33 | #include <linux/initrd.h> | ||
34 | #include <linux/module.h> | ||
35 | #include <linux/fsl_devices.h> | ||
36 | |||
37 | #include <asm/system.h> | ||
38 | #include <asm/pgtable.h> | ||
39 | #include <asm/page.h> | ||
40 | #include <asm/atomic.h> | ||
41 | #include <asm/time.h> | ||
42 | #include <asm/io.h> | ||
43 | #include <asm/machdep.h> | ||
44 | #include <asm/prom.h> | ||
45 | #include <asm/ipic.h> | ||
46 | #include <asm/bootinfo.h> | ||
47 | #include <asm/pci-bridge.h> | ||
48 | #include <asm/mpc83xx.h> | ||
49 | #include <asm/irq.h> | ||
50 | #include <asm/kgdb.h> | ||
51 | #include <asm/ppc_sys.h> | ||
52 | #include <mm/mmu_decl.h> | ||
53 | |||
54 | #include <syslib/ppc83xx_setup.h> | ||
55 | |||
56 | #ifndef CONFIG_PCI | ||
57 | unsigned long isa_io_base = 0; | ||
58 | unsigned long isa_mem_base = 0; | ||
59 | #endif | ||
60 | |||
61 | extern unsigned long total_memory; /* in mm/init */ | ||
62 | |||
63 | unsigned char __res[sizeof (bd_t)]; | ||
64 | |||
65 | #ifdef CONFIG_PCI | ||
66 | #error "PCI is not supported" | ||
67 | /* NEED mpc83xx_map_irq & mpc83xx_exclude_device | ||
68 | see platforms/85xx/mpc85xx_ads_common.c */ | ||
69 | #endif /* CONFIG_PCI */ | ||
70 | |||
71 | /* ************************************************************************ | ||
72 | * | ||
73 | * Setup the architecture | ||
74 | * | ||
75 | */ | ||
76 | static void __init | ||
77 | mpc834x_sys_setup_arch(void) | ||
78 | { | ||
79 | bd_t *binfo = (bd_t *) __res; | ||
80 | unsigned int freq; | ||
81 | struct gianfar_platform_data *pdata; | ||
82 | |||
83 | /* get the core frequency */ | ||
84 | freq = binfo->bi_intfreq; | ||
85 | |||
86 | /* Set loops_per_jiffy to a half-way reasonable value, | ||
87 | for use until calibrate_delay gets called. */ | ||
88 | loops_per_jiffy = freq / HZ; | ||
89 | |||
90 | #ifdef CONFIG_PCI | ||
91 | /* setup PCI host bridges */ | ||
92 | mpc83xx_sys_setup_hose(); | ||
93 | #endif | ||
94 | mpc83xx_early_serial_map(); | ||
95 | |||
96 | /* setup the board related information for the enet controllers */ | ||
97 | pdata = (struct gianfar_platform_data *) ppc_sys_get_pdata(MPC83xx_TSEC1); | ||
98 | pdata->board_flags = FSL_GIANFAR_BRD_HAS_PHY_INTR; | ||
99 | pdata->interruptPHY = MPC83xx_IRQ_EXT1; | ||
100 | pdata->phyid = 0; | ||
101 | /* fixup phy address */ | ||
102 | pdata->phy_reg_addr += binfo->bi_immr_base; | ||
103 | memcpy(pdata->mac_addr, binfo->bi_enetaddr, 6); | ||
104 | |||
105 | pdata = (struct gianfar_platform_data *) ppc_sys_get_pdata(MPC83xx_TSEC2); | ||
106 | pdata->board_flags = FSL_GIANFAR_BRD_HAS_PHY_INTR; | ||
107 | pdata->interruptPHY = MPC83xx_IRQ_EXT2; | ||
108 | pdata->phyid = 1; | ||
109 | /* fixup phy address */ | ||
110 | pdata->phy_reg_addr += binfo->bi_immr_base; | ||
111 | memcpy(pdata->mac_addr, binfo->bi_enet1addr, 6); | ||
112 | |||
113 | #ifdef CONFIG_BLK_DEV_INITRD | ||
114 | if (initrd_start) | ||
115 | ROOT_DEV = Root_RAM0; | ||
116 | else | ||
117 | #endif | ||
118 | #ifdef CONFIG_ROOT_NFS | ||
119 | ROOT_DEV = Root_NFS; | ||
120 | #else | ||
121 | ROOT_DEV = Root_HDA1; | ||
122 | #endif | ||
123 | } | ||
124 | |||
125 | static void __init | ||
126 | mpc834x_sys_map_io(void) | ||
127 | { | ||
128 | /* we steal the lowest ioremap addr for virt space */ | ||
129 | io_block_mapping(VIRT_IMMRBAR, immrbar, 1024*1024, _PAGE_IO); | ||
130 | io_block_mapping(BCSR_VIRT_ADDR, BCSR_PHYS_ADDR, BCSR_SIZE, _PAGE_IO); | ||
131 | } | ||
132 | |||
133 | int | ||
134 | mpc834x_sys_show_cpuinfo(struct seq_file *m) | ||
135 | { | ||
136 | uint pvid, svid, phid1; | ||
137 | bd_t *binfo = (bd_t *) __res; | ||
138 | unsigned int freq; | ||
139 | |||
140 | /* get the core frequency */ | ||
141 | freq = binfo->bi_intfreq; | ||
142 | |||
143 | pvid = mfspr(SPRN_PVR); | ||
144 | svid = mfspr(SPRN_SVR); | ||
145 | |||
146 | seq_printf(m, "Vendor\t\t: Freescale Inc.\n"); | ||
147 | seq_printf(m, "Machine\t\t: mpc%s sys\n", cur_ppc_sys_spec->ppc_sys_name); | ||
148 | seq_printf(m, "core clock\t: %d MHz\n" | ||
149 | "bus clock\t: %d MHz\n", | ||
150 | (int)(binfo->bi_intfreq / 1000000), | ||
151 | (int)(binfo->bi_busfreq / 1000000)); | ||
152 | seq_printf(m, "PVR\t\t: 0x%x\n", pvid); | ||
153 | seq_printf(m, "SVR\t\t: 0x%x\n", svid); | ||
154 | |||
155 | /* Display cpu Pll setting */ | ||
156 | phid1 = mfspr(SPRN_HID1); | ||
157 | seq_printf(m, "PLL setting\t: 0x%x\n", ((phid1 >> 24) & 0x3f)); | ||
158 | |||
159 | /* Display the amount of memory */ | ||
160 | seq_printf(m, "Memory\t\t: %d MB\n", (int)(binfo->bi_memsize / (1024 * 1024))); | ||
161 | |||
162 | return 0; | ||
163 | } | ||
164 | |||
165 | |||
166 | void __init | ||
167 | mpc834x_sys_init_IRQ(void) | ||
168 | { | ||
169 | bd_t *binfo = (bd_t *) __res; | ||
170 | |||
171 | u8 senses[8] = { | ||
172 | 0, /* EXT 0 */ | ||
173 | IRQ_SENSE_LEVEL, /* EXT 1 */ | ||
174 | IRQ_SENSE_LEVEL, /* EXT 2 */ | ||
175 | 0, /* EXT 3 */ | ||
176 | 0, /* EXT 4 */ | ||
177 | 0, /* EXT 5 */ | ||
178 | 0, /* EXT 6 */ | ||
179 | 0, /* EXT 7 */ | ||
180 | }; | ||
181 | |||
182 | ipic_init(binfo->bi_immr_base + 0x00700, 0, MPC83xx_IPIC_IRQ_OFFSET, senses, 8); | ||
183 | |||
184 | /* Initialize the default interrupt mapping priorities, | ||
185 | * in case the boot rom changed something on us. | ||
186 | */ | ||
187 | ipic_set_default_priority(); | ||
188 | } | ||
189 | |||
190 | static __inline__ void | ||
191 | mpc834x_sys_set_bat(void) | ||
192 | { | ||
193 | /* we steal the lowest ioremap addr for virt space */ | ||
194 | mb(); | ||
195 | mtspr(SPRN_DBAT1U, VIRT_IMMRBAR | 0x1e); | ||
196 | mtspr(SPRN_DBAT1L, immrbar | 0x2a); | ||
197 | mb(); | ||
198 | } | ||
199 | |||
200 | void __init | ||
201 | platform_init(unsigned long r3, unsigned long r4, unsigned long r5, | ||
202 | unsigned long r6, unsigned long r7) | ||
203 | { | ||
204 | bd_t *binfo = (bd_t *) __res; | ||
205 | |||
206 | /* parse_bootinfo must always be called first */ | ||
207 | parse_bootinfo(find_bootinfo()); | ||
208 | |||
209 | /* | ||
210 | * If we were passed in a board information, copy it into the | ||
211 | * residual data area. | ||
212 | */ | ||
213 | if (r3) { | ||
214 | memcpy((void *) __res, (void *) (r3 + KERNELBASE), | ||
215 | sizeof (bd_t)); | ||
216 | } | ||
217 | |||
218 | #if defined(CONFIG_BLK_DEV_INITRD) | ||
219 | /* | ||
220 | * If the init RAM disk has been configured in, and there's a valid | ||
221 | * starting address for it, set it up. | ||
222 | */ | ||
223 | if (r4) { | ||
224 | initrd_start = r4 + KERNELBASE; | ||
225 | initrd_end = r5 + KERNELBASE; | ||
226 | } | ||
227 | #endif /* CONFIG_BLK_DEV_INITRD */ | ||
228 | |||
229 | /* Copy the kernel command line arguments to a safe place. */ | ||
230 | if (r6) { | ||
231 | *(char *) (r7 + KERNELBASE) = 0; | ||
232 | strcpy(cmd_line, (char *) (r6 + KERNELBASE)); | ||
233 | } | ||
234 | |||
235 | immrbar = binfo->bi_immr_base; | ||
236 | |||
237 | mpc834x_sys_set_bat(); | ||
238 | |||
239 | #if defined(CONFIG_SERIAL_8250) && defined(CONFIG_SERIAL_TEXT_DEBUG) | ||
240 | { | ||
241 | struct uart_port p; | ||
242 | |||
243 | memset(&p, 0, sizeof (p)); | ||
244 | p.iotype = SERIAL_IO_MEM; | ||
245 | p.membase = (unsigned char __iomem *)(VIRT_IMMRBAR + 0x4500); | ||
246 | p.uartclk = binfo->bi_busfreq; | ||
247 | |||
248 | gen550_init(0, &p); | ||
249 | |||
250 | memset(&p, 0, sizeof (p)); | ||
251 | p.iotype = SERIAL_IO_MEM; | ||
252 | p.membase = (unsigned char __iomem *)(VIRT_IMMRBAR + 0x4600); | ||
253 | p.uartclk = binfo->bi_busfreq; | ||
254 | |||
255 | gen550_init(1, &p); | ||
256 | } | ||
257 | #endif | ||
258 | |||
259 | identify_ppc_sys_by_id(mfspr(SPRN_SVR)); | ||
260 | |||
261 | /* setup the PowerPC module struct */ | ||
262 | ppc_md.setup_arch = mpc834x_sys_setup_arch; | ||
263 | ppc_md.show_cpuinfo = mpc834x_sys_show_cpuinfo; | ||
264 | |||
265 | ppc_md.init_IRQ = mpc834x_sys_init_IRQ; | ||
266 | ppc_md.get_irq = ipic_get_irq; | ||
267 | |||
268 | ppc_md.restart = mpc83xx_restart; | ||
269 | ppc_md.power_off = mpc83xx_power_off; | ||
270 | ppc_md.halt = mpc83xx_halt; | ||
271 | |||
272 | ppc_md.find_end_of_memory = mpc83xx_find_end_of_memory; | ||
273 | ppc_md.setup_io_mappings = mpc834x_sys_map_io; | ||
274 | |||
275 | ppc_md.time_init = mpc83xx_time_init; | ||
276 | ppc_md.set_rtc_time = NULL; | ||
277 | ppc_md.get_rtc_time = NULL; | ||
278 | ppc_md.calibrate_decr = mpc83xx_calibrate_decr; | ||
279 | |||
280 | ppc_md.early_serial_map = mpc83xx_early_serial_map; | ||
281 | #if defined(CONFIG_SERIAL_8250) && defined(CONFIG_SERIAL_TEXT_DEBUG) | ||
282 | ppc_md.progress = gen550_progress; | ||
283 | #endif /* CONFIG_SERIAL_8250 && CONFIG_SERIAL_TEXT_DEBUG */ | ||
284 | |||
285 | if (ppc_md.progress) | ||
286 | ppc_md.progress("mpc834x_sys_init(): exit", 0); | ||
287 | |||
288 | return; | ||
289 | } | ||
diff --git a/arch/ppc/platforms/83xx/mpc834x_sys.h b/arch/ppc/platforms/83xx/mpc834x_sys.h new file mode 100644 index 000000000000..f4d055ae19c1 --- /dev/null +++ b/arch/ppc/platforms/83xx/mpc834x_sys.h | |||
@@ -0,0 +1,51 @@ | |||
1 | /* | ||
2 | * arch/ppc/platforms/83xx/mpc834x_sys.h | ||
3 | * | ||
4 | * MPC834X SYS common board definitions | ||
5 | * | ||
6 | * Maintainer: Kumar Gala <kumar.gala@freescale.com> | ||
7 | * | ||
8 | * Copyright 2005 Freescale Semiconductor, Inc. | ||
9 | * | ||
10 | * This program is free software; you can redistribute it and/or modify it | ||
11 | * under the terms of the GNU General Public License as published by the | ||
12 | * Free Software Foundation; either version 2 of the License, or (at your | ||
13 | * option) any later version. | ||
14 | * | ||
15 | */ | ||
16 | |||
17 | #ifndef __MACH_MPC83XX_SYS_H__ | ||
18 | #define __MACH_MPC83XX_SYS_H__ | ||
19 | |||
20 | #include <linux/config.h> | ||
21 | #include <linux/init.h> | ||
22 | #include <linux/seq_file.h> | ||
23 | #include <syslib/ppc83xx_setup.h> | ||
24 | #include <asm/ppcboot.h> | ||
25 | |||
26 | #define VIRT_IMMRBAR ((uint)0xfe000000) | ||
27 | |||
28 | #define BCSR_PHYS_ADDR ((uint)0xf8000000) | ||
29 | #define BCSR_VIRT_ADDR ((uint)0xfe100000) | ||
30 | #define BCSR_SIZE ((uint)(32 * 1024)) | ||
31 | |||
32 | #ifdef CONFIG_PCI | ||
33 | /* PCI interrupt controller */ | ||
34 | #define PIRQA MPC83xx_IRQ_IRQ4 | ||
35 | #define PIRQB MPC83xx_IRQ_IRQ5 | ||
36 | #define PIRQC MPC83xx_IRQ_IRQ6 | ||
37 | #define PIRQD MPC83xx_IRQ_IRQ7 | ||
38 | |||
39 | #define MPC834x_SYS_PCI1_LOWER_IO 0x00000000 | ||
40 | #define MPC834x_SYS_PCI1_UPPER_IO 0x00ffffff | ||
41 | |||
42 | #define MPC834x_SYS_PCI1_LOWER_MEM 0x80000000 | ||
43 | #define MPC834x_SYS_PCI1_UPPER_MEM 0x9fffffff | ||
44 | |||
45 | #define MPC834x_SYS_PCI1_IO_BASE 0xe2000000 | ||
46 | #define MPC834x_SYS_PCI1_MEM_OFFSET 0x00000000 | ||
47 | |||
48 | #define MPC834x_SYS_PCI1_IO_SIZE 0x01000000 | ||
49 | #endif /* CONFIG_PCI */ | ||
50 | |||
51 | #endif /* __MACH_MPC83XX_SYS_H__ */ | ||
diff --git a/arch/ppc/platforms/85xx/Kconfig b/arch/ppc/platforms/85xx/Kconfig new file mode 100644 index 000000000000..ff92e38e7da1 --- /dev/null +++ b/arch/ppc/platforms/85xx/Kconfig | |||
@@ -0,0 +1,76 @@ | |||
1 | config 85xx | ||
2 | bool | ||
3 | depends on E500 | ||
4 | default y | ||
5 | |||
6 | config PPC_INDIRECT_PCI_BE | ||
7 | bool | ||
8 | depends on 85xx | ||
9 | default y | ||
10 | |||
11 | menu "Freescale 85xx options" | ||
12 | depends on E500 | ||
13 | |||
14 | choice | ||
15 | prompt "Machine Type" | ||
16 | depends on 85xx | ||
17 | default MPC8540_ADS | ||
18 | |||
19 | config MPC8540_ADS | ||
20 | bool "Freescale MPC8540 ADS" | ||
21 | help | ||
22 | This option enables support for the MPC 8540 ADS evaluation board. | ||
23 | |||
24 | config MPC8555_CDS | ||
25 | bool "Freescale MPC8555 CDS" | ||
26 | help | ||
27 | This option enablese support for the MPC8555 CDS evaluation board. | ||
28 | |||
29 | config MPC8560_ADS | ||
30 | bool "Freescale MPC8560 ADS" | ||
31 | help | ||
32 | This option enables support for the MPC 8560 ADS evaluation board. | ||
33 | |||
34 | config SBC8560 | ||
35 | bool "WindRiver PowerQUICC III SBC8560" | ||
36 | help | ||
37 | This option enables support for the WindRiver PowerQUICC III | ||
38 | SBC8560 board. | ||
39 | |||
40 | config STX_GP3 | ||
41 | bool "Silicon Turnkey Express GP3" | ||
42 | help | ||
43 | This option enables support for the Silicon Turnkey Express GP3 | ||
44 | board. | ||
45 | |||
46 | endchoice | ||
47 | |||
48 | # It's often necessary to know the specific 85xx processor type. | ||
49 | # Fortunately, it is implied (so far) from the board type, so we | ||
50 | # don't need to ask more redundant questions. | ||
51 | config MPC8540 | ||
52 | bool | ||
53 | depends on MPC8540_ADS | ||
54 | default y | ||
55 | |||
56 | config MPC8555 | ||
57 | bool | ||
58 | depends on MPC8555_CDS | ||
59 | default y | ||
60 | |||
61 | config MPC8560 | ||
62 | bool | ||
63 | depends on SBC8560 || MPC8560_ADS || STX_GP3 | ||
64 | default y | ||
65 | |||
66 | config 85xx_PCI2 | ||
67 | bool "Supprt for 2nd PCI host controller" | ||
68 | depends on MPC8555_CDS | ||
69 | default y | ||
70 | |||
71 | config PPC_GEN550 | ||
72 | bool | ||
73 | depends on MPC8540 || SBC8560 || MPC8555 | ||
74 | default y | ||
75 | |||
76 | endmenu | ||
diff --git a/arch/ppc/platforms/85xx/Makefile b/arch/ppc/platforms/85xx/Makefile new file mode 100644 index 000000000000..854fbd298ba2 --- /dev/null +++ b/arch/ppc/platforms/85xx/Makefile | |||
@@ -0,0 +1,8 @@ | |||
1 | # | ||
2 | # Makefile for the PowerPC 85xx linux kernel. | ||
3 | # | ||
4 | obj-$(CONFIG_MPC8540_ADS) += mpc85xx_ads_common.o mpc8540_ads.o | ||
5 | obj-$(CONFIG_MPC8555_CDS) += mpc85xx_cds_common.o | ||
6 | obj-$(CONFIG_MPC8560_ADS) += mpc85xx_ads_common.o mpc8560_ads.o | ||
7 | obj-$(CONFIG_SBC8560) += sbc85xx.o sbc8560.o | ||
8 | obj-$(CONFIG_STX_GP3) += stx_gp3.o | ||
diff --git a/arch/ppc/platforms/85xx/mpc8540_ads.c b/arch/ppc/platforms/85xx/mpc8540_ads.c new file mode 100644 index 000000000000..4d857d6d633d --- /dev/null +++ b/arch/ppc/platforms/85xx/mpc8540_ads.c | |||
@@ -0,0 +1,218 @@ | |||
1 | /* | ||
2 | * arch/ppc/platforms/85xx/mpc8540_ads.c | ||
3 | * | ||
4 | * MPC8540ADS board specific routines | ||
5 | * | ||
6 | * Maintainer: Kumar Gala <kumar.gala@freescale.com> | ||
7 | * | ||
8 | * Copyright 2004 Freescale Semiconductor Inc. | ||
9 | * | ||
10 | * This program is free software; you can redistribute it and/or modify it | ||
11 | * under the terms of the GNU General Public License as published by the | ||
12 | * Free Software Foundation; either version 2 of the License, or (at your | ||
13 | * option) any later version. | ||
14 | */ | ||
15 | |||
16 | #include <linux/config.h> | ||
17 | #include <linux/stddef.h> | ||
18 | #include <linux/kernel.h> | ||
19 | #include <linux/init.h> | ||
20 | #include <linux/errno.h> | ||
21 | #include <linux/reboot.h> | ||
22 | #include <linux/pci.h> | ||
23 | #include <linux/kdev_t.h> | ||
24 | #include <linux/major.h> | ||
25 | #include <linux/console.h> | ||
26 | #include <linux/delay.h> | ||
27 | #include <linux/irq.h> | ||
28 | #include <linux/seq_file.h> | ||
29 | #include <linux/root_dev.h> | ||
30 | #include <linux/serial.h> | ||
31 | #include <linux/tty.h> /* for linux/serial_core.h */ | ||
32 | #include <linux/serial_core.h> | ||
33 | #include <linux/initrd.h> | ||
34 | #include <linux/module.h> | ||
35 | #include <linux/fsl_devices.h> | ||
36 | |||
37 | #include <asm/system.h> | ||
38 | #include <asm/pgtable.h> | ||
39 | #include <asm/page.h> | ||
40 | #include <asm/atomic.h> | ||
41 | #include <asm/time.h> | ||
42 | #include <asm/io.h> | ||
43 | #include <asm/machdep.h> | ||
44 | #include <asm/prom.h> | ||
45 | #include <asm/open_pic.h> | ||
46 | #include <asm/bootinfo.h> | ||
47 | #include <asm/pci-bridge.h> | ||
48 | #include <asm/mpc85xx.h> | ||
49 | #include <asm/irq.h> | ||
50 | #include <asm/immap_85xx.h> | ||
51 | #include <asm/kgdb.h> | ||
52 | #include <asm/ppc_sys.h> | ||
53 | #include <mm/mmu_decl.h> | ||
54 | |||
55 | #include <syslib/ppc85xx_setup.h> | ||
56 | |||
57 | /* ************************************************************************ | ||
58 | * | ||
59 | * Setup the architecture | ||
60 | * | ||
61 | */ | ||
62 | static void __init | ||
63 | mpc8540ads_setup_arch(void) | ||
64 | { | ||
65 | bd_t *binfo = (bd_t *) __res; | ||
66 | unsigned int freq; | ||
67 | struct gianfar_platform_data *pdata; | ||
68 | |||
69 | /* get the core frequency */ | ||
70 | freq = binfo->bi_intfreq; | ||
71 | |||
72 | if (ppc_md.progress) | ||
73 | ppc_md.progress("mpc8540ads_setup_arch()", 0); | ||
74 | |||
75 | /* Set loops_per_jiffy to a half-way reasonable value, | ||
76 | for use until calibrate_delay gets called. */ | ||
77 | loops_per_jiffy = freq / HZ; | ||
78 | |||
79 | #ifdef CONFIG_PCI | ||
80 | /* setup PCI host bridges */ | ||
81 | mpc85xx_setup_hose(); | ||
82 | #endif | ||
83 | |||
84 | #ifdef CONFIG_SERIAL_8250 | ||
85 | mpc85xx_early_serial_map(); | ||
86 | #endif | ||
87 | |||
88 | #ifdef CONFIG_SERIAL_TEXT_DEBUG | ||
89 | /* Invalidate the entry we stole earlier the serial ports | ||
90 | * should be properly mapped */ | ||
91 | invalidate_tlbcam_entry(NUM_TLBCAMS - 1); | ||
92 | #endif | ||
93 | |||
94 | /* setup the board related information for the enet controllers */ | ||
95 | pdata = (struct gianfar_platform_data *) ppc_sys_get_pdata(MPC85xx_TSEC1); | ||
96 | pdata->board_flags = FSL_GIANFAR_BRD_HAS_PHY_INTR; | ||
97 | pdata->interruptPHY = MPC85xx_IRQ_EXT5; | ||
98 | pdata->phyid = 0; | ||
99 | /* fixup phy address */ | ||
100 | pdata->phy_reg_addr += binfo->bi_immr_base; | ||
101 | memcpy(pdata->mac_addr, binfo->bi_enetaddr, 6); | ||
102 | |||
103 | pdata = (struct gianfar_platform_data *) ppc_sys_get_pdata(MPC85xx_TSEC2); | ||
104 | pdata->board_flags = FSL_GIANFAR_BRD_HAS_PHY_INTR; | ||
105 | pdata->interruptPHY = MPC85xx_IRQ_EXT5; | ||
106 | pdata->phyid = 1; | ||
107 | /* fixup phy address */ | ||
108 | pdata->phy_reg_addr += binfo->bi_immr_base; | ||
109 | memcpy(pdata->mac_addr, binfo->bi_enet1addr, 6); | ||
110 | |||
111 | pdata = (struct gianfar_platform_data *) ppc_sys_get_pdata(MPC85xx_FEC); | ||
112 | pdata->board_flags = 0; | ||
113 | pdata->interruptPHY = MPC85xx_IRQ_EXT5; | ||
114 | pdata->phyid = 3; | ||
115 | /* fixup phy address */ | ||
116 | pdata->phy_reg_addr += binfo->bi_immr_base; | ||
117 | memcpy(pdata->mac_addr, binfo->bi_enet2addr, 6); | ||
118 | |||
119 | #ifdef CONFIG_BLK_DEV_INITRD | ||
120 | if (initrd_start) | ||
121 | ROOT_DEV = Root_RAM0; | ||
122 | else | ||
123 | #endif | ||
124 | #ifdef CONFIG_ROOT_NFS | ||
125 | ROOT_DEV = Root_NFS; | ||
126 | #else | ||
127 | ROOT_DEV = Root_HDA1; | ||
128 | #endif | ||
129 | } | ||
130 | |||
131 | /* ************************************************************************ */ | ||
132 | void __init | ||
133 | platform_init(unsigned long r3, unsigned long r4, unsigned long r5, | ||
134 | unsigned long r6, unsigned long r7) | ||
135 | { | ||
136 | /* parse_bootinfo must always be called first */ | ||
137 | parse_bootinfo(find_bootinfo()); | ||
138 | |||
139 | /* | ||
140 | * If we were passed in a board information, copy it into the | ||
141 | * residual data area. | ||
142 | */ | ||
143 | if (r3) { | ||
144 | memcpy((void *) __res, (void *) (r3 + KERNELBASE), | ||
145 | sizeof (bd_t)); | ||
146 | } | ||
147 | #ifdef CONFIG_SERIAL_TEXT_DEBUG | ||
148 | { | ||
149 | bd_t *binfo = (bd_t *) __res; | ||
150 | struct uart_port p; | ||
151 | |||
152 | /* Use the last TLB entry to map CCSRBAR to allow access to DUART regs */ | ||
153 | settlbcam(NUM_TLBCAMS - 1, binfo->bi_immr_base, | ||
154 | binfo->bi_immr_base, MPC85xx_CCSRBAR_SIZE, _PAGE_IO, 0); | ||
155 | |||
156 | memset(&p, 0, sizeof (p)); | ||
157 | p.iotype = SERIAL_IO_MEM; | ||
158 | p.membase = (void *) binfo->bi_immr_base + MPC85xx_UART0_OFFSET; | ||
159 | p.uartclk = binfo->bi_busfreq; | ||
160 | |||
161 | gen550_init(0, &p); | ||
162 | |||
163 | memset(&p, 0, sizeof (p)); | ||
164 | p.iotype = SERIAL_IO_MEM; | ||
165 | p.membase = (void *) binfo->bi_immr_base + MPC85xx_UART1_OFFSET; | ||
166 | p.uartclk = binfo->bi_busfreq; | ||
167 | |||
168 | gen550_init(1, &p); | ||
169 | } | ||
170 | #endif | ||
171 | |||
172 | #if defined(CONFIG_BLK_DEV_INITRD) | ||
173 | /* | ||
174 | * If the init RAM disk has been configured in, and there's a valid | ||
175 | * starting address for it, set it up. | ||
176 | */ | ||
177 | if (r4) { | ||
178 | initrd_start = r4 + KERNELBASE; | ||
179 | initrd_end = r5 + KERNELBASE; | ||
180 | } | ||
181 | #endif /* CONFIG_BLK_DEV_INITRD */ | ||
182 | |||
183 | /* Copy the kernel command line arguments to a safe place. */ | ||
184 | |||
185 | if (r6) { | ||
186 | *(char *) (r7 + KERNELBASE) = 0; | ||
187 | strcpy(cmd_line, (char *) (r6 + KERNELBASE)); | ||
188 | } | ||
189 | |||
190 | identify_ppc_sys_by_id(mfspr(SPRN_SVR)); | ||
191 | |||
192 | /* setup the PowerPC module struct */ | ||
193 | ppc_md.setup_arch = mpc8540ads_setup_arch; | ||
194 | ppc_md.show_cpuinfo = mpc85xx_ads_show_cpuinfo; | ||
195 | |||
196 | ppc_md.init_IRQ = mpc85xx_ads_init_IRQ; | ||
197 | ppc_md.get_irq = openpic_get_irq; | ||
198 | |||
199 | ppc_md.restart = mpc85xx_restart; | ||
200 | ppc_md.power_off = mpc85xx_power_off; | ||
201 | ppc_md.halt = mpc85xx_halt; | ||
202 | |||
203 | ppc_md.find_end_of_memory = mpc85xx_find_end_of_memory; | ||
204 | |||
205 | ppc_md.time_init = NULL; | ||
206 | ppc_md.set_rtc_time = NULL; | ||
207 | ppc_md.get_rtc_time = NULL; | ||
208 | ppc_md.calibrate_decr = mpc85xx_calibrate_decr; | ||
209 | |||
210 | #if defined(CONFIG_SERIAL_8250) && defined(CONFIG_SERIAL_TEXT_DEBUG) | ||
211 | ppc_md.progress = gen550_progress; | ||
212 | #endif /* CONFIG_SERIAL_8250 && CONFIG_SERIAL_TEXT_DEBUG */ | ||
213 | |||
214 | if (ppc_md.progress) | ||
215 | ppc_md.progress("mpc8540ads_init(): exit", 0); | ||
216 | |||
217 | return; | ||
218 | } | ||
diff --git a/arch/ppc/platforms/85xx/mpc8540_ads.h b/arch/ppc/platforms/85xx/mpc8540_ads.h new file mode 100644 index 000000000000..3d05d7c4a938 --- /dev/null +++ b/arch/ppc/platforms/85xx/mpc8540_ads.h | |||
@@ -0,0 +1,25 @@ | |||
1 | /* | ||
2 | * arch/ppc/platforms/85xx/mpc8540_ads.h | ||
3 | * | ||
4 | * MPC8540ADS board definitions | ||
5 | * | ||
6 | * Maintainer: Kumar Gala <kumar.gala@freescale.com> | ||
7 | * | ||
8 | * Copyright 2004 Freescale Semiconductor Inc. | ||
9 | * | ||
10 | * This program is free software; you can redistribute it and/or modify it | ||
11 | * under the terms of the GNU General Public License as published by the | ||
12 | * Free Software Foundation; either version 2 of the License, or (at your | ||
13 | * option) any later version. | ||
14 | * | ||
15 | */ | ||
16 | |||
17 | #ifndef __MACH_MPC8540ADS_H__ | ||
18 | #define __MACH_MPC8540ADS_H__ | ||
19 | |||
20 | #include <linux/config.h> | ||
21 | #include <linux/initrd.h> | ||
22 | #include <syslib/ppc85xx_setup.h> | ||
23 | #include <platforms/85xx/mpc85xx_ads_common.h> | ||
24 | |||
25 | #endif /* __MACH_MPC8540ADS_H__ */ | ||
diff --git a/arch/ppc/platforms/85xx/mpc8555_cds.h b/arch/ppc/platforms/85xx/mpc8555_cds.h new file mode 100644 index 000000000000..e0e75568bc57 --- /dev/null +++ b/arch/ppc/platforms/85xx/mpc8555_cds.h | |||
@@ -0,0 +1,26 @@ | |||
1 | /* | ||
2 | * arch/ppc/platforms/mpc8555_cds.h | ||
3 | * | ||
4 | * MPC8555CDS board definitions | ||
5 | * | ||
6 | * Maintainer: Kumar Gala <kumar.gala@freescale.com> | ||
7 | * | ||
8 | * Copyright 2004 Freescale Semiconductor Inc. | ||
9 | * | ||
10 | * This program is free software; you can redistribute it and/or modify it | ||
11 | * under the terms of the GNU General Public License as published by the | ||
12 | * Free Software Foundation; either version 2 of the License, or (at your | ||
13 | * option) any later version. | ||
14 | * | ||
15 | */ | ||
16 | |||
17 | #ifndef __MACH_MPC8555CDS_H__ | ||
18 | #define __MACH_MPC8555CDS_H__ | ||
19 | |||
20 | #include <linux/config.h> | ||
21 | #include <syslib/ppc85xx_setup.h> | ||
22 | #include <platforms/85xx/mpc85xx_cds_common.h> | ||
23 | |||
24 | #define CPM_MAP_ADDR (CCSRBAR + MPC85xx_CPM_OFFSET) | ||
25 | |||
26 | #endif /* __MACH_MPC8555CDS_H__ */ | ||
diff --git a/arch/ppc/platforms/85xx/mpc8560_ads.c b/arch/ppc/platforms/85xx/mpc8560_ads.c new file mode 100644 index 000000000000..761b8c7b25d2 --- /dev/null +++ b/arch/ppc/platforms/85xx/mpc8560_ads.c | |||
@@ -0,0 +1,210 @@ | |||
1 | /* | ||
2 | * arch/ppc/platforms/85xx/mpc8560_ads.c | ||
3 | * | ||
4 | * MPC8560ADS board specific routines | ||
5 | * | ||
6 | * Maintainer: Kumar Gala <kumar.gala@freescale.com> | ||
7 | * | ||
8 | * Copyright 2004 Freescale Semiconductor Inc. | ||
9 | * | ||
10 | * This program is free software; you can redistribute it and/or modify it | ||
11 | * under the terms of the GNU General Public License as published by the | ||
12 | * Free Software Foundation; either version 2 of the License, or (at your | ||
13 | * option) any later version. | ||
14 | */ | ||
15 | |||
16 | #include <linux/config.h> | ||
17 | #include <linux/stddef.h> | ||
18 | #include <linux/kernel.h> | ||
19 | #include <linux/init.h> | ||
20 | #include <linux/errno.h> | ||
21 | #include <linux/reboot.h> | ||
22 | #include <linux/pci.h> | ||
23 | #include <linux/kdev_t.h> | ||
24 | #include <linux/major.h> | ||
25 | #include <linux/console.h> | ||
26 | #include <linux/delay.h> | ||
27 | #include <linux/irq.h> | ||
28 | #include <linux/seq_file.h> | ||
29 | #include <linux/root_dev.h> | ||
30 | #include <linux/serial.h> | ||
31 | #include <linux/tty.h> /* for linux/serial_core.h */ | ||
32 | #include <linux/serial_core.h> | ||
33 | #include <linux/initrd.h> | ||
34 | #include <linux/module.h> | ||
35 | #include <linux/fsl_devices.h> | ||
36 | |||
37 | #include <asm/system.h> | ||
38 | #include <asm/pgtable.h> | ||
39 | #include <asm/page.h> | ||
40 | #include <asm/atomic.h> | ||
41 | #include <asm/time.h> | ||
42 | #include <asm/io.h> | ||
43 | #include <asm/machdep.h> | ||
44 | #include <asm/prom.h> | ||
45 | #include <asm/open_pic.h> | ||
46 | #include <asm/bootinfo.h> | ||
47 | #include <asm/pci-bridge.h> | ||
48 | #include <asm/mpc85xx.h> | ||
49 | #include <asm/irq.h> | ||
50 | #include <asm/immap_85xx.h> | ||
51 | #include <asm/kgdb.h> | ||
52 | #include <asm/ppc_sys.h> | ||
53 | #include <asm/cpm2.h> | ||
54 | #include <mm/mmu_decl.h> | ||
55 | |||
56 | #include <syslib/cpm2_pic.h> | ||
57 | #include <syslib/ppc85xx_common.h> | ||
58 | #include <syslib/ppc85xx_setup.h> | ||
59 | |||
60 | extern void cpm2_reset(void); | ||
61 | |||
62 | /* ************************************************************************ | ||
63 | * | ||
64 | * Setup the architecture | ||
65 | * | ||
66 | */ | ||
67 | |||
68 | static void __init | ||
69 | mpc8560ads_setup_arch(void) | ||
70 | { | ||
71 | bd_t *binfo = (bd_t *) __res; | ||
72 | unsigned int freq; | ||
73 | struct gianfar_platform_data *pdata; | ||
74 | |||
75 | cpm2_reset(); | ||
76 | |||
77 | /* get the core frequency */ | ||
78 | freq = binfo->bi_intfreq; | ||
79 | |||
80 | if (ppc_md.progress) | ||
81 | ppc_md.progress("mpc8560ads_setup_arch()", 0); | ||
82 | |||
83 | /* Set loops_per_jiffy to a half-way reasonable value, | ||
84 | for use until calibrate_delay gets called. */ | ||
85 | loops_per_jiffy = freq / HZ; | ||
86 | |||
87 | #ifdef CONFIG_PCI | ||
88 | /* setup PCI host bridges */ | ||
89 | mpc85xx_setup_hose(); | ||
90 | #endif | ||
91 | |||
92 | /* setup the board related information for the enet controllers */ | ||
93 | pdata = (struct gianfar_platform_data *) ppc_sys_get_pdata(MPC85xx_TSEC1); | ||
94 | pdata->board_flags = FSL_GIANFAR_BRD_HAS_PHY_INTR; | ||
95 | pdata->interruptPHY = MPC85xx_IRQ_EXT5; | ||
96 | pdata->phyid = 0; | ||
97 | /* fixup phy address */ | ||
98 | pdata->phy_reg_addr += binfo->bi_immr_base; | ||
99 | memcpy(pdata->mac_addr, binfo->bi_enetaddr, 6); | ||
100 | |||
101 | pdata = (struct gianfar_platform_data *) ppc_sys_get_pdata(MPC85xx_TSEC2); | ||
102 | pdata->board_flags = FSL_GIANFAR_BRD_HAS_PHY_INTR; | ||
103 | pdata->interruptPHY = MPC85xx_IRQ_EXT5; | ||
104 | pdata->phyid = 1; | ||
105 | /* fixup phy address */ | ||
106 | pdata->phy_reg_addr += binfo->bi_immr_base; | ||
107 | memcpy(pdata->mac_addr, binfo->bi_enet1addr, 6); | ||
108 | |||
109 | #ifdef CONFIG_BLK_DEV_INITRD | ||
110 | if (initrd_start) | ||
111 | ROOT_DEV = Root_RAM0; | ||
112 | else | ||
113 | #endif | ||
114 | #ifdef CONFIG_ROOT_NFS | ||
115 | ROOT_DEV = Root_NFS; | ||
116 | #else | ||
117 | ROOT_DEV = Root_HDA1; | ||
118 | #endif | ||
119 | } | ||
120 | |||
121 | static irqreturn_t cpm2_cascade(int irq, void *dev_id, struct pt_regs *regs) | ||
122 | { | ||
123 | while ((irq = cpm2_get_irq(regs)) >= 0) | ||
124 | __do_IRQ(irq, regs); | ||
125 | return IRQ_HANDLED; | ||
126 | } | ||
127 | |||
128 | static struct irqaction cpm2_irqaction = { | ||
129 | .handler = cpm2_cascade, | ||
130 | .flags = SA_INTERRUPT, | ||
131 | .mask = CPU_MASK_NONE, | ||
132 | .name = "cpm2_cascade", | ||
133 | }; | ||
134 | |||
135 | static void __init | ||
136 | mpc8560_ads_init_IRQ(void) | ||
137 | { | ||
138 | /* Setup OpenPIC */ | ||
139 | mpc85xx_ads_init_IRQ(); | ||
140 | |||
141 | /* Setup CPM2 PIC */ | ||
142 | cpm2_init_IRQ(); | ||
143 | |||
144 | setup_irq(MPC85xx_IRQ_CPM, &cpm2_irqaction); | ||
145 | |||
146 | return; | ||
147 | } | ||
148 | |||
149 | |||
150 | |||
151 | /* ************************************************************************ */ | ||
152 | void __init | ||
153 | platform_init(unsigned long r3, unsigned long r4, unsigned long r5, | ||
154 | unsigned long r6, unsigned long r7) | ||
155 | { | ||
156 | /* parse_bootinfo must always be called first */ | ||
157 | parse_bootinfo(find_bootinfo()); | ||
158 | |||
159 | /* | ||
160 | * If we were passed in a board information, copy it into the | ||
161 | * residual data area. | ||
162 | */ | ||
163 | if (r3) { | ||
164 | memcpy((void *) __res, (void *) (r3 + KERNELBASE), | ||
165 | sizeof (bd_t)); | ||
166 | |||
167 | } | ||
168 | #if defined(CONFIG_BLK_DEV_INITRD) | ||
169 | /* | ||
170 | * If the init RAM disk has been configured in, and there's a valid | ||
171 | * starting address for it, set it up. | ||
172 | */ | ||
173 | if (r4) { | ||
174 | initrd_start = r4 + KERNELBASE; | ||
175 | initrd_end = r5 + KERNELBASE; | ||
176 | } | ||
177 | #endif /* CONFIG_BLK_DEV_INITRD */ | ||
178 | |||
179 | /* Copy the kernel command line arguments to a safe place. */ | ||
180 | |||
181 | if (r6) { | ||
182 | *(char *) (r7 + KERNELBASE) = 0; | ||
183 | strcpy(cmd_line, (char *) (r6 + KERNELBASE)); | ||
184 | } | ||
185 | |||
186 | identify_ppc_sys_by_id(mfspr(SPRN_SVR)); | ||
187 | |||
188 | /* setup the PowerPC module struct */ | ||
189 | ppc_md.setup_arch = mpc8560ads_setup_arch; | ||
190 | ppc_md.show_cpuinfo = mpc85xx_ads_show_cpuinfo; | ||
191 | |||
192 | ppc_md.init_IRQ = mpc8560_ads_init_IRQ; | ||
193 | ppc_md.get_irq = openpic_get_irq; | ||
194 | |||
195 | ppc_md.restart = mpc85xx_restart; | ||
196 | ppc_md.power_off = mpc85xx_power_off; | ||
197 | ppc_md.halt = mpc85xx_halt; | ||
198 | |||
199 | ppc_md.find_end_of_memory = mpc85xx_find_end_of_memory; | ||
200 | |||
201 | ppc_md.time_init = NULL; | ||
202 | ppc_md.set_rtc_time = NULL; | ||
203 | ppc_md.get_rtc_time = NULL; | ||
204 | ppc_md.calibrate_decr = mpc85xx_calibrate_decr; | ||
205 | |||
206 | if (ppc_md.progress) | ||
207 | ppc_md.progress("mpc8560ads_init(): exit", 0); | ||
208 | |||
209 | return; | ||
210 | } | ||
diff --git a/arch/ppc/platforms/85xx/mpc8560_ads.h b/arch/ppc/platforms/85xx/mpc8560_ads.h new file mode 100644 index 000000000000..7df885d73e9d --- /dev/null +++ b/arch/ppc/platforms/85xx/mpc8560_ads.h | |||
@@ -0,0 +1,27 @@ | |||
1 | /* | ||
2 | * arch/ppc/platforms/mpc8560_ads.h | ||
3 | * | ||
4 | * MPC8540ADS board definitions | ||
5 | * | ||
6 | * Maintainer: Kumar Gala <kumar.gala@freescale.com> | ||
7 | * | ||
8 | * Copyright 2004 Freescale Semiconductor Inc. | ||
9 | * | ||
10 | * This program is free software; you can redistribute it and/or modify it | ||
11 | * under the terms of the GNU General Public License as published by the | ||
12 | * Free Software Foundation; either version 2 of the License, or (at your | ||
13 | * option) any later version. | ||
14 | * | ||
15 | */ | ||
16 | |||
17 | #ifndef __MACH_MPC8560ADS_H | ||
18 | #define __MACH_MPC8560ADS_H | ||
19 | |||
20 | #include <linux/config.h> | ||
21 | #include <syslib/ppc85xx_setup.h> | ||
22 | #include <platforms/85xx/mpc85xx_ads_common.h> | ||
23 | |||
24 | #define CPM_MAP_ADDR (CCSRBAR + MPC85xx_CPM_OFFSET) | ||
25 | #define PHY_INTERRUPT MPC85xx_IRQ_EXT7 | ||
26 | |||
27 | #endif /* __MACH_MPC8560ADS_H */ | ||
diff --git a/arch/ppc/platforms/85xx/mpc85xx_ads_common.c b/arch/ppc/platforms/85xx/mpc85xx_ads_common.c new file mode 100644 index 000000000000..ba9f9f562c45 --- /dev/null +++ b/arch/ppc/platforms/85xx/mpc85xx_ads_common.c | |||
@@ -0,0 +1,225 @@ | |||
1 | /* | ||
2 | * arch/ppc/platforms/85xx/mpc85xx_ads_common.c | ||
3 | * | ||
4 | * MPC85xx ADS board common routines | ||
5 | * | ||
6 | * Maintainer: Kumar Gala <kumar.gala@freescale.com> | ||
7 | * | ||
8 | * Copyright 2004 Freescale Semiconductor Inc. | ||
9 | * | ||
10 | * This program is free software; you can redistribute it and/or modify it | ||
11 | * under the terms of the GNU General Public License as published by the | ||
12 | * Free Software Foundation; either version 2 of the License, or (at your | ||
13 | * option) any later version. | ||
14 | */ | ||
15 | |||
16 | #include <linux/config.h> | ||
17 | #include <linux/stddef.h> | ||
18 | #include <linux/kernel.h> | ||
19 | #include <linux/init.h> | ||
20 | #include <linux/errno.h> | ||
21 | #include <linux/reboot.h> | ||
22 | #include <linux/pci.h> | ||
23 | #include <linux/kdev_t.h> | ||
24 | #include <linux/major.h> | ||
25 | #include <linux/console.h> | ||
26 | #include <linux/delay.h> | ||
27 | #include <linux/irq.h> | ||
28 | #include <linux/seq_file.h> | ||
29 | #include <linux/serial.h> | ||
30 | #include <linux/module.h> | ||
31 | |||
32 | #include <asm/system.h> | ||
33 | #include <asm/pgtable.h> | ||
34 | #include <asm/page.h> | ||
35 | #include <asm/atomic.h> | ||
36 | #include <asm/time.h> | ||
37 | #include <asm/io.h> | ||
38 | #include <asm/machdep.h> | ||
39 | #include <asm/prom.h> | ||
40 | #include <asm/open_pic.h> | ||
41 | #include <asm/bootinfo.h> | ||
42 | #include <asm/pci-bridge.h> | ||
43 | #include <asm/mpc85xx.h> | ||
44 | #include <asm/irq.h> | ||
45 | #include <asm/immap_85xx.h> | ||
46 | #include <asm/ppc_sys.h> | ||
47 | |||
48 | #include <mm/mmu_decl.h> | ||
49 | |||
50 | #include <platforms/85xx/mpc85xx_ads_common.h> | ||
51 | |||
52 | #ifndef CONFIG_PCI | ||
53 | unsigned long isa_io_base = 0; | ||
54 | unsigned long isa_mem_base = 0; | ||
55 | #endif | ||
56 | |||
57 | extern unsigned long total_memory; /* in mm/init */ | ||
58 | |||
59 | unsigned char __res[sizeof (bd_t)]; | ||
60 | |||
61 | /* Internal interrupts are all Level Sensitive, and Positive Polarity */ | ||
62 | |||
63 | static u_char mpc85xx_ads_openpic_initsenses[] __initdata = { | ||
64 | (IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE), /* Internal 0: L2 Cache */ | ||
65 | (IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE), /* Internal 1: ECM */ | ||
66 | (IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE), /* Internal 2: DDR DRAM */ | ||
67 | (IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE), /* Internal 3: LBIU */ | ||
68 | (IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE), /* Internal 4: DMA 0 */ | ||
69 | (IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE), /* Internal 5: DMA 1 */ | ||
70 | (IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE), /* Internal 6: DMA 2 */ | ||
71 | (IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE), /* Internal 7: DMA 3 */ | ||
72 | (IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE), /* Internal 8: PCI/PCI-X */ | ||
73 | (IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE), /* Internal 9: RIO Inbound Port Write Error */ | ||
74 | (IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE), /* Internal 10: RIO Doorbell Inbound */ | ||
75 | (IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE), /* Internal 11: RIO Outbound Message */ | ||
76 | (IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE), /* Internal 12: RIO Inbound Message */ | ||
77 | (IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE), /* Internal 13: TSEC 0 Transmit */ | ||
78 | (IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE), /* Internal 14: TSEC 0 Receive */ | ||
79 | (IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE), /* Internal 15: Unused */ | ||
80 | (IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE), /* Internal 16: Unused */ | ||
81 | (IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE), /* Internal 17: Unused */ | ||
82 | (IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE), /* Internal 18: TSEC 0 Receive/Transmit Error */ | ||
83 | (IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE), /* Internal 19: TSEC 1 Transmit */ | ||
84 | (IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE), /* Internal 20: TSEC 1 Receive */ | ||
85 | (IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE), /* Internal 21: Unused */ | ||
86 | (IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE), /* Internal 22: Unused */ | ||
87 | (IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE), /* Internal 23: Unused */ | ||
88 | (IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE), /* Internal 24: TSEC 1 Receive/Transmit Error */ | ||
89 | (IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE), /* Internal 25: Fast Ethernet */ | ||
90 | (IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE), /* Internal 26: DUART */ | ||
91 | (IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE), /* Internal 27: I2C */ | ||
92 | (IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE), /* Internal 28: Performance Monitor */ | ||
93 | (IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE), /* Internal 29: Unused */ | ||
94 | (IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE), /* Internal 30: CPM */ | ||
95 | (IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE), /* Internal 31: Unused */ | ||
96 | 0x0, /* External 0: */ | ||
97 | #if defined(CONFIG_PCI) | ||
98 | (IRQ_SENSE_LEVEL | IRQ_POLARITY_NEGATIVE), /* External 1: PCI slot 0 */ | ||
99 | (IRQ_SENSE_LEVEL | IRQ_POLARITY_NEGATIVE), /* External 2: PCI slot 1 */ | ||
100 | (IRQ_SENSE_LEVEL | IRQ_POLARITY_NEGATIVE), /* External 3: PCI slot 2 */ | ||
101 | (IRQ_SENSE_LEVEL | IRQ_POLARITY_NEGATIVE), /* External 4: PCI slot 3 */ | ||
102 | #else | ||
103 | 0x0, /* External 1: */ | ||
104 | 0x0, /* External 2: */ | ||
105 | 0x0, /* External 3: */ | ||
106 | 0x0, /* External 4: */ | ||
107 | #endif | ||
108 | (IRQ_SENSE_LEVEL | IRQ_POLARITY_NEGATIVE), /* External 5: PHY */ | ||
109 | 0x0, /* External 6: */ | ||
110 | (IRQ_SENSE_LEVEL | IRQ_POLARITY_NEGATIVE), /* External 7: PHY */ | ||
111 | 0x0, /* External 8: */ | ||
112 | 0x0, /* External 9: */ | ||
113 | 0x0, /* External 10: */ | ||
114 | 0x0, /* External 11: */ | ||
115 | }; | ||
116 | |||
117 | /* ************************************************************************ */ | ||
118 | int | ||
119 | mpc85xx_ads_show_cpuinfo(struct seq_file *m) | ||
120 | { | ||
121 | uint pvid, svid, phid1; | ||
122 | uint memsize = total_memory; | ||
123 | bd_t *binfo = (bd_t *) __res; | ||
124 | unsigned int freq; | ||
125 | |||
126 | /* get the core frequency */ | ||
127 | freq = binfo->bi_intfreq; | ||
128 | |||
129 | pvid = mfspr(SPRN_PVR); | ||
130 | svid = mfspr(SPRN_SVR); | ||
131 | |||
132 | seq_printf(m, "Vendor\t\t: Freescale Semiconductor\n"); | ||
133 | seq_printf(m, "Machine\t\t: mpc%sads\n", cur_ppc_sys_spec->ppc_sys_name); | ||
134 | seq_printf(m, "clock\t\t: %dMHz\n", freq / 1000000); | ||
135 | seq_printf(m, "PVR\t\t: 0x%x\n", pvid); | ||
136 | seq_printf(m, "SVR\t\t: 0x%x\n", svid); | ||
137 | |||
138 | /* Display cpu Pll setting */ | ||
139 | phid1 = mfspr(SPRN_HID1); | ||
140 | seq_printf(m, "PLL setting\t: 0x%x\n", ((phid1 >> 24) & 0x3f)); | ||
141 | |||
142 | /* Display the amount of memory */ | ||
143 | seq_printf(m, "Memory\t\t: %d MB\n", memsize / (1024 * 1024)); | ||
144 | |||
145 | return 0; | ||
146 | } | ||
147 | |||
148 | void __init | ||
149 | mpc85xx_ads_init_IRQ(void) | ||
150 | { | ||
151 | bd_t *binfo = (bd_t *) __res; | ||
152 | /* Determine the Physical Address of the OpenPIC regs */ | ||
153 | phys_addr_t OpenPIC_PAddr = | ||
154 | binfo->bi_immr_base + MPC85xx_OPENPIC_OFFSET; | ||
155 | OpenPIC_Addr = ioremap(OpenPIC_PAddr, MPC85xx_OPENPIC_SIZE); | ||
156 | OpenPIC_InitSenses = mpc85xx_ads_openpic_initsenses; | ||
157 | OpenPIC_NumInitSenses = sizeof (mpc85xx_ads_openpic_initsenses); | ||
158 | |||
159 | /* Skip reserved space and internal sources */ | ||
160 | openpic_set_sources(0, 32, OpenPIC_Addr + 0x10200); | ||
161 | /* Map PIC IRQs 0-11 */ | ||
162 | openpic_set_sources(32, 12, OpenPIC_Addr + 0x10000); | ||
163 | |||
164 | /* we let openpic interrupts starting from an offset, to | ||
165 | * leave space for cascading interrupts underneath. | ||
166 | */ | ||
167 | openpic_init(MPC85xx_OPENPIC_IRQ_OFFSET); | ||
168 | |||
169 | return; | ||
170 | } | ||
171 | |||
172 | #ifdef CONFIG_PCI | ||
173 | /* | ||
174 | * interrupt routing | ||
175 | */ | ||
176 | |||
177 | int | ||
178 | mpc85xx_map_irq(struct pci_dev *dev, unsigned char idsel, unsigned char pin) | ||
179 | { | ||
180 | static char pci_irq_table[][4] = | ||
181 | /* | ||
182 | * This is little evil, but works around the fact | ||
183 | * that revA boards have IDSEL starting at 18 | ||
184 | * and others boards (older) start at 12 | ||
185 | * | ||
186 | * PCI IDSEL/INTPIN->INTLINE | ||
187 | * A B C D | ||
188 | */ | ||
189 | { | ||
190 | {PIRQA, PIRQB, PIRQC, PIRQD}, /* IDSEL 2 */ | ||
191 | {PIRQD, PIRQA, PIRQB, PIRQC}, | ||
192 | {PIRQC, PIRQD, PIRQA, PIRQB}, | ||
193 | {PIRQB, PIRQC, PIRQD, PIRQA}, /* IDSEL 5 */ | ||
194 | {0, 0, 0, 0}, /* -- */ | ||
195 | {0, 0, 0, 0}, /* -- */ | ||
196 | {0, 0, 0, 0}, /* -- */ | ||
197 | {0, 0, 0, 0}, /* -- */ | ||
198 | {0, 0, 0, 0}, /* -- */ | ||
199 | {0, 0, 0, 0}, /* -- */ | ||
200 | {PIRQA, PIRQB, PIRQC, PIRQD}, /* IDSEL 12 */ | ||
201 | {PIRQD, PIRQA, PIRQB, PIRQC}, | ||
202 | {PIRQC, PIRQD, PIRQA, PIRQB}, | ||
203 | {PIRQB, PIRQC, PIRQD, PIRQA}, /* IDSEL 15 */ | ||
204 | {0, 0, 0, 0}, /* -- */ | ||
205 | {0, 0, 0, 0}, /* -- */ | ||
206 | {PIRQA, PIRQB, PIRQC, PIRQD}, /* IDSEL 18 */ | ||
207 | {PIRQD, PIRQA, PIRQB, PIRQC}, | ||
208 | {PIRQC, PIRQD, PIRQA, PIRQB}, | ||
209 | {PIRQB, PIRQC, PIRQD, PIRQA}, /* IDSEL 21 */ | ||
210 | }; | ||
211 | |||
212 | const long min_idsel = 2, max_idsel = 21, irqs_per_slot = 4; | ||
213 | return PCI_IRQ_TABLE_LOOKUP; | ||
214 | } | ||
215 | |||
216 | int | ||
217 | mpc85xx_exclude_device(u_char bus, u_char devfn) | ||
218 | { | ||
219 | if (bus == 0 && PCI_SLOT(devfn) == 0) | ||
220 | return PCIBIOS_DEVICE_NOT_FOUND; | ||
221 | else | ||
222 | return PCIBIOS_SUCCESSFUL; | ||
223 | } | ||
224 | |||
225 | #endif /* CONFIG_PCI */ | ||
diff --git a/arch/ppc/platforms/85xx/mpc85xx_ads_common.h b/arch/ppc/platforms/85xx/mpc85xx_ads_common.h new file mode 100644 index 000000000000..3875e839cff7 --- /dev/null +++ b/arch/ppc/platforms/85xx/mpc85xx_ads_common.h | |||
@@ -0,0 +1,50 @@ | |||
1 | /* | ||
2 | * arch/ppc/platforms/85xx/mpc85xx_ads_common.h | ||
3 | * | ||
4 | * MPC85XX ADS common board definitions | ||
5 | * | ||
6 | * Maintainer: Kumar Gala <kumar.gala@freescale.com> | ||
7 | * | ||
8 | * Copyright 2004 Freescale Semiconductor Inc. | ||
9 | * | ||
10 | * This program is free software; you can redistribute it and/or modify it | ||
11 | * under the terms of the GNU General Public License as published by the | ||
12 | * Free Software Foundation; either version 2 of the License, or (at your | ||
13 | * option) any later version. | ||
14 | * | ||
15 | */ | ||
16 | |||
17 | #ifndef __MACH_MPC85XX_ADS_H__ | ||
18 | #define __MACH_MPC85XX_ADS_H__ | ||
19 | |||
20 | #include <linux/config.h> | ||
21 | #include <linux/init.h> | ||
22 | #include <linux/seq_file.h> | ||
23 | #include <asm/ppcboot.h> | ||
24 | |||
25 | #define BOARD_CCSRBAR ((uint)0xe0000000) | ||
26 | #define BCSR_ADDR ((uint)0xf8000000) | ||
27 | #define BCSR_SIZE ((uint)(32 * 1024)) | ||
28 | |||
29 | extern int mpc85xx_ads_show_cpuinfo(struct seq_file *m); | ||
30 | extern void mpc85xx_ads_init_IRQ(void) __init; | ||
31 | extern void mpc85xx_ads_map_io(void) __init; | ||
32 | |||
33 | /* PCI interrupt controller */ | ||
34 | #define PIRQA MPC85xx_IRQ_EXT1 | ||
35 | #define PIRQB MPC85xx_IRQ_EXT2 | ||
36 | #define PIRQC MPC85xx_IRQ_EXT3 | ||
37 | #define PIRQD MPC85xx_IRQ_EXT4 | ||
38 | |||
39 | #define MPC85XX_PCI1_LOWER_IO 0x00000000 | ||
40 | #define MPC85XX_PCI1_UPPER_IO 0x00ffffff | ||
41 | |||
42 | #define MPC85XX_PCI1_LOWER_MEM 0x80000000 | ||
43 | #define MPC85XX_PCI1_UPPER_MEM 0x9fffffff | ||
44 | |||
45 | #define MPC85XX_PCI1_IO_BASE 0xe2000000 | ||
46 | #define MPC85XX_PCI1_MEM_OFFSET 0x00000000 | ||
47 | |||
48 | #define MPC85XX_PCI1_IO_SIZE 0x01000000 | ||
49 | |||
50 | #endif /* __MACH_MPC85XX_ADS_H__ */ | ||
diff --git a/arch/ppc/platforms/85xx/mpc85xx_cds_common.c b/arch/ppc/platforms/85xx/mpc85xx_cds_common.c new file mode 100644 index 000000000000..6c020d67ad70 --- /dev/null +++ b/arch/ppc/platforms/85xx/mpc85xx_cds_common.c | |||
@@ -0,0 +1,467 @@ | |||
1 | /* | ||
2 | * arch/ppc/platform/85xx/mpc85xx_cds_common.c | ||
3 | * | ||
4 | * MPC85xx CDS board specific routines | ||
5 | * | ||
6 | * Maintainer: Kumar Gala <kumar.gala@freescale.com> | ||
7 | * | ||
8 | * Copyright 2004 Freescale Semiconductor, Inc | ||
9 | * | ||
10 | * This program is free software; you can redistribute it and/or modify it | ||
11 | * under the terms of the GNU General Public License as published by the | ||
12 | * Free Software Foundation; either version 2 of the License, or (at your | ||
13 | * option) any later version. | ||
14 | */ | ||
15 | |||
16 | #include <linux/config.h> | ||
17 | #include <linux/stddef.h> | ||
18 | #include <linux/kernel.h> | ||
19 | #include <linux/init.h> | ||
20 | #include <linux/errno.h> | ||
21 | #include <linux/reboot.h> | ||
22 | #include <linux/pci.h> | ||
23 | #include <linux/kdev_t.h> | ||
24 | #include <linux/major.h> | ||
25 | #include <linux/console.h> | ||
26 | #include <linux/delay.h> | ||
27 | #include <linux/irq.h> | ||
28 | #include <linux/seq_file.h> | ||
29 | #include <linux/serial.h> | ||
30 | #include <linux/module.h> | ||
31 | #include <linux/root_dev.h> | ||
32 | #include <linux/initrd.h> | ||
33 | #include <linux/tty.h> | ||
34 | #include <linux/serial_core.h> | ||
35 | #include <linux/fsl_devices.h> | ||
36 | |||
37 | #include <asm/system.h> | ||
38 | #include <asm/pgtable.h> | ||
39 | #include <asm/page.h> | ||
40 | #include <asm/atomic.h> | ||
41 | #include <asm/time.h> | ||
42 | #include <asm/todc.h> | ||
43 | #include <asm/io.h> | ||
44 | #include <asm/machdep.h> | ||
45 | #include <asm/prom.h> | ||
46 | #include <asm/open_pic.h> | ||
47 | #include <asm/bootinfo.h> | ||
48 | #include <asm/pci-bridge.h> | ||
49 | #include <asm/mpc85xx.h> | ||
50 | #include <asm/irq.h> | ||
51 | #include <asm/immap_85xx.h> | ||
52 | #include <asm/immap_cpm2.h> | ||
53 | #include <asm/ppc_sys.h> | ||
54 | #include <asm/kgdb.h> | ||
55 | |||
56 | #include <mm/mmu_decl.h> | ||
57 | #include <syslib/cpm2_pic.h> | ||
58 | #include <syslib/ppc85xx_common.h> | ||
59 | #include <syslib/ppc85xx_setup.h> | ||
60 | |||
61 | |||
62 | #ifndef CONFIG_PCI | ||
63 | unsigned long isa_io_base = 0; | ||
64 | unsigned long isa_mem_base = 0; | ||
65 | #endif | ||
66 | |||
67 | extern unsigned long total_memory; /* in mm/init */ | ||
68 | |||
69 | unsigned char __res[sizeof (bd_t)]; | ||
70 | |||
71 | static int cds_pci_slot = 2; | ||
72 | static volatile u8 * cadmus; | ||
73 | |||
74 | /* Internal interrupts are all Level Sensitive, and Positive Polarity */ | ||
75 | |||
76 | static u_char mpc85xx_cds_openpic_initsenses[] __initdata = { | ||
77 | (IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE), /* Internal 0: L2 Cache */ | ||
78 | (IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE), /* Internal 1: ECM */ | ||
79 | (IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE), /* Internal 2: DDR DRAM */ | ||
80 | (IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE), /* Internal 3: LBIU */ | ||
81 | (IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE), /* Internal 4: DMA 0 */ | ||
82 | (IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE), /* Internal 5: DMA 1 */ | ||
83 | (IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE), /* Internal 6: DMA 2 */ | ||
84 | (IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE), /* Internal 7: DMA 3 */ | ||
85 | (IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE), /* Internal 8: PCI/PCI-X */ | ||
86 | (IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE), /* Internal 9: RIO Inbound Port Write Error */ | ||
87 | (IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE), /* Internal 10: RIO Doorbell Inbound */ | ||
88 | (IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE), /* Internal 11: RIO Outbound Message */ | ||
89 | (IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE), /* Internal 12: RIO Inbound Message */ | ||
90 | (IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE), /* Internal 13: TSEC 0 Transmit */ | ||
91 | (IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE), /* Internal 14: TSEC 0 Receive */ | ||
92 | (IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE), /* Internal 15: Unused */ | ||
93 | (IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE), /* Internal 16: Unused */ | ||
94 | (IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE), /* Internal 17: Unused */ | ||
95 | (IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE), /* Internal 18: TSEC 0 Receive/Transmit Error */ | ||
96 | (IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE), /* Internal 19: TSEC 1 Transmit */ | ||
97 | (IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE), /* Internal 20: TSEC 1 Receive */ | ||
98 | (IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE), /* Internal 21: Unused */ | ||
99 | (IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE), /* Internal 22: Unused */ | ||
100 | (IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE), /* Internal 23: Unused */ | ||
101 | (IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE), /* Internal 24: TSEC 1 Receive/Transmit Error */ | ||
102 | (IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE), /* Internal 25: Fast Ethernet */ | ||
103 | (IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE), /* Internal 26: DUART */ | ||
104 | (IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE), /* Internal 27: I2C */ | ||
105 | (IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE), /* Internal 28: Performance Monitor */ | ||
106 | (IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE), /* Internal 29: Unused */ | ||
107 | (IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE), /* Internal 30: CPM */ | ||
108 | (IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE), /* Internal 31: Unused */ | ||
109 | #if defined(CONFIG_PCI) | ||
110 | (IRQ_SENSE_LEVEL | IRQ_POLARITY_NEGATIVE), /* External 0: PCI1 slot */ | ||
111 | (IRQ_SENSE_LEVEL | IRQ_POLARITY_NEGATIVE), /* External 1: PCI1 slot */ | ||
112 | (IRQ_SENSE_LEVEL | IRQ_POLARITY_NEGATIVE), /* External 2: PCI1 slot */ | ||
113 | (IRQ_SENSE_LEVEL | IRQ_POLARITY_NEGATIVE), /* External 3: PCI1 slot */ | ||
114 | #else | ||
115 | 0x0, /* External 0: */ | ||
116 | 0x0, /* External 1: */ | ||
117 | 0x0, /* External 2: */ | ||
118 | 0x0, /* External 3: */ | ||
119 | #endif | ||
120 | 0x0, /* External 4: */ | ||
121 | (IRQ_SENSE_LEVEL | IRQ_POLARITY_NEGATIVE), /* External 5: PHY */ | ||
122 | 0x0, /* External 6: */ | ||
123 | 0x0, /* External 7: */ | ||
124 | 0x0, /* External 8: */ | ||
125 | 0x0, /* External 9: */ | ||
126 | 0x0, /* External 10: */ | ||
127 | #if defined(CONFIG_85xx_PCI2) && defined(CONFIG_PCI) | ||
128 | (IRQ_SENSE_LEVEL | IRQ_POLARITY_NEGATIVE), /* External 11: PCI2 slot 0 */ | ||
129 | #else | ||
130 | 0x0, /* External 11: */ | ||
131 | #endif | ||
132 | }; | ||
133 | |||
134 | /* ************************************************************************ */ | ||
135 | int | ||
136 | mpc85xx_cds_show_cpuinfo(struct seq_file *m) | ||
137 | { | ||
138 | uint pvid, svid, phid1; | ||
139 | uint memsize = total_memory; | ||
140 | bd_t *binfo = (bd_t *) __res; | ||
141 | unsigned int freq; | ||
142 | |||
143 | /* get the core frequency */ | ||
144 | freq = binfo->bi_intfreq; | ||
145 | |||
146 | pvid = mfspr(SPRN_PVR); | ||
147 | svid = mfspr(SPRN_SVR); | ||
148 | |||
149 | seq_printf(m, "Vendor\t\t: Freescale Semiconductor\n"); | ||
150 | seq_printf(m, "Machine\t\t: CDS - MPC%s (%x)\n", cur_ppc_sys_spec->ppc_sys_name, cadmus[CM_VER]); | ||
151 | seq_printf(m, "clock\t\t: %dMHz\n", freq / 1000000); | ||
152 | seq_printf(m, "PVR\t\t: 0x%x\n", pvid); | ||
153 | seq_printf(m, "SVR\t\t: 0x%x\n", svid); | ||
154 | |||
155 | /* Display cpu Pll setting */ | ||
156 | phid1 = mfspr(SPRN_HID1); | ||
157 | seq_printf(m, "PLL setting\t: 0x%x\n", ((phid1 >> 24) & 0x3f)); | ||
158 | |||
159 | /* Display the amount of memory */ | ||
160 | seq_printf(m, "Memory\t\t: %d MB\n", memsize / (1024 * 1024)); | ||
161 | |||
162 | return 0; | ||
163 | } | ||
164 | |||
165 | #ifdef CONFIG_CPM2 | ||
166 | static void cpm2_cascade(int irq, void *dev_id, struct pt_regs *regs) | ||
167 | { | ||
168 | while((irq = cpm2_get_irq(regs)) >= 0) | ||
169 | __do_IRQ(irq, regs); | ||
170 | } | ||
171 | |||
172 | static struct irqaction cpm2_irqaction = { | ||
173 | .handler = cpm2_cascade, | ||
174 | .flags = SA_INTERRUPT, | ||
175 | .mask = CPU_MASK_NONE, | ||
176 | .name = "cpm2_cascade", | ||
177 | }; | ||
178 | #endif /* CONFIG_CPM2 */ | ||
179 | |||
180 | void __init | ||
181 | mpc85xx_cds_init_IRQ(void) | ||
182 | { | ||
183 | bd_t *binfo = (bd_t *) __res; | ||
184 | |||
185 | /* Determine the Physical Address of the OpenPIC regs */ | ||
186 | phys_addr_t OpenPIC_PAddr = binfo->bi_immr_base + MPC85xx_OPENPIC_OFFSET; | ||
187 | OpenPIC_Addr = ioremap(OpenPIC_PAddr, MPC85xx_OPENPIC_SIZE); | ||
188 | OpenPIC_InitSenses = mpc85xx_cds_openpic_initsenses; | ||
189 | OpenPIC_NumInitSenses = sizeof (mpc85xx_cds_openpic_initsenses); | ||
190 | |||
191 | /* Skip reserved space and internal sources */ | ||
192 | openpic_set_sources(0, 32, OpenPIC_Addr + 0x10200); | ||
193 | /* Map PIC IRQs 0-11 */ | ||
194 | openpic_set_sources(32, 12, OpenPIC_Addr + 0x10000); | ||
195 | |||
196 | /* we let openpic interrupts starting from an offset, to | ||
197 | * leave space for cascading interrupts underneath. | ||
198 | */ | ||
199 | openpic_init(MPC85xx_OPENPIC_IRQ_OFFSET); | ||
200 | |||
201 | #ifdef CONFIG_CPM2 | ||
202 | /* Setup CPM2 PIC */ | ||
203 | cpm2_init_IRQ(); | ||
204 | |||
205 | setup_irq(MPC85xx_IRQ_CPM, &cpm2_irqaction); | ||
206 | #endif | ||
207 | |||
208 | return; | ||
209 | } | ||
210 | |||
211 | #ifdef CONFIG_PCI | ||
212 | /* | ||
213 | * interrupt routing | ||
214 | */ | ||
215 | int | ||
216 | mpc85xx_map_irq(struct pci_dev *dev, unsigned char idsel, unsigned char pin) | ||
217 | { | ||
218 | struct pci_controller *hose = pci_bus_to_hose(dev->bus->number); | ||
219 | |||
220 | if (!hose->index) | ||
221 | { | ||
222 | /* Handle PCI1 interrupts */ | ||
223 | char pci_irq_table[][4] = | ||
224 | /* | ||
225 | * PCI IDSEL/INTPIN->INTLINE | ||
226 | * A B C D | ||
227 | */ | ||
228 | |||
229 | /* Note IRQ assignment for slots is based on which slot the elysium is | ||
230 | * in -- in this setup elysium is in slot #2 (this PIRQA as first | ||
231 | * interrupt on slot */ | ||
232 | { | ||
233 | { 0, 1, 2, 3 }, /* 16 - PMC */ | ||
234 | { 3, 0, 0, 0 }, /* 17 P2P (Tsi320) */ | ||
235 | { 0, 1, 2, 3 }, /* 18 - Slot 1 */ | ||
236 | { 1, 2, 3, 0 }, /* 19 - Slot 2 */ | ||
237 | { 2, 3, 0, 1 }, /* 20 - Slot 3 */ | ||
238 | { 3, 0, 1, 2 }, /* 21 - Slot 4 */ | ||
239 | }; | ||
240 | |||
241 | const long min_idsel = 16, max_idsel = 21, irqs_per_slot = 4; | ||
242 | int i, j; | ||
243 | |||
244 | for (i = 0; i < 6; i++) | ||
245 | for (j = 0; j < 4; j++) | ||
246 | pci_irq_table[i][j] = | ||
247 | ((pci_irq_table[i][j] + 5 - | ||
248 | cds_pci_slot) & 0x3) + PIRQ0A; | ||
249 | |||
250 | return PCI_IRQ_TABLE_LOOKUP; | ||
251 | } else { | ||
252 | /* Handle PCI2 interrupts (if we have one) */ | ||
253 | char pci_irq_table[][4] = | ||
254 | { | ||
255 | /* | ||
256 | * We only have one slot and one interrupt | ||
257 | * going to PIRQA - PIRQD */ | ||
258 | { PIRQ1A, PIRQ1A, PIRQ1A, PIRQ1A }, /* 21 - slot 0 */ | ||
259 | }; | ||
260 | |||
261 | const long min_idsel = 21, max_idsel = 21, irqs_per_slot = 4; | ||
262 | |||
263 | return PCI_IRQ_TABLE_LOOKUP; | ||
264 | } | ||
265 | } | ||
266 | |||
267 | #define ARCADIA_HOST_BRIDGE_IDSEL 17 | ||
268 | #define ARCADIA_2ND_BRIDGE_IDSEL 3 | ||
269 | |||
270 | extern int mpc85xx_pci1_last_busno; | ||
271 | |||
272 | int | ||
273 | mpc85xx_exclude_device(u_char bus, u_char devfn) | ||
274 | { | ||
275 | if (bus == 0 && PCI_SLOT(devfn) == 0) | ||
276 | return PCIBIOS_DEVICE_NOT_FOUND; | ||
277 | #ifdef CONFIG_85xx_PCI2 | ||
278 | if (mpc85xx_pci1_last_busno) | ||
279 | if (bus == (mpc85xx_pci1_last_busno + 1) && PCI_SLOT(devfn) == 0) | ||
280 | return PCIBIOS_DEVICE_NOT_FOUND; | ||
281 | #endif | ||
282 | /* We explicitly do not go past the Tundra 320 Bridge */ | ||
283 | if (bus == 1) | ||
284 | return PCIBIOS_DEVICE_NOT_FOUND; | ||
285 | if ((bus == 0) && (PCI_SLOT(devfn) == ARCADIA_2ND_BRIDGE_IDSEL)) | ||
286 | return PCIBIOS_DEVICE_NOT_FOUND; | ||
287 | else | ||
288 | return PCIBIOS_SUCCESSFUL; | ||
289 | } | ||
290 | #endif /* CONFIG_PCI */ | ||
291 | |||
292 | TODC_ALLOC(); | ||
293 | |||
294 | /* ************************************************************************ | ||
295 | * | ||
296 | * Setup the architecture | ||
297 | * | ||
298 | */ | ||
299 | static void __init | ||
300 | mpc85xx_cds_setup_arch(void) | ||
301 | { | ||
302 | bd_t *binfo = (bd_t *) __res; | ||
303 | unsigned int freq; | ||
304 | struct gianfar_platform_data *pdata; | ||
305 | |||
306 | /* get the core frequency */ | ||
307 | freq = binfo->bi_intfreq; | ||
308 | |||
309 | printk("mpc85xx_cds_setup_arch\n"); | ||
310 | |||
311 | #ifdef CONFIG_CPM2 | ||
312 | cpm2_reset(); | ||
313 | #endif | ||
314 | |||
315 | cadmus = ioremap(CADMUS_BASE, CADMUS_SIZE); | ||
316 | cds_pci_slot = ((cadmus[CM_CSR] >> 6) & 0x3) + 1; | ||
317 | printk("CDS Version = %x in PCI slot %d\n", cadmus[CM_VER], cds_pci_slot); | ||
318 | |||
319 | /* Setup TODC access */ | ||
320 | TODC_INIT(TODC_TYPE_DS1743, | ||
321 | 0, | ||
322 | 0, | ||
323 | ioremap(CDS_RTC_ADDR, CDS_RTC_SIZE), | ||
324 | 8); | ||
325 | |||
326 | /* Set loops_per_jiffy to a half-way reasonable value, | ||
327 | for use until calibrate_delay gets called. */ | ||
328 | loops_per_jiffy = freq / HZ; | ||
329 | |||
330 | #ifdef CONFIG_PCI | ||
331 | /* setup PCI host bridges */ | ||
332 | mpc85xx_setup_hose(); | ||
333 | #endif | ||
334 | |||
335 | #ifdef CONFIG_SERIAL_8250 | ||
336 | mpc85xx_early_serial_map(); | ||
337 | #endif | ||
338 | |||
339 | #ifdef CONFIG_SERIAL_TEXT_DEBUG | ||
340 | /* Invalidate the entry we stole earlier the serial ports | ||
341 | * should be properly mapped */ | ||
342 | invalidate_tlbcam_entry(NUM_TLBCAMS - 1); | ||
343 | #endif | ||
344 | |||
345 | /* setup the board related information for the enet controllers */ | ||
346 | pdata = (struct gianfar_platform_data *) ppc_sys_get_pdata(MPC85xx_TSEC1); | ||
347 | pdata->board_flags = FSL_GIANFAR_BRD_HAS_PHY_INTR; | ||
348 | pdata->interruptPHY = MPC85xx_IRQ_EXT5; | ||
349 | pdata->phyid = 0; | ||
350 | /* fixup phy address */ | ||
351 | pdata->phy_reg_addr += binfo->bi_immr_base; | ||
352 | memcpy(pdata->mac_addr, binfo->bi_enetaddr, 6); | ||
353 | |||
354 | pdata = (struct gianfar_platform_data *) ppc_sys_get_pdata(MPC85xx_TSEC2); | ||
355 | pdata->board_flags = FSL_GIANFAR_BRD_HAS_PHY_INTR; | ||
356 | pdata->interruptPHY = MPC85xx_IRQ_EXT5; | ||
357 | pdata->phyid = 1; | ||
358 | /* fixup phy address */ | ||
359 | pdata->phy_reg_addr += binfo->bi_immr_base; | ||
360 | memcpy(pdata->mac_addr, binfo->bi_enet1addr, 6); | ||
361 | |||
362 | |||
363 | #ifdef CONFIG_BLK_DEV_INITRD | ||
364 | if (initrd_start) | ||
365 | ROOT_DEV = Root_RAM0; | ||
366 | else | ||
367 | #endif | ||
368 | #ifdef CONFIG_ROOT_NFS | ||
369 | ROOT_DEV = Root_NFS; | ||
370 | #else | ||
371 | ROOT_DEV = Root_HDA1; | ||
372 | #endif | ||
373 | } | ||
374 | |||
375 | /* ************************************************************************ */ | ||
376 | void __init | ||
377 | platform_init(unsigned long r3, unsigned long r4, unsigned long r5, | ||
378 | unsigned long r6, unsigned long r7) | ||
379 | { | ||
380 | /* parse_bootinfo must always be called first */ | ||
381 | parse_bootinfo(find_bootinfo()); | ||
382 | |||
383 | /* | ||
384 | * If we were passed in a board information, copy it into the | ||
385 | * residual data area. | ||
386 | */ | ||
387 | if (r3) { | ||
388 | memcpy((void *) __res, (void *) (r3 + KERNELBASE), | ||
389 | sizeof (bd_t)); | ||
390 | |||
391 | } | ||
392 | #ifdef CONFIG_SERIAL_TEXT_DEBUG | ||
393 | { | ||
394 | bd_t *binfo = (bd_t *) __res; | ||
395 | struct uart_port p; | ||
396 | |||
397 | /* Use the last TLB entry to map CCSRBAR to allow access to DUART regs */ | ||
398 | settlbcam(NUM_TLBCAMS - 1, binfo->bi_immr_base, | ||
399 | binfo->bi_immr_base, MPC85xx_CCSRBAR_SIZE, _PAGE_IO, 0); | ||
400 | |||
401 | memset(&p, 0, sizeof (p)); | ||
402 | p.iotype = SERIAL_IO_MEM; | ||
403 | p.membase = (void *) binfo->bi_immr_base + MPC85xx_UART0_OFFSET; | ||
404 | p.uartclk = binfo->bi_busfreq; | ||
405 | |||
406 | gen550_init(0, &p); | ||
407 | |||
408 | memset(&p, 0, sizeof (p)); | ||
409 | p.iotype = SERIAL_IO_MEM; | ||
410 | p.membase = (void *) binfo->bi_immr_base + MPC85xx_UART1_OFFSET; | ||
411 | p.uartclk = binfo->bi_busfreq; | ||
412 | |||
413 | gen550_init(1, &p); | ||
414 | } | ||
415 | #endif | ||
416 | |||
417 | #if defined(CONFIG_BLK_DEV_INITRD) | ||
418 | /* | ||
419 | * If the init RAM disk has been configured in, and there's a valid | ||
420 | * starting address for it, set it up. | ||
421 | */ | ||
422 | if (r4) { | ||
423 | initrd_start = r4 + KERNELBASE; | ||
424 | initrd_end = r5 + KERNELBASE; | ||
425 | } | ||
426 | #endif /* CONFIG_BLK_DEV_INITRD */ | ||
427 | |||
428 | /* Copy the kernel command line arguments to a safe place. */ | ||
429 | |||
430 | if (r6) { | ||
431 | *(char *) (r7 + KERNELBASE) = 0; | ||
432 | strcpy(cmd_line, (char *) (r6 + KERNELBASE)); | ||
433 | } | ||
434 | |||
435 | identify_ppc_sys_by_id(mfspr(SPRN_SVR)); | ||
436 | |||
437 | /* setup the PowerPC module struct */ | ||
438 | ppc_md.setup_arch = mpc85xx_cds_setup_arch; | ||
439 | ppc_md.show_cpuinfo = mpc85xx_cds_show_cpuinfo; | ||
440 | |||
441 | ppc_md.init_IRQ = mpc85xx_cds_init_IRQ; | ||
442 | ppc_md.get_irq = openpic_get_irq; | ||
443 | |||
444 | ppc_md.restart = mpc85xx_restart; | ||
445 | ppc_md.power_off = mpc85xx_power_off; | ||
446 | ppc_md.halt = mpc85xx_halt; | ||
447 | |||
448 | ppc_md.find_end_of_memory = mpc85xx_find_end_of_memory; | ||
449 | |||
450 | ppc_md.calibrate_decr = mpc85xx_calibrate_decr; | ||
451 | |||
452 | ppc_md.time_init = todc_time_init; | ||
453 | ppc_md.set_rtc_time = todc_set_rtc_time; | ||
454 | ppc_md.get_rtc_time = todc_get_rtc_time; | ||
455 | |||
456 | ppc_md.nvram_read_val = todc_direct_read_val; | ||
457 | ppc_md.nvram_write_val = todc_direct_write_val; | ||
458 | |||
459 | #if defined(CONFIG_SERIAL_8250) && defined(CONFIG_SERIAL_TEXT_DEBUG) | ||
460 | ppc_md.progress = gen550_progress; | ||
461 | #endif /* CONFIG_SERIAL_8250 && CONFIG_SERIAL_TEXT_DEBUG */ | ||
462 | |||
463 | if (ppc_md.progress) | ||
464 | ppc_md.progress("mpc85xx_cds_init(): exit", 0); | ||
465 | |||
466 | return; | ||
467 | } | ||
diff --git a/arch/ppc/platforms/85xx/mpc85xx_cds_common.h b/arch/ppc/platforms/85xx/mpc85xx_cds_common.h new file mode 100644 index 000000000000..7627d77504bd --- /dev/null +++ b/arch/ppc/platforms/85xx/mpc85xx_cds_common.h | |||
@@ -0,0 +1,80 @@ | |||
1 | /* | ||
2 | * arch/ppc/platforms/85xx/mpc85xx_cds_common.h | ||
3 | * | ||
4 | * MPC85xx CDS board definitions | ||
5 | * | ||
6 | * Maintainer: Kumar Gala <kumar.gala@freescale.com> | ||
7 | * | ||
8 | * Copyright 2004 Freescale Semiconductor, Inc | ||
9 | * | ||
10 | * This program is free software; you can redistribute it and/or modify it | ||
11 | * under the terms of the GNU General Public License as published by the | ||
12 | * Free Software Foundation; either version 2 of the License, or (at your | ||
13 | * option) any later version. | ||
14 | * | ||
15 | */ | ||
16 | |||
17 | #ifndef __MACH_MPC85XX_CDS_H__ | ||
18 | #define __MACH_MPC85XX_CDS_H__ | ||
19 | |||
20 | #include <linux/config.h> | ||
21 | #include <linux/serial.h> | ||
22 | #include <asm/ppcboot.h> | ||
23 | #include <linux/initrd.h> | ||
24 | #include <syslib/ppc85xx_setup.h> | ||
25 | |||
26 | #define BOARD_CCSRBAR ((uint)0xe0000000) | ||
27 | #define CCSRBAR_SIZE ((uint)1024*1024) | ||
28 | |||
29 | /* CADMUS info */ | ||
30 | #define CADMUS_BASE (0xf8004000) | ||
31 | #define CADMUS_SIZE (256) | ||
32 | #define CM_VER (0) | ||
33 | #define CM_CSR (1) | ||
34 | #define CM_RST (2) | ||
35 | |||
36 | /* CDS NVRAM/RTC */ | ||
37 | #define CDS_RTC_ADDR (0xf8000000) | ||
38 | #define CDS_RTC_SIZE (8 * 1024) | ||
39 | |||
40 | /* PCI config */ | ||
41 | #define PCI1_CFG_ADDR_OFFSET (0x8000) | ||
42 | #define PCI1_CFG_DATA_OFFSET (0x8004) | ||
43 | |||
44 | #define PCI2_CFG_ADDR_OFFSET (0x9000) | ||
45 | #define PCI2_CFG_DATA_OFFSET (0x9004) | ||
46 | |||
47 | /* PCI interrupt controller */ | ||
48 | #define PIRQ0A MPC85xx_IRQ_EXT0 | ||
49 | #define PIRQ0B MPC85xx_IRQ_EXT1 | ||
50 | #define PIRQ0C MPC85xx_IRQ_EXT2 | ||
51 | #define PIRQ0D MPC85xx_IRQ_EXT3 | ||
52 | #define PIRQ1A MPC85xx_IRQ_EXT11 | ||
53 | |||
54 | /* PCI 1 memory map */ | ||
55 | #define MPC85XX_PCI1_LOWER_IO 0x00000000 | ||
56 | #define MPC85XX_PCI1_UPPER_IO 0x00ffffff | ||
57 | |||
58 | #define MPC85XX_PCI1_LOWER_MEM 0x80000000 | ||
59 | #define MPC85XX_PCI1_UPPER_MEM 0x9fffffff | ||
60 | |||
61 | #define MPC85XX_PCI1_IO_BASE 0xe2000000 | ||
62 | #define MPC85XX_PCI1_MEM_OFFSET 0x00000000 | ||
63 | |||
64 | #define MPC85XX_PCI1_IO_SIZE 0x01000000 | ||
65 | |||
66 | /* PCI 2 memory map */ | ||
67 | /* Note: the standard PPC fixups will cause IO space to get bumped by | ||
68 | * hose->io_base_virt - isa_io_base => MPC85XX_PCI1_IO_SIZE */ | ||
69 | #define MPC85XX_PCI2_LOWER_IO 0x00000000 | ||
70 | #define MPC85XX_PCI2_UPPER_IO 0x00ffffff | ||
71 | |||
72 | #define MPC85XX_PCI2_LOWER_MEM 0xa0000000 | ||
73 | #define MPC85XX_PCI2_UPPER_MEM 0xbfffffff | ||
74 | |||
75 | #define MPC85XX_PCI2_IO_BASE 0xe3000000 | ||
76 | #define MPC85XX_PCI2_MEM_OFFSET 0x00000000 | ||
77 | |||
78 | #define MPC85XX_PCI2_IO_SIZE 0x01000000 | ||
79 | |||
80 | #endif /* __MACH_MPC85XX_CDS_H__ */ | ||
diff --git a/arch/ppc/platforms/85xx/sbc8560.c b/arch/ppc/platforms/85xx/sbc8560.c new file mode 100644 index 000000000000..9ab05e590c3e --- /dev/null +++ b/arch/ppc/platforms/85xx/sbc8560.c | |||
@@ -0,0 +1,227 @@ | |||
1 | /* | ||
2 | * arch/ppc/platforms/85xx/sbc8560.c | ||
3 | * | ||
4 | * Wind River SBC8560 board specific routines | ||
5 | * | ||
6 | * Maintainer: Kumar Gala <kumar.gala@freescale.com> | ||
7 | * | ||
8 | * Copyright 2004 Freescale Semiconductor Inc. | ||
9 | * | ||
10 | * This program is free software; you can redistribute it and/or modify it | ||
11 | * under the terms of the GNU General Public License as published by the | ||
12 | * Free Software Foundation; either version 2 of the License, or (at your | ||
13 | * option) any later version. | ||
14 | */ | ||
15 | |||
16 | #include <linux/config.h> | ||
17 | #include <linux/stddef.h> | ||
18 | #include <linux/kernel.h> | ||
19 | #include <linux/init.h> | ||
20 | #include <linux/errno.h> | ||
21 | #include <linux/reboot.h> | ||
22 | #include <linux/pci.h> | ||
23 | #include <linux/kdev_t.h> | ||
24 | #include <linux/major.h> | ||
25 | #include <linux/console.h> | ||
26 | #include <linux/delay.h> | ||
27 | #include <linux/irq.h> | ||
28 | #include <linux/seq_file.h> | ||
29 | #include <linux/root_dev.h> | ||
30 | #include <linux/serial.h> | ||
31 | #include <linux/tty.h> /* for linux/serial_core.h */ | ||
32 | #include <linux/serial_core.h> | ||
33 | #include <linux/initrd.h> | ||
34 | #include <linux/module.h> | ||
35 | #include <linux/fsl_devices.h> | ||
36 | |||
37 | #include <asm/system.h> | ||
38 | #include <asm/pgtable.h> | ||
39 | #include <asm/page.h> | ||
40 | #include <asm/atomic.h> | ||
41 | #include <asm/time.h> | ||
42 | #include <asm/io.h> | ||
43 | #include <asm/machdep.h> | ||
44 | #include <asm/prom.h> | ||
45 | #include <asm/open_pic.h> | ||
46 | #include <asm/bootinfo.h> | ||
47 | #include <asm/pci-bridge.h> | ||
48 | #include <asm/mpc85xx.h> | ||
49 | #include <asm/irq.h> | ||
50 | #include <asm/immap_85xx.h> | ||
51 | #include <asm/kgdb.h> | ||
52 | #include <asm/ppc_sys.h> | ||
53 | #include <mm/mmu_decl.h> | ||
54 | |||
55 | #include <syslib/ppc85xx_common.h> | ||
56 | #include <syslib/ppc85xx_setup.h> | ||
57 | |||
58 | #ifdef CONFIG_SERIAL_8250 | ||
59 | static void __init | ||
60 | sbc8560_early_serial_map(void) | ||
61 | { | ||
62 | struct uart_port uart_req; | ||
63 | |||
64 | /* Setup serial port access */ | ||
65 | memset(&uart_req, 0, sizeof (uart_req)); | ||
66 | uart_req.irq = MPC85xx_IRQ_EXT9; | ||
67 | uart_req.flags = STD_COM_FLAGS; | ||
68 | uart_req.uartclk = BASE_BAUD * 16; | ||
69 | uart_req.iotype = SERIAL_IO_MEM; | ||
70 | uart_req.mapbase = UARTA_ADDR; | ||
71 | uart_req.membase = ioremap(uart_req.mapbase, MPC85xx_UART0_SIZE); | ||
72 | uart_req.type = PORT_16650; | ||
73 | |||
74 | #if defined(CONFIG_SERIAL_TEXT_DEBUG) || defined(CONFIG_KGDB) | ||
75 | gen550_init(0, &uart_req); | ||
76 | #endif | ||
77 | |||
78 | if (early_serial_setup(&uart_req) != 0) | ||
79 | printk("Early serial init of port 0 failed\n"); | ||
80 | |||
81 | /* Assume early_serial_setup() doesn't modify uart_req */ | ||
82 | uart_req.line = 1; | ||
83 | uart_req.mapbase = UARTB_ADDR; | ||
84 | uart_req.membase = ioremap(uart_req.mapbase, MPC85xx_UART1_SIZE); | ||
85 | uart_req.irq = MPC85xx_IRQ_EXT10; | ||
86 | |||
87 | #if defined(CONFIG_SERIAL_TEXT_DEBUG) || defined(CONFIG_KGDB) | ||
88 | gen550_init(1, &uart_req); | ||
89 | #endif | ||
90 | |||
91 | if (early_serial_setup(&uart_req) != 0) | ||
92 | printk("Early serial init of port 1 failed\n"); | ||
93 | } | ||
94 | #endif | ||
95 | |||
96 | /* ************************************************************************ | ||
97 | * | ||
98 | * Setup the architecture | ||
99 | * | ||
100 | */ | ||
101 | static void __init | ||
102 | sbc8560_setup_arch(void) | ||
103 | { | ||
104 | bd_t *binfo = (bd_t *) __res; | ||
105 | unsigned int freq; | ||
106 | struct gianfar_platform_data *pdata; | ||
107 | |||
108 | /* get the core frequency */ | ||
109 | freq = binfo->bi_intfreq; | ||
110 | |||
111 | if (ppc_md.progress) | ||
112 | ppc_md.progress("sbc8560_setup_arch()", 0); | ||
113 | |||
114 | /* Set loops_per_jiffy to a half-way reasonable value, | ||
115 | for use until calibrate_delay gets called. */ | ||
116 | loops_per_jiffy = freq / HZ; | ||
117 | |||
118 | #ifdef CONFIG_PCI | ||
119 | /* setup PCI host bridges */ | ||
120 | mpc85xx_setup_hose(); | ||
121 | #endif | ||
122 | #ifdef CONFIG_SERIAL_8250 | ||
123 | sbc8560_early_serial_map(); | ||
124 | #endif | ||
125 | #ifdef CONFIG_SERIAL_TEXT_DEBUG | ||
126 | /* Invalidate the entry we stole earlier the serial ports | ||
127 | * should be properly mapped */ | ||
128 | invalidate_tlbcam_entry(NUM_TLBCAMS - 1); | ||
129 | #endif | ||
130 | |||
131 | /* setup the board related information for the enet controllers */ | ||
132 | pdata = (struct gianfar_platform_data *) ppc_sys_get_pdata(MPC85xx_TSEC1); | ||
133 | pdata->board_flags = FSL_GIANFAR_BRD_HAS_PHY_INTR; | ||
134 | pdata->interruptPHY = MPC85xx_IRQ_EXT6; | ||
135 | pdata->phyid = 25; | ||
136 | /* fixup phy address */ | ||
137 | pdata->phy_reg_addr += binfo->bi_immr_base; | ||
138 | memcpy(pdata->mac_addr, binfo->bi_enetaddr, 6); | ||
139 | |||
140 | pdata = (struct gianfar_platform_data *) ppc_sys_get_pdata(MPC85xx_TSEC2); | ||
141 | pdata->board_flags = FSL_GIANFAR_BRD_HAS_PHY_INTR; | ||
142 | pdata->interruptPHY = MPC85xx_IRQ_EXT7; | ||
143 | pdata->phyid = 26; | ||
144 | /* fixup phy address */ | ||
145 | pdata->phy_reg_addr += binfo->bi_immr_base; | ||
146 | memcpy(pdata->mac_addr, binfo->bi_enet1addr, 6); | ||
147 | |||
148 | #ifdef CONFIG_BLK_DEV_INITRD | ||
149 | if (initrd_start) | ||
150 | ROOT_DEV = Root_RAM0; | ||
151 | else | ||
152 | #endif | ||
153 | #ifdef CONFIG_ROOT_NFS | ||
154 | ROOT_DEV = Root_NFS; | ||
155 | #else | ||
156 | ROOT_DEV = Root_HDA1; | ||
157 | #endif | ||
158 | } | ||
159 | |||
160 | /* ************************************************************************ */ | ||
161 | void __init | ||
162 | platform_init(unsigned long r3, unsigned long r4, unsigned long r5, | ||
163 | unsigned long r6, unsigned long r7) | ||
164 | { | ||
165 | /* parse_bootinfo must always be called first */ | ||
166 | parse_bootinfo(find_bootinfo()); | ||
167 | |||
168 | /* | ||
169 | * If we were passed in a board information, copy it into the | ||
170 | * residual data area. | ||
171 | */ | ||
172 | if (r3) { | ||
173 | memcpy((void *) __res, (void *) (r3 + KERNELBASE), | ||
174 | sizeof (bd_t)); | ||
175 | } | ||
176 | |||
177 | #ifdef CONFIG_SERIAL_TEXT_DEBUG | ||
178 | /* Use the last TLB entry to map CCSRBAR to allow access to DUART regs */ | ||
179 | settlbcam(NUM_TLBCAMS - 1, UARTA_ADDR, | ||
180 | UARTA_ADDR, 0x1000, _PAGE_IO, 0); | ||
181 | #endif | ||
182 | |||
183 | #if defined(CONFIG_BLK_DEV_INITRD) | ||
184 | /* | ||
185 | * If the init RAM disk has been configured in, and there's a valid | ||
186 | * starting address for it, set it up. | ||
187 | */ | ||
188 | if (r4) { | ||
189 | initrd_start = r4 + KERNELBASE; | ||
190 | initrd_end = r5 + KERNELBASE; | ||
191 | } | ||
192 | #endif /* CONFIG_BLK_DEV_INITRD */ | ||
193 | |||
194 | /* Copy the kernel command line arguments to a safe place. */ | ||
195 | |||
196 | if (r6) { | ||
197 | *(char *) (r7 + KERNELBASE) = 0; | ||
198 | strcpy(cmd_line, (char *) (r6 + KERNELBASE)); | ||
199 | } | ||
200 | |||
201 | identify_ppc_sys_by_id(mfspr(SPRN_SVR)); | ||
202 | |||
203 | /* setup the PowerPC module struct */ | ||
204 | ppc_md.setup_arch = sbc8560_setup_arch; | ||
205 | ppc_md.show_cpuinfo = sbc8560_show_cpuinfo; | ||
206 | |||
207 | ppc_md.init_IRQ = sbc8560_init_IRQ; | ||
208 | ppc_md.get_irq = openpic_get_irq; | ||
209 | |||
210 | ppc_md.restart = mpc85xx_restart; | ||
211 | ppc_md.power_off = mpc85xx_power_off; | ||
212 | ppc_md.halt = mpc85xx_halt; | ||
213 | |||
214 | ppc_md.find_end_of_memory = mpc85xx_find_end_of_memory; | ||
215 | |||
216 | ppc_md.time_init = NULL; | ||
217 | ppc_md.set_rtc_time = NULL; | ||
218 | ppc_md.get_rtc_time = NULL; | ||
219 | ppc_md.calibrate_decr = mpc85xx_calibrate_decr; | ||
220 | |||
221 | #if defined(CONFIG_SERIAL_8250) && defined(CONFIG_SERIAL_TEXT_DEBUG) | ||
222 | ppc_md.progress = gen550_progress; | ||
223 | #endif /* CONFIG_SERIAL_8250 && CONFIG_SERIAL_TEXT_DEBUG */ | ||
224 | |||
225 | if (ppc_md.progress) | ||
226 | ppc_md.progress("sbc8560_init(): exit", 0); | ||
227 | } | ||
diff --git a/arch/ppc/platforms/85xx/sbc8560.h b/arch/ppc/platforms/85xx/sbc8560.h new file mode 100644 index 000000000000..5e1b00c77da5 --- /dev/null +++ b/arch/ppc/platforms/85xx/sbc8560.h | |||
@@ -0,0 +1,49 @@ | |||
1 | /* | ||
2 | * arch/ppc/platforms/85xx/sbc8560.h | ||
3 | * | ||
4 | * Wind River SBC8560 board definitions | ||
5 | * | ||
6 | * Copyright 2003 Motorola Inc. | ||
7 | * | ||
8 | * This program is free software; you can redistribute it and/or modify it | ||
9 | * under the terms of the GNU General Public License as published by the | ||
10 | * Free Software Foundation; either version 2 of the License, or (at your | ||
11 | * option) any later version. | ||
12 | * | ||
13 | */ | ||
14 | |||
15 | #ifndef __MACH_SBC8560_H__ | ||
16 | #define __MACH_SBC8560_H__ | ||
17 | |||
18 | #include <linux/config.h> | ||
19 | #include <platforms/85xx/sbc85xx.h> | ||
20 | |||
21 | #define CPM_MAP_ADDR (CCSRBAR + MPC85xx_CPM_OFFSET) | ||
22 | |||
23 | #ifdef CONFIG_SERIAL_MANY_PORTS | ||
24 | #define RS_TABLE_SIZE 64 | ||
25 | #else | ||
26 | #define RS_TABLE_SIZE 2 | ||
27 | #endif | ||
28 | |||
29 | /* Rate for the 1.8432 Mhz clock for the onboard serial chip */ | ||
30 | #define BASE_BAUD ( 1843200 / 16 ) | ||
31 | |||
32 | #ifdef CONFIG_SERIAL_DETECT_IRQ | ||
33 | #define STD_COM_FLAGS (ASYNC_SKIP_TEST|ASYNC_AUTO_IRQ) | ||
34 | #else | ||
35 | #define STD_COM_FLAGS (ASYNC_SKIP_TEST) | ||
36 | #endif | ||
37 | |||
38 | #define STD_SERIAL_PORT_DFNS \ | ||
39 | { 0, BASE_BAUD, UARTA_ADDR, MPC85xx_IRQ_EXT9, STD_COM_FLAGS, /* ttyS0 */ \ | ||
40 | iomem_base: (u8 *)UARTA_ADDR, \ | ||
41 | io_type: SERIAL_IO_MEM }, \ | ||
42 | { 0, BASE_BAUD, UARTB_ADDR, MPC85xx_IRQ_EXT10, STD_COM_FLAGS, /* ttyS1 */ \ | ||
43 | iomem_base: (u8 *)UARTB_ADDR, \ | ||
44 | io_type: SERIAL_IO_MEM }, | ||
45 | |||
46 | #define SERIAL_PORT_DFNS \ | ||
47 | STD_SERIAL_PORT_DFNS | ||
48 | |||
49 | #endif /* __MACH_SBC8560_H__ */ | ||
diff --git a/arch/ppc/platforms/85xx/sbc85xx.c b/arch/ppc/platforms/85xx/sbc85xx.c new file mode 100644 index 000000000000..2d638c1c1bd6 --- /dev/null +++ b/arch/ppc/platforms/85xx/sbc85xx.c | |||
@@ -0,0 +1,203 @@ | |||
1 | /* | ||
2 | * arch/ppc/platform/85xx/sbc85xx.c | ||
3 | * | ||
4 | * WindRiver PowerQUICC III SBC85xx board common routines | ||
5 | * | ||
6 | * Copyright 2002, 2003 Motorola Inc. | ||
7 | * Copyright 2004 Red Hat, Inc. | ||
8 | * | ||
9 | * This program is free software; you can redistribute it and/or modify it | ||
10 | * under the terms of the GNU General Public License as published by the | ||
11 | * Free Software Foundation; either version 2 of the License, or (at your | ||
12 | * option) any later version. | ||
13 | */ | ||
14 | |||
15 | #include <linux/config.h> | ||
16 | #include <linux/stddef.h> | ||
17 | #include <linux/kernel.h> | ||
18 | #include <linux/init.h> | ||
19 | #include <linux/errno.h> | ||
20 | #include <linux/reboot.h> | ||
21 | #include <linux/pci.h> | ||
22 | #include <linux/kdev_t.h> | ||
23 | #include <linux/major.h> | ||
24 | #include <linux/console.h> | ||
25 | #include <linux/delay.h> | ||
26 | #include <linux/irq.h> | ||
27 | #include <linux/seq_file.h> | ||
28 | #include <linux/serial.h> | ||
29 | #include <linux/module.h> | ||
30 | |||
31 | #include <asm/system.h> | ||
32 | #include <asm/pgtable.h> | ||
33 | #include <asm/page.h> | ||
34 | #include <asm/atomic.h> | ||
35 | #include <asm/time.h> | ||
36 | #include <asm/io.h> | ||
37 | #include <asm/machdep.h> | ||
38 | #include <asm/prom.h> | ||
39 | #include <asm/open_pic.h> | ||
40 | #include <asm/bootinfo.h> | ||
41 | #include <asm/pci-bridge.h> | ||
42 | #include <asm/mpc85xx.h> | ||
43 | #include <asm/irq.h> | ||
44 | #include <asm/immap_85xx.h> | ||
45 | #include <asm/ppc_sys.h> | ||
46 | |||
47 | #include <mm/mmu_decl.h> | ||
48 | |||
49 | #include <platforms/85xx/sbc85xx.h> | ||
50 | |||
51 | unsigned char __res[sizeof (bd_t)]; | ||
52 | |||
53 | #ifndef CONFIG_PCI | ||
54 | unsigned long isa_io_base = 0; | ||
55 | unsigned long isa_mem_base = 0; | ||
56 | unsigned long pci_dram_offset = 0; | ||
57 | #endif | ||
58 | |||
59 | extern unsigned long total_memory; /* in mm/init */ | ||
60 | |||
61 | /* Internal interrupts are all Level Sensitive, and Positive Polarity */ | ||
62 | |||
63 | static u_char sbc8560_openpic_initsenses[] __initdata = { | ||
64 | (IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE), /* Internal 0: L2 Cache */ | ||
65 | (IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE), /* Internal 1: ECM */ | ||
66 | (IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE), /* Internal 2: DDR DRAM */ | ||
67 | (IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE), /* Internal 3: LBIU */ | ||
68 | (IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE), /* Internal 4: DMA 0 */ | ||
69 | (IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE), /* Internal 5: DMA 1 */ | ||
70 | (IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE), /* Internal 6: DMA 2 */ | ||
71 | (IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE), /* Internal 7: DMA 3 */ | ||
72 | (IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE), /* Internal 8: PCI/PCI-X */ | ||
73 | (IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE), /* Internal 9: RIO Inbound Port Write Error */ | ||
74 | (IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE), /* Internal 10: RIO Doorbell Inbound */ | ||
75 | (IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE), /* Internal 11: RIO Outbound Message */ | ||
76 | (IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE), /* Internal 12: RIO Inbound Message */ | ||
77 | (IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE), /* Internal 13: TSEC 0 Transmit */ | ||
78 | (IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE), /* Internal 14: TSEC 0 Receive */ | ||
79 | (IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE), /* Internal 15: Unused */ | ||
80 | (IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE), /* Internal 16: Unused */ | ||
81 | (IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE), /* Internal 17: Unused */ | ||
82 | (IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE), /* Internal 18: TSEC 0 Receive/Transmit Error */ | ||
83 | (IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE), /* Internal 19: TSEC 1 Transmit */ | ||
84 | (IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE), /* Internal 20: TSEC 1 Receive */ | ||
85 | (IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE), /* Internal 21: Unused */ | ||
86 | (IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE), /* Internal 22: Unused */ | ||
87 | (IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE), /* Internal 23: Unused */ | ||
88 | (IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE), /* Internal 24: TSEC 1 Receive/Transmit Error */ | ||
89 | (IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE), /* Internal 25: Fast Ethernet */ | ||
90 | (IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE), /* Internal 26: DUART */ | ||
91 | (IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE), /* Internal 27: I2C */ | ||
92 | (IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE), /* Internal 28: Performance Monitor */ | ||
93 | (IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE), /* Internal 29: Unused */ | ||
94 | (IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE), /* Internal 30: CPM */ | ||
95 | (IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE), /* Internal 31: Unused */ | ||
96 | 0x0, /* External 0: */ | ||
97 | 0x0, /* External 1: */ | ||
98 | #if defined(CONFIG_PCI) | ||
99 | (IRQ_SENSE_LEVEL | IRQ_POLARITY_NEGATIVE), /* External 2: PCI slot 0 */ | ||
100 | (IRQ_SENSE_LEVEL | IRQ_POLARITY_NEGATIVE), /* External 3: PCI slot 1 */ | ||
101 | (IRQ_SENSE_LEVEL | IRQ_POLARITY_NEGATIVE), /* External 4: PCI slot 2 */ | ||
102 | (IRQ_SENSE_LEVEL | IRQ_POLARITY_NEGATIVE), /* External 5: PCI slot 3 */ | ||
103 | #else | ||
104 | 0x0, /* External 2: */ | ||
105 | 0x0, /* External 3: */ | ||
106 | 0x0, /* External 4: */ | ||
107 | 0x0, /* External 5: */ | ||
108 | #endif | ||
109 | (IRQ_SENSE_LEVEL | IRQ_POLARITY_NEGATIVE), /* External 6: PHY */ | ||
110 | (IRQ_SENSE_LEVEL | IRQ_POLARITY_NEGATIVE), /* External 7: PHY */ | ||
111 | 0x0, /* External 8: */ | ||
112 | (IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE), /* External 9: PHY */ | ||
113 | (IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE), /* External 10: PHY */ | ||
114 | 0x0, /* External 11: */ | ||
115 | }; | ||
116 | |||
117 | /* ************************************************************************ */ | ||
118 | int | ||
119 | sbc8560_show_cpuinfo(struct seq_file *m) | ||
120 | { | ||
121 | uint pvid, svid, phid1; | ||
122 | uint memsize = total_memory; | ||
123 | bd_t *binfo = (bd_t *) __res; | ||
124 | unsigned int freq; | ||
125 | |||
126 | /* get the core frequency */ | ||
127 | freq = binfo->bi_intfreq; | ||
128 | |||
129 | pvid = mfspr(SPRN_PVR); | ||
130 | svid = mfspr(SPRN_SVR); | ||
131 | |||
132 | seq_printf(m, "Vendor\t\t: Wind River\n"); | ||
133 | seq_printf(m, "Machine\t\t: SBC%s\n", cur_ppc_sys_spec->ppc_sys_name); | ||
134 | seq_printf(m, "clock\t\t: %dMHz\n", freq / 1000000); | ||
135 | seq_printf(m, "PVR\t\t: 0x%x\n", pvid); | ||
136 | seq_printf(m, "SVR\t\t: 0x%x\n", svid); | ||
137 | |||
138 | /* Display cpu Pll setting */ | ||
139 | phid1 = mfspr(SPRN_HID1); | ||
140 | seq_printf(m, "PLL setting\t: 0x%x\n", ((phid1 >> 24) & 0x3f)); | ||
141 | |||
142 | /* Display the amount of memory */ | ||
143 | seq_printf(m, "Memory\t\t: %d MB\n", memsize / (1024 * 1024)); | ||
144 | |||
145 | return 0; | ||
146 | } | ||
147 | |||
148 | void __init | ||
149 | sbc8560_init_IRQ(void) | ||
150 | { | ||
151 | bd_t *binfo = (bd_t *) __res; | ||
152 | /* Determine the Physical Address of the OpenPIC regs */ | ||
153 | phys_addr_t OpenPIC_PAddr = | ||
154 | binfo->bi_immr_base + MPC85xx_OPENPIC_OFFSET; | ||
155 | OpenPIC_Addr = ioremap(OpenPIC_PAddr, MPC85xx_OPENPIC_SIZE); | ||
156 | OpenPIC_InitSenses = sbc8560_openpic_initsenses; | ||
157 | OpenPIC_NumInitSenses = sizeof (sbc8560_openpic_initsenses); | ||
158 | |||
159 | /* Skip reserved space and internal sources */ | ||
160 | openpic_set_sources(0, 32, OpenPIC_Addr + 0x10200); | ||
161 | /* Map PIC IRQs 0-11 */ | ||
162 | openpic_set_sources(32, 12, OpenPIC_Addr + 0x10000); | ||
163 | |||
164 | /* we let openpic interrupts starting from an offset, to | ||
165 | * leave space for cascading interrupts underneath. | ||
166 | */ | ||
167 | openpic_init(MPC85xx_OPENPIC_IRQ_OFFSET); | ||
168 | |||
169 | return; | ||
170 | } | ||
171 | |||
172 | /* | ||
173 | * interrupt routing | ||
174 | */ | ||
175 | |||
176 | #ifdef CONFIG_PCI | ||
177 | int mpc85xx_map_irq(struct pci_dev *dev, unsigned char idsel, | ||
178 | unsigned char pin) | ||
179 | { | ||
180 | static char pci_irq_table[][4] = | ||
181 | /* | ||
182 | * PCI IDSEL/INTPIN->INTLINE | ||
183 | * A B C D | ||
184 | */ | ||
185 | { | ||
186 | {PIRQA, PIRQB, PIRQC, PIRQD}, | ||
187 | {PIRQD, PIRQA, PIRQB, PIRQC}, | ||
188 | {PIRQC, PIRQD, PIRQA, PIRQB}, | ||
189 | {PIRQB, PIRQC, PIRQD, PIRQA}, | ||
190 | }; | ||
191 | |||
192 | const long min_idsel = 12, max_idsel = 15, irqs_per_slot = 4; | ||
193 | return PCI_IRQ_TABLE_LOOKUP; | ||
194 | } | ||
195 | |||
196 | int mpc85xx_exclude_device(u_char bus, u_char devfn) | ||
197 | { | ||
198 | if (bus == 0 && PCI_SLOT(devfn) == 0) | ||
199 | return PCIBIOS_DEVICE_NOT_FOUND; | ||
200 | else | ||
201 | return PCIBIOS_SUCCESSFUL; | ||
202 | } | ||
203 | #endif /* CONFIG_PCI */ | ||
diff --git a/arch/ppc/platforms/85xx/sbc85xx.h b/arch/ppc/platforms/85xx/sbc85xx.h new file mode 100644 index 000000000000..7af93c691a6b --- /dev/null +++ b/arch/ppc/platforms/85xx/sbc85xx.h | |||
@@ -0,0 +1,55 @@ | |||
1 | /* | ||
2 | * arch/ppc/platforms/85xx/sbc85xx.h | ||
3 | * | ||
4 | * WindRiver PowerQUICC III SBC85xx common board definitions | ||
5 | * | ||
6 | * Copyright 2003 Motorola Inc. | ||
7 | * Copyright 2004 Red Hat, Inc. | ||
8 | * | ||
9 | * This program is free software; you can redistribute it and/or modify it | ||
10 | * under the terms of the GNU General Public License as published by the | ||
11 | * Free Software Foundation; either version 2 of the License, or (at your | ||
12 | * option) any later version. | ||
13 | * | ||
14 | */ | ||
15 | |||
16 | #ifndef __PLATFORMS_85XX_SBC85XX_H__ | ||
17 | #define __PLATFORMS_85XX_SBC85XX_H__ | ||
18 | |||
19 | #include <linux/config.h> | ||
20 | #include <linux/init.h> | ||
21 | #include <linux/seq_file.h> | ||
22 | #include <asm/ppcboot.h> | ||
23 | |||
24 | #define BOARD_CCSRBAR ((uint)0xff700000) | ||
25 | #define CCSRBAR_SIZE ((uint)1024*1024) | ||
26 | |||
27 | #define BCSR_ADDR ((uint)0xfc000000) | ||
28 | #define BCSR_SIZE ((uint)(16 * 1024 * 1024)) | ||
29 | |||
30 | #define UARTA_ADDR (BCSR_ADDR + 0x00700000) | ||
31 | #define UARTB_ADDR (BCSR_ADDR + 0x00800000) | ||
32 | #define RTC_DEVICE_ADDR (BCSR_ADDR + 0x00900000) | ||
33 | #define EEPROM_ADDR (BCSR_ADDR + 0x00b00000) | ||
34 | |||
35 | extern int sbc8560_show_cpuinfo(struct seq_file *m); | ||
36 | extern void sbc8560_init_IRQ(void) __init; | ||
37 | |||
38 | /* PCI interrupt controller */ | ||
39 | #define PIRQA MPC85xx_IRQ_EXT1 | ||
40 | #define PIRQB MPC85xx_IRQ_EXT2 | ||
41 | #define PIRQC MPC85xx_IRQ_EXT3 | ||
42 | #define PIRQD MPC85xx_IRQ_EXT4 | ||
43 | |||
44 | #define MPC85XX_PCI1_LOWER_IO 0x00000000 | ||
45 | #define MPC85XX_PCI1_UPPER_IO 0x00ffffff | ||
46 | |||
47 | #define MPC85XX_PCI1_LOWER_MEM 0x80000000 | ||
48 | #define MPC85XX_PCI1_UPPER_MEM 0x9fffffff | ||
49 | |||
50 | #define MPC85XX_PCI1_IO_BASE 0xe2000000 | ||
51 | #define MPC85XX_PCI1_MEM_OFFSET 0x00000000 | ||
52 | |||
53 | #define MPC85XX_PCI1_IO_SIZE 0x01000000 | ||
54 | |||
55 | #endif /* __PLATFORMS_85XX_SBC85XX_H__ */ | ||
diff --git a/arch/ppc/platforms/85xx/stx_gp3.c b/arch/ppc/platforms/85xx/stx_gp3.c new file mode 100644 index 000000000000..bc95836e417c --- /dev/null +++ b/arch/ppc/platforms/85xx/stx_gp3.c | |||
@@ -0,0 +1,355 @@ | |||
1 | /* | ||
2 | * arch/ppc/platforms/85xx/stx_gp3.c | ||
3 | * | ||
4 | * STx GP3 board specific routines | ||
5 | * | ||
6 | * Dan Malek <dan@embeddededge.com> | ||
7 | * Copyright 2004 Embedded Edge, LLC | ||
8 | * | ||
9 | * Copied from mpc8560_ads.c | ||
10 | * Copyright 2002, 2003 Motorola Inc. | ||
11 | * | ||
12 | * Ported to 2.6, Matt Porter <mporter@kernel.crashing.org> | ||
13 | * Copyright 2004-2005 MontaVista Software, Inc. | ||
14 | * | ||
15 | * This program is free software; you can redistribute it and/or modify it | ||
16 | * under the terms of the GNU General Public License as published by the | ||
17 | * Free Software Foundation; either version 2 of the License, or (at your | ||
18 | * option) any later version. | ||
19 | */ | ||
20 | |||
21 | #include <linux/config.h> | ||
22 | #include <linux/stddef.h> | ||
23 | #include <linux/kernel.h> | ||
24 | #include <linux/init.h> | ||
25 | #include <linux/errno.h> | ||
26 | #include <linux/reboot.h> | ||
27 | #include <linux/pci.h> | ||
28 | #include <linux/kdev_t.h> | ||
29 | #include <linux/major.h> | ||
30 | #include <linux/blkdev.h> | ||
31 | #include <linux/console.h> | ||
32 | #include <linux/delay.h> | ||
33 | #include <linux/irq.h> | ||
34 | #include <linux/root_dev.h> | ||
35 | #include <linux/seq_file.h> | ||
36 | #include <linux/serial.h> | ||
37 | #include <linux/initrd.h> | ||
38 | #include <linux/module.h> | ||
39 | #include <linux/fsl_devices.h> | ||
40 | #include <linux/interrupt.h> | ||
41 | |||
42 | #include <asm/system.h> | ||
43 | #include <asm/pgtable.h> | ||
44 | #include <asm/page.h> | ||
45 | #include <asm/atomic.h> | ||
46 | #include <asm/time.h> | ||
47 | #include <asm/io.h> | ||
48 | #include <asm/machdep.h> | ||
49 | #include <asm/prom.h> | ||
50 | #include <asm/open_pic.h> | ||
51 | #include <asm/bootinfo.h> | ||
52 | #include <asm/pci-bridge.h> | ||
53 | #include <asm/mpc85xx.h> | ||
54 | #include <asm/irq.h> | ||
55 | #include <asm/immap_85xx.h> | ||
56 | #include <asm/immap_cpm2.h> | ||
57 | #include <asm/mpc85xx.h> | ||
58 | #include <asm/ppc_sys.h> | ||
59 | |||
60 | #include <syslib/cpm2_pic.h> | ||
61 | #include <syslib/ppc85xx_common.h> | ||
62 | |||
63 | extern void cpm2_reset(void); | ||
64 | |||
65 | unsigned char __res[sizeof(bd_t)]; | ||
66 | |||
67 | #ifndef CONFIG_PCI | ||
68 | unsigned long isa_io_base = 0; | ||
69 | unsigned long isa_mem_base = 0; | ||
70 | unsigned long pci_dram_offset = 0; | ||
71 | #endif | ||
72 | |||
73 | /* Internal interrupts are all Level Sensitive, and Positive Polarity */ | ||
74 | static u8 gp3_openpic_initsenses[] __initdata = { | ||
75 | (IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE), /* Internal 0: L2 Cache */ | ||
76 | (IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE), /* Internal 1: ECM */ | ||
77 | (IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE), /* Internal 2: DDR DRAM */ | ||
78 | (IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE), /* Internal 3: LBIU */ | ||
79 | (IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE), /* Internal 4: DMA 0 */ | ||
80 | (IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE), /* Internal 5: DMA 1 */ | ||
81 | (IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE), /* Internal 6: DMA 2 */ | ||
82 | (IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE), /* Internal 7: DMA 3 */ | ||
83 | (IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE), /* Internal 8: PCI/PCI-X */ | ||
84 | (IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE), /* Internal 9: RIO Inbound Port Write Error */ | ||
85 | (IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE), /* Internal 10: RIO Doorbell Inbound */ | ||
86 | (IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE), /* Internal 11: RIO Outbound Message */ | ||
87 | (IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE), /* Internal 12: RIO Inbound Message */ | ||
88 | (IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE), /* Internal 13: TSEC 0 Transmit */ | ||
89 | (IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE), /* Internal 14: TSEC 0 Receive */ | ||
90 | (IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE), /* Internal 15: Unused */ | ||
91 | (IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE), /* Internal 16: Unused */ | ||
92 | (IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE), /* Internal 17: Unused */ | ||
93 | (IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE), /* Internal 18: TSEC 0 Receive/Transmit Error */ | ||
94 | (IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE), /* Internal 19: TSEC 1 Transmit */ | ||
95 | (IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE), /* Internal 20: TSEC 1 Receive */ | ||
96 | (IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE), /* Internal 21: Unused */ | ||
97 | (IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE), /* Internal 22: Unused */ | ||
98 | (IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE), /* Internal 23: Unused */ | ||
99 | (IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE), /* Internal 24: TSEC 1 Receive/Transmit Error */ | ||
100 | (IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE), /* Internal 25: Fast Ethernet */ | ||
101 | (IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE), /* Internal 26: DUART */ | ||
102 | (IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE), /* Internal 27: I2C */ | ||
103 | (IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE), /* Internal 28: Performance Monitor */ | ||
104 | (IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE), /* Internal 29: Unused */ | ||
105 | (IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE), /* Internal 30: CPM */ | ||
106 | (IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE), /* Internal 31: Unused */ | ||
107 | 0x0, /* External 0: */ | ||
108 | #if defined(CONFIG_PCI) | ||
109 | (IRQ_SENSE_LEVEL | IRQ_POLARITY_NEGATIVE), /* External 1: PCI slot 0 */ | ||
110 | (IRQ_SENSE_LEVEL | IRQ_POLARITY_NEGATIVE), /* External 2: PCI slot 1 */ | ||
111 | (IRQ_SENSE_LEVEL | IRQ_POLARITY_NEGATIVE), /* External 3: PCI slot 2 */ | ||
112 | (IRQ_SENSE_LEVEL | IRQ_POLARITY_NEGATIVE), /* External 4: PCI slot 3 */ | ||
113 | #else | ||
114 | 0x0, /* External 1: */ | ||
115 | 0x0, /* External 2: */ | ||
116 | 0x0, /* External 3: */ | ||
117 | 0x0, /* External 4: */ | ||
118 | #endif | ||
119 | 0x0, /* External 5: */ | ||
120 | 0x0, /* External 6: */ | ||
121 | 0x0, /* External 7: */ | ||
122 | 0x0, /* External 8: */ | ||
123 | 0x0, /* External 9: */ | ||
124 | 0x0, /* External 10: */ | ||
125 | 0x0, /* External 11: */ | ||
126 | }; | ||
127 | |||
128 | /* | ||
129 | * Setup the architecture | ||
130 | */ | ||
131 | static void __init | ||
132 | gp3_setup_arch(void) | ||
133 | { | ||
134 | bd_t *binfo = (bd_t *) __res; | ||
135 | unsigned int freq; | ||
136 | struct gianfar_platform_data *pdata; | ||
137 | |||
138 | cpm2_reset(); | ||
139 | |||
140 | /* get the core frequency */ | ||
141 | freq = binfo->bi_intfreq; | ||
142 | |||
143 | if (ppc_md.progress) | ||
144 | ppc_md.progress("gp3_setup_arch()", 0); | ||
145 | |||
146 | /* Set loops_per_jiffy to a half-way reasonable value, | ||
147 | for use until calibrate_delay gets called. */ | ||
148 | loops_per_jiffy = freq / HZ; | ||
149 | |||
150 | #ifdef CONFIG_PCI | ||
151 | /* setup PCI host bridges */ | ||
152 | mpc85xx_setup_hose(); | ||
153 | #endif | ||
154 | |||
155 | /* setup the board related information for the enet controllers */ | ||
156 | pdata = (struct gianfar_platform_data *) ppc_sys_get_pdata(MPC85xx_TSEC1); | ||
157 | /* pdata->board_flags = FSL_GIANFAR_BRD_HAS_PHY_INTR; */ | ||
158 | pdata->interruptPHY = MPC85xx_IRQ_EXT5; | ||
159 | pdata->phyid = 2; | ||
160 | pdata->phy_reg_addr += binfo->bi_immr_base; | ||
161 | memcpy(pdata->mac_addr, binfo->bi_enetaddr, 6); | ||
162 | |||
163 | pdata = (struct gianfar_platform_data *) ppc_sys_get_pdata(MPC85xx_TSEC2); | ||
164 | /* pdata->board_flags = FSL_GIANFAR_BRD_HAS_PHY_INTR; */ | ||
165 | pdata->interruptPHY = MPC85xx_IRQ_EXT5; | ||
166 | pdata->phyid = 4; | ||
167 | /* fixup phy address */ | ||
168 | pdata->phy_reg_addr += binfo->bi_immr_base; | ||
169 | memcpy(pdata->mac_addr, binfo->bi_enet1addr, 6); | ||
170 | |||
171 | #ifdef CONFIG_BLK_DEV_INITRD | ||
172 | if (initrd_start) | ||
173 | ROOT_DEV = Root_RAM0; | ||
174 | else | ||
175 | #endif | ||
176 | #ifdef CONFIG_ROOT_NFS | ||
177 | ROOT_DEV = Root_NFS; | ||
178 | #else | ||
179 | ROOT_DEV = Root_HDA1; | ||
180 | #endif | ||
181 | |||
182 | printk ("bi_immr_base = %8.8lx\n", binfo->bi_immr_base); | ||
183 | } | ||
184 | |||
185 | static irqreturn_t cpm2_cascade(int irq, void *dev_id, struct pt_regs *regs) | ||
186 | { | ||
187 | while ((irq = cpm2_get_irq(regs)) >= 0) | ||
188 | __do_IRQ(irq, regs); | ||
189 | |||
190 | return IRQ_HANDLED; | ||
191 | } | ||
192 | |||
193 | static struct irqaction cpm2_irqaction = { | ||
194 | .handler = cpm2_cascade, | ||
195 | .flags = SA_INTERRUPT, | ||
196 | .mask = CPU_MASK_NONE, | ||
197 | .name = "cpm2_cascade", | ||
198 | }; | ||
199 | |||
200 | static void __init | ||
201 | gp3_init_IRQ(void) | ||
202 | { | ||
203 | int i; | ||
204 | bd_t *binfo = (bd_t *) __res; | ||
205 | |||
206 | /* | ||
207 | * Setup OpenPIC | ||
208 | */ | ||
209 | |||
210 | /* Determine the Physical Address of the OpenPIC regs */ | ||
211 | phys_addr_t OpenPIC_PAddr = | ||
212 | binfo->bi_immr_base + MPC85xx_OPENPIC_OFFSET; | ||
213 | OpenPIC_Addr = ioremap(OpenPIC_PAddr, MPC85xx_OPENPIC_SIZE); | ||
214 | OpenPIC_InitSenses = gp3_openpic_initsenses; | ||
215 | OpenPIC_NumInitSenses = sizeof (gp3_openpic_initsenses); | ||
216 | |||
217 | /* Skip reserved space and internal sources */ | ||
218 | openpic_set_sources(0, 32, OpenPIC_Addr + 0x10200); | ||
219 | |||
220 | /* Map PIC IRQs 0-11 */ | ||
221 | openpic_set_sources(32, 12, OpenPIC_Addr + 0x10000); | ||
222 | |||
223 | /* | ||
224 | * Let openpic interrupts starting from an offset, to | ||
225 | * leave space for cascading interrupts underneath. | ||
226 | */ | ||
227 | openpic_init(MPC85xx_OPENPIC_IRQ_OFFSET); | ||
228 | |||
229 | /* Setup CPM2 PIC */ | ||
230 | cpm2_init_IRQ(); | ||
231 | |||
232 | setup_irq(MPC85xx_IRQ_CPM, &cpm2_irqaction); | ||
233 | |||
234 | return; | ||
235 | } | ||
236 | |||
237 | static int | ||
238 | gp3_show_cpuinfo(struct seq_file *m) | ||
239 | { | ||
240 | uint pvid, svid, phid1; | ||
241 | bd_t *binfo = (bd_t *) __res; | ||
242 | uint memsize; | ||
243 | unsigned int freq; | ||
244 | extern unsigned long total_memory; /* in mm/init */ | ||
245 | |||
246 | /* get the core frequency */ | ||
247 | freq = binfo->bi_intfreq; | ||
248 | |||
249 | pvid = mfspr(SPRN_PVR); | ||
250 | svid = mfspr(SPRN_SVR); | ||
251 | |||
252 | memsize = total_memory; | ||
253 | |||
254 | seq_printf(m, "Vendor\t\t: RPC Electronics STx \n"); | ||
255 | seq_printf(m, "Machine\t\t: GP3 - MPC%s\n", cur_ppc_sys_spec->ppc_sys_name); | ||
256 | seq_printf(m, "bus freq\t: %u.%.6u MHz\n", freq / 1000000, | ||
257 | freq % 1000000); | ||
258 | seq_printf(m, "PVR\t\t: 0x%x\n", pvid); | ||
259 | seq_printf(m, "SVR\t\t: 0x%x\n", svid); | ||
260 | |||
261 | /* Display cpu Pll setting */ | ||
262 | phid1 = mfspr(SPRN_HID1); | ||
263 | seq_printf(m, "PLL setting\t: 0x%x\n", ((phid1 >> 24) & 0x3f)); | ||
264 | |||
265 | /* Display the amount of memory */ | ||
266 | seq_printf(m, "Memory\t\t: %d MB\n", memsize / (1024 * 1024)); | ||
267 | |||
268 | return 0; | ||
269 | } | ||
270 | |||
271 | #ifdef CONFIG_PCI | ||
272 | int mpc85xx_map_irq(struct pci_dev *dev, unsigned char idsel, | ||
273 | unsigned char pin) | ||
274 | { | ||
275 | static char pci_irq_table[][4] = | ||
276 | /* | ||
277 | * PCI IDSEL/INTPIN->INTLINE | ||
278 | * A B C D | ||
279 | */ | ||
280 | { | ||
281 | {PIRQA, PIRQB, PIRQC, PIRQD}, | ||
282 | {PIRQD, PIRQA, PIRQB, PIRQC}, | ||
283 | {PIRQC, PIRQD, PIRQA, PIRQB}, | ||
284 | {PIRQB, PIRQC, PIRQD, PIRQA}, | ||
285 | }; | ||
286 | |||
287 | const long min_idsel = 12, max_idsel = 15, irqs_per_slot = 4; | ||
288 | return PCI_IRQ_TABLE_LOOKUP; | ||
289 | } | ||
290 | |||
291 | int mpc85xx_exclude_device(u_char bus, u_char devfn) | ||
292 | { | ||
293 | if (bus == 0 && PCI_SLOT(devfn) == 0) | ||
294 | return PCIBIOS_DEVICE_NOT_FOUND; | ||
295 | else | ||
296 | return PCIBIOS_SUCCESSFUL; | ||
297 | } | ||
298 | #endif /* CONFIG_PCI */ | ||
299 | |||
300 | void __init | ||
301 | platform_init(unsigned long r3, unsigned long r4, unsigned long r5, | ||
302 | unsigned long r6, unsigned long r7) | ||
303 | { | ||
304 | /* parse_bootinfo must always be called first */ | ||
305 | parse_bootinfo(find_bootinfo()); | ||
306 | |||
307 | /* | ||
308 | * If we were passed in a board information, copy it into the | ||
309 | * residual data area. | ||
310 | */ | ||
311 | if (r3) { | ||
312 | memcpy((void *) __res, (void *) (r3 + KERNELBASE), | ||
313 | sizeof (bd_t)); | ||
314 | |||
315 | } | ||
316 | #if defined(CONFIG_BLK_DEV_INITRD) | ||
317 | /* | ||
318 | * If the init RAM disk has been configured in, and there's a valid | ||
319 | * starting address for it, set it up. | ||
320 | */ | ||
321 | if (r4) { | ||
322 | initrd_start = r4 + KERNELBASE; | ||
323 | initrd_end = r5 + KERNELBASE; | ||
324 | } | ||
325 | #endif /* CONFIG_BLK_DEV_INITRD */ | ||
326 | |||
327 | /* Copy the kernel command line arguments to a safe place. */ | ||
328 | |||
329 | if (r6) { | ||
330 | *(char *) (r7 + KERNELBASE) = 0; | ||
331 | strcpy(cmd_line, (char *) (r6 + KERNELBASE)); | ||
332 | } | ||
333 | |||
334 | identify_ppc_sys_by_id(mfspr(SPRN_SVR)); | ||
335 | |||
336 | /* setup the PowerPC module struct */ | ||
337 | ppc_md.setup_arch = gp3_setup_arch; | ||
338 | ppc_md.show_cpuinfo = gp3_show_cpuinfo; | ||
339 | |||
340 | ppc_md.init_IRQ = gp3_init_IRQ; | ||
341 | ppc_md.get_irq = openpic_get_irq; | ||
342 | |||
343 | ppc_md.restart = mpc85xx_restart; | ||
344 | ppc_md.power_off = mpc85xx_power_off; | ||
345 | ppc_md.halt = mpc85xx_halt; | ||
346 | |||
347 | ppc_md.find_end_of_memory = mpc85xx_find_end_of_memory; | ||
348 | |||
349 | ppc_md.calibrate_decr = mpc85xx_calibrate_decr; | ||
350 | |||
351 | if (ppc_md.progress) | ||
352 | ppc_md.progress("platform_init(): exit", 0); | ||
353 | |||
354 | return; | ||
355 | } | ||
diff --git a/arch/ppc/platforms/85xx/stx_gp3.h b/arch/ppc/platforms/85xx/stx_gp3.h new file mode 100644 index 000000000000..7bcc6c35a417 --- /dev/null +++ b/arch/ppc/platforms/85xx/stx_gp3.h | |||
@@ -0,0 +1,74 @@ | |||
1 | /* | ||
2 | * arch/ppc/platforms/stx8560_gp3.h | ||
3 | * | ||
4 | * STx GP3 board definitions | ||
5 | * | ||
6 | * Dan Malek (dan@embeddededge.com) | ||
7 | * Copyright 2004 Embedded Edge, LLC | ||
8 | * | ||
9 | * Ported to 2.6, Matt Porter <mporter@kernel.crashing.org> | ||
10 | * Copyright 2004-2005 MontaVista Software, Inc. | ||
11 | * | ||
12 | * This program is free software; you can redistribute it and/or modify it | ||
13 | * under the terms of the GNU General Public License as published by the | ||
14 | * Free Software Foundation; either version 2 of the License, or (at your | ||
15 | * option) any later version. | ||
16 | * | ||
17 | */ | ||
18 | |||
19 | #ifndef __MACH_STX_GP3_H | ||
20 | #define __MACH_STX_GP3_H | ||
21 | |||
22 | #include <linux/config.h> | ||
23 | #include <linux/init.h> | ||
24 | #include <linux/seq_file.h> | ||
25 | #include <asm/ppcboot.h> | ||
26 | |||
27 | #define BOARD_CCSRBAR ((uint)0xe0000000) | ||
28 | #define CCSRBAR_SIZE ((uint)1024*1024) | ||
29 | |||
30 | #define CPM_MAP_ADDR (CCSRBAR + MPC85xx_CPM_OFFSET) | ||
31 | |||
32 | #define BCSR_ADDR ((uint)0xfc000000) | ||
33 | #define BCSR_SIZE ((uint)(16 * 1024)) | ||
34 | |||
35 | #define BCSR_TSEC1_RESET 0x00000080 | ||
36 | #define BCSR_TSEC2_RESET 0x00000040 | ||
37 | #define BCSR_LED1 0x00000008 | ||
38 | #define BCSR_LED2 0x00000004 | ||
39 | #define BCSR_LED3 0x00000002 | ||
40 | #define BCSR_LED4 0x00000001 | ||
41 | |||
42 | extern void mpc85xx_setup_hose(void) __init; | ||
43 | extern void mpc85xx_restart(char *cmd); | ||
44 | extern void mpc85xx_power_off(void); | ||
45 | extern void mpc85xx_halt(void); | ||
46 | extern int mpc85xx_show_cpuinfo(struct seq_file *m); | ||
47 | extern void mpc85xx_init_IRQ(void) __init; | ||
48 | extern unsigned long mpc85xx_find_end_of_memory(void) __init; | ||
49 | extern void mpc85xx_calibrate_decr(void) __init; | ||
50 | |||
51 | #define PCI_CFG_ADDR_OFFSET (0x8000) | ||
52 | #define PCI_CFG_DATA_OFFSET (0x8004) | ||
53 | |||
54 | /* PCI interrupt controller */ | ||
55 | #define PIRQA MPC85xx_IRQ_EXT1 | ||
56 | #define PIRQB MPC85xx_IRQ_EXT2 | ||
57 | #define PIRQC MPC85xx_IRQ_EXT3 | ||
58 | #define PIRQD MPC85xx_IRQ_EXT4 | ||
59 | #define PCI_MIN_IDSEL 16 | ||
60 | #define PCI_MAX_IDSEL 19 | ||
61 | #define PCI_IRQ_SLOT 4 | ||
62 | |||
63 | #define MPC85XX_PCI1_LOWER_IO 0x00000000 | ||
64 | #define MPC85XX_PCI1_UPPER_IO 0x00ffffff | ||
65 | |||
66 | #define MPC85XX_PCI1_LOWER_MEM 0x80000000 | ||
67 | #define MPC85XX_PCI1_UPPER_MEM 0x9fffffff | ||
68 | |||
69 | #define MPC85XX_PCI1_IO_BASE 0xe2000000 | ||
70 | #define MPC85XX_PCI1_MEM_OFFSET 0x00000000 | ||
71 | |||
72 | #define MPC85XX_PCI1_IO_SIZE 0x01000000 | ||
73 | |||
74 | #endif /* __MACH_STX_GP3_H */ | ||
diff --git a/arch/ppc/platforms/Makefile b/arch/ppc/platforms/Makefile new file mode 100644 index 000000000000..5488a053f415 --- /dev/null +++ b/arch/ppc/platforms/Makefile | |||
@@ -0,0 +1,53 @@ | |||
1 | # | ||
2 | # Makefile for the linux kernel. | ||
3 | # | ||
4 | |||
5 | # Extra CFLAGS so we don't have to do relative includes | ||
6 | CFLAGS_pmac_setup.o += -Iarch/$(ARCH)/mm | ||
7 | |||
8 | obj-$(CONFIG_APUS) += apus_setup.o | ||
9 | ifeq ($(CONFIG_APUS),y) | ||
10 | obj-$(CONFIG_PCI) += apus_pci.o | ||
11 | endif | ||
12 | obj-$(CONFIG_PPC_PMAC) += pmac_pic.o pmac_setup.o pmac_time.o \ | ||
13 | pmac_feature.o pmac_pci.o pmac_sleep.o \ | ||
14 | pmac_low_i2c.o pmac_cache.o | ||
15 | obj-$(CONFIG_PPC_CHRP) += chrp_setup.o chrp_time.o chrp_pci.o \ | ||
16 | chrp_pegasos_eth.o | ||
17 | obj-$(CONFIG_PPC_PREP) += prep_pci.o prep_setup.o | ||
18 | ifeq ($(CONFIG_PPC_PMAC),y) | ||
19 | obj-$(CONFIG_NVRAM) += pmac_nvram.o | ||
20 | obj-$(CONFIG_CPU_FREQ_PMAC) += pmac_cpufreq.o | ||
21 | endif | ||
22 | obj-$(CONFIG_PMAC_BACKLIGHT) += pmac_backlight.o | ||
23 | obj-$(CONFIG_PREP_RESIDUAL) += residual.o | ||
24 | obj-$(CONFIG_ADIR) += adir_setup.o adir_pic.o adir_pci.o | ||
25 | obj-$(CONFIG_PQ2ADS) += pq2ads.o | ||
26 | obj-$(CONFIG_TQM8260) += tqm8260_setup.o | ||
27 | obj-$(CONFIG_CPCI690) += cpci690.o | ||
28 | obj-$(CONFIG_EV64260) += ev64260.o | ||
29 | obj-$(CONFIG_CHESTNUT) += chestnut.o | ||
30 | obj-$(CONFIG_GEMINI) += gemini_pci.o gemini_setup.o gemini_prom.o | ||
31 | obj-$(CONFIG_K2) += k2.o | ||
32 | obj-$(CONFIG_LOPEC) += lopec.o | ||
33 | obj-$(CONFIG_KATANA) += katana.o | ||
34 | obj-$(CONFIG_HDPU) += hdpu.o | ||
35 | obj-$(CONFIG_MCPN765) += mcpn765.o | ||
36 | obj-$(CONFIG_MENF1) += menf1_setup.o menf1_pci.o | ||
37 | obj-$(CONFIG_MVME5100) += mvme5100.o | ||
38 | obj-$(CONFIG_PAL4) += pal4_setup.o pal4_pci.o | ||
39 | obj-$(CONFIG_PCORE) += pcore.o | ||
40 | obj-$(CONFIG_POWERPMC250) += powerpmc250.o | ||
41 | obj-$(CONFIG_PPLUS) += pplus.o | ||
42 | obj-$(CONFIG_PRPMC750) += prpmc750.o | ||
43 | obj-$(CONFIG_PRPMC800) += prpmc800.o | ||
44 | obj-$(CONFIG_RADSTONE_PPC7D) += radstone_ppc7d.o | ||
45 | obj-$(CONFIG_SANDPOINT) += sandpoint.o | ||
46 | obj-$(CONFIG_SBC82xx) += sbc82xx.o | ||
47 | obj-$(CONFIG_SPRUCE) += spruce.o | ||
48 | obj-$(CONFIG_LITE5200) += lite5200.o | ||
49 | |||
50 | ifeq ($(CONFIG_SMP),y) | ||
51 | obj-$(CONFIG_PPC_PMAC) += pmac_smp.o | ||
52 | obj-$(CONFIG_PPC_CHRP) += chrp_smp.o | ||
53 | endif | ||
diff --git a/arch/ppc/platforms/adir.h b/arch/ppc/platforms/adir.h new file mode 100644 index 000000000000..13a748b46956 --- /dev/null +++ b/arch/ppc/platforms/adir.h | |||
@@ -0,0 +1,95 @@ | |||
1 | /* | ||
2 | * arch/ppc/platforms/adir.h | ||
3 | * | ||
4 | * Definitions for SBS Adirondack board support | ||
5 | * | ||
6 | * By Michael Sokolov <msokolov@ivan.Harhan.ORG> | ||
7 | */ | ||
8 | |||
9 | #ifndef __PPC_PLATFORMS_ADIR_H | ||
10 | #define __PPC_PLATFORMS_ADIR_H | ||
11 | |||
12 | /* | ||
13 | * SBS Adirondack definitions | ||
14 | */ | ||
15 | |||
16 | /* PPC physical address space layout. We use the one set up by the firmware. */ | ||
17 | #define ADIR_PCI32_MEM_BASE 0x80000000 | ||
18 | #define ADIR_PCI32_MEM_SIZE 0x20000000 | ||
19 | #define ADIR_PCI64_MEM_BASE 0xA0000000 | ||
20 | #define ADIR_PCI64_MEM_SIZE 0x20000000 | ||
21 | #define ADIR_PCI32_IO_BASE 0xC0000000 | ||
22 | #define ADIR_PCI32_IO_SIZE 0x10000000 | ||
23 | #define ADIR_PCI64_IO_BASE 0xD0000000 | ||
24 | #define ADIR_PCI64_IO_SIZE 0x10000000 | ||
25 | #define ADIR_PCI64_PHB 0xFF400000 | ||
26 | #define ADIR_PCI32_PHB 0xFF500000 | ||
27 | |||
28 | #define ADIR_PCI64_CONFIG_ADDR (ADIR_PCI64_PHB + 0x000f8000) | ||
29 | #define ADIR_PCI64_CONFIG_DATA (ADIR_PCI64_PHB + 0x000f8010) | ||
30 | |||
31 | #define ADIR_PCI32_CONFIG_ADDR (ADIR_PCI32_PHB + 0x000f8000) | ||
32 | #define ADIR_PCI32_CONFIG_DATA (ADIR_PCI32_PHB + 0x000f8010) | ||
33 | |||
34 | /* System memory as seen from PCI */ | ||
35 | #define ADIR_PCI_SYS_MEM_BASE 0x80000000 | ||
36 | |||
37 | /* Static virtual mapping of PCI I/O */ | ||
38 | #define ADIR_PCI32_VIRT_IO_BASE 0xFE000000 | ||
39 | #define ADIR_PCI32_VIRT_IO_SIZE 0x01000000 | ||
40 | #define ADIR_PCI64_VIRT_IO_BASE 0xFF000000 | ||
41 | #define ADIR_PCI64_VIRT_IO_SIZE 0x01000000 | ||
42 | |||
43 | /* Registers */ | ||
44 | #define ADIR_NVRAM_RTC_ADDR 0x74 | ||
45 | #define ADIR_NVRAM_RTC_DATA 0x75 | ||
46 | |||
47 | #define ADIR_BOARD_ID_REG (ADIR_PCI32_VIRT_IO_BASE + 0x08FFF0) | ||
48 | #define ADIR_CPLD1REV_REG (ADIR_PCI32_VIRT_IO_BASE + 0x08FFF1) | ||
49 | #define ADIR_CPLD2REV_REG (ADIR_PCI32_VIRT_IO_BASE + 0x08FFF2) | ||
50 | #define ADIR_FLASHCTL_REG (ADIR_PCI32_VIRT_IO_BASE + 0x08FFF3) | ||
51 | #define ADIR_CPC710_STAT_REG (ADIR_PCI32_VIRT_IO_BASE + 0x08FFF4) | ||
52 | #define ADIR_CLOCK_REG (ADIR_PCI32_VIRT_IO_BASE + 0x08FFF5) | ||
53 | #define ADIR_GPIO_REG (ADIR_PCI32_VIRT_IO_BASE + 0x08FFF8) | ||
54 | #define ADIR_MISC_REG (ADIR_PCI32_VIRT_IO_BASE + 0x08FFF9) | ||
55 | #define ADIR_LED_REG (ADIR_PCI32_VIRT_IO_BASE + 0x08FFFA) | ||
56 | |||
57 | #define ADIR_CLOCK_REG_PD 0x10 | ||
58 | #define ADIR_CLOCK_REG_SPREAD 0x08 | ||
59 | #define ADIR_CLOCK_REG_SEL133 0x04 | ||
60 | #define ADIR_CLOCK_REG_SEL1 0x02 | ||
61 | #define ADIR_CLOCK_REG_SEL0 0x01 | ||
62 | |||
63 | #define ADIR_PROCA_INT_MASK (ADIR_PCI32_VIRT_IO_BASE + 0x0EFFF0) | ||
64 | #define ADIR_PROCB_INT_MASK (ADIR_PCI32_VIRT_IO_BASE + 0x0EFFF2) | ||
65 | #define ADIR_PROCA_INT_STAT (ADIR_PCI32_VIRT_IO_BASE + 0x0EFFF4) | ||
66 | #define ADIR_PROCB_INT_STAT (ADIR_PCI32_VIRT_IO_BASE + 0x0EFFF6) | ||
67 | |||
68 | /* Linux IRQ numbers */ | ||
69 | #define ADIR_IRQ_NONE -1 | ||
70 | #define ADIR_IRQ_SERIAL2 3 | ||
71 | #define ADIR_IRQ_SERIAL1 4 | ||
72 | #define ADIR_IRQ_FDC 6 | ||
73 | #define ADIR_IRQ_PARALLEL 7 | ||
74 | #define ADIR_IRQ_VIA_AUDIO 10 | ||
75 | #define ADIR_IRQ_VIA_USB 11 | ||
76 | #define ADIR_IRQ_IDE0 14 | ||
77 | #define ADIR_IRQ_IDE1 15 | ||
78 | #define ADIR_IRQ_PCI0_INTA 16 | ||
79 | #define ADIR_IRQ_PCI0_INTB 17 | ||
80 | #define ADIR_IRQ_PCI0_INTC 18 | ||
81 | #define ADIR_IRQ_PCI0_INTD 19 | ||
82 | #define ADIR_IRQ_PCI1_INTA 20 | ||
83 | #define ADIR_IRQ_PCI1_INTB 21 | ||
84 | #define ADIR_IRQ_PCI1_INTC 22 | ||
85 | #define ADIR_IRQ_PCI1_INTD 23 | ||
86 | #define ADIR_IRQ_MBSCSI 24 /* motherboard SCSI */ | ||
87 | #define ADIR_IRQ_MBETH1 25 /* motherboard Ethernet 1 */ | ||
88 | #define ADIR_IRQ_MBETH0 26 /* motherboard Ethernet 0 */ | ||
89 | #define ADIR_IRQ_CPC710_INT1 27 | ||
90 | #define ADIR_IRQ_CPC710_INT2 28 | ||
91 | #define ADIR_IRQ_VT82C686_NMI 29 | ||
92 | #define ADIR_IRQ_VT82C686_INTR 30 | ||
93 | #define ADIR_IRQ_INTERPROC 31 | ||
94 | |||
95 | #endif /* __PPC_PLATFORMS_ADIR_H */ | ||
diff --git a/arch/ppc/platforms/adir_pci.c b/arch/ppc/platforms/adir_pci.c new file mode 100644 index 000000000000..f94ac53e0711 --- /dev/null +++ b/arch/ppc/platforms/adir_pci.c | |||
@@ -0,0 +1,247 @@ | |||
1 | /* | ||
2 | * arch/ppc/platforms/adir_pci.c | ||
3 | * | ||
4 | * PCI support for SBS Adirondack | ||
5 | * | ||
6 | * By Michael Sokolov <msokolov@ivan.Harhan.ORG> | ||
7 | * based on the K2 version by Matt Porter <mporter@mvista.com> | ||
8 | */ | ||
9 | |||
10 | #include <linux/kernel.h> | ||
11 | #include <linux/init.h> | ||
12 | #include <linux/pci.h> | ||
13 | #include <linux/slab.h> | ||
14 | |||
15 | #include <asm/byteorder.h> | ||
16 | #include <asm/io.h> | ||
17 | #include <asm/uaccess.h> | ||
18 | #include <asm/machdep.h> | ||
19 | #include <asm/pci-bridge.h> | ||
20 | |||
21 | #include <syslib/cpc710.h> | ||
22 | #include "adir.h" | ||
23 | |||
24 | #undef DEBUG | ||
25 | #ifdef DEBUG | ||
26 | #define DBG(x...) printk(x) | ||
27 | #else | ||
28 | #define DBG(x...) | ||
29 | #endif /* DEBUG */ | ||
30 | |||
31 | static inline int __init | ||
32 | adir_map_irq(struct pci_dev *dev, unsigned char idsel, unsigned char pin) | ||
33 | { | ||
34 | #define PCIIRQ(a,b,c,d) {ADIR_IRQ_##a,ADIR_IRQ_##b,ADIR_IRQ_##c,ADIR_IRQ_##d}, | ||
35 | struct pci_controller *hose = pci_bus_to_hose(dev->bus->number); | ||
36 | /* | ||
37 | * The three PCI devices on the motherboard have dedicated lines to the | ||
38 | * CPLD interrupt controller, bypassing the standard PCI INTA-D and the | ||
39 | * PC interrupt controller. All other PCI devices (slots) have usual | ||
40 | * staggered INTA-D lines, resulting in 8 lines total (PCI0 INTA-D and | ||
41 | * PCI1 INTA-D). All 8 go to the CPLD interrupt controller. PCI0 INTA-D | ||
42 | * also go to the south bridge, so we have the option of taking them | ||
43 | * via the CPLD interrupt controller or via the south bridge 8259 | ||
44 | * 8258 thingy. PCI1 INTA-D can only be taken via the CPLD interrupt | ||
45 | * controller. We take all PCI interrupts via the CPLD interrupt | ||
46 | * controller as recommended by SBS. | ||
47 | * | ||
48 | * We also have some monkey business with the PCI devices within the | ||
49 | * VT82C686B south bridge itself. This chip actually has 7 functions on | ||
50 | * its IDSEL. Function 0 is the actual south bridge, function 1 is IDE, | ||
51 | * and function 4 is some special stuff. The other 4 functions are just | ||
52 | * regular PCI devices bundled in the chip. 2 and 3 are USB UHCIs and 5 | ||
53 | * and 6 are audio (not supported on the Adirondack). | ||
54 | * | ||
55 | * This is where the monkey business begins. PCI devices are supposed | ||
56 | * to signal normal PCI interrupts. But the 4 functions in question are | ||
57 | * located in the south bridge chip, which is designed with the | ||
58 | * assumption that it will be fielding PCI INTA-D interrupts rather | ||
59 | * than generating them. Here's what it does. Each of the functions in | ||
60 | * question routes its interrupt to one of the IRQs on the 8259 thingy. | ||
61 | * Which one? It looks at the Interrupt Line register in the PCI config | ||
62 | * space, even though the PCI spec says it's for BIOS/OS interaction | ||
63 | * only. | ||
64 | * | ||
65 | * How do we deal with this? We take these interrupts via 8259 IRQs as | ||
66 | * we have to. We return the desired IRQ numbers from this routine when | ||
67 | * called for the functions in question. The PCI scan code will then | ||
68 | * stick our return value into the Interrupt Line register in the PCI | ||
69 | * config space, and the interrupt will actually go there. We identify | ||
70 | * these functions within the south bridge IDSEL by their interrupt pin | ||
71 | * numbers, as the VT82C686B has 04 in the Interrupt Pin register for | ||
72 | * USB and 03 for audio. | ||
73 | */ | ||
74 | if (!hose->index) { | ||
75 | static char pci_irq_table[][4] = | ||
76 | /* | ||
77 | * PCI IDSEL/INTPIN->INTLINE | ||
78 | * A B C D | ||
79 | */ | ||
80 | { | ||
81 | /* south bridge */ PCIIRQ(IDE0, NONE, VIA_AUDIO, VIA_USB) | ||
82 | /* Ethernet 0 */ PCIIRQ(MBETH0, MBETH0, MBETH0, MBETH0) | ||
83 | /* PCI0 slot 1 */ PCIIRQ(PCI0_INTB, PCI0_INTC, PCI0_INTD, PCI0_INTA) | ||
84 | /* PCI0 slot 2 */ PCIIRQ(PCI0_INTC, PCI0_INTD, PCI0_INTA, PCI0_INTB) | ||
85 | /* PCI0 slot 3 */ PCIIRQ(PCI0_INTD, PCI0_INTA, PCI0_INTB, PCI0_INTC) | ||
86 | }; | ||
87 | const long min_idsel = 3, max_idsel = 7, irqs_per_slot = 4; | ||
88 | return PCI_IRQ_TABLE_LOOKUP; | ||
89 | } else { | ||
90 | static char pci_irq_table[][4] = | ||
91 | /* | ||
92 | * PCI IDSEL/INTPIN->INTLINE | ||
93 | * A B C D | ||
94 | */ | ||
95 | { | ||
96 | /* Ethernet 1 */ PCIIRQ(MBETH1, MBETH1, MBETH1, MBETH1) | ||
97 | /* SCSI */ PCIIRQ(MBSCSI, MBSCSI, MBSCSI, MBSCSI) | ||
98 | /* PCI1 slot 1 */ PCIIRQ(PCI1_INTB, PCI1_INTC, PCI1_INTD, PCI1_INTA) | ||
99 | /* PCI1 slot 2 */ PCIIRQ(PCI1_INTC, PCI1_INTD, PCI1_INTA, PCI1_INTB) | ||
100 | /* PCI1 slot 3 */ PCIIRQ(PCI1_INTD, PCI1_INTA, PCI1_INTB, PCI1_INTC) | ||
101 | }; | ||
102 | const long min_idsel = 3, max_idsel = 7, irqs_per_slot = 4; | ||
103 | return PCI_IRQ_TABLE_LOOKUP; | ||
104 | } | ||
105 | #undef PCIIRQ | ||
106 | } | ||
107 | |||
108 | static void | ||
109 | adir_pcibios_fixup_resources(struct pci_dev *dev) | ||
110 | { | ||
111 | int i; | ||
112 | |||
113 | if ((dev->vendor == PCI_VENDOR_ID_IBM) && | ||
114 | (dev->device == PCI_DEVICE_ID_IBM_CPC710_PCI64)) | ||
115 | { | ||
116 | DBG("Fixup CPC710 resources\n"); | ||
117 | for (i=0; i<DEVICE_COUNT_RESOURCE; i++) | ||
118 | { | ||
119 | dev->resource[i].start = 0; | ||
120 | dev->resource[i].end = 0; | ||
121 | } | ||
122 | } | ||
123 | } | ||
124 | |||
125 | /* | ||
126 | * CPC710 DD3 has an errata causing it to hang the system if a type 0 config | ||
127 | * cycle is attempted on its PCI32 interface with a device number > 21. | ||
128 | * CPC710's PCI bridges map device numbers 1 through 21 to AD11 through AD31. | ||
129 | * Per the PCI spec it MUST accept all other device numbers and do nothing, and | ||
130 | * software MUST scan all device numbers without assuming how IDSELs are | ||
131 | * mapped. However, as the CPC710 DD3's errata causes such correct scanning | ||
132 | * procedure to hang the system, we have no choice but to introduce this hack | ||
133 | * of knowingly avoiding device numbers > 21 on PCI0, | ||
134 | */ | ||
135 | static int | ||
136 | adir_exclude_device(u_char bus, u_char devfn) | ||
137 | { | ||
138 | if ((bus == 0) && (PCI_SLOT(devfn) > 21)) | ||
139 | return PCIBIOS_DEVICE_NOT_FOUND; | ||
140 | else | ||
141 | return PCIBIOS_SUCCESSFUL; | ||
142 | } | ||
143 | |||
144 | void adir_find_bridges(void) | ||
145 | { | ||
146 | struct pci_controller *hose_a, *hose_b; | ||
147 | |||
148 | /* Setup PCI32 hose */ | ||
149 | hose_a = pcibios_alloc_controller(); | ||
150 | if (!hose_a) | ||
151 | return; | ||
152 | |||
153 | hose_a->first_busno = 0; | ||
154 | hose_a->last_busno = 0xff; | ||
155 | hose_a->pci_mem_offset = ADIR_PCI32_MEM_BASE; | ||
156 | hose_a->io_space.start = 0; | ||
157 | hose_a->io_space.end = ADIR_PCI32_VIRT_IO_SIZE - 1; | ||
158 | hose_a->mem_space.start = 0; | ||
159 | hose_a->mem_space.end = ADIR_PCI32_MEM_SIZE - 1; | ||
160 | hose_a->io_resource.start = 0; | ||
161 | hose_a->io_resource.end = ADIR_PCI32_VIRT_IO_SIZE - 1; | ||
162 | hose_a->io_resource.flags = IORESOURCE_IO; | ||
163 | hose_a->mem_resources[0].start = ADIR_PCI32_MEM_BASE; | ||
164 | hose_a->mem_resources[0].end = ADIR_PCI32_MEM_BASE + | ||
165 | ADIR_PCI32_MEM_SIZE - 1; | ||
166 | hose_a->mem_resources[0].flags = IORESOURCE_MEM; | ||
167 | hose_a->io_base_phys = ADIR_PCI32_IO_BASE; | ||
168 | hose_a->io_base_virt = (void *) ADIR_PCI32_VIRT_IO_BASE; | ||
169 | |||
170 | ppc_md.pci_exclude_device = adir_exclude_device; | ||
171 | setup_indirect_pci(hose_a, ADIR_PCI32_CONFIG_ADDR, | ||
172 | ADIR_PCI32_CONFIG_DATA); | ||
173 | |||
174 | /* Initialize PCI32 bus registers */ | ||
175 | early_write_config_byte(hose_a, | ||
176 | hose_a->first_busno, | ||
177 | PCI_DEVFN(0, 0), | ||
178 | CPC710_BUS_NUMBER, | ||
179 | hose_a->first_busno); | ||
180 | early_write_config_byte(hose_a, | ||
181 | hose_a->first_busno, | ||
182 | PCI_DEVFN(0, 0), | ||
183 | CPC710_SUB_BUS_NUMBER, | ||
184 | hose_a->last_busno); | ||
185 | |||
186 | hose_a->last_busno = pciauto_bus_scan(hose_a, hose_a->first_busno); | ||
187 | |||
188 | /* Write out correct max subordinate bus number for hose A */ | ||
189 | early_write_config_byte(hose_a, | ||
190 | hose_a->first_busno, | ||
191 | PCI_DEVFN(0, 0), | ||
192 | CPC710_SUB_BUS_NUMBER, | ||
193 | hose_a->last_busno); | ||
194 | |||
195 | /* Setup PCI64 hose */ | ||
196 | hose_b = pcibios_alloc_controller(); | ||
197 | if (!hose_b) | ||
198 | return; | ||
199 | |||
200 | hose_b->first_busno = hose_a->last_busno + 1; | ||
201 | hose_b->last_busno = 0xff; | ||
202 | hose_b->pci_mem_offset = ADIR_PCI64_MEM_BASE; | ||
203 | hose_b->io_space.start = 0; | ||
204 | hose_b->io_space.end = ADIR_PCI64_VIRT_IO_SIZE - 1; | ||
205 | hose_b->mem_space.start = 0; | ||
206 | hose_b->mem_space.end = ADIR_PCI64_MEM_SIZE - 1; | ||
207 | hose_b->io_resource.start = 0; | ||
208 | hose_b->io_resource.end = ADIR_PCI64_VIRT_IO_SIZE - 1; | ||
209 | hose_b->io_resource.flags = IORESOURCE_IO; | ||
210 | hose_b->mem_resources[0].start = ADIR_PCI64_MEM_BASE; | ||
211 | hose_b->mem_resources[0].end = ADIR_PCI64_MEM_BASE + | ||
212 | ADIR_PCI64_MEM_SIZE - 1; | ||
213 | hose_b->mem_resources[0].flags = IORESOURCE_MEM; | ||
214 | hose_b->io_base_phys = ADIR_PCI64_IO_BASE; | ||
215 | hose_b->io_base_virt = (void *) ADIR_PCI64_VIRT_IO_BASE; | ||
216 | |||
217 | setup_indirect_pci(hose_b, ADIR_PCI64_CONFIG_ADDR, | ||
218 | ADIR_PCI64_CONFIG_DATA); | ||
219 | |||
220 | /* Initialize PCI64 bus registers */ | ||
221 | early_write_config_byte(hose_b, | ||
222 | 0, | ||
223 | PCI_DEVFN(0, 0), | ||
224 | CPC710_SUB_BUS_NUMBER, | ||
225 | 0xff); | ||
226 | |||
227 | early_write_config_byte(hose_b, | ||
228 | 0, | ||
229 | PCI_DEVFN(0, 0), | ||
230 | CPC710_BUS_NUMBER, | ||
231 | hose_b->first_busno); | ||
232 | |||
233 | hose_b->last_busno = pciauto_bus_scan(hose_b, | ||
234 | hose_b->first_busno); | ||
235 | |||
236 | /* Write out correct max subordinate bus number for hose B */ | ||
237 | early_write_config_byte(hose_b, | ||
238 | hose_b->first_busno, | ||
239 | PCI_DEVFN(0, 0), | ||
240 | CPC710_SUB_BUS_NUMBER, | ||
241 | hose_b->last_busno); | ||
242 | |||
243 | ppc_md.pcibios_fixup = NULL; | ||
244 | ppc_md.pcibios_fixup_resources = adir_pcibios_fixup_resources; | ||
245 | ppc_md.pci_swizzle = common_swizzle; | ||
246 | ppc_md.pci_map_irq = adir_map_irq; | ||
247 | } | ||
diff --git a/arch/ppc/platforms/adir_pic.c b/arch/ppc/platforms/adir_pic.c new file mode 100644 index 000000000000..9947cba52af5 --- /dev/null +++ b/arch/ppc/platforms/adir_pic.c | |||
@@ -0,0 +1,130 @@ | |||
1 | /* | ||
2 | * arch/ppc/platforms/adir_pic.c | ||
3 | * | ||
4 | * Interrupt controller support for SBS Adirondack | ||
5 | * | ||
6 | * By Michael Sokolov <msokolov@ivan.Harhan.ORG> | ||
7 | * based on the K2 and SCM versions by Matt Porter <mporter@mvista.com> | ||
8 | */ | ||
9 | |||
10 | #include <linux/stddef.h> | ||
11 | #include <linux/init.h> | ||
12 | #include <linux/sched.h> | ||
13 | #include <linux/pci.h> | ||
14 | #include <linux/interrupt.h> | ||
15 | |||
16 | #include <asm/io.h> | ||
17 | #include <asm/i8259.h> | ||
18 | #include "adir.h" | ||
19 | |||
20 | static void adir_onboard_pic_enable(unsigned int irq); | ||
21 | static void adir_onboard_pic_disable(unsigned int irq); | ||
22 | |||
23 | __init static void | ||
24 | adir_onboard_pic_init(void) | ||
25 | { | ||
26 | volatile u_short *maskreg = (volatile u_short *) ADIR_PROCA_INT_MASK; | ||
27 | |||
28 | /* Disable all Adirondack onboard interrupts */ | ||
29 | out_be16(maskreg, 0xFFFF); | ||
30 | } | ||
31 | |||
32 | static int | ||
33 | adir_onboard_pic_get_irq(void) | ||
34 | { | ||
35 | volatile u_short *statreg = (volatile u_short *) ADIR_PROCA_INT_STAT; | ||
36 | int irq; | ||
37 | u_short int_status, int_test; | ||
38 | |||
39 | int_status = in_be16(statreg); | ||
40 | for (irq = 0, int_test = 1; irq < 16; irq++, int_test <<= 1) { | ||
41 | if (int_status & int_test) | ||
42 | break; | ||
43 | } | ||
44 | |||
45 | if (irq == 16) | ||
46 | return -1; | ||
47 | |||
48 | return (irq+16); | ||
49 | } | ||
50 | |||
51 | static void | ||
52 | adir_onboard_pic_enable(unsigned int irq) | ||
53 | { | ||
54 | volatile u_short *maskreg = (volatile u_short *) ADIR_PROCA_INT_MASK; | ||
55 | |||
56 | /* Change irq to Adirondack onboard native value */ | ||
57 | irq -= 16; | ||
58 | |||
59 | /* Enable requested irq number */ | ||
60 | out_be16(maskreg, in_be16(maskreg) & ~(1 << irq)); | ||
61 | } | ||
62 | |||
63 | static void | ||
64 | adir_onboard_pic_disable(unsigned int irq) | ||
65 | { | ||
66 | volatile u_short *maskreg = (volatile u_short *) ADIR_PROCA_INT_MASK; | ||
67 | |||
68 | /* Change irq to Adirondack onboard native value */ | ||
69 | irq -= 16; | ||
70 | |||
71 | /* Disable requested irq number */ | ||
72 | out_be16(maskreg, in_be16(maskreg) | (1 << irq)); | ||
73 | } | ||
74 | |||
75 | static struct hw_interrupt_type adir_onboard_pic = { | ||
76 | " ADIR PIC ", | ||
77 | NULL, | ||
78 | NULL, | ||
79 | adir_onboard_pic_enable, /* unmask */ | ||
80 | adir_onboard_pic_disable, /* mask */ | ||
81 | adir_onboard_pic_disable, /* mask and ack */ | ||
82 | NULL, | ||
83 | NULL | ||
84 | }; | ||
85 | |||
86 | static struct irqaction noop_action = { | ||
87 | .handler = no_action, | ||
88 | .flags = SA_INTERRUPT, | ||
89 | .mask = CPU_MASK_NONE, | ||
90 | .name = "82c59 primary cascade", | ||
91 | }; | ||
92 | |||
93 | /* | ||
94 | * Linux interrupt values are assigned as follows: | ||
95 | * | ||
96 | * 0-15 VT82C686 8259 interrupts | ||
97 | * 16-31 Adirondack CPLD interrupts | ||
98 | */ | ||
99 | __init void | ||
100 | adir_init_IRQ(void) | ||
101 | { | ||
102 | int i; | ||
103 | |||
104 | /* Initialize the cascaded 8259's on the VT82C686 */ | ||
105 | for (i=0; i<16; i++) | ||
106 | irq_desc[i].handler = &i8259_pic; | ||
107 | i8259_init(NULL); | ||
108 | |||
109 | /* Initialize Adirondack CPLD PIC and enable 8259 interrupt cascade */ | ||
110 | for (i=16; i<32; i++) | ||
111 | irq_desc[i].handler = &adir_onboard_pic; | ||
112 | adir_onboard_pic_init(); | ||
113 | |||
114 | /* Enable 8259 interrupt cascade */ | ||
115 | setup_irq(ADIR_IRQ_VT82C686_INTR, &noop_action); | ||
116 | } | ||
117 | |||
118 | int | ||
119 | adir_get_irq(struct pt_regs *regs) | ||
120 | { | ||
121 | int irq; | ||
122 | |||
123 | if ((irq = adir_onboard_pic_get_irq()) < 0) | ||
124 | return irq; | ||
125 | |||
126 | if (irq == ADIR_IRQ_VT82C686_INTR) | ||
127 | irq = i8259_irq(regs); | ||
128 | |||
129 | return irq; | ||
130 | } | ||
diff --git a/arch/ppc/platforms/adir_setup.c b/arch/ppc/platforms/adir_setup.c new file mode 100644 index 000000000000..6a6754ee0617 --- /dev/null +++ b/arch/ppc/platforms/adir_setup.c | |||
@@ -0,0 +1,210 @@ | |||
1 | /* | ||
2 | * arch/ppc/platforms/adir_setup.c | ||
3 | * | ||
4 | * Board setup routines for SBS Adirondack | ||
5 | * | ||
6 | * By Michael Sokolov <msokolov@ivan.Harhan.ORG> | ||
7 | * based on the K2 version by Matt Porter <mporter@mvista.com> | ||
8 | */ | ||
9 | |||
10 | #include <linux/config.h> | ||
11 | #include <linux/stddef.h> | ||
12 | #include <linux/kernel.h> | ||
13 | #include <linux/init.h> | ||
14 | #include <linux/errno.h> | ||
15 | #include <linux/reboot.h> | ||
16 | #include <linux/pci.h> | ||
17 | #include <linux/kdev_t.h> | ||
18 | #include <linux/types.h> | ||
19 | #include <linux/major.h> | ||
20 | #include <linux/initrd.h> | ||
21 | #include <linux/console.h> | ||
22 | #include <linux/delay.h> | ||
23 | #include <linux/ide.h> | ||
24 | #include <linux/seq_file.h> | ||
25 | #include <linux/root_dev.h> | ||
26 | |||
27 | #include <asm/system.h> | ||
28 | #include <asm/pgtable.h> | ||
29 | #include <asm/page.h> | ||
30 | #include <asm/dma.h> | ||
31 | #include <asm/io.h> | ||
32 | #include <asm/machdep.h> | ||
33 | #include <asm/time.h> | ||
34 | #include <asm/todc.h> | ||
35 | #include <asm/bootinfo.h> | ||
36 | |||
37 | #include "adir.h" | ||
38 | |||
39 | extern void adir_init_IRQ(void); | ||
40 | extern int adir_get_irq(struct pt_regs *); | ||
41 | extern void adir_find_bridges(void); | ||
42 | extern unsigned long loops_per_jiffy; | ||
43 | |||
44 | static unsigned int cpu_750cx[16] = { | ||
45 | 5, 15, 14, 0, 4, 13, 0, 9, 6, 11, 8, 10, 16, 12, 7, 0 | ||
46 | }; | ||
47 | |||
48 | static int | ||
49 | adir_get_bus_speed(void) | ||
50 | { | ||
51 | if (!(*((u_char *) ADIR_CLOCK_REG) & ADIR_CLOCK_REG_SEL133)) | ||
52 | return 100000000; | ||
53 | else | ||
54 | return 133333333; | ||
55 | } | ||
56 | |||
57 | static int | ||
58 | adir_get_cpu_speed(void) | ||
59 | { | ||
60 | unsigned long hid1; | ||
61 | int cpu_speed; | ||
62 | |||
63 | hid1 = mfspr(SPRN_HID1) >> 28; | ||
64 | |||
65 | hid1 = cpu_750cx[hid1]; | ||
66 | |||
67 | cpu_speed = adir_get_bus_speed()*hid1/2; | ||
68 | return cpu_speed; | ||
69 | } | ||
70 | |||
71 | static void __init | ||
72 | adir_calibrate_decr(void) | ||
73 | { | ||
74 | int freq, divisor = 4; | ||
75 | |||
76 | /* determine processor bus speed */ | ||
77 | freq = adir_get_bus_speed(); | ||
78 | tb_ticks_per_jiffy = freq / HZ / divisor; | ||
79 | tb_to_us = mulhwu_scale_factor(freq/divisor, 1000000); | ||
80 | } | ||
81 | |||
82 | static int | ||
83 | adir_show_cpuinfo(struct seq_file *m) | ||
84 | { | ||
85 | seq_printf(m, "vendor\t\t: SBS\n"); | ||
86 | seq_printf(m, "machine\t\t: Adirondack\n"); | ||
87 | seq_printf(m, "cpu speed\t: %dMhz\n", adir_get_cpu_speed()/1000000); | ||
88 | seq_printf(m, "bus speed\t: %dMhz\n", adir_get_bus_speed()/1000000); | ||
89 | seq_printf(m, "memory type\t: SDRAM\n"); | ||
90 | |||
91 | return 0; | ||
92 | } | ||
93 | |||
94 | extern char cmd_line[]; | ||
95 | |||
96 | TODC_ALLOC(); | ||
97 | |||
98 | static void __init | ||
99 | adir_setup_arch(void) | ||
100 | { | ||
101 | unsigned int cpu; | ||
102 | |||
103 | /* Setup TODC access */ | ||
104 | TODC_INIT(TODC_TYPE_MC146818, ADIR_NVRAM_RTC_ADDR, 0, | ||
105 | ADIR_NVRAM_RTC_DATA, 8); | ||
106 | |||
107 | /* init to some ~sane value until calibrate_delay() runs */ | ||
108 | loops_per_jiffy = 50000000/HZ; | ||
109 | |||
110 | /* Setup PCI host bridges */ | ||
111 | adir_find_bridges(); | ||
112 | |||
113 | #ifdef CONFIG_BLK_DEV_INITRD | ||
114 | if (initrd_start) | ||
115 | ROOT_DEV = Root_RAM0; | ||
116 | else | ||
117 | #endif | ||
118 | #ifdef CONFIG_ROOT_NFS | ||
119 | ROOT_DEV = Root_NFS; | ||
120 | #else | ||
121 | ROOT_DEV = Root_SDA1; | ||
122 | #endif | ||
123 | |||
124 | /* Identify the system */ | ||
125 | printk("System Identification: SBS Adirondack - PowerPC 750CXe @ %d Mhz\n", adir_get_cpu_speed()/1000000); | ||
126 | printk("SBS Adirondack port (C) 2001 SBS Technologies, Inc.\n"); | ||
127 | |||
128 | /* Identify the CPU manufacturer */ | ||
129 | cpu = mfspr(SPRN_PVR); | ||
130 | printk("CPU manufacturer: IBM [rev=%04x]\n", (cpu & 0xffff)); | ||
131 | } | ||
132 | |||
133 | static void | ||
134 | adir_restart(char *cmd) | ||
135 | { | ||
136 | local_irq_disable(); | ||
137 | /* SRR0 has system reset vector, SRR1 has default MSR value */ | ||
138 | /* rfi restores MSR from SRR1 and sets the PC to the SRR0 value */ | ||
139 | __asm__ __volatile__ | ||
140 | ("lis 3,0xfff0\n\t" | ||
141 | "ori 3,3,0x0100\n\t" | ||
142 | "mtspr 26,3\n\t" | ||
143 | "li 3,0\n\t" | ||
144 | "mtspr 27,3\n\t" | ||
145 | "rfi\n\t"); | ||
146 | for(;;); | ||
147 | } | ||
148 | |||
149 | static void | ||
150 | adir_power_off(void) | ||
151 | { | ||
152 | for(;;); | ||
153 | } | ||
154 | |||
155 | static void | ||
156 | adir_halt(void) | ||
157 | { | ||
158 | adir_restart(NULL); | ||
159 | } | ||
160 | |||
161 | static unsigned long __init | ||
162 | adir_find_end_of_memory(void) | ||
163 | { | ||
164 | return boot_mem_size; | ||
165 | } | ||
166 | |||
167 | static void __init | ||
168 | adir_map_io(void) | ||
169 | { | ||
170 | io_block_mapping(ADIR_PCI32_VIRT_IO_BASE, ADIR_PCI32_IO_BASE, | ||
171 | ADIR_PCI32_VIRT_IO_SIZE, _PAGE_IO); | ||
172 | io_block_mapping(ADIR_PCI64_VIRT_IO_BASE, ADIR_PCI64_IO_BASE, | ||
173 | ADIR_PCI64_VIRT_IO_SIZE, _PAGE_IO); | ||
174 | } | ||
175 | |||
176 | void __init | ||
177 | platform_init(unsigned long r3, unsigned long r4, unsigned long r5, | ||
178 | unsigned long r6, unsigned long r7) | ||
179 | { | ||
180 | /* | ||
181 | * On the Adirondack we use bi_recs and pass the pointer to them in R3. | ||
182 | */ | ||
183 | parse_bootinfo((struct bi_record *) (r3 + KERNELBASE)); | ||
184 | |||
185 | /* Remember, isa_io_base is virtual but isa_mem_base is physical! */ | ||
186 | isa_io_base = ADIR_PCI32_VIRT_IO_BASE; | ||
187 | isa_mem_base = ADIR_PCI32_MEM_BASE; | ||
188 | pci_dram_offset = ADIR_PCI_SYS_MEM_BASE; | ||
189 | |||
190 | ppc_md.setup_arch = adir_setup_arch; | ||
191 | ppc_md.show_cpuinfo = adir_show_cpuinfo; | ||
192 | ppc_md.irq_canonicalize = NULL; | ||
193 | ppc_md.init_IRQ = adir_init_IRQ; | ||
194 | ppc_md.get_irq = adir_get_irq; | ||
195 | ppc_md.init = NULL; | ||
196 | |||
197 | ppc_md.find_end_of_memory = adir_find_end_of_memory; | ||
198 | ppc_md.setup_io_mappings = adir_map_io; | ||
199 | |||
200 | ppc_md.restart = adir_restart; | ||
201 | ppc_md.power_off = adir_power_off; | ||
202 | ppc_md.halt = adir_halt; | ||
203 | |||
204 | ppc_md.time_init = todc_time_init; | ||
205 | ppc_md.set_rtc_time = todc_set_rtc_time; | ||
206 | ppc_md.get_rtc_time = todc_get_rtc_time; | ||
207 | ppc_md.nvram_read_val = todc_mc146818_read_val; | ||
208 | ppc_md.nvram_write_val = todc_mc146818_write_val; | ||
209 | ppc_md.calibrate_decr = adir_calibrate_decr; | ||
210 | } | ||
diff --git a/arch/ppc/platforms/apus_pci.c b/arch/ppc/platforms/apus_pci.c new file mode 100644 index 000000000000..33dad6db8243 --- /dev/null +++ b/arch/ppc/platforms/apus_pci.c | |||
@@ -0,0 +1,208 @@ | |||
1 | /* | ||
2 | * Copyright (C) Michel Dänzer <michdaen@iiic.ethz.ch> | ||
3 | * | ||
4 | * APUS PCI routines. | ||
5 | * | ||
6 | * Currently, only B/CVisionPPC cards (Permedia2) are supported. | ||
7 | * | ||
8 | * Thanks to Geert Uytterhoeven for the idea: | ||
9 | * Read values from given config space(s) for the first devices, -1 otherwise | ||
10 | * | ||
11 | */ | ||
12 | |||
13 | #include <linux/config.h> | ||
14 | #ifdef CONFIG_AMIGA | ||
15 | |||
16 | #include <linux/kernel.h> | ||
17 | #include <linux/pci.h> | ||
18 | #include <linux/delay.h> | ||
19 | #include <linux/string.h> | ||
20 | #include <linux/init.h> | ||
21 | |||
22 | #include <asm/io.h> | ||
23 | #include <asm/pci-bridge.h> | ||
24 | #include <asm/machdep.h> | ||
25 | |||
26 | #include "apus_pci.h" | ||
27 | |||
28 | |||
29 | /* These definitions are mostly adapted from pm2fb.c */ | ||
30 | |||
31 | #undef APUS_PCI_MASTER_DEBUG | ||
32 | #ifdef APUS_PCI_MASTER_DEBUG | ||
33 | #define DPRINTK(a,b...) printk(KERN_DEBUG "apus_pci: %s: " a, __FUNCTION__ , ## b) | ||
34 | #else | ||
35 | #define DPRINTK(a,b...) | ||
36 | #endif | ||
37 | |||
38 | /* | ||
39 | * The _DEFINITIVE_ memory mapping/unmapping functions. | ||
40 | * This is due to the fact that they're changing soooo often... | ||
41 | */ | ||
42 | #define DEFW() wmb() | ||
43 | #define DEFR() rmb() | ||
44 | #define DEFRW() mb() | ||
45 | |||
46 | #define DEVNO(d) ((d)>>3) | ||
47 | #define FNNO(d) ((d)&7) | ||
48 | |||
49 | |||
50 | extern unsigned long powerup_PCI_present; | ||
51 | |||
52 | static struct pci_controller *apus_hose; | ||
53 | |||
54 | |||
55 | void *pci_io_base(unsigned int bus) | ||
56 | { | ||
57 | return 0; | ||
58 | } | ||
59 | |||
60 | |||
61 | int | ||
62 | apus_pcibios_read_config(struct pci_bus *bus, int devfn, int offset, | ||
63 | int len, u32 *val) | ||
64 | { | ||
65 | int fnno = FNNO(devfn); | ||
66 | int devno = DEVNO(devfn); | ||
67 | volatile unsigned char *cfg_data; | ||
68 | |||
69 | if (bus->number > 0 || devno != 1) { | ||
70 | *val = ~0; | ||
71 | return PCIBIOS_DEVICE_NOT_FOUND; | ||
72 | } | ||
73 | /* base address + function offset + offset ^ endianness conversion */ | ||
74 | /* XXX the fnno<<5 bit seems wacky -- paulus */ | ||
75 | cfg_data = apus_hose->cfg_data + (fnno<<5) + (offset ^ (len - 1)); | ||
76 | switch (len) { | ||
77 | case 1: | ||
78 | *val = readb(cfg_data); | ||
79 | break; | ||
80 | case 2: | ||
81 | *val = readw(cfg_data); | ||
82 | break; | ||
83 | default: | ||
84 | *val = readl(cfg_data); | ||
85 | break; | ||
86 | } | ||
87 | |||
88 | DPRINTK("read b: 0x%x, d: 0x%x, f: 0x%x, o: 0x%x, l: %d, v: 0x%x\n", | ||
89 | bus->number, devfn>>3, devfn&7, offset, len, *val); | ||
90 | return PCIBIOS_SUCCESSFUL; | ||
91 | } | ||
92 | |||
93 | int | ||
94 | apus_pcibios_write_config(struct pci_bus *bus, int devfn, int offset, | ||
95 | int len, u32 *val) | ||
96 | { | ||
97 | int fnno = FNNO(devfn); | ||
98 | int devno = DEVNO(devfn); | ||
99 | volatile unsigned char *cfg_data; | ||
100 | |||
101 | if (bus->number > 0 || devno != 1) { | ||
102 | return PCIBIOS_DEVICE_NOT_FOUND; | ||
103 | } | ||
104 | /* base address + function offset + offset ^ endianness conversion */ | ||
105 | /* XXX the fnno<<5 bit seems wacky -- paulus */ | ||
106 | cfg_data = apus_hose->cfg_data + (fnno<<5) + (offset ^ (len - 1)); | ||
107 | switch (len) { | ||
108 | case 1: | ||
109 | writeb(val, cfg_data); DEFW(); | ||
110 | break; | ||
111 | case 2: | ||
112 | writew(val, cfg_data); DEFW(); | ||
113 | break; | ||
114 | default: | ||
115 | writel(val, cfg_data); DEFW(); | ||
116 | break; | ||
117 | } | ||
118 | |||
119 | DPRINTK("write b: 0x%x, d: 0x%x, f: 0x%x, o: 0x%x, l: %d, v: 0x%x\n", | ||
120 | bus->number, devfn>>3, devfn&7, offset, len, val); | ||
121 | return PCIBIOS_SUCCESSFUL; | ||
122 | } | ||
123 | |||
124 | static struct pci_ops apus_pci_ops = { | ||
125 | apus_pcibios_read_config, | ||
126 | apus_pcibios_write_config | ||
127 | }; | ||
128 | |||
129 | static struct resource pci_mem = { "B/CVisionPPC PCI mem", CVPPC_FB_APERTURE_ONE, CVPPC_PCI_CONFIG, IORESOURCE_MEM }; | ||
130 | |||
131 | void __init | ||
132 | apus_pcibios_fixup(void) | ||
133 | { | ||
134 | /* struct pci_dev *dev = pci_find_slot(0, 1<<3); | ||
135 | unsigned int reg, val, offset;*/ | ||
136 | |||
137 | /* FIXME: interrupt? */ | ||
138 | /*dev->interrupt = xxx;*/ | ||
139 | |||
140 | request_resource(&iomem_resource, &pci_mem); | ||
141 | printk("%s: PCI mem resource requested\n", __FUNCTION__); | ||
142 | } | ||
143 | |||
144 | static void __init apus_pcibios_fixup_bus(struct pci_bus *bus) | ||
145 | { | ||
146 | bus->resource[1] = &pci_mem; | ||
147 | } | ||
148 | |||
149 | |||
150 | /* | ||
151 | * This is from pm2fb.c again | ||
152 | * | ||
153 | * Check if PCI (B/CVisionPPC) is available, initialize it and set up | ||
154 | * the pcibios_* pointers | ||
155 | */ | ||
156 | |||
157 | |||
158 | void __init | ||
159 | apus_setup_pci_ptrs(void) | ||
160 | { | ||
161 | if (!powerup_PCI_present) { | ||
162 | DPRINTK("no PCI bridge detected\n"); | ||
163 | return; | ||
164 | } | ||
165 | DPRINTK("Phase5 B/CVisionPPC PCI bridge detected.\n"); | ||
166 | |||
167 | apus_hose = pcibios_alloc_controller(); | ||
168 | if (!apus_hose) { | ||
169 | printk("apus_pci: Can't allocate PCI controller structure\n"); | ||
170 | return; | ||
171 | } | ||
172 | |||
173 | if (!(apus_hose->cfg_data = ioremap(CVPPC_PCI_CONFIG, 256))) { | ||
174 | printk("apus_pci: unable to map PCI config region\n"); | ||
175 | return; | ||
176 | } | ||
177 | |||
178 | if (!(apus_hose->cfg_addr = ioremap(CSPPC_PCI_BRIDGE, 256))) { | ||
179 | printk("apus_pci: unable to map PCI bridge\n"); | ||
180 | return; | ||
181 | } | ||
182 | |||
183 | writel(CSPPCF_BRIDGE_BIG_ENDIAN, apus_hose->cfg_addr + CSPPC_BRIDGE_ENDIAN); | ||
184 | DEFW(); | ||
185 | |||
186 | writel(CVPPC_REGS_REGION, apus_hose->cfg_data+ PCI_BASE_ADDRESS_0); | ||
187 | DEFW(); | ||
188 | writel(CVPPC_FB_APERTURE_ONE, apus_hose->cfg_data + PCI_BASE_ADDRESS_1); | ||
189 | DEFW(); | ||
190 | writel(CVPPC_FB_APERTURE_TWO, apus_hose->cfg_data + PCI_BASE_ADDRESS_2); | ||
191 | DEFW(); | ||
192 | writel(CVPPC_ROM_ADDRESS, apus_hose->cfg_data + PCI_ROM_ADDRESS); | ||
193 | DEFW(); | ||
194 | |||
195 | writel(0xef000000 | PCI_COMMAND_IO | PCI_COMMAND_MEMORY | | ||
196 | PCI_COMMAND_MASTER, apus_hose->cfg_data + PCI_COMMAND); | ||
197 | DEFW(); | ||
198 | |||
199 | apus_hose->first_busno = 0; | ||
200 | apus_hose->last_busno = 0; | ||
201 | apus_hose->ops = &apus_pci_ops; | ||
202 | ppc_md.pcibios_fixup = apus_pcibios_fixup; | ||
203 | ppc_md.pcibios_fixup_bus = apus_pcibios_fixup_bus; | ||
204 | |||
205 | return; | ||
206 | } | ||
207 | |||
208 | #endif /* CONFIG_AMIGA */ | ||
diff --git a/arch/ppc/platforms/apus_pci.h b/arch/ppc/platforms/apus_pci.h new file mode 100644 index 000000000000..f15974ae0189 --- /dev/null +++ b/arch/ppc/platforms/apus_pci.h | |||
@@ -0,0 +1,34 @@ | |||
1 | /* | ||
2 | * Phase5 CybervisionPPC (TVP4020) definitions for the Permedia2 framebuffer | ||
3 | * driver. | ||
4 | * | ||
5 | * Copyright (c) 1998-1999 Ilario Nardinocchi (nardinoc@CS.UniBO.IT) | ||
6 | * -------------------------------------------------------------------------- | ||
7 | * This file is subject to the terms and conditions of the GNU General Public | ||
8 | * License. See the file README.legal in the main directory of this archive | ||
9 | * for more details. | ||
10 | */ | ||
11 | |||
12 | #ifndef APUS_PCI_H | ||
13 | #define APUS_PCI_H | ||
14 | |||
15 | |||
16 | #define CSPPC_PCI_BRIDGE 0xfffe0000 | ||
17 | #define CSPPC_BRIDGE_ENDIAN 0x0000 | ||
18 | #define CSPPC_BRIDGE_INT 0x0010 | ||
19 | |||
20 | #define CVPPC_PCI_CONFIG 0xfffc0000 | ||
21 | #define CVPPC_ROM_ADDRESS 0xe2000001 | ||
22 | #define CVPPC_REGS_REGION 0xef000000 | ||
23 | #define CVPPC_FB_APERTURE_ONE 0xe0000000 | ||
24 | #define CVPPC_FB_APERTURE_TWO 0xe1000000 | ||
25 | #define CVPPC_FB_SIZE 0x00800000 | ||
26 | |||
27 | /* CVPPC_BRIDGE_ENDIAN */ | ||
28 | #define CSPPCF_BRIDGE_BIG_ENDIAN 0x02 | ||
29 | |||
30 | /* CVPPC_BRIDGE_INT */ | ||
31 | #define CSPPCF_BRIDGE_ACTIVE_INT2 0x01 | ||
32 | |||
33 | |||
34 | #endif /* APUS_PCI_H */ | ||
diff --git a/arch/ppc/platforms/apus_setup.c b/arch/ppc/platforms/apus_setup.c new file mode 100644 index 000000000000..2f74fde98ebc --- /dev/null +++ b/arch/ppc/platforms/apus_setup.c | |||
@@ -0,0 +1,815 @@ | |||
1 | /* | ||
2 | * arch/ppc/platforms/apus_setup.c | ||
3 | * | ||
4 | * Copyright (C) 1998, 1999 Jesper Skov | ||
5 | * | ||
6 | * Basically what is needed to replace functionality found in | ||
7 | * arch/m68k allowing Amiga drivers to work under APUS. | ||
8 | * Bits of code and/or ideas from arch/m68k and arch/ppc files. | ||
9 | * | ||
10 | * TODO: | ||
11 | * This file needs a *really* good cleanup. Restructure and optimize. | ||
12 | * Make sure it can be compiled for non-APUS configs. Begin to move | ||
13 | * Amiga specific stuff into mach/amiga. | ||
14 | */ | ||
15 | |||
16 | #include <linux/config.h> | ||
17 | #include <linux/kernel.h> | ||
18 | #include <linux/sched.h> | ||
19 | #include <linux/init.h> | ||
20 | #include <linux/initrd.h> | ||
21 | #include <linux/seq_file.h> | ||
22 | |||
23 | /* Needs INITSERIAL call in head.S! */ | ||
24 | #undef APUS_DEBUG | ||
25 | |||
26 | #include <asm/bootinfo.h> | ||
27 | #include <asm/setup.h> | ||
28 | #include <asm/amigahw.h> | ||
29 | #include <asm/amigaints.h> | ||
30 | #include <asm/amigappc.h> | ||
31 | #include <asm/pgtable.h> | ||
32 | #include <asm/dma.h> | ||
33 | #include <asm/machdep.h> | ||
34 | #include <asm/time.h> | ||
35 | |||
36 | unsigned long m68k_machtype; | ||
37 | char debug_device[6] = ""; | ||
38 | |||
39 | extern void amiga_init_IRQ(void); | ||
40 | |||
41 | extern void apus_setup_pci_ptrs(void); | ||
42 | |||
43 | void (*mach_sched_init) (void (*handler)(int, void *, struct pt_regs *)) __initdata = NULL; | ||
44 | /* machine dependent irq functions */ | ||
45 | void (*mach_init_IRQ) (void) __initdata = NULL; | ||
46 | void (*(*mach_default_handler)[]) (int, void *, struct pt_regs *) = NULL; | ||
47 | void (*mach_get_model) (char *model) = NULL; | ||
48 | int (*mach_get_hardware_list) (char *buffer) = NULL; | ||
49 | int (*mach_get_irq_list) (struct seq_file *, void *) = NULL; | ||
50 | void (*mach_process_int) (int, struct pt_regs *) = NULL; | ||
51 | /* machine dependent timer functions */ | ||
52 | unsigned long (*mach_gettimeoffset) (void); | ||
53 | void (*mach_gettod) (int*, int*, int*, int*, int*, int*); | ||
54 | int (*mach_hwclk) (int, struct hwclk_time*) = NULL; | ||
55 | int (*mach_set_clock_mmss) (unsigned long) = NULL; | ||
56 | void (*mach_reset)( void ); | ||
57 | long mach_max_dma_address = 0x00ffffff; /* default set to the lower 16MB */ | ||
58 | #if defined(CONFIG_AMIGA_FLOPPY) | ||
59 | void (*mach_floppy_setup) (char *, int *) __initdata = NULL; | ||
60 | #endif | ||
61 | #ifdef CONFIG_HEARTBEAT | ||
62 | void (*mach_heartbeat) (int) = NULL; | ||
63 | extern void apus_heartbeat (void); | ||
64 | #endif | ||
65 | |||
66 | extern unsigned long amiga_model; | ||
67 | extern unsigned decrementer_count;/* count value for 1e6/HZ microseconds */ | ||
68 | extern unsigned count_period_num; /* 1 decrementer count equals */ | ||
69 | extern unsigned count_period_den; /* count_period_num / count_period_den us */ | ||
70 | |||
71 | int num_memory = 0; | ||
72 | struct mem_info memory[NUM_MEMINFO];/* memory description */ | ||
73 | /* FIXME: Duplicate memory data to avoid conflicts with m68k shared code. */ | ||
74 | int m68k_realnum_memory = 0; | ||
75 | struct mem_info m68k_memory[NUM_MEMINFO];/* memory description */ | ||
76 | |||
77 | struct mem_info ramdisk; | ||
78 | |||
79 | extern void amiga_floppy_setup(char *, int *); | ||
80 | extern void config_amiga(void); | ||
81 | |||
82 | static int __60nsram = 0; | ||
83 | |||
84 | /* for cpuinfo */ | ||
85 | static int __bus_speed = 0; | ||
86 | static int __speed_test_failed = 0; | ||
87 | |||
88 | /********************************************** COMPILE PROTECTION */ | ||
89 | /* Provide some stubs that links to Amiga specific functions. | ||
90 | * This allows CONFIG_APUS to be removed from generic PPC files while | ||
91 | * preventing link errors for other PPC targets. | ||
92 | */ | ||
93 | unsigned long apus_get_rtc_time(void) | ||
94 | { | ||
95 | #ifdef CONFIG_APUS | ||
96 | extern unsigned long m68k_get_rtc_time(void); | ||
97 | |||
98 | return m68k_get_rtc_time (); | ||
99 | #else | ||
100 | return 0; | ||
101 | #endif | ||
102 | } | ||
103 | |||
104 | int apus_set_rtc_time(unsigned long nowtime) | ||
105 | { | ||
106 | #ifdef CONFIG_APUS | ||
107 | extern int m68k_set_rtc_time(unsigned long nowtime); | ||
108 | |||
109 | return m68k_set_rtc_time (nowtime); | ||
110 | #else | ||
111 | return 0; | ||
112 | #endif | ||
113 | } | ||
114 | |||
115 | /*********************************************************** SETUP */ | ||
116 | /* From arch/m68k/kernel/setup.c. */ | ||
117 | void __init apus_setup_arch(void) | ||
118 | { | ||
119 | #ifdef CONFIG_APUS | ||
120 | extern char cmd_line[]; | ||
121 | int i; | ||
122 | char *p, *q; | ||
123 | |||
124 | /* Let m68k-shared code know it should do the Amiga thing. */ | ||
125 | m68k_machtype = MACH_AMIGA; | ||
126 | |||
127 | /* Parse the command line for arch-specific options. | ||
128 | * For the m68k, this is currently only "debug=xxx" to enable printing | ||
129 | * certain kernel messages to some machine-specific device. */ | ||
130 | for( p = cmd_line; p && *p; ) { | ||
131 | i = 0; | ||
132 | if (!strncmp( p, "debug=", 6 )) { | ||
133 | strlcpy( debug_device, p+6, sizeof(debug_device) ); | ||
134 | if ((q = strchr( debug_device, ' ' ))) *q = 0; | ||
135 | i = 1; | ||
136 | } else if (!strncmp( p, "60nsram", 7 )) { | ||
137 | APUS_WRITE (APUS_REG_WAITSTATE, | ||
138 | REGWAITSTATE_SETRESET | ||
139 | |REGWAITSTATE_PPCR | ||
140 | |REGWAITSTATE_PPCW); | ||
141 | __60nsram = 1; | ||
142 | i = 1; | ||
143 | } | ||
144 | |||
145 | if (i) { | ||
146 | /* option processed, delete it */ | ||
147 | if ((q = strchr( p, ' ' ))) | ||
148 | strcpy( p, q+1 ); | ||
149 | else | ||
150 | *p = 0; | ||
151 | } else { | ||
152 | if ((p = strchr( p, ' ' ))) ++p; | ||
153 | } | ||
154 | } | ||
155 | |||
156 | config_amiga(); | ||
157 | |||
158 | #if 0 /* Enable for logging - also include logging.o in Makefile rule */ | ||
159 | { | ||
160 | #define LOG_SIZE 4096 | ||
161 | void* base; | ||
162 | |||
163 | /* Throw away some memory - the P5 firmare stomps on top | ||
164 | * of CHIP memory during bootup. | ||
165 | */ | ||
166 | amiga_chip_alloc(0x1000); | ||
167 | |||
168 | base = amiga_chip_alloc(LOG_SIZE+sizeof(klog_data_t)); | ||
169 | LOG_INIT(base, base+sizeof(klog_data_t), LOG_SIZE); | ||
170 | } | ||
171 | #endif | ||
172 | #endif | ||
173 | } | ||
174 | |||
175 | int | ||
176 | apus_show_cpuinfo(struct seq_file *m) | ||
177 | { | ||
178 | extern int __map_without_bats; | ||
179 | extern unsigned long powerup_PCI_present; | ||
180 | |||
181 | seq_printf(m, "machine\t\t: Amiga\n"); | ||
182 | seq_printf(m, "bus speed\t: %d%s", __bus_speed, | ||
183 | (__speed_test_failed) ? " [failed]\n" : "\n"); | ||
184 | seq_printf(m, "using BATs\t: %s\n", | ||
185 | (__map_without_bats) ? "No" : "Yes"); | ||
186 | seq_printf(m, "ram speed\t: %dns\n", (__60nsram) ? 60 : 70); | ||
187 | seq_printf(m, "PCI bridge\t: %s\n", | ||
188 | (powerup_PCI_present) ? "Yes" : "No"); | ||
189 | return 0; | ||
190 | } | ||
191 | |||
192 | static void get_current_tb(unsigned long long *time) | ||
193 | { | ||
194 | __asm __volatile ("1:mftbu 4 \n\t" | ||
195 | " mftb 5 \n\t" | ||
196 | " mftbu 6 \n\t" | ||
197 | " cmpw 4,6 \n\t" | ||
198 | " bne 1b \n\t" | ||
199 | " stw 4,0(%0)\n\t" | ||
200 | " stw 5,4(%0)\n\t" | ||
201 | : | ||
202 | : "r" (time) | ||
203 | : "r4", "r5", "r6"); | ||
204 | } | ||
205 | |||
206 | |||
207 | void apus_calibrate_decr(void) | ||
208 | { | ||
209 | #ifdef CONFIG_APUS | ||
210 | unsigned long freq; | ||
211 | |||
212 | /* This algorithm for determining the bus speed was | ||
213 | contributed by Ralph Schmidt. */ | ||
214 | unsigned long long start, stop; | ||
215 | int bus_speed; | ||
216 | int speed_test_failed = 0; | ||
217 | |||
218 | { | ||
219 | unsigned long loop = amiga_eclock / 10; | ||
220 | |||
221 | get_current_tb (&start); | ||
222 | while (loop--) { | ||
223 | unsigned char tmp; | ||
224 | |||
225 | tmp = ciaa.pra; | ||
226 | } | ||
227 | get_current_tb (&stop); | ||
228 | } | ||
229 | |||
230 | bus_speed = (((unsigned long)(stop-start))*10*4) / 1000000; | ||
231 | if (AMI_1200 == amiga_model) | ||
232 | bus_speed /= 2; | ||
233 | |||
234 | if ((bus_speed >= 47) && (bus_speed < 53)) { | ||
235 | bus_speed = 50; | ||
236 | freq = 12500000; | ||
237 | } else if ((bus_speed >= 57) && (bus_speed < 63)) { | ||
238 | bus_speed = 60; | ||
239 | freq = 15000000; | ||
240 | } else if ((bus_speed >= 63) && (bus_speed < 69)) { | ||
241 | bus_speed = 67; | ||
242 | freq = 16666667; | ||
243 | } else { | ||
244 | printk ("APUS: Unable to determine bus speed (%d). " | ||
245 | "Defaulting to 50MHz", bus_speed); | ||
246 | bus_speed = 50; | ||
247 | freq = 12500000; | ||
248 | speed_test_failed = 1; | ||
249 | } | ||
250 | |||
251 | /* Ease diagnostics... */ | ||
252 | { | ||
253 | extern int __map_without_bats; | ||
254 | extern unsigned long powerup_PCI_present; | ||
255 | |||
256 | printk ("APUS: BATs=%d, BUS=%dMHz", | ||
257 | (__map_without_bats) ? 0 : 1, | ||
258 | bus_speed); | ||
259 | if (speed_test_failed) | ||
260 | printk ("[FAILED - please report]"); | ||
261 | |||
262 | printk (", RAM=%dns, PCI bridge=%d\n", | ||
263 | (__60nsram) ? 60 : 70, | ||
264 | (powerup_PCI_present) ? 1 : 0); | ||
265 | |||
266 | /* print a bit more if asked politely... */ | ||
267 | if (!(ciaa.pra & 0x40)){ | ||
268 | extern unsigned int bat_addrs[4][3]; | ||
269 | int b; | ||
270 | for (b = 0; b < 4; ++b) { | ||
271 | printk ("APUS: BAT%d ", b); | ||
272 | printk ("%08x-%08x -> %08x\n", | ||
273 | bat_addrs[b][0], | ||
274 | bat_addrs[b][1], | ||
275 | bat_addrs[b][2]); | ||
276 | } | ||
277 | } | ||
278 | |||
279 | } | ||
280 | |||
281 | printk("time_init: decrementer frequency = %lu.%.6lu MHz\n", | ||
282 | freq/1000000, freq%1000000); | ||
283 | tb_ticks_per_jiffy = freq / HZ; | ||
284 | tb_to_us = mulhwu_scale_factor(freq, 1000000); | ||
285 | |||
286 | __bus_speed = bus_speed; | ||
287 | __speed_test_failed = speed_test_failed; | ||
288 | #endif | ||
289 | } | ||
290 | |||
291 | void arch_gettod(int *year, int *mon, int *day, int *hour, | ||
292 | int *min, int *sec) | ||
293 | { | ||
294 | #ifdef CONFIG_APUS | ||
295 | if (mach_gettod) | ||
296 | mach_gettod(year, mon, day, hour, min, sec); | ||
297 | else | ||
298 | *year = *mon = *day = *hour = *min = *sec = 0; | ||
299 | #endif | ||
300 | } | ||
301 | |||
302 | /* for "kbd-reset" cmdline param */ | ||
303 | __init | ||
304 | void kbd_reset_setup(char *str, int *ints) | ||
305 | { | ||
306 | } | ||
307 | |||
308 | /*********************************************************** FLOPPY */ | ||
309 | #if defined(CONFIG_AMIGA_FLOPPY) | ||
310 | __init | ||
311 | void floppy_setup(char *str, int *ints) | ||
312 | { | ||
313 | if (mach_floppy_setup) | ||
314 | mach_floppy_setup (str, ints); | ||
315 | } | ||
316 | #endif | ||
317 | |||
318 | /*********************************************************** MEMORY */ | ||
319 | #define KMAP_MAX 32 | ||
320 | unsigned long kmap_chunks[KMAP_MAX*3]; | ||
321 | int kmap_chunk_count = 0; | ||
322 | |||
323 | /* From pgtable.h */ | ||
324 | static __inline__ pte_t *my_find_pte(struct mm_struct *mm,unsigned long va) | ||
325 | { | ||
326 | pgd_t *dir = 0; | ||
327 | pmd_t *pmd = 0; | ||
328 | pte_t *pte = 0; | ||
329 | |||
330 | va &= PAGE_MASK; | ||
331 | |||
332 | dir = pgd_offset( mm, va ); | ||
333 | if (dir) | ||
334 | { | ||
335 | pmd = pmd_offset(dir, va & PAGE_MASK); | ||
336 | if (pmd && pmd_present(*pmd)) | ||
337 | { | ||
338 | pte = pte_offset(pmd, va); | ||
339 | } | ||
340 | } | ||
341 | return pte; | ||
342 | } | ||
343 | |||
344 | |||
345 | /* Again simulating an m68k/mm/kmap.c function. */ | ||
346 | void kernel_set_cachemode( unsigned long address, unsigned long size, | ||
347 | unsigned int cmode ) | ||
348 | { | ||
349 | unsigned long mask, flags; | ||
350 | |||
351 | switch (cmode) | ||
352 | { | ||
353 | case IOMAP_FULL_CACHING: | ||
354 | mask = ~(_PAGE_NO_CACHE | _PAGE_GUARDED); | ||
355 | flags = 0; | ||
356 | break; | ||
357 | case IOMAP_NOCACHE_SER: | ||
358 | mask = ~0; | ||
359 | flags = (_PAGE_NO_CACHE | _PAGE_GUARDED); | ||
360 | break; | ||
361 | default: | ||
362 | panic ("kernel_set_cachemode() doesn't support mode %d\n", | ||
363 | cmode); | ||
364 | break; | ||
365 | } | ||
366 | |||
367 | size /= PAGE_SIZE; | ||
368 | address &= PAGE_MASK; | ||
369 | while (size--) | ||
370 | { | ||
371 | pte_t *pte; | ||
372 | |||
373 | pte = my_find_pte(&init_mm, address); | ||
374 | if ( !pte ) | ||
375 | { | ||
376 | printk("pte NULL in kernel_set_cachemode()\n"); | ||
377 | return; | ||
378 | } | ||
379 | |||
380 | pte_val (*pte) &= mask; | ||
381 | pte_val (*pte) |= flags; | ||
382 | flush_tlb_page(find_vma(&init_mm,address),address); | ||
383 | |||
384 | address += PAGE_SIZE; | ||
385 | } | ||
386 | } | ||
387 | |||
388 | unsigned long mm_ptov (unsigned long paddr) | ||
389 | { | ||
390 | unsigned long ret; | ||
391 | if (paddr < 16*1024*1024) | ||
392 | ret = ZTWO_VADDR(paddr); | ||
393 | else { | ||
394 | int i; | ||
395 | |||
396 | for (i = 0; i < kmap_chunk_count;){ | ||
397 | unsigned long phys = kmap_chunks[i++]; | ||
398 | unsigned long size = kmap_chunks[i++]; | ||
399 | unsigned long virt = kmap_chunks[i++]; | ||
400 | if (paddr >= phys | ||
401 | && paddr < (phys + size)){ | ||
402 | ret = virt + paddr - phys; | ||
403 | goto exit; | ||
404 | } | ||
405 | } | ||
406 | |||
407 | ret = (unsigned long) __va(paddr); | ||
408 | } | ||
409 | exit: | ||
410 | #ifdef DEBUGPV | ||
411 | printk ("PTOV(%lx)=%lx\n", paddr, ret); | ||
412 | #endif | ||
413 | return ret; | ||
414 | } | ||
415 | |||
416 | int mm_end_of_chunk (unsigned long addr, int len) | ||
417 | { | ||
418 | if (memory[0].addr + memory[0].size == addr + len) | ||
419 | return 1; | ||
420 | return 0; | ||
421 | } | ||
422 | |||
423 | /*********************************************************** CACHE */ | ||
424 | |||
425 | #define L1_CACHE_BYTES 32 | ||
426 | #define MAX_CACHE_SIZE 8192 | ||
427 | void cache_push(__u32 addr, int length) | ||
428 | { | ||
429 | addr = mm_ptov(addr); | ||
430 | |||
431 | if (MAX_CACHE_SIZE < length) | ||
432 | length = MAX_CACHE_SIZE; | ||
433 | |||
434 | while(length > 0){ | ||
435 | __asm ("dcbf 0,%0\n\t" | ||
436 | : : "r" (addr)); | ||
437 | addr += L1_CACHE_BYTES; | ||
438 | length -= L1_CACHE_BYTES; | ||
439 | } | ||
440 | /* Also flush trailing block */ | ||
441 | __asm ("dcbf 0,%0\n\t" | ||
442 | "sync \n\t" | ||
443 | : : "r" (addr)); | ||
444 | } | ||
445 | |||
446 | void cache_clear(__u32 addr, int length) | ||
447 | { | ||
448 | if (MAX_CACHE_SIZE < length) | ||
449 | length = MAX_CACHE_SIZE; | ||
450 | |||
451 | addr = mm_ptov(addr); | ||
452 | |||
453 | __asm ("dcbf 0,%0\n\t" | ||
454 | "sync \n\t" | ||
455 | "icbi 0,%0 \n\t" | ||
456 | "isync \n\t" | ||
457 | : : "r" (addr)); | ||
458 | |||
459 | addr += L1_CACHE_BYTES; | ||
460 | length -= L1_CACHE_BYTES; | ||
461 | |||
462 | while(length > 0){ | ||
463 | __asm ("dcbf 0,%0\n\t" | ||
464 | "sync \n\t" | ||
465 | "icbi 0,%0 \n\t" | ||
466 | "isync \n\t" | ||
467 | : : "r" (addr)); | ||
468 | addr += L1_CACHE_BYTES; | ||
469 | length -= L1_CACHE_BYTES; | ||
470 | } | ||
471 | |||
472 | __asm ("dcbf 0,%0\n\t" | ||
473 | "sync \n\t" | ||
474 | "icbi 0,%0 \n\t" | ||
475 | "isync \n\t" | ||
476 | : : "r" (addr)); | ||
477 | } | ||
478 | |||
479 | /****************************************************** from setup.c */ | ||
480 | void | ||
481 | apus_restart(char *cmd) | ||
482 | { | ||
483 | local_irq_disable(); | ||
484 | |||
485 | APUS_WRITE(APUS_REG_LOCK, | ||
486 | REGLOCK_BLACKMAGICK1|REGLOCK_BLACKMAGICK2); | ||
487 | APUS_WRITE(APUS_REG_LOCK, | ||
488 | REGLOCK_BLACKMAGICK1|REGLOCK_BLACKMAGICK3); | ||
489 | APUS_WRITE(APUS_REG_LOCK, | ||
490 | REGLOCK_BLACKMAGICK2|REGLOCK_BLACKMAGICK3); | ||
491 | APUS_WRITE(APUS_REG_SHADOW, REGSHADOW_SELFRESET); | ||
492 | APUS_WRITE(APUS_REG_RESET, REGRESET_AMIGARESET); | ||
493 | for(;;); | ||
494 | } | ||
495 | |||
496 | void | ||
497 | apus_power_off(void) | ||
498 | { | ||
499 | for (;;); | ||
500 | } | ||
501 | |||
502 | void | ||
503 | apus_halt(void) | ||
504 | { | ||
505 | apus_restart(NULL); | ||
506 | } | ||
507 | |||
508 | /****************************************************** IRQ stuff */ | ||
509 | |||
510 | static unsigned char last_ipl[8]; | ||
511 | |||
512 | int apus_get_irq(struct pt_regs* regs) | ||
513 | { | ||
514 | unsigned char ipl_emu, mask; | ||
515 | unsigned int level; | ||
516 | |||
517 | APUS_READ(APUS_IPL_EMU, ipl_emu); | ||
518 | level = (ipl_emu >> 3) & IPLEMU_IPLMASK; | ||
519 | mask = IPLEMU_SETRESET|IPLEMU_DISABLEINT|level; | ||
520 | level ^= 7; | ||
521 | |||
522 | /* Save previous IPL value */ | ||
523 | if (last_ipl[level]) | ||
524 | return -2; | ||
525 | last_ipl[level] = ipl_emu; | ||
526 | |||
527 | /* Set to current IPL value */ | ||
528 | APUS_WRITE(APUS_IPL_EMU, mask); | ||
529 | APUS_WRITE(APUS_IPL_EMU, IPLEMU_DISABLEINT|level); | ||
530 | |||
531 | |||
532 | #ifdef __INTERRUPT_DEBUG | ||
533 | printk("<%d:%d>", level, ~ipl_emu & IPLEMU_IPLMASK); | ||
534 | #endif | ||
535 | return level + IRQ_AMIGA_AUTO; | ||
536 | } | ||
537 | |||
538 | void apus_end_irq(unsigned int irq) | ||
539 | { | ||
540 | unsigned char ipl_emu; | ||
541 | unsigned int level = irq - IRQ_AMIGA_AUTO; | ||
542 | #ifdef __INTERRUPT_DEBUG | ||
543 | printk("{%d}", ~last_ipl[level] & IPLEMU_IPLMASK); | ||
544 | #endif | ||
545 | /* Restore IPL to the previous value */ | ||
546 | ipl_emu = last_ipl[level] & IPLEMU_IPLMASK; | ||
547 | APUS_WRITE(APUS_IPL_EMU, IPLEMU_SETRESET|IPLEMU_DISABLEINT|ipl_emu); | ||
548 | last_ipl[level] = 0; | ||
549 | ipl_emu ^= 7; | ||
550 | APUS_WRITE(APUS_IPL_EMU, IPLEMU_DISABLEINT|ipl_emu); | ||
551 | } | ||
552 | |||
553 | /****************************************************** debugging */ | ||
554 | |||
555 | /* some serial hardware definitions */ | ||
556 | #define SDR_OVRUN (1<<15) | ||
557 | #define SDR_RBF (1<<14) | ||
558 | #define SDR_TBE (1<<13) | ||
559 | #define SDR_TSRE (1<<12) | ||
560 | |||
561 | #define AC_SETCLR (1<<15) | ||
562 | #define AC_UARTBRK (1<<11) | ||
563 | |||
564 | #define SER_DTR (1<<7) | ||
565 | #define SER_RTS (1<<6) | ||
566 | #define SER_DCD (1<<5) | ||
567 | #define SER_CTS (1<<4) | ||
568 | #define SER_DSR (1<<3) | ||
569 | |||
570 | static __inline__ void ser_RTSon(void) | ||
571 | { | ||
572 | ciab.pra &= ~SER_RTS; /* active low */ | ||
573 | } | ||
574 | |||
575 | int __debug_ser_out( unsigned char c ) | ||
576 | { | ||
577 | custom.serdat = c | 0x100; | ||
578 | mb(); | ||
579 | while (!(custom.serdatr & 0x2000)) | ||
580 | barrier(); | ||
581 | return 1; | ||
582 | } | ||
583 | |||
584 | unsigned char __debug_ser_in( void ) | ||
585 | { | ||
586 | unsigned char c; | ||
587 | |||
588 | /* XXX: is that ok?? derived from amiga_ser.c... */ | ||
589 | while( !(custom.intreqr & IF_RBF) ) | ||
590 | barrier(); | ||
591 | c = custom.serdatr; | ||
592 | /* clear the interrupt, so that another character can be read */ | ||
593 | custom.intreq = IF_RBF; | ||
594 | return c; | ||
595 | } | ||
596 | |||
597 | int __debug_serinit( void ) | ||
598 | { | ||
599 | unsigned long flags; | ||
600 | |||
601 | local_irq_save(flags); | ||
602 | |||
603 | /* turn off Rx and Tx interrupts */ | ||
604 | custom.intena = IF_RBF | IF_TBE; | ||
605 | |||
606 | /* clear any pending interrupt */ | ||
607 | custom.intreq = IF_RBF | IF_TBE; | ||
608 | |||
609 | local_irq_restore(flags); | ||
610 | |||
611 | /* | ||
612 | * set the appropriate directions for the modem control flags, | ||
613 | * and clear RTS and DTR | ||
614 | */ | ||
615 | ciab.ddra |= (SER_DTR | SER_RTS); /* outputs */ | ||
616 | ciab.ddra &= ~(SER_DCD | SER_CTS | SER_DSR); /* inputs */ | ||
617 | |||
618 | #ifdef CONFIG_KGDB | ||
619 | /* turn Rx interrupts on for GDB */ | ||
620 | custom.intena = IF_SETCLR | IF_RBF; | ||
621 | ser_RTSon(); | ||
622 | #endif | ||
623 | |||
624 | return 0; | ||
625 | } | ||
626 | |||
627 | void __debug_print_hex(unsigned long x) | ||
628 | { | ||
629 | int i; | ||
630 | char hexchars[] = "0123456789ABCDEF"; | ||
631 | |||
632 | for (i = 0; i < 8; i++) { | ||
633 | __debug_ser_out(hexchars[(x >> 28) & 15]); | ||
634 | x <<= 4; | ||
635 | } | ||
636 | __debug_ser_out('\n'); | ||
637 | __debug_ser_out('\r'); | ||
638 | } | ||
639 | |||
640 | void __debug_print_string(char* s) | ||
641 | { | ||
642 | unsigned char c; | ||
643 | while((c = *s++)) | ||
644 | __debug_ser_out(c); | ||
645 | __debug_ser_out('\n'); | ||
646 | __debug_ser_out('\r'); | ||
647 | } | ||
648 | |||
649 | static void apus_progress(char *s, unsigned short value) | ||
650 | { | ||
651 | __debug_print_string(s); | ||
652 | } | ||
653 | |||
654 | /****************************************************** init */ | ||
655 | |||
656 | /* The number of spurious interrupts */ | ||
657 | volatile unsigned int num_spurious; | ||
658 | |||
659 | extern struct irqaction amiga_sys_irqaction[AUTO_IRQS]; | ||
660 | |||
661 | |||
662 | extern void amiga_enable_irq(unsigned int irq); | ||
663 | extern void amiga_disable_irq(unsigned int irq); | ||
664 | |||
665 | struct hw_interrupt_type amiga_sys_irqctrl = { | ||
666 | .typename = "Amiga IPL", | ||
667 | .end = apus_end_irq, | ||
668 | }; | ||
669 | |||
670 | struct hw_interrupt_type amiga_irqctrl = { | ||
671 | .typename = "Amiga ", | ||
672 | .enable = amiga_enable_irq, | ||
673 | .disable = amiga_disable_irq, | ||
674 | }; | ||
675 | |||
676 | #define HARDWARE_MAPPED_SIZE (512*1024) | ||
677 | unsigned long __init apus_find_end_of_memory(void) | ||
678 | { | ||
679 | int shadow = 0; | ||
680 | unsigned long total; | ||
681 | |||
682 | /* The memory size reported by ADOS excludes the 512KB | ||
683 | reserved for PPC exception registers and possibly 512KB | ||
684 | containing a shadow of the ADOS ROM. */ | ||
685 | { | ||
686 | unsigned long size = memory[0].size; | ||
687 | |||
688 | /* If 2MB aligned, size was probably user | ||
689 | specified. We can't tell anything about shadowing | ||
690 | in this case so skip shadow assignment. */ | ||
691 | if (0 != (size & 0x1fffff)){ | ||
692 | /* Align to 512KB to ensure correct handling | ||
693 | of both memfile and system specified | ||
694 | sizes. */ | ||
695 | size = ((size+0x0007ffff) & 0xfff80000); | ||
696 | /* If memory is 1MB aligned, assume | ||
697 | shadowing. */ | ||
698 | shadow = !(size & 0x80000); | ||
699 | } | ||
700 | |||
701 | /* Add the chunk that ADOS does not see. by aligning | ||
702 | the size to the nearest 2MB limit upwards. */ | ||
703 | memory[0].size = ((size+0x001fffff) & 0xffe00000); | ||
704 | } | ||
705 | |||
706 | ppc_memstart = memory[0].addr; | ||
707 | ppc_memoffset = PAGE_OFFSET - PPC_MEMSTART; | ||
708 | total = memory[0].size; | ||
709 | |||
710 | /* Remove the memory chunks that are controlled by special | ||
711 | Phase5 hardware. */ | ||
712 | |||
713 | /* Remove the upper 512KB if it contains a shadow of | ||
714 | the ADOS ROM. FIXME: It might be possible to | ||
715 | disable this shadow HW. Check the booter | ||
716 | (ppc_boot.c) */ | ||
717 | if (shadow) | ||
718 | total -= HARDWARE_MAPPED_SIZE; | ||
719 | |||
720 | /* Remove the upper 512KB where the PPC exception | ||
721 | vectors are mapped. */ | ||
722 | total -= HARDWARE_MAPPED_SIZE; | ||
723 | |||
724 | /* Linux/APUS only handles one block of memory -- the one on | ||
725 | the PowerUP board. Other system memory is horrible slow in | ||
726 | comparison. The user can use other memory for swapping | ||
727 | using the z2ram device. */ | ||
728 | return total; | ||
729 | } | ||
730 | |||
731 | static void __init | ||
732 | apus_map_io(void) | ||
733 | { | ||
734 | /* Map PPC exception vectors. */ | ||
735 | io_block_mapping(0xfff00000, 0xfff00000, 0x00020000, _PAGE_KERNEL); | ||
736 | /* Map chip and ZorroII memory */ | ||
737 | io_block_mapping(zTwoBase, 0x00000000, 0x01000000, _PAGE_IO); | ||
738 | } | ||
739 | |||
740 | __init | ||
741 | void apus_init_IRQ(void) | ||
742 | { | ||
743 | struct irqaction *action; | ||
744 | int i; | ||
745 | |||
746 | #ifdef CONFIG_PCI | ||
747 | apus_setup_pci_ptrs(); | ||
748 | #endif | ||
749 | |||
750 | for ( i = 0 ; i < AMI_IRQS; i++ ) { | ||
751 | irq_desc[i].status = IRQ_LEVEL; | ||
752 | if (i < IRQ_AMIGA_AUTO) { | ||
753 | irq_desc[i].handler = &amiga_irqctrl; | ||
754 | } else { | ||
755 | irq_desc[i].handler = &amiga_sys_irqctrl; | ||
756 | action = &amiga_sys_irqaction[i-IRQ_AMIGA_AUTO]; | ||
757 | if (action->name) | ||
758 | setup_irq(i, action); | ||
759 | } | ||
760 | } | ||
761 | |||
762 | amiga_init_IRQ(); | ||
763 | |||
764 | } | ||
765 | |||
766 | __init | ||
767 | void platform_init(unsigned long r3, unsigned long r4, unsigned long r5, | ||
768 | unsigned long r6, unsigned long r7) | ||
769 | { | ||
770 | extern int parse_bootinfo(const struct bi_record *); | ||
771 | extern char _end[]; | ||
772 | |||
773 | /* Parse bootinfo. The bootinfo is located right after | ||
774 | the kernel bss */ | ||
775 | parse_bootinfo((const struct bi_record *)&_end); | ||
776 | #ifdef CONFIG_BLK_DEV_INITRD | ||
777 | /* Take care of initrd if we have one. Use data from | ||
778 | bootinfo to avoid the need to initialize PPC | ||
779 | registers when kernel is booted via a PPC reset. */ | ||
780 | if ( ramdisk.addr ) { | ||
781 | initrd_start = (unsigned long) __va(ramdisk.addr); | ||
782 | initrd_end = (unsigned long) | ||
783 | __va(ramdisk.size + ramdisk.addr); | ||
784 | } | ||
785 | #endif /* CONFIG_BLK_DEV_INITRD */ | ||
786 | |||
787 | ISA_DMA_THRESHOLD = 0x00ffffff; | ||
788 | |||
789 | ppc_md.setup_arch = apus_setup_arch; | ||
790 | ppc_md.show_cpuinfo = apus_show_cpuinfo; | ||
791 | ppc_md.init_IRQ = apus_init_IRQ; | ||
792 | ppc_md.get_irq = apus_get_irq; | ||
793 | |||
794 | #ifdef CONFIG_HEARTBEAT | ||
795 | ppc_md.heartbeat = apus_heartbeat; | ||
796 | ppc_md.heartbeat_count = 1; | ||
797 | #endif | ||
798 | #ifdef APUS_DEBUG | ||
799 | __debug_serinit(); | ||
800 | ppc_md.progress = apus_progress; | ||
801 | #endif | ||
802 | ppc_md.init = NULL; | ||
803 | |||
804 | ppc_md.restart = apus_restart; | ||
805 | ppc_md.power_off = apus_power_off; | ||
806 | ppc_md.halt = apus_halt; | ||
807 | |||
808 | ppc_md.time_init = NULL; | ||
809 | ppc_md.set_rtc_time = apus_set_rtc_time; | ||
810 | ppc_md.get_rtc_time = apus_get_rtc_time; | ||
811 | ppc_md.calibrate_decr = apus_calibrate_decr; | ||
812 | |||
813 | ppc_md.find_end_of_memory = apus_find_end_of_memory; | ||
814 | ppc_md.setup_io_mappings = apus_map_io; | ||
815 | } | ||
diff --git a/arch/ppc/platforms/bseip.h b/arch/ppc/platforms/bseip.h new file mode 100644 index 000000000000..691f4a52b0a5 --- /dev/null +++ b/arch/ppc/platforms/bseip.h | |||
@@ -0,0 +1,38 @@ | |||
1 | /* | ||
2 | * A collection of structures, addresses, and values associated with | ||
3 | * the Bright Star Engineering ip-Engine board. Copied from the MBX stuff. | ||
4 | * | ||
5 | * Copyright (c) 1998 Dan Malek (dmalek@jlc.net) | ||
6 | */ | ||
7 | #ifndef __MACH_BSEIP_DEFS | ||
8 | #define __MACH_BSEIP_DEFS | ||
9 | |||
10 | #ifndef __ASSEMBLY__ | ||
11 | /* A Board Information structure that is given to a program when | ||
12 | * prom starts it up. | ||
13 | */ | ||
14 | typedef struct bd_info { | ||
15 | unsigned int bi_memstart; /* Memory start address */ | ||
16 | unsigned int bi_memsize; /* Memory (end) size in bytes */ | ||
17 | unsigned int bi_intfreq; /* Internal Freq, in Hz */ | ||
18 | unsigned int bi_busfreq; /* Bus Freq, in Hz */ | ||
19 | unsigned char bi_enetaddr[6]; | ||
20 | unsigned int bi_baudrate; | ||
21 | } bd_t; | ||
22 | |||
23 | extern bd_t m8xx_board_info; | ||
24 | |||
25 | /* Memory map is configured by the PROM startup. | ||
26 | * All we need to get started is the IMMR. | ||
27 | */ | ||
28 | #define IMAP_ADDR ((uint)0xff000000) | ||
29 | #define IMAP_SIZE ((uint)(64 * 1024)) | ||
30 | #define PCMCIA_MEM_ADDR ((uint)0x04000000) | ||
31 | #define PCMCIA_MEM_SIZE ((uint)(64 * 1024)) | ||
32 | #endif /* !__ASSEMBLY__ */ | ||
33 | |||
34 | /* We don't use the 8259. | ||
35 | */ | ||
36 | #define NR_8259_INTS 0 | ||
37 | |||
38 | #endif | ||
diff --git a/arch/ppc/platforms/ccm.h b/arch/ppc/platforms/ccm.h new file mode 100644 index 000000000000..edb87b573831 --- /dev/null +++ b/arch/ppc/platforms/ccm.h | |||
@@ -0,0 +1,28 @@ | |||
1 | /* | ||
2 | * Siemens Card Controller Module specific definitions | ||
3 | * | ||
4 | * Copyright (C) 2001-2002 Wolfgang Denk (wd@denx.de) | ||
5 | */ | ||
6 | |||
7 | #ifndef __MACH_CCM_H | ||
8 | #define __MACH_CCM_H | ||
9 | |||
10 | #include <linux/config.h> | ||
11 | |||
12 | #include <asm/ppcboot.h> | ||
13 | |||
14 | #define CCM_IMMR_BASE 0xF0000000 /* phys. addr of IMMR */ | ||
15 | #define CCM_IMAP_SIZE (64 * 1024) /* size of mapped area */ | ||
16 | |||
17 | #define IMAP_ADDR CCM_IMMR_BASE /* physical base address of IMMR area */ | ||
18 | #define IMAP_SIZE CCM_IMAP_SIZE /* mapped size of IMMR area */ | ||
19 | |||
20 | #define FEC_INTERRUPT 13 /* = SIU_LEVEL6 */ | ||
21 | #define DEC_INTERRUPT 11 /* = SIU_LEVEL5 */ | ||
22 | #define CPM_INTERRUPT 9 /* = SIU_LEVEL4 */ | ||
23 | |||
24 | /* We don't use the 8259. | ||
25 | */ | ||
26 | #define NR_8259_INTS 0 | ||
27 | |||
28 | #endif /* __MACH_CCM_H */ | ||
diff --git a/arch/ppc/platforms/chestnut.c b/arch/ppc/platforms/chestnut.c new file mode 100644 index 000000000000..7786818bd9d0 --- /dev/null +++ b/arch/ppc/platforms/chestnut.c | |||
@@ -0,0 +1,580 @@ | |||
1 | /* | ||
2 | * arch/ppc/platforms/chestnut.c | ||
3 | * | ||
4 | * Board setup routines for IBM Chestnut | ||
5 | * | ||
6 | * Author: <source@mvista.com> | ||
7 | * | ||
8 | * <2004> (c) MontaVista Software, Inc. This file is licensed under | ||
9 | * the terms of the GNU General Public License version 2. This program | ||
10 | * is licensed "as is" without any warranty of any kind, whether express | ||
11 | * or implied. | ||
12 | */ | ||
13 | |||
14 | #include <linux/config.h> | ||
15 | #include <linux/stddef.h> | ||
16 | #include <linux/kernel.h> | ||
17 | #include <linux/init.h> | ||
18 | #include <linux/errno.h> | ||
19 | #include <linux/reboot.h> | ||
20 | #include <linux/kdev_t.h> | ||
21 | #include <linux/major.h> | ||
22 | #include <linux/blkdev.h> | ||
23 | #include <linux/console.h> | ||
24 | #include <linux/root_dev.h> | ||
25 | #include <linux/initrd.h> | ||
26 | #include <linux/delay.h> | ||
27 | #include <linux/seq_file.h> | ||
28 | #include <linux/ide.h> | ||
29 | #include <linux/serial.h> | ||
30 | #include <linux/serial_core.h> | ||
31 | #include <linux/mtd/physmap.h> | ||
32 | #include <asm/system.h> | ||
33 | #include <asm/pgtable.h> | ||
34 | #include <asm/page.h> | ||
35 | #include <asm/time.h> | ||
36 | #include <asm/dma.h> | ||
37 | #include <asm/io.h> | ||
38 | #include <linux/irq.h> | ||
39 | #include <asm/hw_irq.h> | ||
40 | #include <asm/machdep.h> | ||
41 | #include <asm/kgdb.h> | ||
42 | #include <asm/bootinfo.h> | ||
43 | #include <asm/mv64x60.h> | ||
44 | #include <platforms/chestnut.h> | ||
45 | |||
46 | static void __iomem *sram_base; /* Virtual addr of Internal SRAM */ | ||
47 | static void __iomem *cpld_base; /* Virtual addr of CPLD Regs */ | ||
48 | |||
49 | static mv64x60_handle_t bh; | ||
50 | |||
51 | extern void gen550_progress(char *, unsigned short); | ||
52 | extern void gen550_init(int, struct uart_port *); | ||
53 | extern void mv64360_pcibios_fixup(mv64x60_handle_t *bh); | ||
54 | |||
55 | #define BIT(x) (1<<x) | ||
56 | #define CHESTNUT_PRESERVE_MASK (BIT(MV64x60_CPU2DEV_0_WIN) | \ | ||
57 | BIT(MV64x60_CPU2DEV_1_WIN) | \ | ||
58 | BIT(MV64x60_CPU2DEV_2_WIN) | \ | ||
59 | BIT(MV64x60_CPU2DEV_3_WIN) | \ | ||
60 | BIT(MV64x60_CPU2BOOT_WIN)) | ||
61 | /************************************************************************** | ||
62 | * FUNCTION: chestnut_calibrate_decr | ||
63 | * | ||
64 | * DESCRIPTION: initialize decrementer interrupt frequency (used as system | ||
65 | * timer) | ||
66 | * | ||
67 | ****/ | ||
68 | static void __init | ||
69 | chestnut_calibrate_decr(void) | ||
70 | { | ||
71 | ulong freq; | ||
72 | |||
73 | freq = CHESTNUT_BUS_SPEED / 4; | ||
74 | |||
75 | printk("time_init: decrementer frequency = %lu.%.6lu MHz\n", | ||
76 | freq/1000000, freq%1000000); | ||
77 | |||
78 | tb_ticks_per_jiffy = freq / HZ; | ||
79 | tb_to_us = mulhwu_scale_factor(freq, 1000000); | ||
80 | } | ||
81 | |||
82 | static int | ||
83 | chestnut_show_cpuinfo(struct seq_file *m) | ||
84 | { | ||
85 | seq_printf(m, "vendor\t\t: IBM\n"); | ||
86 | seq_printf(m, "machine\t\t: 750FX/GX Eval Board (Chestnut/Buckeye)\n"); | ||
87 | |||
88 | return 0; | ||
89 | } | ||
90 | |||
91 | /************************************************************************** | ||
92 | * FUNCTION: chestnut_find_end_of_memory | ||
93 | * | ||
94 | * DESCRIPTION: ppc_md memory size callback | ||
95 | * | ||
96 | ****/ | ||
97 | unsigned long __init | ||
98 | chestnut_find_end_of_memory(void) | ||
99 | { | ||
100 | static int mem_size = 0; | ||
101 | |||
102 | if (mem_size == 0) { | ||
103 | mem_size = mv64x60_get_mem_size(CONFIG_MV64X60_NEW_BASE, | ||
104 | MV64x60_TYPE_MV64460); | ||
105 | } | ||
106 | return mem_size; | ||
107 | } | ||
108 | |||
109 | #if defined(CONFIG_SERIAL_8250) | ||
110 | static void __init | ||
111 | chestnut_early_serial_map(void) | ||
112 | { | ||
113 | struct uart_port port; | ||
114 | |||
115 | /* Setup serial port access */ | ||
116 | memset(&port, 0, sizeof(port)); | ||
117 | port.uartclk = BASE_BAUD * 16; | ||
118 | port.irq = UART0_INT; | ||
119 | port.flags = STD_COM_FLAGS | UPF_IOREMAP; | ||
120 | port.iotype = SERIAL_IO_MEM; | ||
121 | port.mapbase = CHESTNUT_UART0_IO_BASE; | ||
122 | port.regshift = 0; | ||
123 | |||
124 | if (early_serial_setup(&port) != 0) | ||
125 | printk("Early serial init of port 0 failed\n"); | ||
126 | |||
127 | /* Assume early_serial_setup() doesn't modify serial_req */ | ||
128 | port.line = 1; | ||
129 | port.irq = UART1_INT; | ||
130 | port.mapbase = CHESTNUT_UART1_IO_BASE; | ||
131 | |||
132 | if (early_serial_setup(&port) != 0) | ||
133 | printk("Early serial init of port 1 failed\n"); | ||
134 | } | ||
135 | #endif | ||
136 | |||
137 | /************************************************************************** | ||
138 | * FUNCTION: chestnut_map_irq | ||
139 | * | ||
140 | * DESCRIPTION: 0 return since PCI IRQs not needed | ||
141 | * | ||
142 | ****/ | ||
143 | static int __init | ||
144 | chestnut_map_irq(struct pci_dev *dev, unsigned char idsel, unsigned char pin) | ||
145 | { | ||
146 | static char pci_irq_table[][4] = { | ||
147 | {CHESTNUT_PCI_SLOT0_IRQ, CHESTNUT_PCI_SLOT0_IRQ, | ||
148 | CHESTNUT_PCI_SLOT0_IRQ, CHESTNUT_PCI_SLOT0_IRQ}, | ||
149 | {CHESTNUT_PCI_SLOT1_IRQ, CHESTNUT_PCI_SLOT1_IRQ, | ||
150 | CHESTNUT_PCI_SLOT1_IRQ, CHESTNUT_PCI_SLOT1_IRQ}, | ||
151 | {CHESTNUT_PCI_SLOT2_IRQ, CHESTNUT_PCI_SLOT2_IRQ, | ||
152 | CHESTNUT_PCI_SLOT2_IRQ, CHESTNUT_PCI_SLOT2_IRQ}, | ||
153 | {CHESTNUT_PCI_SLOT3_IRQ, CHESTNUT_PCI_SLOT3_IRQ, | ||
154 | CHESTNUT_PCI_SLOT3_IRQ, CHESTNUT_PCI_SLOT3_IRQ}, | ||
155 | }; | ||
156 | const long min_idsel = 1, max_idsel = 4, irqs_per_slot = 4; | ||
157 | |||
158 | return PCI_IRQ_TABLE_LOOKUP; | ||
159 | } | ||
160 | |||
161 | |||
162 | /************************************************************************** | ||
163 | * FUNCTION: chestnut_setup_bridge | ||
164 | * | ||
165 | * DESCRIPTION: initalize board-specific settings on the MV64360 | ||
166 | * | ||
167 | ****/ | ||
168 | static void __init | ||
169 | chestnut_setup_bridge(void) | ||
170 | { | ||
171 | struct mv64x60_setup_info si; | ||
172 | int i; | ||
173 | |||
174 | if ( ppc_md.progress ) | ||
175 | ppc_md.progress("chestnut_setup_bridge: enter", 0); | ||
176 | |||
177 | memset(&si, 0, sizeof(si)); | ||
178 | |||
179 | si.phys_reg_base = CONFIG_MV64X60_NEW_BASE; | ||
180 | |||
181 | /* setup only PCI bus 0 (bus 1 not used) */ | ||
182 | si.pci_0.enable_bus = 1; | ||
183 | si.pci_0.pci_io.cpu_base = CHESTNUT_PCI0_IO_PROC_ADDR; | ||
184 | si.pci_0.pci_io.pci_base_hi = 0; | ||
185 | si.pci_0.pci_io.pci_base_lo = CHESTNUT_PCI0_IO_PCI_ADDR; | ||
186 | si.pci_0.pci_io.size = CHESTNUT_PCI0_IO_SIZE; | ||
187 | si.pci_0.pci_io.swap = MV64x60_CPU2PCI_SWAP_NONE; /* no swapping */ | ||
188 | si.pci_0.pci_mem[0].cpu_base = CHESTNUT_PCI0_MEM_PROC_ADDR; | ||
189 | si.pci_0.pci_mem[0].pci_base_hi = CHESTNUT_PCI0_MEM_PCI_HI_ADDR; | ||
190 | si.pci_0.pci_mem[0].pci_base_lo = CHESTNUT_PCI0_MEM_PCI_LO_ADDR; | ||
191 | si.pci_0.pci_mem[0].size = CHESTNUT_PCI0_MEM_SIZE; | ||
192 | si.pci_0.pci_mem[0].swap = MV64x60_CPU2PCI_SWAP_NONE; /* no swapping */ | ||
193 | si.pci_0.pci_cmd_bits = 0; | ||
194 | si.pci_0.latency_timer = 0x80; | ||
195 | |||
196 | for (i=0; i<MV64x60_CPU2MEM_WINDOWS; i++) { | ||
197 | #if defined(CONFIG_NOT_COHERENT_CACHE) | ||
198 | si.cpu_prot_options[i] = 0; | ||
199 | si.enet_options[i] = MV64360_ENET2MEM_SNOOP_NONE; | ||
200 | si.mpsc_options[i] = MV64360_MPSC2MEM_SNOOP_NONE; | ||
201 | si.idma_options[i] = MV64360_IDMA2MEM_SNOOP_NONE; | ||
202 | |||
203 | si.pci_1.acc_cntl_options[i] = | ||
204 | MV64360_PCI_ACC_CNTL_SNOOP_NONE | | ||
205 | MV64360_PCI_ACC_CNTL_SWAP_NONE | | ||
206 | MV64360_PCI_ACC_CNTL_MBURST_128_BYTES | | ||
207 | MV64360_PCI_ACC_CNTL_RDSIZE_256_BYTES; | ||
208 | #else | ||
209 | si.cpu_prot_options[i] = 0; | ||
210 | si.enet_options[i] = MV64360_ENET2MEM_SNOOP_NONE; /* errata */ | ||
211 | si.mpsc_options[i] = MV64360_MPSC2MEM_SNOOP_NONE; /* errata */ | ||
212 | si.idma_options[i] = MV64360_IDMA2MEM_SNOOP_NONE; /* errata */ | ||
213 | |||
214 | si.pci_1.acc_cntl_options[i] = | ||
215 | MV64360_PCI_ACC_CNTL_SNOOP_WB | | ||
216 | MV64360_PCI_ACC_CNTL_SWAP_NONE | | ||
217 | MV64360_PCI_ACC_CNTL_MBURST_32_BYTES | | ||
218 | MV64360_PCI_ACC_CNTL_RDSIZE_32_BYTES; | ||
219 | #endif | ||
220 | } | ||
221 | |||
222 | /* Lookup host bridge - on CPU 0 - no SMP support */ | ||
223 | if (mv64x60_init(&bh, &si)) { | ||
224 | printk("\n\nPCI Bridge initialization failed!\n"); | ||
225 | } | ||
226 | |||
227 | pci_dram_offset = 0; | ||
228 | ppc_md.pci_swizzle = common_swizzle; | ||
229 | ppc_md.pci_map_irq = chestnut_map_irq; | ||
230 | ppc_md.pci_exclude_device = mv64x60_pci_exclude_device; | ||
231 | |||
232 | mv64x60_set_bus(&bh, 0, 0); | ||
233 | bh.hose_a->first_busno = 0; | ||
234 | bh.hose_a->last_busno = 0xff; | ||
235 | bh.hose_a->last_busno = pciauto_bus_scan(bh.hose_a, 0); | ||
236 | } | ||
237 | |||
238 | void __init | ||
239 | chestnut_setup_peripherals(void) | ||
240 | { | ||
241 | mv64x60_set_32bit_window(&bh, MV64x60_CPU2BOOT_WIN, | ||
242 | CHESTNUT_BOOT_8BIT_BASE, CHESTNUT_BOOT_8BIT_SIZE, 0); | ||
243 | bh.ci->enable_window_32bit(&bh, MV64x60_CPU2BOOT_WIN); | ||
244 | |||
245 | mv64x60_set_32bit_window(&bh, MV64x60_CPU2DEV_0_WIN, | ||
246 | CHESTNUT_32BIT_BASE, CHESTNUT_32BIT_SIZE, 0); | ||
247 | bh.ci->enable_window_32bit(&bh, MV64x60_CPU2DEV_0_WIN); | ||
248 | |||
249 | mv64x60_set_32bit_window(&bh, MV64x60_CPU2DEV_1_WIN, | ||
250 | CHESTNUT_CPLD_BASE, CHESTNUT_CPLD_SIZE, 0); | ||
251 | bh.ci->enable_window_32bit(&bh, MV64x60_CPU2DEV_1_WIN); | ||
252 | cpld_base = ioremap(CHESTNUT_CPLD_BASE, CHESTNUT_CPLD_SIZE); | ||
253 | |||
254 | mv64x60_set_32bit_window(&bh, MV64x60_CPU2DEV_2_WIN, | ||
255 | CHESTNUT_UART_BASE, CHESTNUT_UART_SIZE, 0); | ||
256 | bh.ci->enable_window_32bit(&bh, MV64x60_CPU2DEV_2_WIN); | ||
257 | |||
258 | mv64x60_set_32bit_window(&bh, MV64x60_CPU2DEV_3_WIN, | ||
259 | CHESTNUT_FRAM_BASE, CHESTNUT_FRAM_SIZE, 0); | ||
260 | bh.ci->enable_window_32bit(&bh, MV64x60_CPU2DEV_3_WIN); | ||
261 | |||
262 | mv64x60_set_32bit_window(&bh, MV64x60_CPU2SRAM_WIN, | ||
263 | CHESTNUT_INTERNAL_SRAM_BASE, MV64360_SRAM_SIZE, 0); | ||
264 | bh.ci->enable_window_32bit(&bh, MV64x60_CPU2SRAM_WIN); | ||
265 | |||
266 | #ifdef CONFIG_NOT_COHERENT_CACHE | ||
267 | mv64x60_write(&bh, MV64360_SRAM_CONFIG, 0x001600b0); | ||
268 | #else | ||
269 | mv64x60_write(&bh, MV64360_SRAM_CONFIG, 0x001600b2); | ||
270 | #endif | ||
271 | sram_base = ioremap(CHESTNUT_INTERNAL_SRAM_BASE, MV64360_SRAM_SIZE); | ||
272 | memset(sram_base, 0, MV64360_SRAM_SIZE); | ||
273 | |||
274 | /* | ||
275 | * Configure MPP pins for PCI DMA | ||
276 | * | ||
277 | * PCI Slot GNT pin REQ pin | ||
278 | * 0 MPP16 MPP17 | ||
279 | * 1 MPP18 MPP19 | ||
280 | * 2 MPP20 MPP21 | ||
281 | * 3 MPP22 MPP23 | ||
282 | */ | ||
283 | mv64x60_write(&bh, MV64x60_MPP_CNTL_2, | ||
284 | (0x1 << 0) | /* MPPSel16 PCI0_GNT[0] */ | ||
285 | (0x1 << 4) | /* MPPSel17 PCI0_REQ[0] */ | ||
286 | (0x1 << 8) | /* MPPSel18 PCI0_GNT[1] */ | ||
287 | (0x1 << 12) | /* MPPSel19 PCI0_REQ[1] */ | ||
288 | (0x1 << 16) | /* MPPSel20 PCI0_GNT[2] */ | ||
289 | (0x1 << 20) | /* MPPSel21 PCI0_REQ[2] */ | ||
290 | (0x1 << 24) | /* MPPSel22 PCI0_GNT[3] */ | ||
291 | (0x1 << 28)); /* MPPSel23 PCI0_REQ[3] */ | ||
292 | /* | ||
293 | * Set unused MPP pins for output, as per schematic note | ||
294 | * | ||
295 | * Unused Pins: MPP01, MPP02, MPP04, MPP05, MPP06 | ||
296 | * MPP09, MPP10, MPP13, MPP14, MPP15 | ||
297 | */ | ||
298 | mv64x60_clr_bits(&bh, MV64x60_MPP_CNTL_0, | ||
299 | (0xf << 4) | /* MPPSel01 GPIO[1] */ | ||
300 | (0xf << 8) | /* MPPSel02 GPIO[2] */ | ||
301 | (0xf << 16) | /* MPPSel04 GPIO[4] */ | ||
302 | (0xf << 20) | /* MPPSel05 GPIO[5] */ | ||
303 | (0xf << 24)); /* MPPSel06 GPIO[6] */ | ||
304 | mv64x60_clr_bits(&bh, MV64x60_MPP_CNTL_1, | ||
305 | (0xf << 4) | /* MPPSel09 GPIO[9] */ | ||
306 | (0xf << 8) | /* MPPSel10 GPIO[10] */ | ||
307 | (0xf << 20) | /* MPPSel13 GPIO[13] */ | ||
308 | (0xf << 24) | /* MPPSel14 GPIO[14] */ | ||
309 | (0xf << 28)); /* MPPSel15 GPIO[15] */ | ||
310 | mv64x60_set_bits(&bh, MV64x60_GPP_IO_CNTL, /* Output */ | ||
311 | BIT(1) | BIT(2) | BIT(4) | BIT(5) | BIT(6) | | ||
312 | BIT(9) | BIT(10) | BIT(13) | BIT(14) | BIT(15)); | ||
313 | |||
314 | /* | ||
315 | * Configure the following MPP pins to indicate a level | ||
316 | * triggered interrupt | ||
317 | * | ||
318 | * MPP24 - Board Reset (just map the MPP & GPP for chestnut_reset) | ||
319 | * MPP25 - UART A (high) | ||
320 | * MPP26 - UART B (high) | ||
321 | * MPP28 - PCI Slot 3 (low) | ||
322 | * MPP29 - PCI Slot 2 (low) | ||
323 | * MPP30 - PCI Slot 1 (low) | ||
324 | * MPP31 - PCI Slot 0 (low) | ||
325 | */ | ||
326 | mv64x60_clr_bits(&bh, MV64x60_MPP_CNTL_3, | ||
327 | BIT(3) | BIT(2) | BIT(1) | BIT(0) | /* MPP 24 */ | ||
328 | BIT(7) | BIT(6) | BIT(5) | BIT(4) | /* MPP 25 */ | ||
329 | BIT(11) | BIT(10) | BIT(9) | BIT(8) | /* MPP 26 */ | ||
330 | BIT(19) | BIT(18) | BIT(17) | BIT(16) | /* MPP 28 */ | ||
331 | BIT(23) | BIT(22) | BIT(21) | BIT(20) | /* MPP 29 */ | ||
332 | BIT(27) | BIT(26) | BIT(25) | BIT(24) | /* MPP 30 */ | ||
333 | BIT(31) | BIT(30) | BIT(29) | BIT(28)); /* MPP 31 */ | ||
334 | |||
335 | /* | ||
336 | * Define GPP 25 (high), 26 (high), 28 (low), 29 (low), 30 (low), | ||
337 | * 31 (low) interrupt polarity input signal and level triggered | ||
338 | */ | ||
339 | mv64x60_clr_bits(&bh, MV64x60_GPP_LEVEL_CNTL, BIT(25) | BIT(26)); | ||
340 | mv64x60_set_bits(&bh, MV64x60_GPP_LEVEL_CNTL, | ||
341 | BIT(28) | BIT(29) | BIT(30) | BIT(31)); | ||
342 | mv64x60_clr_bits(&bh, MV64x60_GPP_IO_CNTL, | ||
343 | BIT(25) | BIT(26) | BIT(28) | BIT(29) | BIT(30) | | ||
344 | BIT(31)); | ||
345 | |||
346 | /* Config GPP interrupt controller to respond to level trigger */ | ||
347 | mv64x60_set_bits(&bh, MV64360_COMM_ARBITER_CNTL, BIT(10)); | ||
348 | |||
349 | /* | ||
350 | * Dismiss and then enable interrupt on GPP interrupt cause for CPU #0 | ||
351 | */ | ||
352 | mv64x60_write(&bh, MV64x60_GPP_INTR_CAUSE, | ||
353 | ~(BIT(25) | BIT(26) | BIT(28) | BIT(29) | BIT(30) | | ||
354 | BIT(31))); | ||
355 | mv64x60_set_bits(&bh, MV64x60_GPP_INTR_MASK, | ||
356 | BIT(25) | BIT(26) | BIT(28) | BIT(29) | BIT(30) | | ||
357 | BIT(31)); | ||
358 | |||
359 | /* | ||
360 | * Dismiss and then enable interrupt on CPU #0 high cause register | ||
361 | * BIT27 summarizes GPP interrupts 24-31 | ||
362 | */ | ||
363 | mv64x60_set_bits(&bh, MV64360_IC_CPU0_INTR_MASK_HI, BIT(27)); | ||
364 | |||
365 | if (ppc_md.progress) | ||
366 | ppc_md.progress("chestnut_setup_bridge: exit", 0); | ||
367 | } | ||
368 | |||
369 | /************************************************************************** | ||
370 | * FUNCTION: chestnut_setup_arch | ||
371 | * | ||
372 | * DESCRIPTION: ppc_md machine configuration callback | ||
373 | * | ||
374 | ****/ | ||
375 | static void __init | ||
376 | chestnut_setup_arch(void) | ||
377 | { | ||
378 | if (ppc_md.progress) | ||
379 | ppc_md.progress("chestnut_setup_arch: enter", 0); | ||
380 | |||
381 | /* init to some ~sane value until calibrate_delay() runs */ | ||
382 | loops_per_jiffy = 50000000 / HZ; | ||
383 | |||
384 | /* if the time base value is greater than bus freq/4 (the TB and | ||
385 | * decrementer tick rate) + signed integer rollover value, we | ||
386 | * can spend a fair amount of time waiting for the rollover to | ||
387 | * happen. To get around this, initialize the time base register | ||
388 | * to a "safe" value. | ||
389 | */ | ||
390 | set_tb(0, 0); | ||
391 | |||
392 | #ifdef CONFIG_BLK_DEV_INITRD | ||
393 | if (initrd_start) | ||
394 | ROOT_DEV = Root_RAM0; | ||
395 | else | ||
396 | #endif | ||
397 | #ifdef CONFIG_ROOT_NFS | ||
398 | ROOT_DEV = Root_NFS; | ||
399 | #else | ||
400 | ROOT_DEV = Root_SDA2; | ||
401 | #endif | ||
402 | |||
403 | /* | ||
404 | * Set up the L2CR register. | ||
405 | */ | ||
406 | _set_L2CR(_get_L2CR() | L2CR_L2E); | ||
407 | |||
408 | chestnut_setup_bridge(); | ||
409 | chestnut_setup_peripherals(); | ||
410 | |||
411 | #ifdef CONFIG_DUMMY_CONSOLE | ||
412 | conswitchp = &dummy_con; | ||
413 | #endif | ||
414 | |||
415 | #if defined(CONFIG_SERIAL_8250) | ||
416 | chestnut_early_serial_map(); | ||
417 | #endif | ||
418 | |||
419 | /* Identify the system */ | ||
420 | printk(KERN_INFO "System Identification: IBM 750FX/GX Eval Board\n"); | ||
421 | printk(KERN_INFO "IBM 750FX/GX port (C) 2004 MontaVista Software, Inc." | ||
422 | " (source@mvista.com)\n"); | ||
423 | |||
424 | if (ppc_md.progress) | ||
425 | ppc_md.progress("chestnut_setup_arch: exit", 0); | ||
426 | } | ||
427 | |||
428 | #ifdef CONFIG_MTD_PHYSMAP | ||
429 | static struct mtd_partition ptbl; | ||
430 | |||
431 | static int __init | ||
432 | chestnut_setup_mtd(void) | ||
433 | { | ||
434 | memset(&ptbl, 0, sizeof(ptbl)); | ||
435 | |||
436 | ptbl.name = "User FS"; | ||
437 | ptbl.size = CHESTNUT_32BIT_SIZE; | ||
438 | |||
439 | physmap_map.size = CHESTNUT_32BIT_SIZE; | ||
440 | physmap_set_partitions(&ptbl, 1); | ||
441 | return 0; | ||
442 | } | ||
443 | |||
444 | arch_initcall(chestnut_setup_mtd); | ||
445 | #endif | ||
446 | |||
447 | /************************************************************************** | ||
448 | * FUNCTION: chestnut_restart | ||
449 | * | ||
450 | * DESCRIPTION: ppc_md machine reset callback | ||
451 | * reset the board via the CPLD command register | ||
452 | * | ||
453 | ****/ | ||
454 | static void | ||
455 | chestnut_restart(char *cmd) | ||
456 | { | ||
457 | volatile ulong i = 10000000; | ||
458 | |||
459 | local_irq_disable(); | ||
460 | |||
461 | /* | ||
462 | * Set CPLD Reg 3 bit 0 to 1 to allow MPP signals on reset to work | ||
463 | * | ||
464 | * MPP24 - board reset | ||
465 | */ | ||
466 | writeb(0x1, cpld_base + 3); | ||
467 | |||
468 | /* GPP pin tied to MPP earlier */ | ||
469 | mv64x60_set_bits(&bh, MV64x60_GPP_VALUE_SET, BIT(24)); | ||
470 | |||
471 | while (i-- > 0); | ||
472 | panic("restart failed\n"); | ||
473 | } | ||
474 | |||
475 | static void | ||
476 | chestnut_halt(void) | ||
477 | { | ||
478 | local_irq_disable(); | ||
479 | for (;;); | ||
480 | /* NOTREACHED */ | ||
481 | } | ||
482 | |||
483 | static void | ||
484 | chestnut_power_off(void) | ||
485 | { | ||
486 | chestnut_halt(); | ||
487 | /* NOTREACHED */ | ||
488 | } | ||
489 | |||
490 | /************************************************************************** | ||
491 | * FUNCTION: chestnut_map_io | ||
492 | * | ||
493 | * DESCRIPTION: configure fixed memory-mapped IO | ||
494 | * | ||
495 | ****/ | ||
496 | static void __init | ||
497 | chestnut_map_io(void) | ||
498 | { | ||
499 | #if defined(CONFIG_SERIAL_TEXT_DEBUG) || defined(CONFIG_KGDB) | ||
500 | io_block_mapping(CHESTNUT_UART_BASE, CHESTNUT_UART_BASE, 0x100000, | ||
501 | _PAGE_IO); | ||
502 | #endif | ||
503 | } | ||
504 | |||
505 | /************************************************************************** | ||
506 | * FUNCTION: chestnut_set_bat | ||
507 | * | ||
508 | * DESCRIPTION: configures a (temporary) bat mapping for early access to | ||
509 | * device I/O | ||
510 | * | ||
511 | ****/ | ||
512 | static __inline__ void | ||
513 | chestnut_set_bat(void) | ||
514 | { | ||
515 | mb(); | ||
516 | mtspr(SPRN_DBAT3U, 0xf0001ffe); | ||
517 | mtspr(SPRN_DBAT3L, 0xf000002a); | ||
518 | mb(); | ||
519 | } | ||
520 | |||
521 | /************************************************************************** | ||
522 | * FUNCTION: platform_init | ||
523 | * | ||
524 | * DESCRIPTION: main entry point for configuring board-specific machine | ||
525 | * callbacks | ||
526 | * | ||
527 | ****/ | ||
528 | void __init | ||
529 | platform_init(unsigned long r3, unsigned long r4, unsigned long r5, | ||
530 | unsigned long r6, unsigned long r7) | ||
531 | { | ||
532 | parse_bootinfo(find_bootinfo()); | ||
533 | |||
534 | /* Copy the kernel command line arguments to a safe place. */ | ||
535 | |||
536 | if (r6) { | ||
537 | *(char *) (r7 + KERNELBASE) = 0; | ||
538 | strcpy(cmd_line, (char *) (r6 + KERNELBASE)); | ||
539 | } | ||
540 | |||
541 | isa_mem_base = 0; | ||
542 | |||
543 | ppc_md.setup_arch = chestnut_setup_arch; | ||
544 | ppc_md.show_cpuinfo = chestnut_show_cpuinfo; | ||
545 | ppc_md.irq_canonicalize = NULL; | ||
546 | ppc_md.init_IRQ = mv64360_init_irq; | ||
547 | ppc_md.get_irq = mv64360_get_irq; | ||
548 | ppc_md.init = NULL; | ||
549 | |||
550 | ppc_md.find_end_of_memory = chestnut_find_end_of_memory; | ||
551 | ppc_md.setup_io_mappings = chestnut_map_io; | ||
552 | |||
553 | ppc_md.restart = chestnut_restart; | ||
554 | ppc_md.power_off = chestnut_power_off; | ||
555 | ppc_md.halt = chestnut_halt; | ||
556 | |||
557 | ppc_md.time_init = NULL; | ||
558 | ppc_md.set_rtc_time = NULL; | ||
559 | ppc_md.get_rtc_time = NULL; | ||
560 | ppc_md.calibrate_decr = chestnut_calibrate_decr; | ||
561 | |||
562 | ppc_md.nvram_read_val = NULL; | ||
563 | ppc_md.nvram_write_val = NULL; | ||
564 | |||
565 | ppc_md.heartbeat = NULL; | ||
566 | |||
567 | bh.p_base = CONFIG_MV64X60_NEW_BASE; | ||
568 | |||
569 | chestnut_set_bat(); | ||
570 | |||
571 | #if defined(CONFIG_SERIAL_TEXT_DEBUG) | ||
572 | ppc_md.progress = gen550_progress; | ||
573 | #endif | ||
574 | #if defined(CONFIG_KGDB) | ||
575 | ppc_md.kgdb_map_scc = gen550_kgdb_map_scc; | ||
576 | #endif | ||
577 | |||
578 | if (ppc_md.progress) | ||
579 | ppc_md.progress("chestnut_init(): exit", 0); | ||
580 | } | ||
diff --git a/arch/ppc/platforms/chestnut.h b/arch/ppc/platforms/chestnut.h new file mode 100644 index 000000000000..0400b2be40ab --- /dev/null +++ b/arch/ppc/platforms/chestnut.h | |||
@@ -0,0 +1,129 @@ | |||
1 | /* | ||
2 | * arch/ppc/platforms/chestnut.h | ||
3 | * | ||
4 | * Definitions for IBM 750FXGX Eval (Chestnut) | ||
5 | * | ||
6 | * Author: <source@mvista.com> | ||
7 | * | ||
8 | * Based on Artesyn Katana code done by Tim Montgomery <timm@artesyncp.com> | ||
9 | * Based on code done by Rabeeh Khoury - rabeeh@galileo.co.il | ||
10 | * Based on code done by Mark A. Greer <mgreer@mvista.com> | ||
11 | * | ||
12 | * <2004> (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 | /* | ||
19 | * This is the CPU physical memory map (windows must be at least 1MB and start | ||
20 | * on a boundary that is a multiple of the window size): | ||
21 | * | ||
22 | * Seems on the IBM 750FXGX Eval board, the MV64460 Registers can be in | ||
23 | * only 2 places per switch U17 0x14000000 or 0xf1000000 easily - chose to | ||
24 | * implement at 0xf1000000 only at this time | ||
25 | * | ||
26 | * 0xfff00000-0xffffffff - 8 Flash | ||
27 | * 0xffe00000-0xffefffff - BOOT SRAM | ||
28 | * 0xffd00000-0xffd00004 - CPLD | ||
29 | * 0xffc00000-0xffc0000f - UART | ||
30 | * 0xffb00000-0xffb07fff - FRAM | ||
31 | * 0xff840000-0xffafffff - *** HOLE *** | ||
32 | * 0xff800000-0xff83ffff - MV64460 Integrated SRAM | ||
33 | * 0xfe000000-0xff8fffff - *** HOLE *** | ||
34 | * 0xfc000000-0xfdffffff - 32bit Flash | ||
35 | * 0xf1010000-0xfbffffff - *** HOLE *** | ||
36 | * 0xf1000000-0xf100ffff - MV64460 Registers | ||
37 | */ | ||
38 | |||
39 | #ifndef __PPC_PLATFORMS_CHESTNUT_H__ | ||
40 | #define __PPC_PLATFORMS_CHESTNUT_H__ | ||
41 | |||
42 | #define CHESTNUT_BOOT_8BIT_BASE 0xfff00000 | ||
43 | #define CHESTNUT_BOOT_8BIT_SIZE_ACTUAL (1024*1024) | ||
44 | #define CHESTNUT_BOOT_SRAM_BASE 0xffe00000 | ||
45 | #define CHESTNUT_BOOT_SRAM_SIZE_ACTUAL (1024*1024) | ||
46 | #define CHESTNUT_CPLD_BASE 0xffd00000 | ||
47 | #define CHESTNUT_CPLD_SIZE_ACTUAL 5 | ||
48 | #define CHESTNUT_CPLD_REG3 (CHESTNUT_CPLD_BASE+3) | ||
49 | #define CHESTNUT_UART_BASE 0xffc00000 | ||
50 | #define CHESTNUT_UART_SIZE_ACTUAL 16 | ||
51 | #define CHESTNUT_FRAM_BASE 0xffb00000 | ||
52 | #define CHESTNUT_FRAM_SIZE_ACTUAL (32*1024) | ||
53 | #define CHESTNUT_INTERNAL_SRAM_BASE 0xff800000 | ||
54 | #define CHESTNUT_32BIT_BASE 0xfc000000 | ||
55 | #define CHESTNUT_32BIT_SIZE (32*1024*1024) | ||
56 | |||
57 | #define CHESTNUT_BOOT_8BIT_SIZE max(MV64360_WINDOW_SIZE_MIN, \ | ||
58 | CHESTNUT_BOOT_8BIT_SIZE_ACTUAL) | ||
59 | #define CHESTNUT_BOOT_SRAM_SIZE max(MV64360_WINDOW_SIZE_MIN, \ | ||
60 | CHESTNUT_BOOT_SRAM_SIZE_ACTUAL) | ||
61 | #define CHESTNUT_CPLD_SIZE max(MV64360_WINDOW_SIZE_MIN, \ | ||
62 | CHESTNUT_CPLD_SIZE_ACTUAL) | ||
63 | #define CHESTNUT_UART_SIZE max(MV64360_WINDOW_SIZE_MIN, \ | ||
64 | CHESTNUT_UART_SIZE_ACTUAL) | ||
65 | #define CHESTNUT_FRAM_SIZE max(MV64360_WINDOW_SIZE_MIN, \ | ||
66 | CHESTNUT_FRAM_SIZE_ACTUAL) | ||
67 | |||
68 | #define CHESTNUT_BUS_SPEED 200000000 | ||
69 | #define CHESTNUT_PIBS_DATABASE 0xf0000 /* from PIBS src code */ | ||
70 | |||
71 | #define KATANA_ETH0_PHY_ADDR 12 | ||
72 | #define KATANA_ETH1_PHY_ADDR 11 | ||
73 | #define KATANA_ETH2_PHY_ADDR 4 | ||
74 | |||
75 | #define CHESTNUT_ETH_TX_QUEUE_SIZE 800 | ||
76 | #define CHESTNUT_ETH_RX_QUEUE_SIZE 400 | ||
77 | |||
78 | /* | ||
79 | * PCI windows | ||
80 | */ | ||
81 | |||
82 | #define CHESTNUT_PCI0_MEM_PROC_ADDR 0x80000000 | ||
83 | #define CHESTNUT_PCI0_MEM_PCI_HI_ADDR 0x00000000 | ||
84 | #define CHESTNUT_PCI0_MEM_PCI_LO_ADDR 0x80000000 | ||
85 | #define CHESTNUT_PCI0_MEM_SIZE 0x10000000 | ||
86 | #define CHESTNUT_PCI0_IO_PROC_ADDR 0xa0000000 | ||
87 | #define CHESTNUT_PCI0_IO_PCI_ADDR 0x00000000 | ||
88 | #define CHESTNUT_PCI0_IO_SIZE 0x01000000 | ||
89 | |||
90 | /* | ||
91 | * Board-specific IRQ info | ||
92 | */ | ||
93 | #define CHESTNUT_PCI_SLOT0_IRQ (64 + 31) | ||
94 | #define CHESTNUT_PCI_SLOT1_IRQ (64 + 30) | ||
95 | #define CHESTNUT_PCI_SLOT2_IRQ (64 + 29) | ||
96 | #define CHESTNUT_PCI_SLOT3_IRQ (64 + 28) | ||
97 | |||
98 | /* serial port definitions */ | ||
99 | #define CHESTNUT_UART0_IO_BASE (CHESTNUT_UART_BASE + 8) | ||
100 | #define CHESTNUT_UART1_IO_BASE CHESTNUT_UART_BASE | ||
101 | |||
102 | #define UART0_INT (64 + 25) | ||
103 | #define UART1_INT (64 + 26) | ||
104 | |||
105 | #ifdef CONFIG_SERIAL_MANY_PORTS | ||
106 | #define RS_TABLE_SIZE 64 | ||
107 | #else | ||
108 | #define RS_TABLE_SIZE 2 | ||
109 | #endif | ||
110 | |||
111 | /* Rate for the 3.6864 Mhz clock for the onboard serial chip */ | ||
112 | #define BASE_BAUD (3686400 / 16) | ||
113 | |||
114 | #ifdef CONFIG_SERIAL_DETECT_IRQ | ||
115 | #define STD_COM_FLAGS (ASYNC_BOOT_AUTOCONF|ASYNC_SKIP_TEST|ASYNC_AUTO_IRQ) | ||
116 | #else | ||
117 | #define STD_COM_FLAGS (ASYNC_BOOT_AUTOCONF|ASYNC_SKIP_TEST) | ||
118 | #endif | ||
119 | |||
120 | #define STD_UART_OP(num) \ | ||
121 | { 0, BASE_BAUD, 0, UART##num##_INT, STD_COM_FLAGS, \ | ||
122 | iomem_base: (u8 *)CHESTNUT_UART##num##_IO_BASE, \ | ||
123 | io_type: SERIAL_IO_MEM}, | ||
124 | |||
125 | #define SERIAL_PORT_DFNS \ | ||
126 | STD_UART_OP(0) \ | ||
127 | STD_UART_OP(1) | ||
128 | |||
129 | #endif /* __PPC_PLATFORMS_CHESTNUT_H__ */ | ||
diff --git a/arch/ppc/platforms/chrp_pci.c b/arch/ppc/platforms/chrp_pci.c new file mode 100644 index 000000000000..5bb6492ecf8c --- /dev/null +++ b/arch/ppc/platforms/chrp_pci.c | |||
@@ -0,0 +1,309 @@ | |||
1 | /* | ||
2 | * CHRP pci routines. | ||
3 | */ | ||
4 | |||
5 | #include <linux/config.h> | ||
6 | #include <linux/kernel.h> | ||
7 | #include <linux/pci.h> | ||
8 | #include <linux/delay.h> | ||
9 | #include <linux/string.h> | ||
10 | #include <linux/init.h> | ||
11 | #include <linux/ide.h> | ||
12 | #include <linux/bootmem.h> | ||
13 | |||
14 | #include <asm/io.h> | ||
15 | #include <asm/pgtable.h> | ||
16 | #include <asm/irq.h> | ||
17 | #include <asm/hydra.h> | ||
18 | #include <asm/prom.h> | ||
19 | #include <asm/gg2.h> | ||
20 | #include <asm/machdep.h> | ||
21 | #include <asm/sections.h> | ||
22 | #include <asm/pci-bridge.h> | ||
23 | #include <asm/open_pic.h> | ||
24 | |||
25 | /* LongTrail */ | ||
26 | void __iomem *gg2_pci_config_base; | ||
27 | |||
28 | /* | ||
29 | * The VLSI Golden Gate II has only 512K of PCI configuration space, so we | ||
30 | * limit the bus number to 3 bits | ||
31 | */ | ||
32 | |||
33 | int __chrp gg2_read_config(struct pci_bus *bus, unsigned int devfn, int off, | ||
34 | int len, u32 *val) | ||
35 | { | ||
36 | volatile void __iomem *cfg_data; | ||
37 | struct pci_controller *hose = bus->sysdata; | ||
38 | |||
39 | if (bus->number > 7) | ||
40 | return PCIBIOS_DEVICE_NOT_FOUND; | ||
41 | /* | ||
42 | * Note: the caller has already checked that off is | ||
43 | * suitably aligned and that len is 1, 2 or 4. | ||
44 | */ | ||
45 | cfg_data = hose->cfg_data + ((bus->number<<16) | (devfn<<8) | off); | ||
46 | switch (len) { | ||
47 | case 1: | ||
48 | *val = in_8(cfg_data); | ||
49 | break; | ||
50 | case 2: | ||
51 | *val = in_le16(cfg_data); | ||
52 | break; | ||
53 | default: | ||
54 | *val = in_le32(cfg_data); | ||
55 | break; | ||
56 | } | ||
57 | return PCIBIOS_SUCCESSFUL; | ||
58 | } | ||
59 | |||
60 | int __chrp gg2_write_config(struct pci_bus *bus, unsigned int devfn, int off, | ||
61 | int len, u32 val) | ||
62 | { | ||
63 | volatile void __iomem *cfg_data; | ||
64 | struct pci_controller *hose = bus->sysdata; | ||
65 | |||
66 | if (bus->number > 7) | ||
67 | return PCIBIOS_DEVICE_NOT_FOUND; | ||
68 | /* | ||
69 | * Note: the caller has already checked that off is | ||
70 | * suitably aligned and that len is 1, 2 or 4. | ||
71 | */ | ||
72 | cfg_data = hose->cfg_data + ((bus->number<<16) | (devfn<<8) | off); | ||
73 | switch (len) { | ||
74 | case 1: | ||
75 | out_8(cfg_data, val); | ||
76 | break; | ||
77 | case 2: | ||
78 | out_le16(cfg_data, val); | ||
79 | break; | ||
80 | default: | ||
81 | out_le32(cfg_data, val); | ||
82 | break; | ||
83 | } | ||
84 | return PCIBIOS_SUCCESSFUL; | ||
85 | } | ||
86 | |||
87 | static struct pci_ops gg2_pci_ops = | ||
88 | { | ||
89 | gg2_read_config, | ||
90 | gg2_write_config | ||
91 | }; | ||
92 | |||
93 | /* | ||
94 | * Access functions for PCI config space using RTAS calls. | ||
95 | */ | ||
96 | int __chrp | ||
97 | rtas_read_config(struct pci_bus *bus, unsigned int devfn, int offset, | ||
98 | int len, u32 *val) | ||
99 | { | ||
100 | struct pci_controller *hose = bus->sysdata; | ||
101 | unsigned long addr = (offset & 0xff) | ((devfn & 0xff) << 8) | ||
102 | | (((bus->number - hose->first_busno) & 0xff) << 16) | ||
103 | | (hose->index << 24); | ||
104 | unsigned long ret = ~0UL; | ||
105 | int rval; | ||
106 | |||
107 | rval = call_rtas("read-pci-config", 2, 2, &ret, addr, len); | ||
108 | *val = ret; | ||
109 | return rval? PCIBIOS_DEVICE_NOT_FOUND: PCIBIOS_SUCCESSFUL; | ||
110 | } | ||
111 | |||
112 | int __chrp | ||
113 | rtas_write_config(struct pci_bus *bus, unsigned int devfn, int offset, | ||
114 | int len, u32 val) | ||
115 | { | ||
116 | struct pci_controller *hose = bus->sysdata; | ||
117 | unsigned long addr = (offset & 0xff) | ((devfn & 0xff) << 8) | ||
118 | | (((bus->number - hose->first_busno) & 0xff) << 16) | ||
119 | | (hose->index << 24); | ||
120 | int rval; | ||
121 | |||
122 | rval = call_rtas("write-pci-config", 3, 1, NULL, addr, len, val); | ||
123 | return rval? PCIBIOS_DEVICE_NOT_FOUND: PCIBIOS_SUCCESSFUL; | ||
124 | } | ||
125 | |||
126 | static struct pci_ops rtas_pci_ops = | ||
127 | { | ||
128 | rtas_read_config, | ||
129 | rtas_write_config | ||
130 | }; | ||
131 | |||
132 | volatile struct Hydra *Hydra = NULL; | ||
133 | |||
134 | int __init | ||
135 | hydra_init(void) | ||
136 | { | ||
137 | struct device_node *np; | ||
138 | |||
139 | np = find_devices("mac-io"); | ||
140 | if (np == NULL || np->n_addrs == 0) | ||
141 | return 0; | ||
142 | Hydra = ioremap(np->addrs[0].address, np->addrs[0].size); | ||
143 | printk("Hydra Mac I/O at %x\n", np->addrs[0].address); | ||
144 | printk("Hydra Feature_Control was %x", | ||
145 | in_le32(&Hydra->Feature_Control)); | ||
146 | out_le32(&Hydra->Feature_Control, (HYDRA_FC_SCC_CELL_EN | | ||
147 | HYDRA_FC_SCSI_CELL_EN | | ||
148 | HYDRA_FC_SCCA_ENABLE | | ||
149 | HYDRA_FC_SCCB_ENABLE | | ||
150 | HYDRA_FC_ARB_BYPASS | | ||
151 | HYDRA_FC_MPIC_ENABLE | | ||
152 | HYDRA_FC_SLOW_SCC_PCLK | | ||
153 | HYDRA_FC_MPIC_IS_MASTER)); | ||
154 | printk(", now %x\n", in_le32(&Hydra->Feature_Control)); | ||
155 | return 1; | ||
156 | } | ||
157 | |||
158 | void __init | ||
159 | chrp_pcibios_fixup(void) | ||
160 | { | ||
161 | struct pci_dev *dev = NULL; | ||
162 | struct device_node *np; | ||
163 | |||
164 | /* PCI interrupts are controlled by the OpenPIC */ | ||
165 | for_each_pci_dev(dev) { | ||
166 | np = pci_device_to_OF_node(dev); | ||
167 | if ((np != 0) && (np->n_intrs > 0) && (np->intrs[0].line != 0)) | ||
168 | dev->irq = np->intrs[0].line; | ||
169 | pci_write_config_byte(dev, PCI_INTERRUPT_LINE, dev->irq); | ||
170 | } | ||
171 | } | ||
172 | |||
173 | #define PRG_CL_RESET_VALID 0x00010000 | ||
174 | |||
175 | static void __init | ||
176 | setup_python(struct pci_controller *hose, struct device_node *dev) | ||
177 | { | ||
178 | u32 *reg, val; | ||
179 | unsigned long addr = dev->addrs[0].address; | ||
180 | |||
181 | setup_indirect_pci(hose, addr + 0xf8000, addr + 0xf8010); | ||
182 | |||
183 | /* Clear the magic go-slow bit */ | ||
184 | reg = (u32 *) ioremap(dev->addrs[0].address + 0xf6000, 0x40); | ||
185 | val = in_be32(®[12]); | ||
186 | if (val & PRG_CL_RESET_VALID) { | ||
187 | out_be32(®[12], val & ~PRG_CL_RESET_VALID); | ||
188 | in_be32(®[12]); | ||
189 | } | ||
190 | iounmap(reg); | ||
191 | } | ||
192 | |||
193 | /* Marvell Discovery II based Pegasos 2 */ | ||
194 | static void __init setup_peg2(struct pci_controller *hose, struct device_node *dev) | ||
195 | { | ||
196 | struct device_node *root = find_path_device("/"); | ||
197 | struct device_node *rtas; | ||
198 | |||
199 | rtas = of_find_node_by_name (root, "rtas"); | ||
200 | if (rtas) { | ||
201 | hose->ops = &rtas_pci_ops; | ||
202 | } else { | ||
203 | printk ("RTAS supporting Pegasos OF not found, please upgrade" | ||
204 | " your firmware\n"); | ||
205 | } | ||
206 | pci_assign_all_busses = 1; | ||
207 | } | ||
208 | |||
209 | void __init | ||
210 | chrp_find_bridges(void) | ||
211 | { | ||
212 | struct device_node *dev; | ||
213 | int *bus_range; | ||
214 | int len, index = -1; | ||
215 | struct pci_controller *hose; | ||
216 | unsigned int *dma; | ||
217 | char *model, *machine; | ||
218 | int is_longtrail = 0, is_mot = 0, is_pegasos = 0; | ||
219 | struct device_node *root = find_path_device("/"); | ||
220 | |||
221 | /* | ||
222 | * The PCI host bridge nodes on some machines don't have | ||
223 | * properties to adequately identify them, so we have to | ||
224 | * look at what sort of machine this is as well. | ||
225 | */ | ||
226 | machine = get_property(root, "model", NULL); | ||
227 | if (machine != NULL) { | ||
228 | is_longtrail = strncmp(machine, "IBM,LongTrail", 13) == 0; | ||
229 | is_mot = strncmp(machine, "MOT", 3) == 0; | ||
230 | if (strncmp(machine, "Pegasos2", 8) == 0) | ||
231 | is_pegasos = 2; | ||
232 | else if (strncmp(machine, "Pegasos", 7) == 0) | ||
233 | is_pegasos = 1; | ||
234 | } | ||
235 | for (dev = root->child; dev != NULL; dev = dev->sibling) { | ||
236 | if (dev->type == NULL || strcmp(dev->type, "pci") != 0) | ||
237 | continue; | ||
238 | ++index; | ||
239 | /* The GG2 bridge on the LongTrail doesn't have an address */ | ||
240 | if (dev->n_addrs < 1 && !is_longtrail) { | ||
241 | printk(KERN_WARNING "Can't use %s: no address\n", | ||
242 | dev->full_name); | ||
243 | continue; | ||
244 | } | ||
245 | bus_range = (int *) get_property(dev, "bus-range", &len); | ||
246 | if (bus_range == NULL || len < 2 * sizeof(int)) { | ||
247 | printk(KERN_WARNING "Can't get bus-range for %s\n", | ||
248 | dev->full_name); | ||
249 | continue; | ||
250 | } | ||
251 | if (bus_range[1] == bus_range[0]) | ||
252 | printk(KERN_INFO "PCI bus %d", bus_range[0]); | ||
253 | else | ||
254 | printk(KERN_INFO "PCI buses %d..%d", | ||
255 | bus_range[0], bus_range[1]); | ||
256 | printk(" controlled by %s", dev->type); | ||
257 | if (dev->n_addrs > 0) | ||
258 | printk(" at %x", dev->addrs[0].address); | ||
259 | printk("\n"); | ||
260 | |||
261 | hose = pcibios_alloc_controller(); | ||
262 | if (!hose) { | ||
263 | printk("Can't allocate PCI controller structure for %s\n", | ||
264 | dev->full_name); | ||
265 | continue; | ||
266 | } | ||
267 | hose->arch_data = dev; | ||
268 | hose->first_busno = bus_range[0]; | ||
269 | hose->last_busno = bus_range[1]; | ||
270 | |||
271 | model = get_property(dev, "model", NULL); | ||
272 | if (model == NULL) | ||
273 | model = "<none>"; | ||
274 | if (device_is_compatible(dev, "IBM,python")) { | ||
275 | setup_python(hose, dev); | ||
276 | } else if (is_mot | ||
277 | || strncmp(model, "Motorola, Grackle", 17) == 0) { | ||
278 | setup_grackle(hose); | ||
279 | } else if (is_longtrail) { | ||
280 | void __iomem *p = ioremap(GG2_PCI_CONFIG_BASE, 0x80000); | ||
281 | hose->ops = &gg2_pci_ops; | ||
282 | hose->cfg_data = p; | ||
283 | gg2_pci_config_base = p; | ||
284 | } else if (is_pegasos == 1) { | ||
285 | setup_indirect_pci(hose, 0xfec00cf8, 0xfee00cfc); | ||
286 | } else if (is_pegasos == 2) { | ||
287 | setup_peg2(hose, dev); | ||
288 | } else { | ||
289 | printk("No methods for %s (model %s), using RTAS\n", | ||
290 | dev->full_name, model); | ||
291 | hose->ops = &rtas_pci_ops; | ||
292 | } | ||
293 | |||
294 | pci_process_bridge_OF_ranges(hose, dev, index == 0); | ||
295 | |||
296 | /* check the first bridge for a property that we can | ||
297 | use to set pci_dram_offset */ | ||
298 | dma = (unsigned int *) | ||
299 | get_property(dev, "ibm,dma-ranges", &len); | ||
300 | if (index == 0 && dma != NULL && len >= 6 * sizeof(*dma)) { | ||
301 | pci_dram_offset = dma[2] - dma[3]; | ||
302 | printk("pci_dram_offset = %lx\n", pci_dram_offset); | ||
303 | } | ||
304 | } | ||
305 | |||
306 | /* Do not fixup interrupts from OF tree on pegasos */ | ||
307 | if (is_pegasos == 0) | ||
308 | ppc_md.pcibios_fixup = chrp_pcibios_fixup; | ||
309 | } | ||
diff --git a/arch/ppc/platforms/chrp_pegasos_eth.c b/arch/ppc/platforms/chrp_pegasos_eth.c new file mode 100644 index 000000000000..cad5bfa153b2 --- /dev/null +++ b/arch/ppc/platforms/chrp_pegasos_eth.c | |||
@@ -0,0 +1,101 @@ | |||
1 | /* | ||
2 | * arch/ppc/platforms/chrp_pegasos_eth.c | ||
3 | * | ||
4 | * Copyright (C) 2005 Sven Luther <sl@bplan-gmbh.de> | ||
5 | * Thanks to : | ||
6 | * Dale Farnsworth <dale@farnsworth.org> | ||
7 | * Mark A. Greer <mgreer@mvista.com> | ||
8 | * Nicolas DET <nd@bplan-gmbh.de> | ||
9 | * Benjamin Herrenschmidt <benh@kernel.crashing.org> | ||
10 | * And anyone else who helped me on this. | ||
11 | */ | ||
12 | |||
13 | #include <linux/types.h> | ||
14 | #include <linux/init.h> | ||
15 | #include <linux/ioport.h> | ||
16 | #include <linux/device.h> | ||
17 | #include <linux/mv643xx.h> | ||
18 | #include <linux/pci.h> | ||
19 | |||
20 | /* Pegasos 2 specific Marvell MV 64361 gigabit ethernet port setup */ | ||
21 | static struct resource mv643xx_eth_shared_resources[] = { | ||
22 | [0] = { | ||
23 | .name = "ethernet shared base", | ||
24 | .start = 0xf1000000 + MV643XX_ETH_SHARED_REGS, | ||
25 | .end = 0xf1000000 + MV643XX_ETH_SHARED_REGS + | ||
26 | MV643XX_ETH_SHARED_REGS_SIZE - 1, | ||
27 | .flags = IORESOURCE_MEM, | ||
28 | }, | ||
29 | }; | ||
30 | |||
31 | static struct platform_device mv643xx_eth_shared_device = { | ||
32 | .name = MV643XX_ETH_SHARED_NAME, | ||
33 | .id = 0, | ||
34 | .num_resources = ARRAY_SIZE(mv643xx_eth_shared_resources), | ||
35 | .resource = mv643xx_eth_shared_resources, | ||
36 | }; | ||
37 | |||
38 | static struct resource mv643xx_eth0_resources[] = { | ||
39 | [0] = { | ||
40 | .name = "eth0 irq", | ||
41 | .start = 9, | ||
42 | .end = 9, | ||
43 | .flags = IORESOURCE_IRQ, | ||
44 | }, | ||
45 | }; | ||
46 | |||
47 | static struct mv643xx_eth_platform_data eth0_pd; | ||
48 | |||
49 | static struct platform_device eth0_device = { | ||
50 | .name = MV643XX_ETH_NAME, | ||
51 | .id = 0, | ||
52 | .num_resources = ARRAY_SIZE(mv643xx_eth0_resources), | ||
53 | .resource = mv643xx_eth0_resources, | ||
54 | .dev = { | ||
55 | .platform_data = ð0_pd, | ||
56 | }, | ||
57 | }; | ||
58 | |||
59 | static struct resource mv643xx_eth1_resources[] = { | ||
60 | [0] = { | ||
61 | .name = "eth1 irq", | ||
62 | .start = 9, | ||
63 | .end = 9, | ||
64 | .flags = IORESOURCE_IRQ, | ||
65 | }, | ||
66 | }; | ||
67 | |||
68 | static struct mv643xx_eth_platform_data eth1_pd; | ||
69 | |||
70 | static struct platform_device eth1_device = { | ||
71 | .name = MV643XX_ETH_NAME, | ||
72 | .id = 1, | ||
73 | .num_resources = ARRAY_SIZE(mv643xx_eth1_resources), | ||
74 | .resource = mv643xx_eth1_resources, | ||
75 | .dev = { | ||
76 | .platform_data = ð1_pd, | ||
77 | }, | ||
78 | }; | ||
79 | |||
80 | static struct platform_device *mv643xx_eth_pd_devs[] __initdata = { | ||
81 | &mv643xx_eth_shared_device, | ||
82 | ð0_device, | ||
83 | ð1_device, | ||
84 | }; | ||
85 | |||
86 | |||
87 | int | ||
88 | mv643xx_eth_add_pds(void) | ||
89 | { | ||
90 | int ret = 0; | ||
91 | static struct pci_device_id pci_marvell_mv64360[] = { | ||
92 | { PCI_DEVICE(PCI_VENDOR_ID_MARVELL, PCI_DEVICE_ID_MARVELL_MV64360) }, | ||
93 | { } | ||
94 | }; | ||
95 | |||
96 | if (pci_dev_present(pci_marvell_mv64360)) { | ||
97 | ret = platform_add_devices(mv643xx_eth_pd_devs, ARRAY_SIZE(mv643xx_eth_pd_devs)); | ||
98 | } | ||
99 | return ret; | ||
100 | } | ||
101 | device_initcall(mv643xx_eth_add_pds); | ||
diff --git a/arch/ppc/platforms/chrp_setup.c b/arch/ppc/platforms/chrp_setup.c new file mode 100644 index 000000000000..f23c4f320760 --- /dev/null +++ b/arch/ppc/platforms/chrp_setup.c | |||
@@ -0,0 +1,615 @@ | |||
1 | /* | ||
2 | * arch/ppc/platforms/setup.c | ||
3 | * | ||
4 | * Copyright (C) 1995 Linus Torvalds | ||
5 | * Adapted from 'alpha' version by Gary Thomas | ||
6 | * Modified by Cort Dougan (cort@cs.nmt.edu) | ||
7 | */ | ||
8 | |||
9 | /* | ||
10 | * bootup setup stuff.. | ||
11 | */ | ||
12 | |||
13 | #include <linux/config.h> | ||
14 | #include <linux/errno.h> | ||
15 | #include <linux/sched.h> | ||
16 | #include <linux/kernel.h> | ||
17 | #include <linux/mm.h> | ||
18 | #include <linux/stddef.h> | ||
19 | #include <linux/unistd.h> | ||
20 | #include <linux/ptrace.h> | ||
21 | #include <linux/slab.h> | ||
22 | #include <linux/user.h> | ||
23 | #include <linux/a.out.h> | ||
24 | #include <linux/tty.h> | ||
25 | #include <linux/major.h> | ||
26 | #include <linux/interrupt.h> | ||
27 | #include <linux/reboot.h> | ||
28 | #include <linux/init.h> | ||
29 | #include <linux/pci.h> | ||
30 | #include <linux/version.h> | ||
31 | #include <linux/adb.h> | ||
32 | #include <linux/module.h> | ||
33 | #include <linux/delay.h> | ||
34 | #include <linux/ide.h> | ||
35 | #include <linux/irq.h> | ||
36 | #include <linux/console.h> | ||
37 | #include <linux/seq_file.h> | ||
38 | #include <linux/root_dev.h> | ||
39 | #include <linux/initrd.h> | ||
40 | #include <linux/module.h> | ||
41 | |||
42 | #include <asm/io.h> | ||
43 | #include <asm/pgtable.h> | ||
44 | #include <asm/prom.h> | ||
45 | #include <asm/gg2.h> | ||
46 | #include <asm/pci-bridge.h> | ||
47 | #include <asm/dma.h> | ||
48 | #include <asm/machdep.h> | ||
49 | #include <asm/irq.h> | ||
50 | #include <asm/hydra.h> | ||
51 | #include <asm/sections.h> | ||
52 | #include <asm/time.h> | ||
53 | #include <asm/btext.h> | ||
54 | #include <asm/i8259.h> | ||
55 | #include <asm/open_pic.h> | ||
56 | #include <asm/xmon.h> | ||
57 | |||
58 | unsigned long chrp_get_rtc_time(void); | ||
59 | int chrp_set_rtc_time(unsigned long nowtime); | ||
60 | void chrp_calibrate_decr(void); | ||
61 | long chrp_time_init(void); | ||
62 | |||
63 | void chrp_find_bridges(void); | ||
64 | void chrp_event_scan(void); | ||
65 | void rtas_display_progress(char *, unsigned short); | ||
66 | void rtas_indicator_progress(char *, unsigned short); | ||
67 | void btext_progress(char *, unsigned short); | ||
68 | |||
69 | extern unsigned long pmac_find_end_of_memory(void); | ||
70 | extern int of_show_percpuinfo(struct seq_file *, int); | ||
71 | |||
72 | int _chrp_type; | ||
73 | EXPORT_SYMBOL(_chrp_type); | ||
74 | |||
75 | /* | ||
76 | * XXX this should be in xmon.h, but putting it there means xmon.h | ||
77 | * has to include <linux/interrupt.h> (to get irqreturn_t), which | ||
78 | * causes all sorts of problems. -- paulus | ||
79 | */ | ||
80 | extern irqreturn_t xmon_irq(int, void *, struct pt_regs *); | ||
81 | |||
82 | extern dev_t boot_dev; | ||
83 | |||
84 | extern PTE *Hash, *Hash_end; | ||
85 | extern unsigned long Hash_size, Hash_mask; | ||
86 | extern int probingmem; | ||
87 | extern unsigned long loops_per_jiffy; | ||
88 | static int max_width; | ||
89 | |||
90 | #ifdef CONFIG_SMP | ||
91 | extern struct smp_ops_t chrp_smp_ops; | ||
92 | #endif | ||
93 | |||
94 | static const char *gg2_memtypes[4] = { | ||
95 | "FPM", "SDRAM", "EDO", "BEDO" | ||
96 | }; | ||
97 | static const char *gg2_cachesizes[4] = { | ||
98 | "256 KB", "512 KB", "1 MB", "Reserved" | ||
99 | }; | ||
100 | static const char *gg2_cachetypes[4] = { | ||
101 | "Asynchronous", "Reserved", "Flow-Through Synchronous", | ||
102 | "Pipelined Synchronous" | ||
103 | }; | ||
104 | static const char *gg2_cachemodes[4] = { | ||
105 | "Disabled", "Write-Through", "Copy-Back", "Transparent Mode" | ||
106 | }; | ||
107 | |||
108 | int __chrp | ||
109 | chrp_show_cpuinfo(struct seq_file *m) | ||
110 | { | ||
111 | int i, sdramen; | ||
112 | unsigned int t; | ||
113 | struct device_node *root; | ||
114 | const char *model = ""; | ||
115 | |||
116 | root = find_path_device("/"); | ||
117 | if (root) | ||
118 | model = get_property(root, "model", NULL); | ||
119 | seq_printf(m, "machine\t\t: CHRP %s\n", model); | ||
120 | |||
121 | /* longtrail (goldengate) stuff */ | ||
122 | if (!strncmp(model, "IBM,LongTrail", 13)) { | ||
123 | /* VLSI VAS96011/12 `Golden Gate 2' */ | ||
124 | /* Memory banks */ | ||
125 | sdramen = (in_le32(gg2_pci_config_base + GG2_PCI_DRAM_CTRL) | ||
126 | >>31) & 1; | ||
127 | for (i = 0; i < (sdramen ? 4 : 6); i++) { | ||
128 | t = in_le32(gg2_pci_config_base+ | ||
129 | GG2_PCI_DRAM_BANK0+ | ||
130 | i*4); | ||
131 | if (!(t & 1)) | ||
132 | continue; | ||
133 | switch ((t>>8) & 0x1f) { | ||
134 | case 0x1f: | ||
135 | model = "4 MB"; | ||
136 | break; | ||
137 | case 0x1e: | ||
138 | model = "8 MB"; | ||
139 | break; | ||
140 | case 0x1c: | ||
141 | model = "16 MB"; | ||
142 | break; | ||
143 | case 0x18: | ||
144 | model = "32 MB"; | ||
145 | break; | ||
146 | case 0x10: | ||
147 | model = "64 MB"; | ||
148 | break; | ||
149 | case 0x00: | ||
150 | model = "128 MB"; | ||
151 | break; | ||
152 | default: | ||
153 | model = "Reserved"; | ||
154 | break; | ||
155 | } | ||
156 | seq_printf(m, "memory bank %d\t: %s %s\n", i, model, | ||
157 | gg2_memtypes[sdramen ? 1 : ((t>>1) & 3)]); | ||
158 | } | ||
159 | /* L2 cache */ | ||
160 | t = in_le32(gg2_pci_config_base+GG2_PCI_CC_CTRL); | ||
161 | seq_printf(m, "board l2\t: %s %s (%s)\n", | ||
162 | gg2_cachesizes[(t>>7) & 3], | ||
163 | gg2_cachetypes[(t>>2) & 3], | ||
164 | gg2_cachemodes[t & 3]); | ||
165 | } | ||
166 | return 0; | ||
167 | } | ||
168 | |||
169 | /* | ||
170 | * Fixes for the National Semiconductor PC78308VUL SuperI/O | ||
171 | * | ||
172 | * Some versions of Open Firmware incorrectly initialize the IRQ settings | ||
173 | * for keyboard and mouse | ||
174 | */ | ||
175 | static inline void __init sio_write(u8 val, u8 index) | ||
176 | { | ||
177 | outb(index, 0x15c); | ||
178 | outb(val, 0x15d); | ||
179 | } | ||
180 | |||
181 | static inline u8 __init sio_read(u8 index) | ||
182 | { | ||
183 | outb(index, 0x15c); | ||
184 | return inb(0x15d); | ||
185 | } | ||
186 | |||
187 | static void __init sio_fixup_irq(const char *name, u8 device, u8 level, | ||
188 | u8 type) | ||
189 | { | ||
190 | u8 level0, type0, active; | ||
191 | |||
192 | /* select logical device */ | ||
193 | sio_write(device, 0x07); | ||
194 | active = sio_read(0x30); | ||
195 | level0 = sio_read(0x70); | ||
196 | type0 = sio_read(0x71); | ||
197 | if (level0 != level || type0 != type || !active) { | ||
198 | printk(KERN_WARNING "sio: %s irq level %d, type %d, %sactive: " | ||
199 | "remapping to level %d, type %d, active\n", | ||
200 | name, level0, type0, !active ? "in" : "", level, type); | ||
201 | sio_write(0x01, 0x30); | ||
202 | sio_write(level, 0x70); | ||
203 | sio_write(type, 0x71); | ||
204 | } | ||
205 | } | ||
206 | |||
207 | static void __init sio_init(void) | ||
208 | { | ||
209 | struct device_node *root; | ||
210 | |||
211 | if ((root = find_path_device("/")) && | ||
212 | !strncmp(get_property(root, "model", NULL), "IBM,LongTrail", 13)) { | ||
213 | /* logical device 0 (KBC/Keyboard) */ | ||
214 | sio_fixup_irq("keyboard", 0, 1, 2); | ||
215 | /* select logical device 1 (KBC/Mouse) */ | ||
216 | sio_fixup_irq("mouse", 1, 12, 2); | ||
217 | } | ||
218 | } | ||
219 | |||
220 | |||
221 | static void __init pegasos_set_l2cr(void) | ||
222 | { | ||
223 | struct device_node *np; | ||
224 | |||
225 | /* On Pegasos, enable the l2 cache if needed, as the OF forgets it */ | ||
226 | if (_chrp_type != _CHRP_Pegasos) | ||
227 | return; | ||
228 | |||
229 | /* Enable L2 cache if needed */ | ||
230 | np = find_type_devices("cpu"); | ||
231 | if (np != NULL) { | ||
232 | unsigned int *l2cr = (unsigned int *) | ||
233 | get_property (np, "l2cr", NULL); | ||
234 | if (l2cr == NULL) { | ||
235 | printk ("Pegasos l2cr : no cpu l2cr property found\n"); | ||
236 | return; | ||
237 | } | ||
238 | if (!((*l2cr) & 0x80000000)) { | ||
239 | printk ("Pegasos l2cr : L2 cache was not active, " | ||
240 | "activating\n"); | ||
241 | _set_L2CR(0); | ||
242 | _set_L2CR((*l2cr) | 0x80000000); | ||
243 | } | ||
244 | } | ||
245 | } | ||
246 | |||
247 | void __init chrp_setup_arch(void) | ||
248 | { | ||
249 | struct device_node *device; | ||
250 | |||
251 | /* init to some ~sane value until calibrate_delay() runs */ | ||
252 | loops_per_jiffy = 50000000/HZ; | ||
253 | |||
254 | #ifdef CONFIG_BLK_DEV_INITRD | ||
255 | /* this is fine for chrp */ | ||
256 | initrd_below_start_ok = 1; | ||
257 | |||
258 | if (initrd_start) | ||
259 | ROOT_DEV = Root_RAM0; | ||
260 | else | ||
261 | #endif | ||
262 | ROOT_DEV = Root_SDA2; /* sda2 (sda1 is for the kernel) */ | ||
263 | |||
264 | /* On pegasos, enable the L2 cache if not already done by OF */ | ||
265 | pegasos_set_l2cr(); | ||
266 | |||
267 | /* Lookup PCI host bridges */ | ||
268 | chrp_find_bridges(); | ||
269 | |||
270 | #ifndef CONFIG_PPC64BRIDGE | ||
271 | /* | ||
272 | * Temporary fixes for PCI devices. | ||
273 | * -- Geert | ||
274 | */ | ||
275 | hydra_init(); /* Mac I/O */ | ||
276 | |||
277 | #endif /* CONFIG_PPC64BRIDGE */ | ||
278 | |||
279 | /* | ||
280 | * Fix the Super I/O configuration | ||
281 | */ | ||
282 | sio_init(); | ||
283 | |||
284 | /* Get the event scan rate for the rtas so we know how | ||
285 | * often it expects a heartbeat. -- Cort | ||
286 | */ | ||
287 | if ( rtas_data ) { | ||
288 | struct property *p; | ||
289 | device = find_devices("rtas"); | ||
290 | for ( p = device->properties; | ||
291 | p && strncmp(p->name, "rtas-event-scan-rate", 20); | ||
292 | p = p->next ) | ||
293 | /* nothing */ ; | ||
294 | if ( p && *(unsigned long *)p->value ) { | ||
295 | ppc_md.heartbeat = chrp_event_scan; | ||
296 | ppc_md.heartbeat_reset = (HZ/(*(unsigned long *)p->value)*30)-1; | ||
297 | ppc_md.heartbeat_count = 1; | ||
298 | printk("RTAS Event Scan Rate: %lu (%lu jiffies)\n", | ||
299 | *(unsigned long *)p->value, ppc_md.heartbeat_reset ); | ||
300 | } | ||
301 | } | ||
302 | |||
303 | pci_create_OF_bus_map(); | ||
304 | } | ||
305 | |||
306 | void __chrp | ||
307 | chrp_event_scan(void) | ||
308 | { | ||
309 | unsigned char log[1024]; | ||
310 | unsigned long ret = 0; | ||
311 | /* XXX: we should loop until the hardware says no more error logs -- Cort */ | ||
312 | call_rtas( "event-scan", 4, 1, &ret, 0xffffffff, 0, | ||
313 | __pa(log), 1024 ); | ||
314 | ppc_md.heartbeat_count = ppc_md.heartbeat_reset; | ||
315 | } | ||
316 | |||
317 | void __chrp | ||
318 | chrp_restart(char *cmd) | ||
319 | { | ||
320 | printk("RTAS system-reboot returned %d\n", | ||
321 | call_rtas("system-reboot", 0, 1, NULL)); | ||
322 | for (;;); | ||
323 | } | ||
324 | |||
325 | void __chrp | ||
326 | chrp_power_off(void) | ||
327 | { | ||
328 | /* allow power on only with power button press */ | ||
329 | printk("RTAS power-off returned %d\n", | ||
330 | call_rtas("power-off", 2, 1, NULL,0xffffffff,0xffffffff)); | ||
331 | for (;;); | ||
332 | } | ||
333 | |||
334 | void __chrp | ||
335 | chrp_halt(void) | ||
336 | { | ||
337 | chrp_power_off(); | ||
338 | } | ||
339 | |||
340 | u_int __chrp | ||
341 | chrp_irq_canonicalize(u_int irq) | ||
342 | { | ||
343 | if (irq == 2) | ||
344 | return 9; | ||
345 | return irq; | ||
346 | } | ||
347 | |||
348 | /* | ||
349 | * Finds the open-pic node and sets OpenPIC_Addr based on its reg property. | ||
350 | * Then checks if it has an interrupt-ranges property. If it does then | ||
351 | * we have a distributed open-pic, so call openpic_set_sources to tell | ||
352 | * the openpic code where to find the interrupt source registers. | ||
353 | */ | ||
354 | static void __init chrp_find_openpic(void) | ||
355 | { | ||
356 | struct device_node *np; | ||
357 | int len, i; | ||
358 | unsigned int *iranges; | ||
359 | void *isu; | ||
360 | |||
361 | np = find_type_devices("open-pic"); | ||
362 | if (np == NULL || np->n_addrs == 0) | ||
363 | return; | ||
364 | printk(KERN_INFO "OpenPIC at %x (size %x)\n", | ||
365 | np->addrs[0].address, np->addrs[0].size); | ||
366 | OpenPIC_Addr = ioremap(np->addrs[0].address, 0x40000); | ||
367 | if (OpenPIC_Addr == NULL) { | ||
368 | printk(KERN_ERR "Failed to map OpenPIC!\n"); | ||
369 | return; | ||
370 | } | ||
371 | |||
372 | iranges = (unsigned int *) get_property(np, "interrupt-ranges", &len); | ||
373 | if (iranges == NULL || len < 2 * sizeof(unsigned int)) | ||
374 | return; /* not distributed */ | ||
375 | |||
376 | /* | ||
377 | * The first pair of cells in interrupt-ranges refers to the | ||
378 | * IDU; subsequent pairs refer to the ISUs. | ||
379 | */ | ||
380 | len /= 2 * sizeof(unsigned int); | ||
381 | if (np->n_addrs < len) { | ||
382 | printk(KERN_ERR "Insufficient addresses for distributed" | ||
383 | " OpenPIC (%d < %d)\n", np->n_addrs, len); | ||
384 | return; | ||
385 | } | ||
386 | if (iranges[1] != 0) { | ||
387 | printk(KERN_INFO "OpenPIC irqs %d..%d in IDU\n", | ||
388 | iranges[0], iranges[0] + iranges[1] - 1); | ||
389 | openpic_set_sources(iranges[0], iranges[1], NULL); | ||
390 | } | ||
391 | for (i = 1; i < len; ++i) { | ||
392 | iranges += 2; | ||
393 | printk(KERN_INFO "OpenPIC irqs %d..%d in ISU at %x (%x)\n", | ||
394 | iranges[0], iranges[0] + iranges[1] - 1, | ||
395 | np->addrs[i].address, np->addrs[i].size); | ||
396 | isu = ioremap(np->addrs[i].address, np->addrs[i].size); | ||
397 | if (isu != NULL) | ||
398 | openpic_set_sources(iranges[0], iranges[1], isu); | ||
399 | else | ||
400 | printk(KERN_ERR "Failed to map OpenPIC ISU at %x!\n", | ||
401 | np->addrs[i].address); | ||
402 | } | ||
403 | } | ||
404 | |||
405 | #if defined(CONFIG_VT) && defined(CONFIG_INPUT_ADBHID) && defined(XMON) | ||
406 | static struct irqaction xmon_irqaction = { | ||
407 | .handler = xmon_irq, | ||
408 | .mask = CPU_MASK_NONE, | ||
409 | .name = "XMON break", | ||
410 | }; | ||
411 | #endif | ||
412 | |||
413 | void __init chrp_init_IRQ(void) | ||
414 | { | ||
415 | struct device_node *np; | ||
416 | int i; | ||
417 | unsigned long chrp_int_ack = 0; | ||
418 | unsigned char init_senses[NR_IRQS - NUM_8259_INTERRUPTS]; | ||
419 | #if defined(CONFIG_VT) && defined(CONFIG_INPUT_ADBHID) && defined(XMON) | ||
420 | struct device_node *kbd; | ||
421 | #endif | ||
422 | |||
423 | for (np = find_devices("pci"); np != NULL; np = np->next) { | ||
424 | unsigned int *addrp = (unsigned int *) | ||
425 | get_property(np, "8259-interrupt-acknowledge", NULL); | ||
426 | |||
427 | if (addrp == NULL) | ||
428 | continue; | ||
429 | chrp_int_ack = addrp[prom_n_addr_cells(np)-1]; | ||
430 | break; | ||
431 | } | ||
432 | if (np == NULL) | ||
433 | printk(KERN_ERR "Cannot find PCI interrupt acknowledge address\n"); | ||
434 | |||
435 | chrp_find_openpic(); | ||
436 | |||
437 | if (OpenPIC_Addr) { | ||
438 | prom_get_irq_senses(init_senses, NUM_8259_INTERRUPTS, NR_IRQS); | ||
439 | OpenPIC_InitSenses = init_senses; | ||
440 | OpenPIC_NumInitSenses = NR_IRQS - NUM_8259_INTERRUPTS; | ||
441 | |||
442 | openpic_init(NUM_8259_INTERRUPTS); | ||
443 | /* We have a cascade on OpenPIC IRQ 0, Linux IRQ 16 */ | ||
444 | openpic_hookup_cascade(NUM_8259_INTERRUPTS, "82c59 cascade", | ||
445 | i8259_irq); | ||
446 | |||
447 | } | ||
448 | for (i = 0; i < NUM_8259_INTERRUPTS; i++) | ||
449 | irq_desc[i].handler = &i8259_pic; | ||
450 | i8259_init(chrp_int_ack); | ||
451 | |||
452 | #if defined(CONFIG_VT) && defined(CONFIG_INPUT_ADBHID) && defined(XMON) | ||
453 | /* see if there is a keyboard in the device tree | ||
454 | with a parent of type "adb" */ | ||
455 | for (kbd = find_devices("keyboard"); kbd; kbd = kbd->next) | ||
456 | if (kbd->parent && kbd->parent->type | ||
457 | && strcmp(kbd->parent->type, "adb") == 0) | ||
458 | break; | ||
459 | if (kbd) | ||
460 | setup_irq(HYDRA_INT_ADB_NMI, &xmon_irqaction); | ||
461 | #endif | ||
462 | } | ||
463 | |||
464 | void __init | ||
465 | chrp_init2(void) | ||
466 | { | ||
467 | #ifdef CONFIG_NVRAM | ||
468 | // XX replace this in a more saner way | ||
469 | // pmac_nvram_init(); | ||
470 | #endif | ||
471 | |||
472 | request_region(0x20,0x20,"pic1"); | ||
473 | request_region(0xa0,0x20,"pic2"); | ||
474 | request_region(0x00,0x20,"dma1"); | ||
475 | request_region(0x40,0x20,"timer"); | ||
476 | request_region(0x80,0x10,"dma page reg"); | ||
477 | request_region(0xc0,0x20,"dma2"); | ||
478 | |||
479 | if (ppc_md.progress) | ||
480 | ppc_md.progress(" Have fun! ", 0x7777); | ||
481 | } | ||
482 | |||
483 | void __init | ||
484 | chrp_init(unsigned long r3, unsigned long r4, unsigned long r5, | ||
485 | unsigned long r6, unsigned long r7) | ||
486 | { | ||
487 | struct device_node *root = find_path_device ("/"); | ||
488 | char *machine = NULL; | ||
489 | |||
490 | #ifdef CONFIG_BLK_DEV_INITRD | ||
491 | /* take care of initrd if we have one */ | ||
492 | if ( r6 ) | ||
493 | { | ||
494 | initrd_start = r6 + KERNELBASE; | ||
495 | initrd_end = r6 + r7 + KERNELBASE; | ||
496 | } | ||
497 | #endif /* CONFIG_BLK_DEV_INITRD */ | ||
498 | |||
499 | ISA_DMA_THRESHOLD = ~0L; | ||
500 | DMA_MODE_READ = 0x44; | ||
501 | DMA_MODE_WRITE = 0x48; | ||
502 | isa_io_base = CHRP_ISA_IO_BASE; /* default value */ | ||
503 | |||
504 | if (root) | ||
505 | machine = get_property(root, "model", NULL); | ||
506 | if (machine && strncmp(machine, "Pegasos", 7) == 0) { | ||
507 | _chrp_type = _CHRP_Pegasos; | ||
508 | } else if (machine && strncmp(machine, "IBM", 3) == 0) { | ||
509 | _chrp_type = _CHRP_IBM; | ||
510 | } else if (machine && strncmp(machine, "MOT", 3) == 0) { | ||
511 | _chrp_type = _CHRP_Motorola; | ||
512 | } else { | ||
513 | /* Let's assume it is an IBM chrp if all else fails */ | ||
514 | _chrp_type = _CHRP_IBM; | ||
515 | } | ||
516 | |||
517 | ppc_md.setup_arch = chrp_setup_arch; | ||
518 | ppc_md.show_percpuinfo = of_show_percpuinfo; | ||
519 | ppc_md.show_cpuinfo = chrp_show_cpuinfo; | ||
520 | |||
521 | ppc_md.irq_canonicalize = chrp_irq_canonicalize; | ||
522 | ppc_md.init_IRQ = chrp_init_IRQ; | ||
523 | if (_chrp_type == _CHRP_Pegasos) | ||
524 | ppc_md.get_irq = i8259_irq; | ||
525 | else | ||
526 | ppc_md.get_irq = openpic_get_irq; | ||
527 | |||
528 | ppc_md.init = chrp_init2; | ||
529 | |||
530 | ppc_md.phys_mem_access_prot = pci_phys_mem_access_prot; | ||
531 | |||
532 | ppc_md.restart = chrp_restart; | ||
533 | ppc_md.power_off = chrp_power_off; | ||
534 | ppc_md.halt = chrp_halt; | ||
535 | |||
536 | ppc_md.time_init = chrp_time_init; | ||
537 | ppc_md.set_rtc_time = chrp_set_rtc_time; | ||
538 | ppc_md.get_rtc_time = chrp_get_rtc_time; | ||
539 | ppc_md.calibrate_decr = chrp_calibrate_decr; | ||
540 | |||
541 | ppc_md.find_end_of_memory = pmac_find_end_of_memory; | ||
542 | |||
543 | if (rtas_data) { | ||
544 | struct device_node *rtas; | ||
545 | unsigned int *p; | ||
546 | |||
547 | rtas = find_devices("rtas"); | ||
548 | if (rtas != NULL) { | ||
549 | if (get_property(rtas, "display-character", NULL)) { | ||
550 | ppc_md.progress = rtas_display_progress; | ||
551 | p = (unsigned int *) get_property | ||
552 | (rtas, "ibm,display-line-length", NULL); | ||
553 | if (p) | ||
554 | max_width = *p; | ||
555 | } else if (get_property(rtas, "set-indicator", NULL)) | ||
556 | ppc_md.progress = rtas_indicator_progress; | ||
557 | } | ||
558 | } | ||
559 | #ifdef CONFIG_BOOTX_TEXT | ||
560 | if (ppc_md.progress == NULL && boot_text_mapped) | ||
561 | ppc_md.progress = btext_progress; | ||
562 | #endif | ||
563 | |||
564 | #ifdef CONFIG_SMP | ||
565 | ppc_md.smp_ops = &chrp_smp_ops; | ||
566 | #endif /* CONFIG_SMP */ | ||
567 | |||
568 | /* | ||
569 | * Print the banner, then scroll down so boot progress | ||
570 | * can be printed. -- Cort | ||
571 | */ | ||
572 | if (ppc_md.progress) ppc_md.progress("Linux/PPC "UTS_RELEASE"\n", 0x0); | ||
573 | } | ||
574 | |||
575 | void __chrp | ||
576 | rtas_display_progress(char *s, unsigned short hex) | ||
577 | { | ||
578 | int width; | ||
579 | char *os = s; | ||
580 | |||
581 | if ( call_rtas( "display-character", 1, 1, NULL, '\r' ) ) | ||
582 | return; | ||
583 | |||
584 | width = max_width; | ||
585 | while ( *os ) | ||
586 | { | ||
587 | if ( (*os == '\n') || (*os == '\r') ) | ||
588 | width = max_width; | ||
589 | else | ||
590 | width--; | ||
591 | call_rtas( "display-character", 1, 1, NULL, *os++ ); | ||
592 | /* if we overwrite the screen length */ | ||
593 | if ( width == 0 ) | ||
594 | while ( (*os != 0) && (*os != '\n') && (*os != '\r') ) | ||
595 | os++; | ||
596 | } | ||
597 | |||
598 | /*while ( width-- > 0 )*/ | ||
599 | call_rtas( "display-character", 1, 1, NULL, ' ' ); | ||
600 | } | ||
601 | |||
602 | void __chrp | ||
603 | rtas_indicator_progress(char *s, unsigned short hex) | ||
604 | { | ||
605 | call_rtas("set-indicator", 3, 1, NULL, 6, 0, hex); | ||
606 | } | ||
607 | |||
608 | #ifdef CONFIG_BOOTX_TEXT | ||
609 | void | ||
610 | btext_progress(char *s, unsigned short hex) | ||
611 | { | ||
612 | prom_print(s); | ||
613 | prom_print("\n"); | ||
614 | } | ||
615 | #endif /* CONFIG_BOOTX_TEXT */ | ||
diff --git a/arch/ppc/platforms/chrp_smp.c b/arch/ppc/platforms/chrp_smp.c new file mode 100644 index 000000000000..0ea1f7d9e46a --- /dev/null +++ b/arch/ppc/platforms/chrp_smp.c | |||
@@ -0,0 +1,98 @@ | |||
1 | /* | ||
2 | * Smp support for CHRP machines. | ||
3 | * | ||
4 | * Written by Cort Dougan (cort@cs.nmt.edu) borrowing a great | ||
5 | * deal of code from the sparc and intel versions. | ||
6 | * | ||
7 | * Copyright (C) 1999 Cort Dougan <cort@cs.nmt.edu> | ||
8 | * | ||
9 | */ | ||
10 | |||
11 | #include <linux/config.h> | ||
12 | #include <linux/kernel.h> | ||
13 | #include <linux/sched.h> | ||
14 | #include <linux/smp.h> | ||
15 | #include <linux/smp_lock.h> | ||
16 | #include <linux/interrupt.h> | ||
17 | #include <linux/kernel_stat.h> | ||
18 | #include <linux/delay.h> | ||
19 | #include <linux/init.h> | ||
20 | #include <linux/spinlock.h> | ||
21 | |||
22 | #include <asm/ptrace.h> | ||
23 | #include <asm/atomic.h> | ||
24 | #include <asm/irq.h> | ||
25 | #include <asm/page.h> | ||
26 | #include <asm/pgtable.h> | ||
27 | #include <asm/sections.h> | ||
28 | #include <asm/io.h> | ||
29 | #include <asm/prom.h> | ||
30 | #include <asm/smp.h> | ||
31 | #include <asm/residual.h> | ||
32 | #include <asm/time.h> | ||
33 | #include <asm/open_pic.h> | ||
34 | |||
35 | extern unsigned long smp_chrp_cpu_nr; | ||
36 | |||
37 | static int __init | ||
38 | smp_chrp_probe(void) | ||
39 | { | ||
40 | if (smp_chrp_cpu_nr > 1) | ||
41 | openpic_request_IPIs(); | ||
42 | |||
43 | return smp_chrp_cpu_nr; | ||
44 | } | ||
45 | |||
46 | static void __devinit | ||
47 | smp_chrp_kick_cpu(int nr) | ||
48 | { | ||
49 | *(unsigned long *)KERNELBASE = nr; | ||
50 | asm volatile("dcbf 0,%0"::"r"(KERNELBASE):"memory"); | ||
51 | } | ||
52 | |||
53 | static void __devinit | ||
54 | smp_chrp_setup_cpu(int cpu_nr) | ||
55 | { | ||
56 | if (OpenPIC_Addr) | ||
57 | do_openpic_setup_cpu(); | ||
58 | } | ||
59 | |||
60 | static DEFINE_SPINLOCK(timebase_lock); | ||
61 | static unsigned int timebase_upper = 0, timebase_lower = 0; | ||
62 | |||
63 | void __devinit | ||
64 | smp_chrp_give_timebase(void) | ||
65 | { | ||
66 | spin_lock(&timebase_lock); | ||
67 | call_rtas("freeze-time-base", 0, 1, NULL); | ||
68 | timebase_upper = get_tbu(); | ||
69 | timebase_lower = get_tbl(); | ||
70 | spin_unlock(&timebase_lock); | ||
71 | |||
72 | while (timebase_upper || timebase_lower) | ||
73 | barrier(); | ||
74 | call_rtas("thaw-time-base", 0, 1, NULL); | ||
75 | } | ||
76 | |||
77 | void __devinit | ||
78 | smp_chrp_take_timebase(void) | ||
79 | { | ||
80 | while (!(timebase_upper || timebase_lower)) | ||
81 | barrier(); | ||
82 | spin_lock(&timebase_lock); | ||
83 | set_tb(timebase_upper, timebase_lower); | ||
84 | timebase_upper = 0; | ||
85 | timebase_lower = 0; | ||
86 | spin_unlock(&timebase_lock); | ||
87 | printk("CPU %i taken timebase\n", smp_processor_id()); | ||
88 | } | ||
89 | |||
90 | /* CHRP with openpic */ | ||
91 | struct smp_ops_t chrp_smp_ops __chrpdata = { | ||
92 | .message_pass = smp_openpic_message_pass, | ||
93 | .probe = smp_chrp_probe, | ||
94 | .kick_cpu = smp_chrp_kick_cpu, | ||
95 | .setup_cpu = smp_chrp_setup_cpu, | ||
96 | .give_timebase = smp_chrp_give_timebase, | ||
97 | .take_timebase = smp_chrp_take_timebase, | ||
98 | }; | ||
diff --git a/arch/ppc/platforms/chrp_time.c b/arch/ppc/platforms/chrp_time.c new file mode 100644 index 000000000000..e2be0c838d8a --- /dev/null +++ b/arch/ppc/platforms/chrp_time.c | |||
@@ -0,0 +1,194 @@ | |||
1 | /* | ||
2 | * arch/ppc/platforms/chrp_time.c | ||
3 | * | ||
4 | * Copyright (C) 1991, 1992, 1995 Linus Torvalds | ||
5 | * | ||
6 | * Adapted for PowerPC (PReP) by Gary Thomas | ||
7 | * Modified by Cort Dougan (cort@cs.nmt.edu). | ||
8 | * Copied and modified from arch/i386/kernel/time.c | ||
9 | * | ||
10 | */ | ||
11 | #include <linux/errno.h> | ||
12 | #include <linux/sched.h> | ||
13 | #include <linux/kernel.h> | ||
14 | #include <linux/param.h> | ||
15 | #include <linux/string.h> | ||
16 | #include <linux/mm.h> | ||
17 | #include <linux/interrupt.h> | ||
18 | #include <linux/time.h> | ||
19 | #include <linux/timex.h> | ||
20 | #include <linux/kernel_stat.h> | ||
21 | #include <linux/mc146818rtc.h> | ||
22 | #include <linux/init.h> | ||
23 | #include <linux/bcd.h> | ||
24 | |||
25 | #include <asm/segment.h> | ||
26 | #include <asm/io.h> | ||
27 | #include <asm/nvram.h> | ||
28 | #include <asm/prom.h> | ||
29 | #include <asm/sections.h> | ||
30 | #include <asm/time.h> | ||
31 | |||
32 | extern spinlock_t rtc_lock; | ||
33 | |||
34 | static int nvram_as1 = NVRAM_AS1; | ||
35 | static int nvram_as0 = NVRAM_AS0; | ||
36 | static int nvram_data = NVRAM_DATA; | ||
37 | |||
38 | long __init chrp_time_init(void) | ||
39 | { | ||
40 | struct device_node *rtcs; | ||
41 | int base; | ||
42 | |||
43 | rtcs = find_compatible_devices("rtc", "pnpPNP,b00"); | ||
44 | if (rtcs == NULL) | ||
45 | rtcs = find_compatible_devices("rtc", "ds1385-rtc"); | ||
46 | if (rtcs == NULL || rtcs->addrs == NULL) | ||
47 | return 0; | ||
48 | base = rtcs->addrs[0].address; | ||
49 | nvram_as1 = 0; | ||
50 | nvram_as0 = base; | ||
51 | nvram_data = base + 1; | ||
52 | |||
53 | return 0; | ||
54 | } | ||
55 | |||
56 | int __chrp chrp_cmos_clock_read(int addr) | ||
57 | { | ||
58 | if (nvram_as1 != 0) | ||
59 | outb(addr>>8, nvram_as1); | ||
60 | outb(addr, nvram_as0); | ||
61 | return (inb(nvram_data)); | ||
62 | } | ||
63 | |||
64 | void __chrp chrp_cmos_clock_write(unsigned long val, int addr) | ||
65 | { | ||
66 | if (nvram_as1 != 0) | ||
67 | outb(addr>>8, nvram_as1); | ||
68 | outb(addr, nvram_as0); | ||
69 | outb(val, nvram_data); | ||
70 | return; | ||
71 | } | ||
72 | |||
73 | /* | ||
74 | * Set the hardware clock. -- Cort | ||
75 | */ | ||
76 | int __chrp chrp_set_rtc_time(unsigned long nowtime) | ||
77 | { | ||
78 | unsigned char save_control, save_freq_select; | ||
79 | struct rtc_time tm; | ||
80 | |||
81 | spin_lock(&rtc_lock); | ||
82 | to_tm(nowtime, &tm); | ||
83 | |||
84 | save_control = chrp_cmos_clock_read(RTC_CONTROL); /* tell the clock it's being set */ | ||
85 | |||
86 | chrp_cmos_clock_write((save_control|RTC_SET), RTC_CONTROL); | ||
87 | |||
88 | save_freq_select = chrp_cmos_clock_read(RTC_FREQ_SELECT); /* stop and reset prescaler */ | ||
89 | |||
90 | chrp_cmos_clock_write((save_freq_select|RTC_DIV_RESET2), RTC_FREQ_SELECT); | ||
91 | |||
92 | tm.tm_year -= 1900; | ||
93 | if (!(save_control & RTC_DM_BINARY) || RTC_ALWAYS_BCD) { | ||
94 | BIN_TO_BCD(tm.tm_sec); | ||
95 | BIN_TO_BCD(tm.tm_min); | ||
96 | BIN_TO_BCD(tm.tm_hour); | ||
97 | BIN_TO_BCD(tm.tm_mon); | ||
98 | BIN_TO_BCD(tm.tm_mday); | ||
99 | BIN_TO_BCD(tm.tm_year); | ||
100 | } | ||
101 | chrp_cmos_clock_write(tm.tm_sec,RTC_SECONDS); | ||
102 | chrp_cmos_clock_write(tm.tm_min,RTC_MINUTES); | ||
103 | chrp_cmos_clock_write(tm.tm_hour,RTC_HOURS); | ||
104 | chrp_cmos_clock_write(tm.tm_mon,RTC_MONTH); | ||
105 | chrp_cmos_clock_write(tm.tm_mday,RTC_DAY_OF_MONTH); | ||
106 | chrp_cmos_clock_write(tm.tm_year,RTC_YEAR); | ||
107 | |||
108 | /* The following flags have to be released exactly in this order, | ||
109 | * otherwise the DS12887 (popular MC146818A clone with integrated | ||
110 | * battery and quartz) will not reset the oscillator and will not | ||
111 | * update precisely 500 ms later. You won't find this mentioned in | ||
112 | * the Dallas Semiconductor data sheets, but who believes data | ||
113 | * sheets anyway ... -- Markus Kuhn | ||
114 | */ | ||
115 | chrp_cmos_clock_write(save_control, RTC_CONTROL); | ||
116 | chrp_cmos_clock_write(save_freq_select, RTC_FREQ_SELECT); | ||
117 | |||
118 | if ( (time_state == TIME_ERROR) || (time_state == TIME_BAD) ) | ||
119 | time_state = TIME_OK; | ||
120 | spin_unlock(&rtc_lock); | ||
121 | return 0; | ||
122 | } | ||
123 | |||
124 | unsigned long __chrp chrp_get_rtc_time(void) | ||
125 | { | ||
126 | unsigned int year, mon, day, hour, min, sec; | ||
127 | int uip, i; | ||
128 | |||
129 | /* The Linux interpretation of the CMOS clock register contents: | ||
130 | * When the Update-In-Progress (UIP) flag goes from 1 to 0, the | ||
131 | * RTC registers show the second which has precisely just started. | ||
132 | * Let's hope other operating systems interpret the RTC the same way. | ||
133 | */ | ||
134 | |||
135 | /* Since the UIP flag is set for about 2.2 ms and the clock | ||
136 | * is typically written with a precision of 1 jiffy, trying | ||
137 | * to obtain a precision better than a few milliseconds is | ||
138 | * an illusion. Only consistency is interesting, this also | ||
139 | * allows to use the routine for /dev/rtc without a potential | ||
140 | * 1 second kernel busy loop triggered by any reader of /dev/rtc. | ||
141 | */ | ||
142 | |||
143 | for ( i = 0; i<1000000; i++) { | ||
144 | uip = chrp_cmos_clock_read(RTC_FREQ_SELECT); | ||
145 | sec = chrp_cmos_clock_read(RTC_SECONDS); | ||
146 | min = chrp_cmos_clock_read(RTC_MINUTES); | ||
147 | hour = chrp_cmos_clock_read(RTC_HOURS); | ||
148 | day = chrp_cmos_clock_read(RTC_DAY_OF_MONTH); | ||
149 | mon = chrp_cmos_clock_read(RTC_MONTH); | ||
150 | year = chrp_cmos_clock_read(RTC_YEAR); | ||
151 | uip |= chrp_cmos_clock_read(RTC_FREQ_SELECT); | ||
152 | if ((uip & RTC_UIP)==0) break; | ||
153 | } | ||
154 | |||
155 | if (!(chrp_cmos_clock_read(RTC_CONTROL) & RTC_DM_BINARY) || RTC_ALWAYS_BCD) | ||
156 | { | ||
157 | BCD_TO_BIN(sec); | ||
158 | BCD_TO_BIN(min); | ||
159 | BCD_TO_BIN(hour); | ||
160 | BCD_TO_BIN(day); | ||
161 | BCD_TO_BIN(mon); | ||
162 | BCD_TO_BIN(year); | ||
163 | } | ||
164 | if ((year += 1900) < 1970) | ||
165 | year += 100; | ||
166 | return mktime(year, mon, day, hour, min, sec); | ||
167 | } | ||
168 | |||
169 | |||
170 | void __init chrp_calibrate_decr(void) | ||
171 | { | ||
172 | struct device_node *cpu; | ||
173 | unsigned int freq, *fp; | ||
174 | |||
175 | if (via_calibrate_decr()) | ||
176 | return; | ||
177 | |||
178 | /* | ||
179 | * The cpu node should have a timebase-frequency property | ||
180 | * to tell us the rate at which the decrementer counts. | ||
181 | */ | ||
182 | freq = 16666000; /* hardcoded default */ | ||
183 | cpu = find_type_devices("cpu"); | ||
184 | if (cpu != 0) { | ||
185 | fp = (unsigned int *) | ||
186 | get_property(cpu, "timebase-frequency", NULL); | ||
187 | if (fp != 0) | ||
188 | freq = *fp; | ||
189 | } | ||
190 | printk("time_init: decrementer frequency = %u.%.6u MHz\n", | ||
191 | freq/1000000, freq%1000000); | ||
192 | tb_ticks_per_jiffy = freq / HZ; | ||
193 | tb_to_us = mulhwu_scale_factor(freq, 1000000); | ||
194 | } | ||
diff --git a/arch/ppc/platforms/cpci690.c b/arch/ppc/platforms/cpci690.c new file mode 100644 index 000000000000..507870c9a97a --- /dev/null +++ b/arch/ppc/platforms/cpci690.c | |||
@@ -0,0 +1,491 @@ | |||
1 | /* | ||
2 | * arch/ppc/platforms/cpci690.c | ||
3 | * | ||
4 | * Board setup routines for the Force CPCI690 board. | ||
5 | * | ||
6 | * Author: Mark A. Greer <mgreer@mvista.com> | ||
7 | * | ||
8 | * 2003 (c) MontaVista Software, Inc. This file is licensed under | ||
9 | * the terms of the GNU General Public License version 2. This programr | ||
10 | * is licensed "as is" without any warranty of any kind, whether express | ||
11 | * or implied. | ||
12 | */ | ||
13 | #include <linux/config.h> | ||
14 | #include <linux/delay.h> | ||
15 | #include <linux/pci.h> | ||
16 | #include <linux/ide.h> | ||
17 | #include <linux/irq.h> | ||
18 | #include <linux/fs.h> | ||
19 | #include <linux/seq_file.h> | ||
20 | #include <linux/console.h> | ||
21 | #include <linux/initrd.h> | ||
22 | #include <linux/root_dev.h> | ||
23 | #include <linux/mv643xx.h> | ||
24 | #include <asm/bootinfo.h> | ||
25 | #include <asm/machdep.h> | ||
26 | #include <asm/todc.h> | ||
27 | #include <asm/time.h> | ||
28 | #include <asm/mv64x60.h> | ||
29 | #include <platforms/cpci690.h> | ||
30 | |||
31 | #define BOARD_VENDOR "Force" | ||
32 | #define BOARD_MACHINE "CPCI690" | ||
33 | |||
34 | /* Set IDE controllers into Native mode? */ | ||
35 | #define SET_PCI_IDE_NATIVE | ||
36 | |||
37 | static struct mv64x60_handle bh; | ||
38 | static u32 cpci690_br_base; | ||
39 | |||
40 | static const unsigned int cpu_7xx[16] = { /* 7xx & 74xx (but not 745x) */ | ||
41 | 18, 15, 14, 2, 4, 13, 5, 9, 6, 11, 8, 10, 16, 12, 7, 0 | ||
42 | }; | ||
43 | |||
44 | TODC_ALLOC(); | ||
45 | |||
46 | static int __init | ||
47 | cpci690_map_irq(struct pci_dev *dev, unsigned char idsel, unsigned char pin) | ||
48 | { | ||
49 | struct pci_controller *hose = pci_bus_to_hose(dev->bus->number); | ||
50 | |||
51 | if (hose->index == 0) { | ||
52 | static char pci_irq_table[][4] = | ||
53 | /* | ||
54 | * PCI IDSEL/INTPIN->INTLINE | ||
55 | * A B C D | ||
56 | */ | ||
57 | { | ||
58 | { 90, 91, 88, 89}, /* IDSEL 30/20 - Sentinel */ | ||
59 | }; | ||
60 | |||
61 | const long min_idsel = 20, max_idsel = 20, irqs_per_slot = 4; | ||
62 | return PCI_IRQ_TABLE_LOOKUP; | ||
63 | } else { | ||
64 | static char pci_irq_table[][4] = | ||
65 | /* | ||
66 | * PCI IDSEL/INTPIN->INTLINE | ||
67 | * A B C D | ||
68 | */ | ||
69 | { | ||
70 | { 93, 94, 95, 92}, /* IDSEL 28/18 - PMC slot 2 */ | ||
71 | { 0, 0, 0, 0}, /* IDSEL 29/19 - Not used */ | ||
72 | { 94, 95, 92, 93}, /* IDSEL 30/20 - PMC slot 1 */ | ||
73 | }; | ||
74 | |||
75 | const long min_idsel = 18, max_idsel = 20, irqs_per_slot = 4; | ||
76 | return PCI_IRQ_TABLE_LOOKUP; | ||
77 | } | ||
78 | } | ||
79 | |||
80 | static int | ||
81 | cpci690_get_cpu_speed(void) | ||
82 | { | ||
83 | unsigned long hid1; | ||
84 | |||
85 | hid1 = mfspr(SPRN_HID1) >> 28; | ||
86 | return CPCI690_BUS_FREQ * cpu_7xx[hid1]/2; | ||
87 | } | ||
88 | |||
89 | #define KB (1024UL) | ||
90 | #define MB (1024UL * KB) | ||
91 | #define GB (1024UL * MB) | ||
92 | |||
93 | unsigned long __init | ||
94 | cpci690_find_end_of_memory(void) | ||
95 | { | ||
96 | u32 mem_ctlr_size; | ||
97 | static u32 board_size; | ||
98 | static u8 first_time = 1; | ||
99 | |||
100 | if (first_time) { | ||
101 | /* Using cpci690_set_bat() mapping ==> virt addr == phys addr */ | ||
102 | switch (in_8((u8 *) (cpci690_br_base + | ||
103 | CPCI690_BR_MEM_CTLR)) & 0x07) { | ||
104 | case 0x01: | ||
105 | board_size = 256*MB; | ||
106 | break; | ||
107 | case 0x02: | ||
108 | board_size = 512*MB; | ||
109 | break; | ||
110 | case 0x03: | ||
111 | board_size = 768*MB; | ||
112 | break; | ||
113 | case 0x04: | ||
114 | board_size = 1*GB; | ||
115 | break; | ||
116 | case 0x05: | ||
117 | board_size = 1*GB + 512*MB; | ||
118 | break; | ||
119 | case 0x06: | ||
120 | board_size = 2*GB; | ||
121 | break; | ||
122 | default: | ||
123 | board_size = 0xffffffff; /* use mem ctlr size */ | ||
124 | } /* switch */ | ||
125 | |||
126 | mem_ctlr_size = mv64x60_get_mem_size(CONFIG_MV64X60_NEW_BASE, | ||
127 | MV64x60_TYPE_GT64260A); | ||
128 | |||
129 | /* Check that mem ctlr & board reg agree. If not, pick MIN. */ | ||
130 | if (board_size != mem_ctlr_size) { | ||
131 | printk(KERN_WARNING "Board register & memory controller" | ||
132 | "mem size disagree (board reg: 0x%lx, " | ||
133 | "mem ctlr: 0x%lx)\n", | ||
134 | (ulong)board_size, (ulong)mem_ctlr_size); | ||
135 | board_size = min(board_size, mem_ctlr_size); | ||
136 | } | ||
137 | |||
138 | first_time = 0; | ||
139 | } /* if */ | ||
140 | |||
141 | return board_size; | ||
142 | } | ||
143 | |||
144 | static void __init | ||
145 | cpci690_setup_bridge(void) | ||
146 | { | ||
147 | struct mv64x60_setup_info si; | ||
148 | int i; | ||
149 | |||
150 | memset(&si, 0, sizeof(si)); | ||
151 | |||
152 | si.phys_reg_base = CONFIG_MV64X60_NEW_BASE; | ||
153 | |||
154 | si.pci_0.enable_bus = 1; | ||
155 | si.pci_0.pci_io.cpu_base = CPCI690_PCI0_IO_START_PROC_ADDR; | ||
156 | si.pci_0.pci_io.pci_base_hi = 0; | ||
157 | si.pci_0.pci_io.pci_base_lo = CPCI690_PCI0_IO_START_PCI_ADDR; | ||
158 | si.pci_0.pci_io.size = CPCI690_PCI0_IO_SIZE; | ||
159 | si.pci_0.pci_io.swap = MV64x60_CPU2PCI_SWAP_NONE; | ||
160 | si.pci_0.pci_mem[0].cpu_base = CPCI690_PCI0_MEM_START_PROC_ADDR; | ||
161 | si.pci_0.pci_mem[0].pci_base_hi = CPCI690_PCI0_MEM_START_PCI_HI_ADDR; | ||
162 | si.pci_0.pci_mem[0].pci_base_lo = CPCI690_PCI0_MEM_START_PCI_LO_ADDR; | ||
163 | si.pci_0.pci_mem[0].size = CPCI690_PCI0_MEM_SIZE; | ||
164 | si.pci_0.pci_mem[0].swap = MV64x60_CPU2PCI_SWAP_NONE; | ||
165 | si.pci_0.pci_cmd_bits = 0; | ||
166 | si.pci_0.latency_timer = 0x80; | ||
167 | |||
168 | si.pci_1.enable_bus = 1; | ||
169 | si.pci_1.pci_io.cpu_base = CPCI690_PCI1_IO_START_PROC_ADDR; | ||
170 | si.pci_1.pci_io.pci_base_hi = 0; | ||
171 | si.pci_1.pci_io.pci_base_lo = CPCI690_PCI1_IO_START_PCI_ADDR; | ||
172 | si.pci_1.pci_io.size = CPCI690_PCI1_IO_SIZE; | ||
173 | si.pci_1.pci_io.swap = MV64x60_CPU2PCI_SWAP_NONE; | ||
174 | si.pci_1.pci_mem[0].cpu_base = CPCI690_PCI1_MEM_START_PROC_ADDR; | ||
175 | si.pci_1.pci_mem[0].pci_base_hi = CPCI690_PCI1_MEM_START_PCI_HI_ADDR; | ||
176 | si.pci_1.pci_mem[0].pci_base_lo = CPCI690_PCI1_MEM_START_PCI_LO_ADDR; | ||
177 | si.pci_1.pci_mem[0].size = CPCI690_PCI1_MEM_SIZE; | ||
178 | si.pci_1.pci_mem[0].swap = MV64x60_CPU2PCI_SWAP_NONE; | ||
179 | si.pci_1.pci_cmd_bits = 0; | ||
180 | si.pci_1.latency_timer = 0x80; | ||
181 | |||
182 | for (i=0; i<MV64x60_CPU2MEM_WINDOWS; i++) { | ||
183 | si.cpu_prot_options[i] = 0; | ||
184 | si.cpu_snoop_options[i] = GT64260_CPU_SNOOP_WB; | ||
185 | si.pci_0.acc_cntl_options[i] = | ||
186 | GT64260_PCI_ACC_CNTL_DREADEN | | ||
187 | GT64260_PCI_ACC_CNTL_RDPREFETCH | | ||
188 | GT64260_PCI_ACC_CNTL_RDLINEPREFETCH | | ||
189 | GT64260_PCI_ACC_CNTL_RDMULPREFETCH | | ||
190 | GT64260_PCI_ACC_CNTL_SWAP_NONE | | ||
191 | GT64260_PCI_ACC_CNTL_MBURST_32_BTYES; | ||
192 | si.pci_0.snoop_options[i] = GT64260_PCI_SNOOP_WB; | ||
193 | si.pci_1.acc_cntl_options[i] = | ||
194 | GT64260_PCI_ACC_CNTL_DREADEN | | ||
195 | GT64260_PCI_ACC_CNTL_RDPREFETCH | | ||
196 | GT64260_PCI_ACC_CNTL_RDLINEPREFETCH | | ||
197 | GT64260_PCI_ACC_CNTL_RDMULPREFETCH | | ||
198 | GT64260_PCI_ACC_CNTL_SWAP_NONE | | ||
199 | GT64260_PCI_ACC_CNTL_MBURST_32_BTYES; | ||
200 | si.pci_1.snoop_options[i] = GT64260_PCI_SNOOP_WB; | ||
201 | } | ||
202 | |||
203 | /* Lookup PCI host bridges */ | ||
204 | if (mv64x60_init(&bh, &si)) | ||
205 | printk(KERN_ERR "Bridge initialization failed.\n"); | ||
206 | |||
207 | pci_dram_offset = 0; /* System mem at same addr on PCI & cpu bus */ | ||
208 | ppc_md.pci_swizzle = common_swizzle; | ||
209 | ppc_md.pci_map_irq = cpci690_map_irq; | ||
210 | ppc_md.pci_exclude_device = mv64x60_pci_exclude_device; | ||
211 | |||
212 | mv64x60_set_bus(&bh, 0, 0); | ||
213 | bh.hose_a->first_busno = 0; | ||
214 | bh.hose_a->last_busno = 0xff; | ||
215 | bh.hose_a->last_busno = pciauto_bus_scan(bh.hose_a, 0); | ||
216 | |||
217 | bh.hose_b->first_busno = bh.hose_a->last_busno + 1; | ||
218 | mv64x60_set_bus(&bh, 1, bh.hose_b->first_busno); | ||
219 | bh.hose_b->last_busno = 0xff; | ||
220 | bh.hose_b->last_busno = pciauto_bus_scan(bh.hose_b, | ||
221 | bh.hose_b->first_busno); | ||
222 | } | ||
223 | |||
224 | static void __init | ||
225 | cpci690_setup_peripherals(void) | ||
226 | { | ||
227 | /* Set up windows to CPLD, RTC/TODC, IPMI. */ | ||
228 | mv64x60_set_32bit_window(&bh, MV64x60_CPU2DEV_0_WIN, CPCI690_BR_BASE, | ||
229 | CPCI690_BR_SIZE, 0); | ||
230 | bh.ci->enable_window_32bit(&bh, MV64x60_CPU2DEV_0_WIN); | ||
231 | cpci690_br_base = (u32)ioremap(CPCI690_BR_BASE, CPCI690_BR_SIZE); | ||
232 | |||
233 | mv64x60_set_32bit_window(&bh, MV64x60_CPU2DEV_1_WIN, CPCI690_TODC_BASE, | ||
234 | CPCI690_TODC_SIZE, 0); | ||
235 | bh.ci->enable_window_32bit(&bh, MV64x60_CPU2DEV_1_WIN); | ||
236 | TODC_INIT(TODC_TYPE_MK48T35, 0, 0, | ||
237 | ioremap(CPCI690_TODC_BASE, CPCI690_TODC_SIZE), 8); | ||
238 | |||
239 | mv64x60_set_32bit_window(&bh, MV64x60_CPU2DEV_2_WIN, CPCI690_IPMI_BASE, | ||
240 | CPCI690_IPMI_SIZE, 0); | ||
241 | bh.ci->enable_window_32bit(&bh, MV64x60_CPU2DEV_2_WIN); | ||
242 | |||
243 | mv64x60_set_bits(&bh, MV64x60_PCI0_ARBITER_CNTL, (1<<31)); | ||
244 | mv64x60_set_bits(&bh, MV64x60_PCI1_ARBITER_CNTL, (1<<31)); | ||
245 | |||
246 | mv64x60_set_bits(&bh, MV64x60_CPU_MASTER_CNTL, (1<<9)); /* Only 1 cpu */ | ||
247 | |||
248 | /* | ||
249 | * Turn off timer/counters. Not turning off watchdog timer because | ||
250 | * can't read its reg on the 64260A so don't know if we'll be enabling | ||
251 | * or disabling. | ||
252 | */ | ||
253 | mv64x60_clr_bits(&bh, MV64x60_TIMR_CNTR_0_3_CNTL, | ||
254 | ((1<<0) | (1<<8) | (1<<16) | (1<<24))); | ||
255 | mv64x60_clr_bits(&bh, GT64260_TIMR_CNTR_4_7_CNTL, | ||
256 | ((1<<0) | (1<<8) | (1<<16) | (1<<24))); | ||
257 | |||
258 | /* | ||
259 | * Set MPSC Multiplex RMII | ||
260 | * NOTE: ethernet driver modifies bit 0 and 1 | ||
261 | */ | ||
262 | mv64x60_write(&bh, GT64260_MPP_SERIAL_PORTS_MULTIPLEX, 0x00001102); | ||
263 | |||
264 | #define GPP_EXTERNAL_INTERRUPTS \ | ||
265 | ((1<<24) | (1<<25) | (1<<26) | (1<<27) | \ | ||
266 | (1<<28) | (1<<29) | (1<<30) | (1<<31)) | ||
267 | /* PCI interrupts are inputs */ | ||
268 | mv64x60_clr_bits(&bh, MV64x60_GPP_IO_CNTL, GPP_EXTERNAL_INTERRUPTS); | ||
269 | /* PCI interrupts are active low */ | ||
270 | mv64x60_set_bits(&bh, MV64x60_GPP_LEVEL_CNTL, GPP_EXTERNAL_INTERRUPTS); | ||
271 | |||
272 | /* Clear any pending interrupts for these inputs and enable them. */ | ||
273 | mv64x60_write(&bh, MV64x60_GPP_INTR_CAUSE, ~GPP_EXTERNAL_INTERRUPTS); | ||
274 | mv64x60_set_bits(&bh, MV64x60_GPP_INTR_MASK, GPP_EXTERNAL_INTERRUPTS); | ||
275 | |||
276 | /* Route MPP interrupt inputs to GPP */ | ||
277 | mv64x60_write(&bh, MV64x60_MPP_CNTL_2, 0x00000000); | ||
278 | mv64x60_write(&bh, MV64x60_MPP_CNTL_3, 0x00000000); | ||
279 | } | ||
280 | |||
281 | static void __init | ||
282 | cpci690_setup_arch(void) | ||
283 | { | ||
284 | if (ppc_md.progress) | ||
285 | ppc_md.progress("cpci690_setup_arch: enter", 0); | ||
286 | #ifdef CONFIG_BLK_DEV_INITRD | ||
287 | if (initrd_start) | ||
288 | ROOT_DEV = Root_RAM0; | ||
289 | else | ||
290 | #endif | ||
291 | #ifdef CONFIG_ROOT_NFS | ||
292 | ROOT_DEV = Root_NFS; | ||
293 | #else | ||
294 | ROOT_DEV = Root_SDA2; | ||
295 | #endif | ||
296 | |||
297 | if (ppc_md.progress) | ||
298 | ppc_md.progress("cpci690_setup_arch: Enabling L2 cache", 0); | ||
299 | |||
300 | /* Enable L2 and L3 caches (if 745x) */ | ||
301 | _set_L2CR(_get_L2CR() | L2CR_L2E); | ||
302 | _set_L3CR(_get_L3CR() | L3CR_L3E); | ||
303 | |||
304 | if (ppc_md.progress) | ||
305 | ppc_md.progress("cpci690_setup_arch: Initializing bridge", 0); | ||
306 | |||
307 | cpci690_setup_bridge(); /* set up PCI bridge(s) */ | ||
308 | cpci690_setup_peripherals(); /* set up chip selects/GPP/MPP etc */ | ||
309 | |||
310 | if (ppc_md.progress) | ||
311 | ppc_md.progress("cpci690_setup_arch: bridge init complete", 0); | ||
312 | |||
313 | printk(KERN_INFO "%s %s port (C) 2003 MontaVista Software, Inc. " | ||
314 | "(source@mvista.com)\n", BOARD_VENDOR, BOARD_MACHINE); | ||
315 | |||
316 | if (ppc_md.progress) | ||
317 | ppc_md.progress("cpci690_setup_arch: exit", 0); | ||
318 | } | ||
319 | |||
320 | /* Platform device data fixup routines. */ | ||
321 | #if defined(CONFIG_SERIAL_MPSC) | ||
322 | static void __init | ||
323 | cpci690_fixup_mpsc_pdata(struct platform_device *pdev) | ||
324 | { | ||
325 | struct mpsc_pdata *pdata; | ||
326 | |||
327 | pdata = (struct mpsc_pdata *)pdev->dev.platform_data; | ||
328 | |||
329 | pdata->max_idle = 40; | ||
330 | pdata->default_baud = CPCI690_MPSC_BAUD; | ||
331 | pdata->brg_clk_src = CPCI690_MPSC_CLK_SRC; | ||
332 | pdata->brg_clk_freq = CPCI690_BUS_FREQ; | ||
333 | } | ||
334 | |||
335 | static int __init | ||
336 | cpci690_platform_notify(struct device *dev) | ||
337 | { | ||
338 | static struct { | ||
339 | char *bus_id; | ||
340 | void ((*rtn)(struct platform_device *pdev)); | ||
341 | } dev_map[] = { | ||
342 | { MPSC_CTLR_NAME ".0", cpci690_fixup_mpsc_pdata }, | ||
343 | { MPSC_CTLR_NAME ".1", cpci690_fixup_mpsc_pdata }, | ||
344 | }; | ||
345 | struct platform_device *pdev; | ||
346 | int i; | ||
347 | |||
348 | if (dev && dev->bus_id) | ||
349 | for (i=0; i<ARRAY_SIZE(dev_map); i++) | ||
350 | if (!strncmp(dev->bus_id, dev_map[i].bus_id, | ||
351 | BUS_ID_SIZE)) { | ||
352 | |||
353 | pdev = container_of(dev, | ||
354 | struct platform_device, dev); | ||
355 | dev_map[i].rtn(pdev); | ||
356 | } | ||
357 | |||
358 | return 0; | ||
359 | } | ||
360 | #endif | ||
361 | |||
362 | static void | ||
363 | cpci690_reset_board(void) | ||
364 | { | ||
365 | u32 i = 10000; | ||
366 | |||
367 | local_irq_disable(); | ||
368 | out_8((u8 *)(cpci690_br_base + CPCI690_BR_SW_RESET), 0x11); | ||
369 | |||
370 | while (i != 0) i++; | ||
371 | panic("restart failed\n"); | ||
372 | } | ||
373 | |||
374 | static void | ||
375 | cpci690_restart(char *cmd) | ||
376 | { | ||
377 | cpci690_reset_board(); | ||
378 | } | ||
379 | |||
380 | static void | ||
381 | cpci690_halt(void) | ||
382 | { | ||
383 | while (1); | ||
384 | /* NOTREACHED */ | ||
385 | } | ||
386 | |||
387 | static void | ||
388 | cpci690_power_off(void) | ||
389 | { | ||
390 | cpci690_halt(); | ||
391 | /* NOTREACHED */ | ||
392 | } | ||
393 | |||
394 | static int | ||
395 | cpci690_show_cpuinfo(struct seq_file *m) | ||
396 | { | ||
397 | seq_printf(m, "vendor\t\t: " BOARD_VENDOR "\n"); | ||
398 | seq_printf(m, "machine\t\t: " BOARD_MACHINE "\n"); | ||
399 | seq_printf(m, "cpu MHz\t\t: %d\n", cpci690_get_cpu_speed()/1000/1000); | ||
400 | seq_printf(m, "bus MHz\t\t: %d\n", CPCI690_BUS_FREQ/1000/1000); | ||
401 | |||
402 | return 0; | ||
403 | } | ||
404 | |||
405 | static void __init | ||
406 | cpci690_calibrate_decr(void) | ||
407 | { | ||
408 | ulong freq; | ||
409 | |||
410 | freq = CPCI690_BUS_FREQ / 4; | ||
411 | |||
412 | printk(KERN_INFO "time_init: decrementer frequency = %lu.%.6lu MHz\n", | ||
413 | freq/1000000, freq%1000000); | ||
414 | |||
415 | tb_ticks_per_jiffy = freq / HZ; | ||
416 | tb_to_us = mulhwu_scale_factor(freq, 1000000); | ||
417 | } | ||
418 | |||
419 | static __inline__ void | ||
420 | cpci690_set_bat(u32 addr, u32 size) | ||
421 | { | ||
422 | addr &= 0xfffe0000; | ||
423 | size &= 0x1ffe0000; | ||
424 | size = ((size >> 17) - 1) << 2; | ||
425 | |||
426 | mb(); | ||
427 | mtspr(SPRN_DBAT1U, addr | size | 0x2); /* Vs == 1; Vp == 0 */ | ||
428 | mtspr(SPRN_DBAT1L, addr | 0x2a); /* WIMG bits == 0101; PP == r/w access */ | ||
429 | mb(); | ||
430 | } | ||
431 | |||
432 | #if defined(CONFIG_SERIAL_TEXT_DEBUG) || defined(CONFIG_KGDB) | ||
433 | static void __init | ||
434 | cpci690_map_io(void) | ||
435 | { | ||
436 | io_block_mapping(CONFIG_MV64X60_NEW_BASE, CONFIG_MV64X60_NEW_BASE, | ||
437 | 128 * KB, _PAGE_IO); | ||
438 | } | ||
439 | #endif | ||
440 | |||
441 | void __init | ||
442 | platform_init(unsigned long r3, unsigned long r4, unsigned long r5, | ||
443 | unsigned long r6, unsigned long r7) | ||
444 | { | ||
445 | #ifdef CONFIG_BLK_DEV_INITRD | ||
446 | initrd_start=initrd_end=0; | ||
447 | initrd_below_start_ok=0; | ||
448 | #endif /* CONFIG_BLK_DEV_INITRD */ | ||
449 | |||
450 | parse_bootinfo(find_bootinfo()); | ||
451 | |||
452 | loops_per_jiffy = cpci690_get_cpu_speed() / HZ; | ||
453 | |||
454 | isa_mem_base = 0; | ||
455 | |||
456 | ppc_md.setup_arch = cpci690_setup_arch; | ||
457 | ppc_md.show_cpuinfo = cpci690_show_cpuinfo; | ||
458 | ppc_md.init_IRQ = gt64260_init_irq; | ||
459 | ppc_md.get_irq = gt64260_get_irq; | ||
460 | ppc_md.restart = cpci690_restart; | ||
461 | ppc_md.power_off = cpci690_power_off; | ||
462 | ppc_md.halt = cpci690_halt; | ||
463 | ppc_md.find_end_of_memory = cpci690_find_end_of_memory; | ||
464 | ppc_md.time_init = todc_time_init; | ||
465 | ppc_md.set_rtc_time = todc_set_rtc_time; | ||
466 | ppc_md.get_rtc_time = todc_get_rtc_time; | ||
467 | ppc_md.nvram_read_val = todc_direct_read_val; | ||
468 | ppc_md.nvram_write_val = todc_direct_write_val; | ||
469 | ppc_md.calibrate_decr = cpci690_calibrate_decr; | ||
470 | |||
471 | /* | ||
472 | * Need to map in board regs (used by cpci690_find_end_of_memory()) | ||
473 | * and the bridge's regs (used by progress); | ||
474 | */ | ||
475 | cpci690_set_bat(CPCI690_BR_BASE, 32 * MB); | ||
476 | cpci690_br_base = CPCI690_BR_BASE; | ||
477 | |||
478 | #ifdef CONFIG_SERIAL_TEXT_DEBUG | ||
479 | ppc_md.setup_io_mappings = cpci690_map_io; | ||
480 | ppc_md.progress = mv64x60_mpsc_progress; | ||
481 | mv64x60_progress_init(CONFIG_MV64X60_NEW_BASE); | ||
482 | #endif /* CONFIG_SERIAL_TEXT_DEBUG */ | ||
483 | #ifdef CONFIG_KGDB | ||
484 | ppc_md.setup_io_mappings = cpci690_map_io; | ||
485 | ppc_md.early_serial_map = cpci690_early_serial_map; | ||
486 | #endif /* CONFIG_KGDB */ | ||
487 | |||
488 | #if defined(CONFIG_SERIAL_MPSC) | ||
489 | platform_notify = cpci690_platform_notify; | ||
490 | #endif | ||
491 | } | ||
diff --git a/arch/ppc/platforms/cpci690.h b/arch/ppc/platforms/cpci690.h new file mode 100644 index 000000000000..36cd2673c742 --- /dev/null +++ b/arch/ppc/platforms/cpci690.h | |||
@@ -0,0 +1,78 @@ | |||
1 | /* | ||
2 | * arch/ppc/platforms/cpci690.h | ||
3 | * | ||
4 | * Definitions for Force CPCI690 | ||
5 | * | ||
6 | * Author: Mark A. Greer <mgreer@mvista.com> | ||
7 | * | ||
8 | * 2003 (c) MontaVista, Software, Inc. This file is licensed under | ||
9 | * the terms of the GNU General Public License version 2. This program | ||
10 | * is licensed "as is" without any warranty of any kind, whether express | ||
11 | * or implied. | ||
12 | */ | ||
13 | |||
14 | /* | ||
15 | * The GT64260 has 2 PCI buses each with 1 window from the CPU bus to | ||
16 | * PCI I/O space and 4 windows from the CPU bus to PCI MEM space. | ||
17 | */ | ||
18 | |||
19 | #ifndef __PPC_PLATFORMS_CPCI690_H | ||
20 | #define __PPC_PLATFORMS_CPCI690_H | ||
21 | |||
22 | /* | ||
23 | * Define bd_t to pass in the MAC addresses used by the GT64260's enet ctlrs. | ||
24 | */ | ||
25 | #define CPCI690_BI_MAGIC 0xFE8765DC | ||
26 | |||
27 | typedef struct board_info { | ||
28 | u32 bi_magic; | ||
29 | u8 bi_enetaddr[3][6]; | ||
30 | } bd_t; | ||
31 | |||
32 | /* PCI bus Resource setup */ | ||
33 | #define CPCI690_PCI0_MEM_START_PROC_ADDR 0x80000000 | ||
34 | #define CPCI690_PCI0_MEM_START_PCI_HI_ADDR 0x00000000 | ||
35 | #define CPCI690_PCI0_MEM_START_PCI_LO_ADDR 0x80000000 | ||
36 | #define CPCI690_PCI0_MEM_SIZE 0x10000000 | ||
37 | #define CPCI690_PCI0_IO_START_PROC_ADDR 0xa0000000 | ||
38 | #define CPCI690_PCI0_IO_START_PCI_ADDR 0x00000000 | ||
39 | #define CPCI690_PCI0_IO_SIZE 0x01000000 | ||
40 | |||
41 | #define CPCI690_PCI1_MEM_START_PROC_ADDR 0x90000000 | ||
42 | #define CPCI690_PCI1_MEM_START_PCI_HI_ADDR 0x00000000 | ||
43 | #define CPCI690_PCI1_MEM_START_PCI_LO_ADDR 0x90000000 | ||
44 | #define CPCI690_PCI1_MEM_SIZE 0x10000000 | ||
45 | #define CPCI690_PCI1_IO_START_PROC_ADDR 0xa1000000 | ||
46 | #define CPCI690_PCI1_IO_START_PCI_ADDR 0x01000000 | ||
47 | #define CPCI690_PCI1_IO_SIZE 0x01000000 | ||
48 | |||
49 | /* Board Registers */ | ||
50 | #define CPCI690_BR_BASE 0xf0000000 | ||
51 | #define CPCI690_BR_SIZE_ACTUAL 0x8 | ||
52 | #define CPCI690_BR_SIZE max(GT64260_WINDOW_SIZE_MIN, \ | ||
53 | CPCI690_BR_SIZE_ACTUAL) | ||
54 | #define CPCI690_BR_LED_CNTL 0x00 | ||
55 | #define CPCI690_BR_SW_RESET 0x01 | ||
56 | #define CPCI690_BR_MISC_STATUS 0x02 | ||
57 | #define CPCI690_BR_SWITCH_STATUS 0x03 | ||
58 | #define CPCI690_BR_MEM_CTLR 0x04 | ||
59 | #define CPCI690_BR_LAST_RESET_1 0x05 | ||
60 | #define CPCI690_BR_LAST_RESET_2 0x06 | ||
61 | |||
62 | #define CPCI690_TODC_BASE 0xf0100000 | ||
63 | #define CPCI690_TODC_SIZE_ACTUAL 0x8000 /* Size or NVRAM + RTC */ | ||
64 | #define CPCI690_TODC_SIZE max(GT64260_WINDOW_SIZE_MIN, \ | ||
65 | CPCI690_TODC_SIZE_ACTUAL) | ||
66 | #define CPCI690_MAC_OFFSET 0x7c10 /* MAC in RTC NVRAM */ | ||
67 | |||
68 | #define CPCI690_IPMI_BASE 0xf0200000 | ||
69 | #define CPCI690_IPMI_SIZE_ACTUAL 0x10 /* 16 bytes of IPMI */ | ||
70 | #define CPCI690_IPMI_SIZE max(GT64260_WINDOW_SIZE_MIN, \ | ||
71 | CPCI690_IPMI_SIZE_ACTUAL) | ||
72 | |||
73 | #define CPCI690_MPSC_BAUD 9600 | ||
74 | #define CPCI690_MPSC_CLK_SRC 8 /* TCLK */ | ||
75 | |||
76 | #define CPCI690_BUS_FREQ 133333333 | ||
77 | |||
78 | #endif /* __PPC_PLATFORMS_CPCI690_H */ | ||
diff --git a/arch/ppc/platforms/est8260.h b/arch/ppc/platforms/est8260.h new file mode 100644 index 000000000000..adba68ecf57b --- /dev/null +++ b/arch/ppc/platforms/est8260.h | |||
@@ -0,0 +1,35 @@ | |||
1 | /* Board information for the EST8260, which should be generic for | ||
2 | * all 8260 boards. The IMMR is now given to us so the hard define | ||
3 | * will soon be removed. All of the clock values are computed from | ||
4 | * the configuration SCMR and the Power-On-Reset word. | ||
5 | */ | ||
6 | #ifndef __EST8260_PLATFORM | ||
7 | #define __EST8260_PLATFORM | ||
8 | |||
9 | #define CPM_MAP_ADDR ((uint)0xf0000000) | ||
10 | |||
11 | #define BOOTROM_RESTART_ADDR ((uint)0xff000104) | ||
12 | |||
13 | /* For our show_cpuinfo hooks. */ | ||
14 | #define CPUINFO_VENDOR "EST Corporation" | ||
15 | #define CPUINFO_MACHINE "SBC8260 PowerPC" | ||
16 | |||
17 | /* A Board Information structure that is given to a program when | ||
18 | * prom starts it up. | ||
19 | */ | ||
20 | typedef struct bd_info { | ||
21 | unsigned int bi_memstart; /* Memory start address */ | ||
22 | unsigned int bi_memsize; /* Memory (end) size in bytes */ | ||
23 | unsigned int bi_intfreq; /* Internal Freq, in Hz */ | ||
24 | unsigned int bi_busfreq; /* Bus Freq, in MHz */ | ||
25 | unsigned int bi_cpmfreq; /* CPM Freq, in MHz */ | ||
26 | unsigned int bi_brgfreq; /* BRG Freq, in MHz */ | ||
27 | unsigned int bi_vco; /* VCO Out from PLL */ | ||
28 | unsigned int bi_baudrate; /* Default console baud rate */ | ||
29 | unsigned int bi_immr; /* IMMR when called from boot rom */ | ||
30 | unsigned char bi_enetaddr[6]; | ||
31 | } bd_t; | ||
32 | |||
33 | extern bd_t m8xx_board_info; | ||
34 | |||
35 | #endif /* __EST8260_PLATFORM */ | ||
diff --git a/arch/ppc/platforms/ev64260.c b/arch/ppc/platforms/ev64260.c new file mode 100644 index 000000000000..aa50637a5cfb --- /dev/null +++ b/arch/ppc/platforms/ev64260.c | |||
@@ -0,0 +1,651 @@ | |||
1 | /* | ||
2 | * arch/ppc/platforms/ev64260.c | ||
3 | * | ||
4 | * Board setup routines for the Marvell/Galileo EV-64260-BP Evaluation Board. | ||
5 | * | ||
6 | * Author: Mark A. Greer <mgreer@mvista.com> | ||
7 | * | ||
8 | * 2001-2003 (c) MontaVista, Software, Inc. This file is licensed under | ||
9 | * the terms of the GNU General Public License version 2. This program | ||
10 | * is licensed "as is" without any warranty of any kind, whether express | ||
11 | * or implied. | ||
12 | */ | ||
13 | |||
14 | /* | ||
15 | * The EV-64260-BP port is the result of hard work from many people from | ||
16 | * many companies. In particular, employees of Marvell/Galileo, Mission | ||
17 | * Critical Linux, Xyterra, and MontaVista Software were heavily involved. | ||
18 | * | ||
19 | * Note: I have not been able to get *all* PCI slots to work reliably | ||
20 | * at 66 MHz. I recommend setting jumpers J15 & J16 to short pins 1&2 | ||
21 | * so that 33 MHz is used. --MAG | ||
22 | * Note: The 750CXe and 7450 are not stable with a 125MHz or 133MHz TCLK/SYSCLK. | ||
23 | * At 100MHz, they are solid. | ||
24 | */ | ||
25 | #include <linux/config.h> | ||
26 | |||
27 | #include <linux/delay.h> | ||
28 | #include <linux/pci.h> | ||
29 | #include <linux/ide.h> | ||
30 | #include <linux/irq.h> | ||
31 | #include <linux/fs.h> | ||
32 | #include <linux/seq_file.h> | ||
33 | #include <linux/console.h> | ||
34 | #include <linux/initrd.h> | ||
35 | #include <linux/root_dev.h> | ||
36 | #if !defined(CONFIG_SERIAL_MPSC_CONSOLE) | ||
37 | #include <linux/serial.h> | ||
38 | #include <linux/tty.h> | ||
39 | #include <linux/serial_core.h> | ||
40 | #else | ||
41 | #include <linux/mv643xx.h> | ||
42 | #endif | ||
43 | #include <asm/bootinfo.h> | ||
44 | #include <asm/machdep.h> | ||
45 | #include <asm/mv64x60.h> | ||
46 | #include <asm/todc.h> | ||
47 | #include <asm/time.h> | ||
48 | |||
49 | #include <platforms/ev64260.h> | ||
50 | |||
51 | #define BOARD_VENDOR "Marvell/Galileo" | ||
52 | #define BOARD_MACHINE "EV-64260-BP" | ||
53 | |||
54 | static struct mv64x60_handle bh; | ||
55 | |||
56 | #if !defined(CONFIG_SERIAL_MPSC_CONSOLE) | ||
57 | extern void gen550_progress(char *, unsigned short); | ||
58 | extern void gen550_init(int, struct uart_port *); | ||
59 | #endif | ||
60 | |||
61 | static const unsigned int cpu_7xx[16] = { /* 7xx & 74xx (but not 745x) */ | ||
62 | 18, 15, 14, 2, 4, 13, 5, 9, 6, 11, 8, 10, 16, 12, 7, 0 | ||
63 | }; | ||
64 | static const unsigned int cpu_745x[2][16] = { /* PLL_EXT 0 & 1 */ | ||
65 | { 1, 15, 14, 2, 4, 13, 5, 9, 6, 11, 8, 10, 16, 12, 7, 0 }, | ||
66 | { 0, 30, 0, 2, 0, 26, 0, 18, 0, 22, 20, 24, 28, 32, 0, 0 } | ||
67 | }; | ||
68 | |||
69 | |||
70 | TODC_ALLOC(); | ||
71 | |||
72 | static int | ||
73 | ev64260_get_bus_speed(void) | ||
74 | { | ||
75 | return 100000000; | ||
76 | } | ||
77 | |||
78 | static int | ||
79 | ev64260_get_cpu_speed(void) | ||
80 | { | ||
81 | unsigned long pvr, hid1, pll_ext; | ||
82 | |||
83 | pvr = PVR_VER(mfspr(SPRN_PVR)); | ||
84 | |||
85 | if (pvr != PVR_VER(PVR_7450)) { | ||
86 | hid1 = mfspr(SPRN_HID1) >> 28; | ||
87 | return ev64260_get_bus_speed() * cpu_7xx[hid1]/2; | ||
88 | } | ||
89 | else { | ||
90 | hid1 = (mfspr(SPRN_HID1) & 0x0001e000) >> 13; | ||
91 | pll_ext = 0; /* No way to read; must get from schematic */ | ||
92 | return ev64260_get_bus_speed() * cpu_745x[pll_ext][hid1]/2; | ||
93 | } | ||
94 | } | ||
95 | |||
96 | unsigned long __init | ||
97 | ev64260_find_end_of_memory(void) | ||
98 | { | ||
99 | return mv64x60_get_mem_size(CONFIG_MV64X60_NEW_BASE, | ||
100 | MV64x60_TYPE_GT64260A); | ||
101 | } | ||
102 | |||
103 | /* | ||
104 | * Marvell/Galileo EV-64260-BP Evaluation Board PCI interrupt routing. | ||
105 | * Note: By playing with J8 and JP1-4, you can get 2 IRQ's from the first | ||
106 | * PCI bus (in which cast, INTPIN B would be EV64260_PCI_1_IRQ). | ||
107 | * This is the most IRQs you can get from one bus with this board, though. | ||
108 | */ | ||
109 | static int __init | ||
110 | ev64260_map_irq(struct pci_dev *dev, unsigned char idsel, unsigned char pin) | ||
111 | { | ||
112 | struct pci_controller *hose = pci_bus_to_hose(dev->bus->number); | ||
113 | |||
114 | if (hose->index == 0) { | ||
115 | static char pci_irq_table[][4] = | ||
116 | /* | ||
117 | * PCI IDSEL/INTPIN->INTLINE | ||
118 | * A B C D | ||
119 | */ | ||
120 | { | ||
121 | {EV64260_PCI_0_IRQ,0,0,0}, /* IDSEL 7 - PCI bus 0 */ | ||
122 | {EV64260_PCI_0_IRQ,0,0,0}, /* IDSEL 8 - PCI bus 0 */ | ||
123 | }; | ||
124 | |||
125 | const long min_idsel = 7, max_idsel = 8, irqs_per_slot = 4; | ||
126 | return PCI_IRQ_TABLE_LOOKUP; | ||
127 | } | ||
128 | else { | ||
129 | static char pci_irq_table[][4] = | ||
130 | /* | ||
131 | * PCI IDSEL/INTPIN->INTLINE | ||
132 | * A B C D | ||
133 | */ | ||
134 | { | ||
135 | { EV64260_PCI_1_IRQ,0,0,0}, /* IDSEL 7 - PCI bus 1 */ | ||
136 | { EV64260_PCI_1_IRQ,0,0,0}, /* IDSEL 8 - PCI bus 1 */ | ||
137 | }; | ||
138 | |||
139 | const long min_idsel = 7, max_idsel = 8, irqs_per_slot = 4; | ||
140 | return PCI_IRQ_TABLE_LOOKUP; | ||
141 | } | ||
142 | } | ||
143 | |||
144 | static void __init | ||
145 | ev64260_setup_peripherals(void) | ||
146 | { | ||
147 | mv64x60_set_32bit_window(&bh, MV64x60_CPU2BOOT_WIN, | ||
148 | EV64260_EMB_FLASH_BASE, EV64260_EMB_FLASH_SIZE, 0); | ||
149 | bh.ci->enable_window_32bit(&bh, MV64x60_CPU2BOOT_WIN); | ||
150 | mv64x60_set_32bit_window(&bh, MV64x60_CPU2DEV_0_WIN, | ||
151 | EV64260_EXT_SRAM_BASE, EV64260_EXT_SRAM_SIZE, 0); | ||
152 | bh.ci->enable_window_32bit(&bh, MV64x60_CPU2DEV_0_WIN); | ||
153 | mv64x60_set_32bit_window(&bh, MV64x60_CPU2DEV_1_WIN, | ||
154 | EV64260_TODC_BASE, EV64260_TODC_SIZE, 0); | ||
155 | bh.ci->enable_window_32bit(&bh, MV64x60_CPU2DEV_1_WIN); | ||
156 | mv64x60_set_32bit_window(&bh, MV64x60_CPU2DEV_2_WIN, | ||
157 | EV64260_UART_BASE, EV64260_UART_SIZE, 0); | ||
158 | bh.ci->enable_window_32bit(&bh, MV64x60_CPU2DEV_2_WIN); | ||
159 | mv64x60_set_32bit_window(&bh, MV64x60_CPU2DEV_3_WIN, | ||
160 | EV64260_EXT_FLASH_BASE, EV64260_EXT_FLASH_SIZE, 0); | ||
161 | bh.ci->enable_window_32bit(&bh, MV64x60_CPU2DEV_3_WIN); | ||
162 | |||
163 | TODC_INIT(TODC_TYPE_DS1501, 0, 0, | ||
164 | ioremap(EV64260_TODC_BASE, EV64260_TODC_SIZE), 8); | ||
165 | |||
166 | mv64x60_clr_bits(&bh, MV64x60_CPU_CONFIG,((1<<12) | (1<<28) | (1<<29))); | ||
167 | mv64x60_set_bits(&bh, MV64x60_CPU_CONFIG, (1<<27)); | ||
168 | |||
169 | if (ev64260_get_bus_speed() > 100000000) | ||
170 | mv64x60_set_bits(&bh, MV64x60_CPU_CONFIG, (1<<23)); | ||
171 | |||
172 | mv64x60_set_bits(&bh, MV64x60_PCI0_PCI_DECODE_CNTL, ((1<<0) | (1<<3))); | ||
173 | mv64x60_set_bits(&bh, MV64x60_PCI1_PCI_DECODE_CNTL, ((1<<0) | (1<<3))); | ||
174 | |||
175 | /* | ||
176 | * Enabling of PCI internal-vs-external arbitration | ||
177 | * is a platform- and errata-dependent decision. | ||
178 | */ | ||
179 | if (bh.type == MV64x60_TYPE_GT64260A ) { | ||
180 | mv64x60_set_bits(&bh, MV64x60_PCI0_ARBITER_CNTL, (1<<31)); | ||
181 | mv64x60_set_bits(&bh, MV64x60_PCI1_ARBITER_CNTL, (1<<31)); | ||
182 | } | ||
183 | |||
184 | mv64x60_set_bits(&bh, MV64x60_CPU_MASTER_CNTL, (1<<9)); /* Only 1 cpu */ | ||
185 | |||
186 | /* | ||
187 | * Turn off timer/counters. Not turning off watchdog timer because | ||
188 | * can't read its reg on the 64260A so don't know if we'll be enabling | ||
189 | * or disabling. | ||
190 | */ | ||
191 | mv64x60_clr_bits(&bh, MV64x60_TIMR_CNTR_0_3_CNTL, | ||
192 | ((1<<0) | (1<<8) | (1<<16) | (1<<24))); | ||
193 | mv64x60_clr_bits(&bh, GT64260_TIMR_CNTR_4_7_CNTL, | ||
194 | ((1<<0) | (1<<8) | (1<<16) | (1<<24))); | ||
195 | |||
196 | /* | ||
197 | * Set MPSC Multiplex RMII | ||
198 | * NOTE: ethernet driver modifies bit 0 and 1 | ||
199 | */ | ||
200 | mv64x60_write(&bh, GT64260_MPP_SERIAL_PORTS_MULTIPLEX, 0x00001102); | ||
201 | |||
202 | /* | ||
203 | * The EV-64260-BP uses several Multi-Purpose Pins (MPP) on the 64260 | ||
204 | * bridge as interrupt inputs (via the General Purpose Ports (GPP) | ||
205 | * register). Need to route the MPP inputs to the GPP and set the | ||
206 | * polarity correctly. | ||
207 | * | ||
208 | * In MPP Control 2 Register | ||
209 | * MPP 21 -> GPP 21 (DUART channel A intr) bits 20-23 -> 0 | ||
210 | * MPP 22 -> GPP 22 (DUART channel B intr) bits 24-27 -> 0 | ||
211 | */ | ||
212 | mv64x60_clr_bits(&bh, MV64x60_MPP_CNTL_2, (0xf<<20) | (0xf<<24) ); | ||
213 | |||
214 | /* | ||
215 | * In MPP Control 3 Register | ||
216 | * MPP 26 -> GPP 26 (RTC INT) bits 8-11 -> 0 | ||
217 | * MPP 27 -> GPP 27 (PCI 0 INTA) bits 12-15 -> 0 | ||
218 | * MPP 29 -> GPP 29 (PCI 1 INTA) bits 20-23 -> 0 | ||
219 | */ | ||
220 | mv64x60_clr_bits(&bh, MV64x60_MPP_CNTL_3, (0xf<<8)|(0xf<<12)|(0xf<<20)); | ||
221 | |||
222 | #define GPP_EXTERNAL_INTERRUPTS \ | ||
223 | ((1<<21) | (1<<22) | (1<<26) | (1<<27) | (1<<29)) | ||
224 | /* DUART & PCI interrupts are inputs */ | ||
225 | mv64x60_clr_bits(&bh, MV64x60_GPP_IO_CNTL, GPP_EXTERNAL_INTERRUPTS); | ||
226 | /* DUART & PCI interrupts are active low */ | ||
227 | mv64x60_set_bits(&bh, MV64x60_GPP_LEVEL_CNTL, GPP_EXTERNAL_INTERRUPTS); | ||
228 | |||
229 | /* Clear any pending interrupts for these inputs and enable them. */ | ||
230 | mv64x60_write(&bh, MV64x60_GPP_INTR_CAUSE, ~GPP_EXTERNAL_INTERRUPTS); | ||
231 | mv64x60_set_bits(&bh, MV64x60_GPP_INTR_MASK, GPP_EXTERNAL_INTERRUPTS); | ||
232 | |||
233 | return; | ||
234 | } | ||
235 | |||
236 | static void __init | ||
237 | ev64260_setup_bridge(void) | ||
238 | { | ||
239 | struct mv64x60_setup_info si; | ||
240 | int i; | ||
241 | |||
242 | memset(&si, 0, sizeof(si)); | ||
243 | |||
244 | si.phys_reg_base = CONFIG_MV64X60_NEW_BASE; | ||
245 | |||
246 | si.pci_0.enable_bus = 1; | ||
247 | si.pci_0.pci_io.cpu_base = EV64260_PCI0_IO_CPU_BASE; | ||
248 | si.pci_0.pci_io.pci_base_hi = 0; | ||
249 | si.pci_0.pci_io.pci_base_lo = EV64260_PCI0_IO_PCI_BASE; | ||
250 | si.pci_0.pci_io.size = EV64260_PCI0_IO_SIZE; | ||
251 | si.pci_0.pci_io.swap = MV64x60_CPU2PCI_SWAP_NONE; | ||
252 | si.pci_0.pci_mem[0].cpu_base = EV64260_PCI0_MEM_CPU_BASE; | ||
253 | si.pci_0.pci_mem[0].pci_base_hi = 0; | ||
254 | si.pci_0.pci_mem[0].pci_base_lo = EV64260_PCI0_MEM_PCI_BASE; | ||
255 | si.pci_0.pci_mem[0].size = EV64260_PCI0_MEM_SIZE; | ||
256 | si.pci_0.pci_mem[0].swap = MV64x60_CPU2PCI_SWAP_NONE; | ||
257 | si.pci_0.pci_cmd_bits = 0; | ||
258 | si.pci_0.latency_timer = 0x8; | ||
259 | |||
260 | si.pci_1.enable_bus = 1; | ||
261 | si.pci_1.pci_io.cpu_base = EV64260_PCI1_IO_CPU_BASE; | ||
262 | si.pci_1.pci_io.pci_base_hi = 0; | ||
263 | si.pci_1.pci_io.pci_base_lo = EV64260_PCI1_IO_PCI_BASE; | ||
264 | si.pci_1.pci_io.size = EV64260_PCI1_IO_SIZE; | ||
265 | si.pci_1.pci_io.swap = MV64x60_CPU2PCI_SWAP_NONE; | ||
266 | si.pci_1.pci_mem[0].cpu_base = EV64260_PCI1_MEM_CPU_BASE; | ||
267 | si.pci_1.pci_mem[0].pci_base_hi = 0; | ||
268 | si.pci_1.pci_mem[0].pci_base_lo = EV64260_PCI1_MEM_PCI_BASE; | ||
269 | si.pci_1.pci_mem[0].size = EV64260_PCI1_MEM_SIZE; | ||
270 | si.pci_1.pci_mem[0].swap = MV64x60_CPU2PCI_SWAP_NONE; | ||
271 | si.pci_1.pci_cmd_bits = 0; | ||
272 | si.pci_1.latency_timer = 0x8; | ||
273 | |||
274 | for (i=0; i<MV64x60_CPU2MEM_WINDOWS; i++) { | ||
275 | si.cpu_prot_options[i] = 0; | ||
276 | si.cpu_snoop_options[i] = GT64260_CPU_SNOOP_WB; | ||
277 | si.pci_0.acc_cntl_options[i] = | ||
278 | GT64260_PCI_ACC_CNTL_DREADEN | | ||
279 | GT64260_PCI_ACC_CNTL_RDPREFETCH | | ||
280 | GT64260_PCI_ACC_CNTL_RDLINEPREFETCH | | ||
281 | GT64260_PCI_ACC_CNTL_RDMULPREFETCH | | ||
282 | GT64260_PCI_ACC_CNTL_SWAP_NONE | | ||
283 | GT64260_PCI_ACC_CNTL_MBURST_32_BTYES; | ||
284 | si.pci_0.snoop_options[i] = GT64260_PCI_SNOOP_WB; | ||
285 | si.pci_1.acc_cntl_options[i] = | ||
286 | GT64260_PCI_ACC_CNTL_DREADEN | | ||
287 | GT64260_PCI_ACC_CNTL_RDPREFETCH | | ||
288 | GT64260_PCI_ACC_CNTL_RDLINEPREFETCH | | ||
289 | GT64260_PCI_ACC_CNTL_RDMULPREFETCH | | ||
290 | GT64260_PCI_ACC_CNTL_SWAP_NONE | | ||
291 | GT64260_PCI_ACC_CNTL_MBURST_32_BTYES; | ||
292 | si.pci_1.snoop_options[i] = GT64260_PCI_SNOOP_WB; | ||
293 | } | ||
294 | |||
295 | /* Lookup PCI host bridges */ | ||
296 | if (mv64x60_init(&bh, &si)) | ||
297 | printk(KERN_ERR "Bridge initialization failed.\n"); | ||
298 | |||
299 | pci_dram_offset = 0; /* System mem at same addr on PCI & cpu bus */ | ||
300 | ppc_md.pci_swizzle = common_swizzle; | ||
301 | ppc_md.pci_map_irq = ev64260_map_irq; | ||
302 | ppc_md.pci_exclude_device = mv64x60_pci_exclude_device; | ||
303 | |||
304 | mv64x60_set_bus(&bh, 0, 0); | ||
305 | bh.hose_a->first_busno = 0; | ||
306 | bh.hose_a->last_busno = 0xff; | ||
307 | bh.hose_a->last_busno = pciauto_bus_scan(bh.hose_a, 0); | ||
308 | |||
309 | bh.hose_b->first_busno = bh.hose_a->last_busno + 1; | ||
310 | mv64x60_set_bus(&bh, 1, bh.hose_b->first_busno); | ||
311 | bh.hose_b->last_busno = 0xff; | ||
312 | bh.hose_b->last_busno = pciauto_bus_scan(bh.hose_b, | ||
313 | bh.hose_b->first_busno); | ||
314 | |||
315 | return; | ||
316 | } | ||
317 | |||
318 | #if defined(CONFIG_SERIAL_8250) && !defined(CONFIG_SERIAL_MPSC_CONSOLE) | ||
319 | static void __init | ||
320 | ev64260_early_serial_map(void) | ||
321 | { | ||
322 | struct uart_port port; | ||
323 | static char first_time = 1; | ||
324 | |||
325 | if (first_time) { | ||
326 | memset(&port, 0, sizeof(port)); | ||
327 | |||
328 | port.membase = ioremap(EV64260_SERIAL_0, EV64260_UART_SIZE); | ||
329 | port.irq = EV64260_UART_0_IRQ; | ||
330 | port.uartclk = BASE_BAUD * 16; | ||
331 | port.regshift = 2; | ||
332 | port.iotype = SERIAL_IO_MEM; | ||
333 | port.flags = STD_COM_FLAGS; | ||
334 | |||
335 | #if defined(CONFIG_SERIAL_TEXT_DEBUG) || defined(CONFIG_KGDB) | ||
336 | gen550_init(0, &port); | ||
337 | #endif | ||
338 | |||
339 | if (early_serial_setup(&port) != 0) | ||
340 | printk(KERN_WARNING "Early serial init of port 0" | ||
341 | "failed\n"); | ||
342 | |||
343 | first_time = 0; | ||
344 | } | ||
345 | |||
346 | return; | ||
347 | } | ||
348 | #elif defined(CONFIG_SERIAL_MPSC_CONSOLE) | ||
349 | static void __init | ||
350 | ev64260_early_serial_map(void) | ||
351 | { | ||
352 | } | ||
353 | #endif | ||
354 | |||
355 | static void __init | ||
356 | ev64260_setup_arch(void) | ||
357 | { | ||
358 | if (ppc_md.progress) | ||
359 | ppc_md.progress("ev64260_setup_arch: enter", 0); | ||
360 | |||
361 | #ifdef CONFIG_BLK_DEV_INITRD | ||
362 | if (initrd_start) | ||
363 | ROOT_DEV = Root_RAM0; | ||
364 | else | ||
365 | #endif | ||
366 | #ifdef CONFIG_ROOT_NFS | ||
367 | ROOT_DEV = Root_NFS; | ||
368 | #else | ||
369 | ROOT_DEV = Root_SDA2; | ||
370 | #endif | ||
371 | |||
372 | if (ppc_md.progress) | ||
373 | ppc_md.progress("ev64260_setup_arch: Enabling L2 cache", 0); | ||
374 | |||
375 | /* Enable L2 and L3 caches (if 745x) */ | ||
376 | _set_L2CR(_get_L2CR() | L2CR_L2E); | ||
377 | _set_L3CR(_get_L3CR() | L3CR_L3E); | ||
378 | |||
379 | if (ppc_md.progress) | ||
380 | ppc_md.progress("ev64260_setup_arch: Initializing bridge", 0); | ||
381 | |||
382 | ev64260_setup_bridge(); /* set up PCI bridge(s) */ | ||
383 | ev64260_setup_peripherals(); /* set up chip selects/GPP/MPP etc */ | ||
384 | |||
385 | if (ppc_md.progress) | ||
386 | ppc_md.progress("ev64260_setup_arch: bridge init complete", 0); | ||
387 | |||
388 | #if defined(CONFIG_SERIAL_8250) || defined(CONFIG_SERIAL_MPSC_CONSOLE) | ||
389 | ev64260_early_serial_map(); | ||
390 | #endif | ||
391 | |||
392 | printk(KERN_INFO "%s %s port (C) 2001 MontaVista Software, Inc." | ||
393 | "(source@mvista.com)\n", BOARD_VENDOR, BOARD_MACHINE); | ||
394 | |||
395 | if (ppc_md.progress) | ||
396 | ppc_md.progress("ev64260_setup_arch: exit", 0); | ||
397 | |||
398 | return; | ||
399 | } | ||
400 | |||
401 | /* Platform device data fixup routines. */ | ||
402 | #if defined(CONFIG_SERIAL_MPSC) | ||
403 | static void __init | ||
404 | ev64260_fixup_mpsc_pdata(struct platform_device *pdev) | ||
405 | { | ||
406 | struct mpsc_pdata *pdata; | ||
407 | |||
408 | pdata = (struct mpsc_pdata *)pdev->dev.platform_data; | ||
409 | |||
410 | pdata->max_idle = 40; | ||
411 | pdata->default_baud = EV64260_DEFAULT_BAUD; | ||
412 | pdata->brg_clk_src = EV64260_MPSC_CLK_SRC; | ||
413 | pdata->brg_clk_freq = EV64260_MPSC_CLK_FREQ; | ||
414 | |||
415 | return; | ||
416 | } | ||
417 | |||
418 | static int __init | ||
419 | ev64260_platform_notify(struct device *dev) | ||
420 | { | ||
421 | static struct { | ||
422 | char *bus_id; | ||
423 | void ((*rtn)(struct platform_device *pdev)); | ||
424 | } dev_map[] = { | ||
425 | { MPSC_CTLR_NAME ".0", ev64260_fixup_mpsc_pdata }, | ||
426 | { MPSC_CTLR_NAME ".1", ev64260_fixup_mpsc_pdata }, | ||
427 | }; | ||
428 | struct platform_device *pdev; | ||
429 | int i; | ||
430 | |||
431 | if (dev && dev->bus_id) | ||
432 | for (i=0; i<ARRAY_SIZE(dev_map); i++) | ||
433 | if (!strncmp(dev->bus_id, dev_map[i].bus_id, | ||
434 | BUS_ID_SIZE)) { | ||
435 | |||
436 | pdev = container_of(dev, | ||
437 | struct platform_device, dev); | ||
438 | dev_map[i].rtn(pdev); | ||
439 | } | ||
440 | |||
441 | return 0; | ||
442 | } | ||
443 | #endif | ||
444 | |||
445 | static void | ||
446 | ev64260_reset_board(void *addr) | ||
447 | { | ||
448 | local_irq_disable(); | ||
449 | |||
450 | /* disable and invalidate the L2 cache */ | ||
451 | _set_L2CR(0); | ||
452 | _set_L2CR(0x200000); | ||
453 | |||
454 | /* flush and disable L1 I/D cache */ | ||
455 | __asm__ __volatile__ | ||
456 | ("mfspr 3,1008\n\t" | ||
457 | "ori 5,5,0xcc00\n\t" | ||
458 | "ori 4,3,0xc00\n\t" | ||
459 | "andc 5,3,5\n\t" | ||
460 | "sync\n\t" | ||
461 | "mtspr 1008,4\n\t" | ||
462 | "isync\n\t" | ||
463 | "sync\n\t" | ||
464 | "mtspr 1008,5\n\t" | ||
465 | "isync\n\t" | ||
466 | "sync\n\t"); | ||
467 | |||
468 | /* unmap any other random cs's that might overlap with bootcs */ | ||
469 | mv64x60_set_32bit_window(&bh, MV64x60_CPU2DEV_0_WIN, 0, 0, 0); | ||
470 | bh.ci->disable_window_32bit(&bh, MV64x60_CPU2DEV_0_WIN); | ||
471 | mv64x60_set_32bit_window(&bh, MV64x60_CPU2DEV_1_WIN, 0, 0, 0); | ||
472 | bh.ci->disable_window_32bit(&bh, MV64x60_CPU2DEV_1_WIN); | ||
473 | mv64x60_set_32bit_window(&bh, MV64x60_CPU2DEV_2_WIN, 0, 0, 0); | ||
474 | bh.ci->disable_window_32bit(&bh, MV64x60_CPU2DEV_2_WIN); | ||
475 | mv64x60_set_32bit_window(&bh, MV64x60_CPU2DEV_3_WIN, 0, 0, 0); | ||
476 | bh.ci->disable_window_32bit(&bh, MV64x60_CPU2DEV_3_WIN); | ||
477 | |||
478 | /* map bootrom back in to gt @ reset defaults */ | ||
479 | mv64x60_set_32bit_window(&bh, MV64x60_CPU2BOOT_WIN, | ||
480 | 0xff800000, 8*1024*1024, 0); | ||
481 | bh.ci->enable_window_32bit(&bh, MV64x60_CPU2BOOT_WIN); | ||
482 | |||
483 | /* move reg base back to default, setup default pci0 */ | ||
484 | mv64x60_write(&bh, MV64x60_INTERNAL_SPACE_DECODE, | ||
485 | (1<<24) | CONFIG_MV64X60_BASE >> 20); | ||
486 | |||
487 | /* NOTE: FROM NOW ON no more GT_REGS accesses.. 0x1 is not mapped | ||
488 | * via BAT or MMU, and MSR IR/DR is ON */ | ||
489 | /* SRR0 has system reset vector, SRR1 has default MSR value */ | ||
490 | /* rfi restores MSR from SRR1 and sets the PC to the SRR0 value */ | ||
491 | /* NOTE: assumes reset vector is at 0xfff00100 */ | ||
492 | __asm__ __volatile__ | ||
493 | ("mtspr 26, %0\n\t" | ||
494 | "li 4,(1<<6)\n\t" | ||
495 | "mtspr 27,4\n\t" | ||
496 | "rfi\n\t" | ||
497 | :: "r" (addr):"r4"); | ||
498 | |||
499 | return; | ||
500 | } | ||
501 | |||
502 | static void | ||
503 | ev64260_restart(char *cmd) | ||
504 | { | ||
505 | volatile ulong i = 10000000; | ||
506 | |||
507 | ev64260_reset_board((void *)0xfff00100); | ||
508 | |||
509 | while (i-- > 0); | ||
510 | panic("restart failed\n"); | ||
511 | } | ||
512 | |||
513 | static void | ||
514 | ev64260_halt(void) | ||
515 | { | ||
516 | local_irq_disable(); | ||
517 | while (1); | ||
518 | /* NOTREACHED */ | ||
519 | } | ||
520 | |||
521 | static void | ||
522 | ev64260_power_off(void) | ||
523 | { | ||
524 | ev64260_halt(); | ||
525 | /* NOTREACHED */ | ||
526 | } | ||
527 | |||
528 | static int | ||
529 | ev64260_show_cpuinfo(struct seq_file *m) | ||
530 | { | ||
531 | uint pvid; | ||
532 | |||
533 | pvid = mfspr(SPRN_PVR); | ||
534 | seq_printf(m, "vendor\t\t: " BOARD_VENDOR "\n"); | ||
535 | seq_printf(m, "machine\t\t: " BOARD_MACHINE "\n"); | ||
536 | seq_printf(m, "cpu MHz\t\t: %d\n", ev64260_get_cpu_speed()/1000/1000); | ||
537 | seq_printf(m, "bus MHz\t\t: %d\n", ev64260_get_bus_speed()/1000/1000); | ||
538 | |||
539 | return 0; | ||
540 | } | ||
541 | |||
542 | /* DS1501 RTC has too much variation to use RTC for calibration */ | ||
543 | static void __init | ||
544 | ev64260_calibrate_decr(void) | ||
545 | { | ||
546 | ulong freq; | ||
547 | |||
548 | freq = ev64260_get_bus_speed()/4; | ||
549 | |||
550 | printk(KERN_INFO "time_init: decrementer frequency = %lu.%.6lu MHz\n", | ||
551 | freq/1000000, freq%1000000); | ||
552 | |||
553 | tb_ticks_per_jiffy = freq / HZ; | ||
554 | tb_to_us = mulhwu_scale_factor(freq, 1000000); | ||
555 | |||
556 | return; | ||
557 | } | ||
558 | |||
559 | /* | ||
560 | * Set BAT 3 to map 0xfb000000 to 0xfc000000 of physical memory space. | ||
561 | */ | ||
562 | static __inline__ void | ||
563 | ev64260_set_bat(void) | ||
564 | { | ||
565 | mb(); | ||
566 | mtspr(SPRN_DBAT1U, 0xfb0001fe); | ||
567 | mtspr(SPRN_DBAT1L, 0xfb00002a); | ||
568 | mb(); | ||
569 | |||
570 | return; | ||
571 | } | ||
572 | |||
573 | #if defined(CONFIG_SERIAL_TEXT_DEBUG) || defined(CONFIG_KGDB) | ||
574 | static void __init | ||
575 | ev64260_map_io(void) | ||
576 | { | ||
577 | io_block_mapping(0xfb000000, 0xfb000000, 0x01000000, _PAGE_IO); | ||
578 | } | ||
579 | #endif | ||
580 | |||
581 | void __init | ||
582 | platform_init(unsigned long r3, unsigned long r4, unsigned long r5, | ||
583 | unsigned long r6, unsigned long r7) | ||
584 | { | ||
585 | #ifdef CONFIG_BLK_DEV_INITRD | ||
586 | extern int initrd_below_start_ok; | ||
587 | |||
588 | initrd_start=initrd_end=0; | ||
589 | initrd_below_start_ok=0; | ||
590 | #endif /* CONFIG_BLK_DEV_INITRD */ | ||
591 | |||
592 | parse_bootinfo(find_bootinfo()); | ||
593 | |||
594 | isa_mem_base = 0; | ||
595 | isa_io_base = EV64260_PCI0_IO_CPU_BASE; | ||
596 | pci_dram_offset = EV64260_PCI0_MEM_CPU_BASE; | ||
597 | |||
598 | loops_per_jiffy = ev64260_get_cpu_speed() / HZ; | ||
599 | |||
600 | ppc_md.setup_arch = ev64260_setup_arch; | ||
601 | ppc_md.show_cpuinfo = ev64260_show_cpuinfo; | ||
602 | ppc_md.init_IRQ = gt64260_init_irq; | ||
603 | ppc_md.get_irq = gt64260_get_irq; | ||
604 | |||
605 | ppc_md.restart = ev64260_restart; | ||
606 | ppc_md.power_off = ev64260_power_off; | ||
607 | ppc_md.halt = ev64260_halt; | ||
608 | |||
609 | ppc_md.find_end_of_memory = ev64260_find_end_of_memory; | ||
610 | |||
611 | ppc_md.init = NULL; | ||
612 | |||
613 | ppc_md.time_init = todc_time_init; | ||
614 | ppc_md.set_rtc_time = todc_set_rtc_time; | ||
615 | ppc_md.get_rtc_time = todc_get_rtc_time; | ||
616 | ppc_md.nvram_read_val = todc_direct_read_val; | ||
617 | ppc_md.nvram_write_val = todc_direct_write_val; | ||
618 | ppc_md.calibrate_decr = ev64260_calibrate_decr; | ||
619 | |||
620 | bh.p_base = CONFIG_MV64X60_NEW_BASE; | ||
621 | |||
622 | ev64260_set_bat(); | ||
623 | |||
624 | #ifdef CONFIG_SERIAL_8250 | ||
625 | #if defined(CONFIG_SERIAL_TEXT_DEBUG) | ||
626 | ppc_md.setup_io_mappings = ev64260_map_io; | ||
627 | ppc_md.progress = gen550_progress; | ||
628 | #endif | ||
629 | #if defined(CONFIG_KGDB) | ||
630 | ppc_md.setup_io_mappings = ev64260_map_io; | ||
631 | ppc_md.early_serial_map = ev64260_early_serial_map; | ||
632 | #endif | ||
633 | #elif defined(CONFIG_SERIAL_MPSC_CONSOLE) | ||
634 | #ifdef CONFIG_SERIAL_TEXT_DEBUG | ||
635 | ppc_md.setup_io_mappings = ev64260_map_io; | ||
636 | ppc_md.progress = mv64x60_mpsc_progress; | ||
637 | mv64x60_progress_init(CONFIG_MV64X60_NEW_BASE); | ||
638 | #endif /* CONFIG_SERIAL_TEXT_DEBUG */ | ||
639 | #ifdef CONFIG_KGDB | ||
640 | ppc_md.setup_io_mappings = ev64260_map_io; | ||
641 | ppc_md.early_serial_map = ev64260_early_serial_map; | ||
642 | #endif /* CONFIG_KGDB */ | ||
643 | |||
644 | #endif | ||
645 | |||
646 | #if defined(CONFIG_SERIAL_MPSC) | ||
647 | platform_notify = ev64260_platform_notify; | ||
648 | #endif | ||
649 | |||
650 | return; | ||
651 | } | ||
diff --git a/arch/ppc/platforms/ev64260.h b/arch/ppc/platforms/ev64260.h new file mode 100644 index 000000000000..bedffced3a02 --- /dev/null +++ b/arch/ppc/platforms/ev64260.h | |||
@@ -0,0 +1,128 @@ | |||
1 | /* | ||
2 | * arch/ppc/platforms/ev64260.h | ||
3 | * | ||
4 | * Definitions for Marvell/Galileo EV-64260-BP Evaluation Board. | ||
5 | * | ||
6 | * Author: Mark A. Greer <mgreer@mvista.com> | ||
7 | * | ||
8 | * 2001-2002 (c) MontaVista, Software, Inc. This file is licensed under | ||
9 | * the terms of the GNU General Public License version 2. This program | ||
10 | * is licensed "as is" without any warranty of any kind, whether express | ||
11 | * or implied. | ||
12 | */ | ||
13 | |||
14 | /* | ||
15 | * The MV64x60 has 2 PCI buses each with 1 window from the CPU bus to | ||
16 | * PCI I/O space and 4 windows from the CPU bus to PCI MEM space. | ||
17 | * We'll only use one PCI MEM window on each PCI bus. | ||
18 | * | ||
19 | * This is the CPU physical memory map (windows must be at least 1MB and start | ||
20 | * on a boundary that is a multiple of the window size): | ||
21 | * | ||
22 | * 0xfc000000-0xffffffff - External FLASH on device module | ||
23 | * 0xfbf00000-0xfbffffff - Embedded (on board) FLASH | ||
24 | * 0xfbe00000-0xfbefffff - GT64260 Registers (preferably) | ||
25 | * but really a config option | ||
26 | * 0xfbd00000-0xfbdfffff - External SRAM on device module | ||
27 | * 0xfbc00000-0xfbcfffff - TODC chip on device module | ||
28 | * 0xfbb00000-0xfbbfffff - External UART on device module | ||
29 | * 0xa2000000-0xfbafffff - <hole> | ||
30 | * 0xa1000000-0xa1ffffff - PCI 1 I/O (defined in gt64260.h) | ||
31 | * 0xa0000000-0xa0ffffff - PCI 0 I/O (defined in gt64260.h) | ||
32 | * 0x90000000-0x9fffffff - PCI 1 MEM (defined in gt64260.h) | ||
33 | * 0x80000000-0x8fffffff - PCI 0 MEM (defined in gt64260.h) | ||
34 | */ | ||
35 | |||
36 | #ifndef __PPC_PLATFORMS_EV64260_H | ||
37 | #define __PPC_PLATFORMS_EV64260_H | ||
38 | |||
39 | /* PCI mappings */ | ||
40 | #define EV64260_PCI0_IO_CPU_BASE 0xa0000000 | ||
41 | #define EV64260_PCI0_IO_PCI_BASE 0x00000000 | ||
42 | #define EV64260_PCI0_IO_SIZE 0x01000000 | ||
43 | |||
44 | #define EV64260_PCI0_MEM_CPU_BASE 0x80000000 | ||
45 | #define EV64260_PCI0_MEM_PCI_BASE 0x80000000 | ||
46 | #define EV64260_PCI0_MEM_SIZE 0x10000000 | ||
47 | |||
48 | #define EV64260_PCI1_IO_CPU_BASE (EV64260_PCI0_IO_CPU_BASE + \ | ||
49 | EV64260_PCI0_IO_SIZE) | ||
50 | #define EV64260_PCI1_IO_PCI_BASE (EV64260_PCI0_IO_PCI_BASE + \ | ||
51 | EV64260_PCI0_IO_SIZE) | ||
52 | #define EV64260_PCI1_IO_SIZE 0x01000000 | ||
53 | |||
54 | #define EV64260_PCI1_MEM_CPU_BASE (EV64260_PCI0_MEM_CPU_BASE + \ | ||
55 | EV64260_PCI0_MEM_SIZE) | ||
56 | #define EV64260_PCI1_MEM_PCI_BASE (EV64260_PCI0_MEM_PCI_BASE + \ | ||
57 | EV64260_PCI0_MEM_SIZE) | ||
58 | #define EV64260_PCI1_MEM_SIZE 0x10000000 | ||
59 | |||
60 | /* CPU Physical Memory Map setup (other than PCI) */ | ||
61 | #define EV64260_EXT_FLASH_BASE 0xfc000000 | ||
62 | #define EV64260_EMB_FLASH_BASE 0xfbf00000 | ||
63 | #define EV64260_EXT_SRAM_BASE 0xfbd00000 | ||
64 | #define EV64260_TODC_BASE 0xfbc00000 | ||
65 | #define EV64260_UART_BASE 0xfbb00000 | ||
66 | |||
67 | #define EV64260_EXT_FLASH_SIZE_ACTUAL 0x04000000 /* <= 64MB Extern FLASH */ | ||
68 | #define EV64260_EMB_FLASH_SIZE_ACTUAL 0x00080000 /* 512KB of Embed FLASH */ | ||
69 | #define EV64260_EXT_SRAM_SIZE_ACTUAL 0x00100000 /* 1MB SDRAM */ | ||
70 | #define EV64260_TODC_SIZE_ACTUAL 0x00000020 /* 32 bytes for TODC */ | ||
71 | #define EV64260_UART_SIZE_ACTUAL 0x00000040 /* 64 bytes for DUART */ | ||
72 | |||
73 | #define EV64260_EXT_FLASH_SIZE max(GT64260_WINDOW_SIZE_MIN, \ | ||
74 | EV64260_EXT_FLASH_SIZE_ACTUAL) | ||
75 | #define EV64260_EMB_FLASH_SIZE max(GT64260_WINDOW_SIZE_MIN, \ | ||
76 | EV64260_EMB_FLASH_SIZE_ACTUAL) | ||
77 | #define EV64260_EXT_SRAM_SIZE max(GT64260_WINDOW_SIZE_MIN, \ | ||
78 | EV64260_EXT_SRAM_SIZE_ACTUAL) | ||
79 | #define EV64260_TODC_SIZE max(GT64260_WINDOW_SIZE_MIN, \ | ||
80 | EV64260_TODC_SIZE_ACTUAL) | ||
81 | /* Assembler in bootwrapper blows up if 'max' is used */ | ||
82 | #define EV64260_UART_SIZE GT64260_WINDOW_SIZE_MIN | ||
83 | #define EV64260_UART_END ((EV64260_UART_BASE + \ | ||
84 | EV64260_UART_SIZE - 1) & 0xfff00000) | ||
85 | |||
86 | /* Board-specific IRQ info */ | ||
87 | #define EV64260_UART_0_IRQ 85 | ||
88 | #define EV64260_UART_1_IRQ 86 | ||
89 | #define EV64260_PCI_0_IRQ 91 | ||
90 | #define EV64260_PCI_1_IRQ 93 | ||
91 | |||
92 | /* Serial port setup */ | ||
93 | #define EV64260_DEFAULT_BAUD 115200 | ||
94 | |||
95 | #if defined(CONFIG_SERIAL_MPSC_CONSOLE) | ||
96 | #define SERIAL_PORT_DFNS | ||
97 | |||
98 | #define EV64260_MPSC_CLK_SRC 8 /* TCLK */ | ||
99 | #define EV64260_MPSC_CLK_FREQ 100000000 /* 100MHz clk */ | ||
100 | #else | ||
101 | #define EV64260_SERIAL_0 (EV64260_UART_BASE + 0x20) | ||
102 | #define EV64260_SERIAL_1 EV64260_UART_BASE | ||
103 | |||
104 | #define BASE_BAUD (EV64260_DEFAULT_BAUD * 2) | ||
105 | |||
106 | #ifdef CONFIG_SERIAL_MANY_PORTS | ||
107 | #define RS_TABLE_SIZE 64 | ||
108 | #else | ||
109 | #define RS_TABLE_SIZE 2 | ||
110 | #endif | ||
111 | |||
112 | #ifdef CONFIG_SERIAL_DETECT_IRQ | ||
113 | #define STD_COM_FLAGS (ASYNC_BOOT_AUTOCONF|ASYNC_SKIP_TEST|ASYNC_AUTO_IRQ) | ||
114 | #else | ||
115 | #define STD_COM_FLAGS (ASYNC_BOOT_AUTOCONF|ASYNC_SKIP_TEST) | ||
116 | #endif | ||
117 | |||
118 | /* Required for bootloader's ns16550.c code */ | ||
119 | #define STD_SERIAL_PORT_DFNS \ | ||
120 | { 0, BASE_BAUD, EV64260_SERIAL_0, EV64260_UART_0_IRQ, STD_COM_FLAGS, \ | ||
121 | iomem_base: (u8 *)EV64260_SERIAL_0, /* ttyS0 */ \ | ||
122 | iomem_reg_shift: 2, \ | ||
123 | io_type: SERIAL_IO_MEM }, | ||
124 | |||
125 | #define SERIAL_PORT_DFNS \ | ||
126 | STD_SERIAL_PORT_DFNS | ||
127 | #endif | ||
128 | #endif /* __PPC_PLATFORMS_EV64260_H */ | ||
diff --git a/arch/ppc/platforms/fads.h b/arch/ppc/platforms/fads.h new file mode 100644 index 000000000000..632b8178ce66 --- /dev/null +++ b/arch/ppc/platforms/fads.h | |||
@@ -0,0 +1,57 @@ | |||
1 | /* | ||
2 | * A collection of structures, addresses, and values associated with | ||
3 | * the Motorola 860T FADS board. Copied from the MBX stuff. | ||
4 | * | ||
5 | * Copyright (c) 1998 Dan Malek (dmalek@jlc.net) | ||
6 | */ | ||
7 | #ifdef __KERNEL__ | ||
8 | #ifndef __ASM_FADS_H__ | ||
9 | #define __ASM_FADS_H__ | ||
10 | |||
11 | #include <linux/config.h> | ||
12 | |||
13 | #include <asm/ppcboot.h> | ||
14 | |||
15 | /* Memory map is configured by the PROM startup. | ||
16 | * I tried to follow the FADS manual, although the startup PROM | ||
17 | * dictates this and we simply have to move some of the physical | ||
18 | * addresses for Linux. | ||
19 | */ | ||
20 | #define BCSR_ADDR ((uint)0xff010000) | ||
21 | #define BCSR_SIZE ((uint)(64 * 1024)) | ||
22 | #define BCSR0 ((uint)0xff010000) | ||
23 | #define BCSR1 ((uint)0xff010004) | ||
24 | #define BCSR2 ((uint)0xff010008) | ||
25 | #define BCSR3 ((uint)0xff01000c) | ||
26 | #define BCSR4 ((uint)0xff010010) | ||
27 | |||
28 | #define IMAP_ADDR ((uint)0xff000000) | ||
29 | #define IMAP_SIZE ((uint)(64 * 1024)) | ||
30 | |||
31 | #define PCMCIA_MEM_ADDR ((uint)0xff020000) | ||
32 | #define PCMCIA_MEM_SIZE ((uint)(64 * 1024)) | ||
33 | |||
34 | /* Bits of interest in the BCSRs. | ||
35 | */ | ||
36 | #define BCSR1_ETHEN ((uint)0x20000000) | ||
37 | #define BCSR1_RS232EN_1 ((uint)0x01000000) | ||
38 | #define BCSR1_RS232EN_2 ((uint)0x00040000) | ||
39 | #define BCSR4_ETHLOOP ((uint)0x80000000) /* EEST Loopback */ | ||
40 | #define BCSR4_EEFDX ((uint)0x40000000) /* EEST FDX enable */ | ||
41 | #define BCSR4_FETH_EN ((uint)0x08000000) /* PHY enable */ | ||
42 | #define BCSR4_FETHCFG0 ((uint)0x04000000) /* PHY autoneg mode */ | ||
43 | #define BCSR4_FETHCFG1 ((uint)0x00400000) /* PHY autoneg mode */ | ||
44 | #define BCSR4_FETHFDE ((uint)0x02000000) /* PHY FDX advertise */ | ||
45 | #define BCSR4_FETHRST ((uint)0x00200000) /* PHY Reset */ | ||
46 | |||
47 | /* Interrupt level assignments. | ||
48 | */ | ||
49 | #define FEC_INTERRUPT SIU_LEVEL1 /* FEC interrupt */ | ||
50 | #define PHY_INTERRUPT SIU_IRQ2 /* PHY link change interrupt */ | ||
51 | |||
52 | /* We don't use the 8259. | ||
53 | */ | ||
54 | #define NR_8259_INTS 0 | ||
55 | |||
56 | #endif /* __ASM_FADS_H__ */ | ||
57 | #endif /* __KERNEL__ */ | ||
diff --git a/arch/ppc/platforms/gemini.h b/arch/ppc/platforms/gemini.h new file mode 100644 index 000000000000..06de59248918 --- /dev/null +++ b/arch/ppc/platforms/gemini.h | |||
@@ -0,0 +1,168 @@ | |||
1 | /* | ||
2 | * arch/ppc/platforms/gemini.h | ||
3 | * | ||
4 | * | ||
5 | * Onboard registers and descriptions for Synergy Microsystems' | ||
6 | * "Gemini" boards. | ||
7 | * | ||
8 | */ | ||
9 | #ifdef __KERNEL__ | ||
10 | #ifndef __PPC_GEMINI_H | ||
11 | #define __PPC_GEMINI_H | ||
12 | |||
13 | /* Registers */ | ||
14 | |||
15 | #define GEMINI_SERIAL_B (0xffeffb00) | ||
16 | #define GEMINI_SERIAL_A (0xffeffb08) | ||
17 | #define GEMINI_USWITCH (0xffeffd00) | ||
18 | #define GEMINI_BREV (0xffeffe00) | ||
19 | #define GEMINI_BECO (0xffeffe08) | ||
20 | #define GEMINI_FEAT (0xffeffe10) | ||
21 | #define GEMINI_BSTAT (0xffeffe18) | ||
22 | #define GEMINI_CPUSTAT (0xffeffe20) | ||
23 | #define GEMINI_L2CFG (0xffeffe30) | ||
24 | #define GEMINI_MEMCFG (0xffeffe38) | ||
25 | #define GEMINI_FLROM (0xffeffe40) | ||
26 | #define GEMINI_P0PCI (0xffeffe48) | ||
27 | #define GEMINI_FLWIN (0xffeffe50) | ||
28 | #define GEMINI_P0INTMASK (0xffeffe60) | ||
29 | #define GEMINI_P0INTAP (0xffeffe68) | ||
30 | #define GEMINI_PCIERR (0xffeffe70) | ||
31 | #define GEMINI_LEDBASE (0xffeffe80) | ||
32 | #define GEMINI_RTC (0xffe9fff8) | ||
33 | #define GEMINI_LEDS 8 | ||
34 | #define GEMINI_SWITCHES 8 | ||
35 | |||
36 | |||
37 | /* Flash ROM bit definitions */ | ||
38 | #define GEMINI_FLS_WEN (1<<0) | ||
39 | #define GEMINI_FLS_JMP (1<<6) | ||
40 | #define GEMINI_FLS_BOOT (1<<7) | ||
41 | |||
42 | /* Memory bit definitions */ | ||
43 | #define GEMINI_MEM_TYPE_MASK 0xc0 | ||
44 | #define GEMINI_MEM_SIZE_MASK 0x38 | ||
45 | #define GEMINI_MEM_BANK_MASK 0x07 | ||
46 | |||
47 | /* L2 cache bit definitions */ | ||
48 | #define GEMINI_L2_SIZE_MASK 0xc0 | ||
49 | #define GEMINI_L2_RATIO_MASK 0x03 | ||
50 | |||
51 | /* Timebase register bit definitons */ | ||
52 | #define GEMINI_TIMEB0_EN (1<<0) | ||
53 | #define GEMINI_TIMEB1_EN (1<<1) | ||
54 | #define GEMINI_TIMEB2_EN (1<<2) | ||
55 | #define GEMINI_TIMEB3_EN (1<<3) | ||
56 | |||
57 | /* CPU status bit definitions */ | ||
58 | #define GEMINI_CPU_ID_MASK 0x03 | ||
59 | #define GEMINI_CPU_COUNT_MASK 0x0c | ||
60 | #define GEMINI_CPU0_HALTED (1<<4) | ||
61 | #define GEMINI_CPU1_HALTED (1<<5) | ||
62 | #define GEMINI_CPU2_HALTED (1<<6) | ||
63 | #define GEMINI_CPU3_HALTED (1<<7) | ||
64 | |||
65 | /* Board status bit definitions */ | ||
66 | #define GEMINI_BRD_FAIL (1<<0) /* FAIL led is lit */ | ||
67 | #define GEMINI_BRD_BUS_MASK 0x0c /* PowerPC bus speed */ | ||
68 | |||
69 | /* Board family/feature bit descriptions */ | ||
70 | #define GEMINI_FEAT_HAS_FLASH (1<<0) | ||
71 | #define GEMINI_FEAT_HAS_ETH (1<<1) | ||
72 | #define GEMINI_FEAT_HAS_SCSI (1<<2) | ||
73 | #define GEMINI_FEAT_HAS_P0 (1<<3) | ||
74 | #define GEMINI_FEAT_FAM_MASK 0xf0 | ||
75 | |||
76 | /* Mod/ECO bit definitions */ | ||
77 | #define GEMINI_ECO_LEVEL_MASK 0x0f | ||
78 | #define GEMINI_MOD_MASK 0xf0 | ||
79 | |||
80 | /* Type/revision bit definitions */ | ||
81 | #define GEMINI_REV_MASK 0x0f | ||
82 | #define GEMINI_TYPE_MASK 0xf0 | ||
83 | |||
84 | /* User switch definitions */ | ||
85 | #define GEMINI_SWITCH_VERBOSE 1 /* adds "debug" to boot cmd line */ | ||
86 | #define GEMINI_SWITCH_SINGLE_USER 7 /* boots into "single-user" mode */ | ||
87 | |||
88 | #define SGS_RTC_CONTROL 0 | ||
89 | #define SGS_RTC_SECONDS 1 | ||
90 | #define SGS_RTC_MINUTES 2 | ||
91 | #define SGS_RTC_HOURS 3 | ||
92 | #define SGS_RTC_DAY 4 | ||
93 | #define SGS_RTC_DAY_OF_MONTH 5 | ||
94 | #define SGS_RTC_MONTH 6 | ||
95 | #define SGS_RTC_YEAR 7 | ||
96 | |||
97 | #define SGS_RTC_SET 0x80 | ||
98 | #define SGS_RTC_IS_STOPPED 0x80 | ||
99 | |||
100 | #define GRACKLE_CONFIG_ADDR_ADDR (0xfec00000) | ||
101 | #define GRACKLE_CONFIG_DATA_ADDR (0xfee00000) | ||
102 | |||
103 | #define GEMINI_BOOT_INIT (0xfff00100) | ||
104 | |||
105 | #ifndef __ASSEMBLY__ | ||
106 | |||
107 | static inline void grackle_write( unsigned long addr, unsigned long data ) | ||
108 | { | ||
109 | __asm__ __volatile__( | ||
110 | " stwbrx %1, 0, %0\n \ | ||
111 | sync\n \ | ||
112 | stwbrx %3, 0, %2\n \ | ||
113 | sync " | ||
114 | : /* no output */ | ||
115 | : "r" (GRACKLE_CONFIG_ADDR_ADDR), "r" (addr), | ||
116 | "r" (GRACKLE_CONFIG_DATA_ADDR), "r" (data)); | ||
117 | } | ||
118 | |||
119 | static inline unsigned long grackle_read( unsigned long addr ) | ||
120 | { | ||
121 | unsigned long val; | ||
122 | |||
123 | __asm__ __volatile__( | ||
124 | " stwbrx %1, 0, %2\n \ | ||
125 | sync\n \ | ||
126 | lwbrx %0, 0, %3\n \ | ||
127 | sync " | ||
128 | : "=r" (val) | ||
129 | : "r" (addr), "r" (GRACKLE_CONFIG_ADDR_ADDR), | ||
130 | "r" (GRACKLE_CONFIG_DATA_ADDR)); | ||
131 | |||
132 | return val; | ||
133 | } | ||
134 | |||
135 | static inline void gemini_led_on( int led ) | ||
136 | { | ||
137 | if (led >= 0 && led < GEMINI_LEDS) | ||
138 | *(unsigned char *)(GEMINI_LEDBASE + (led<<3)) = 1; | ||
139 | } | ||
140 | |||
141 | static inline void gemini_led_off(int led) | ||
142 | { | ||
143 | if (led >= 0 && led < GEMINI_LEDS) | ||
144 | *(unsigned char *)(GEMINI_LEDBASE + (led<<3)) = 0; | ||
145 | } | ||
146 | |||
147 | static inline int gemini_led_val(int led) | ||
148 | { | ||
149 | int val = 0; | ||
150 | if (led >= 0 && led < GEMINI_LEDS) | ||
151 | val = *(unsigned char *)(GEMINI_LEDBASE + (led<<3)); | ||
152 | return (val & 0x1); | ||
153 | } | ||
154 | |||
155 | /* returns processor id from the board */ | ||
156 | static inline int gemini_processor(void) | ||
157 | { | ||
158 | unsigned char cpu = *(unsigned char *)(GEMINI_CPUSTAT); | ||
159 | return (int) ((cpu == 0) ? 4 : (cpu & GEMINI_CPU_ID_MASK)); | ||
160 | } | ||
161 | |||
162 | |||
163 | extern void _gemini_reboot(void); | ||
164 | extern void gemini_prom_init(void); | ||
165 | extern void gemini_init_l2(void); | ||
166 | #endif /* __ASSEMBLY__ */ | ||
167 | #endif | ||
168 | #endif /* __KERNEL__ */ | ||
diff --git a/arch/ppc/platforms/gemini_pci.c b/arch/ppc/platforms/gemini_pci.c new file mode 100644 index 000000000000..95656091ba2b --- /dev/null +++ b/arch/ppc/platforms/gemini_pci.c | |||
@@ -0,0 +1,41 @@ | |||
1 | #include <linux/kernel.h> | ||
2 | #include <linux/init.h> | ||
3 | #include <linux/pci.h> | ||
4 | #include <linux/slab.h> | ||
5 | |||
6 | #include <asm/machdep.h> | ||
7 | #include <platforms/gemini.h> | ||
8 | #include <asm/byteorder.h> | ||
9 | #include <asm/io.h> | ||
10 | #include <asm/uaccess.h> | ||
11 | #include <asm/pci-bridge.h> | ||
12 | |||
13 | void __init gemini_pcibios_fixup(void) | ||
14 | { | ||
15 | int i; | ||
16 | struct pci_dev *dev = NULL; | ||
17 | |||
18 | for_each_pci_dev(dev) { | ||
19 | for(i = 0; i < 6; i++) { | ||
20 | if (dev->resource[i].flags & IORESOURCE_IO) { | ||
21 | dev->resource[i].start |= (0xfe << 24); | ||
22 | dev->resource[i].end |= (0xfe << 24); | ||
23 | } | ||
24 | } | ||
25 | } | ||
26 | } | ||
27 | |||
28 | |||
29 | /* The "bootloader" for Synergy boards does none of this for us, so we need to | ||
30 | lay it all out ourselves... --Dan */ | ||
31 | void __init gemini_find_bridges(void) | ||
32 | { | ||
33 | struct pci_controller* hose; | ||
34 | |||
35 | ppc_md.pcibios_fixup = gemini_pcibios_fixup; | ||
36 | |||
37 | hose = pcibios_alloc_controller(); | ||
38 | if (!hose) | ||
39 | return; | ||
40 | setup_indirect_pci(hose, 0xfec00000, 0xfee00000); | ||
41 | } | ||
diff --git a/arch/ppc/platforms/gemini_prom.S b/arch/ppc/platforms/gemini_prom.S new file mode 100644 index 000000000000..8c5065d56505 --- /dev/null +++ b/arch/ppc/platforms/gemini_prom.S | |||
@@ -0,0 +1,93 @@ | |||
1 | /* | ||
2 | * arch/ppc/platforms/gemini_prom.S | ||
3 | * | ||
4 | * Not really prom support code (yet), but sort of anti-prom code. The current | ||
5 | * bootloader does a number of things it shouldn't and doesn't do things that it | ||
6 | * should. The stuff in here is mainly a hodge-podge collection of setup code | ||
7 | * to get the board up and running. | ||
8 | * ---Dan | ||
9 | */ | ||
10 | |||
11 | #include <linux/config.h> | ||
12 | #include <asm/reg.h> | ||
13 | #include <asm/page.h> | ||
14 | #include <platforms/gemini.h> | ||
15 | #include <asm/ppc_asm.h> | ||
16 | |||
17 | /* | ||
18 | * On 750's the MMU is on when Linux is booted, so we need to clear out the | ||
19 | * bootloader's BAT settings, make sure we're in supervisor state (gotcha!), | ||
20 | * and turn off the MMU. | ||
21 | * | ||
22 | */ | ||
23 | |||
24 | _GLOBAL(gemini_prom_init) | ||
25 | #ifdef CONFIG_SMP | ||
26 | /* Since the MMU's on, get stuff in rom space that we'll need */ | ||
27 | lis r4,GEMINI_CPUSTAT@h | ||
28 | ori r4,r4,GEMINI_CPUSTAT@l | ||
29 | lbz r5,0(r4) | ||
30 | andi. r5,r5,3 | ||
31 | mr r24,r5 /* cpu # used later on */ | ||
32 | #endif | ||
33 | mfmsr r4 | ||
34 | li r3,MSR_PR /* ensure supervisor! */ | ||
35 | ori r3,r3,MSR_IR|MSR_DR | ||
36 | andc r4,r4,r3 | ||
37 | mtmsr r4 | ||
38 | isync | ||
39 | #if 0 | ||
40 | /* zero out the bats now that the MMU is off */ | ||
41 | prom_no_mmu: | ||
42 | li r3,0 | ||
43 | mtspr SPRN_IBAT0U,r3 | ||
44 | mtspr SPRN_IBAT0L,r3 | ||
45 | mtspr SPRN_IBAT1U,r3 | ||
46 | mtspr SPRN_IBAT1L,r3 | ||
47 | mtspr SPRN_IBAT2U,r3 | ||
48 | mtspr SPRN_IBAT2L,r3 | ||
49 | mtspr SPRN_IBAT3U,r3 | ||
50 | mtspr SPRN_IBAT3L,r3 | ||
51 | |||
52 | mtspr SPRN_DBAT0U,r3 | ||
53 | mtspr SPRN_DBAT0L,r3 | ||
54 | mtspr SPRN_DBAT1U,r3 | ||
55 | mtspr SPRN_DBAT1L,r3 | ||
56 | mtspr SPRN_DBAT2U,r3 | ||
57 | mtspr SPRN_DBAT2L,r3 | ||
58 | mtspr SPRN_DBAT3U,r3 | ||
59 | mtspr SPRN_DBAT3L,r3 | ||
60 | #endif | ||
61 | |||
62 | /* the bootloader (as far as I'm currently aware) doesn't mess with page | ||
63 | tables, but since we're already here, might as well zap these, too */ | ||
64 | li r4,0 | ||
65 | mtspr SPRN_SDR1,r4 | ||
66 | |||
67 | li r4,16 | ||
68 | mtctr r4 | ||
69 | li r3,0 | ||
70 | li r4,0 | ||
71 | 3: mtsrin r3,r4 | ||
72 | addi r3,r3,1 | ||
73 | bdnz 3b | ||
74 | |||
75 | #ifdef CONFIG_SMP | ||
76 | /* The 750 book (and Mot/IBM support) says that this will "assist" snooping | ||
77 | when in SMP. Not sure yet whether this should stay or leave... */ | ||
78 | mfspr r4,SPRN_HID0 | ||
79 | ori r4,r4,HID0_ABE | ||
80 | mtspr SPRN_HID0,r4 | ||
81 | sync | ||
82 | #endif /* CONFIG_SMP */ | ||
83 | blr | ||
84 | |||
85 | /* apparently, SMon doesn't pay attention to HID0[SRST]. Disable the MMU and | ||
86 | branch to 0xfff00100 */ | ||
87 | _GLOBAL(_gemini_reboot) | ||
88 | lis r5,GEMINI_BOOT_INIT@h | ||
89 | ori r5,r5,GEMINI_BOOT_INIT@l | ||
90 | li r6,MSR_IP | ||
91 | mtspr SPRN_SRR0,r5 | ||
92 | mtspr SPRN_SRR1,r6 | ||
93 | rfi | ||
diff --git a/arch/ppc/platforms/gemini_serial.h b/arch/ppc/platforms/gemini_serial.h new file mode 100644 index 000000000000..69855aeec888 --- /dev/null +++ b/arch/ppc/platforms/gemini_serial.h | |||
@@ -0,0 +1,41 @@ | |||
1 | #ifdef __KERNEL__ | ||
2 | #ifndef __ASMPPC_GEMINI_SERIAL_H | ||
3 | #define __ASMPPC_GEMINI_SERIAL_H | ||
4 | |||
5 | #include <linux/config.h> | ||
6 | #include <platforms/gemini.h> | ||
7 | |||
8 | #ifdef CONFIG_SERIAL_MANY_PORTS | ||
9 | #define RS_TABLE_SIZE 64 | ||
10 | #else | ||
11 | #define RS_TABLE_SIZE 4 | ||
12 | #endif | ||
13 | |||
14 | /* Rate for the 24.576 Mhz clock for the onboard serial chip */ | ||
15 | #define BASE_BAUD (24576000 / 16) | ||
16 | |||
17 | #ifdef CONFIG_SERIAL_DETECT_IRQ | ||
18 | #define STD_COM_FLAGS (ASYNC_BOOT_AUTOCONF|ASYNC_SKIP_TEST|ASYNC_AUTO_IRQ) | ||
19 | #define STD_COM4_FLAGS (ASYNC_BOOT_AUTOCONF|ASYNC_AUTO_IRQ) | ||
20 | #else | ||
21 | #define STD_COM_FLAGS (ASYNC_BOOT_AUTOCONF|ASYNC_SKIP_TEST) | ||
22 | #define STD_COM4_FLAGS (ASYNC_BOOT_AUTOCONF) | ||
23 | #endif | ||
24 | |||
25 | #define STD_SERIAL_PORT_DEFNS \ | ||
26 | { 0, BASE_BAUD, GEMINI_SERIAL_A, 15, STD_COM_FLAGS }, /* ttyS0 */ \ | ||
27 | { 0, BASE_BAUD, GEMINI_SERIAL_B, 14, STD_COM_FLAGS }, /* ttyS1 */ \ | ||
28 | |||
29 | #ifdef CONFIG_GEMINI_PU32 | ||
30 | #define PU32_SERIAL_PORT_DEFNS \ | ||
31 | { 0, BASE_BAUD, NULL, 0, STD_COM_FLAGS }, | ||
32 | #else | ||
33 | #define PU32_SERIAL_PORT_DEFNS | ||
34 | #endif | ||
35 | |||
36 | #define SERIAL_PORT_DFNS \ | ||
37 | STD_SERIAL_PORT_DEFNS \ | ||
38 | PU32_SERIAL_PORT_DEFNS | ||
39 | |||
40 | #endif | ||
41 | #endif /* __KERNEL__ */ | ||
diff --git a/arch/ppc/platforms/gemini_setup.c b/arch/ppc/platforms/gemini_setup.c new file mode 100644 index 000000000000..1a42cb9b1134 --- /dev/null +++ b/arch/ppc/platforms/gemini_setup.c | |||
@@ -0,0 +1,584 @@ | |||
1 | /* | ||
2 | * arch/ppc/platforms/gemini_setup.c | ||
3 | * | ||
4 | * Copyright (C) 1995 Linus Torvalds | ||
5 | * Adapted from 'alpha' version by Gary Thomas | ||
6 | * Modified by Cort Dougan (cort@cs.nmt.edu) | ||
7 | * Synergy Microsystems board support by Dan Cox (dan@synergymicro.com) | ||
8 | * | ||
9 | */ | ||
10 | |||
11 | #include <linux/config.h> | ||
12 | #include <linux/stddef.h> | ||
13 | #include <linux/kernel.h> | ||
14 | #include <linux/init.h> | ||
15 | #include <linux/errno.h> | ||
16 | #include <linux/reboot.h> | ||
17 | #include <linux/pci.h> | ||
18 | #include <linux/time.h> | ||
19 | #include <linux/kdev_t.h> | ||
20 | #include <linux/types.h> | ||
21 | #include <linux/major.h> | ||
22 | #include <linux/initrd.h> | ||
23 | #include <linux/console.h> | ||
24 | #include <linux/irq.h> | ||
25 | #include <linux/seq_file.h> | ||
26 | #include <linux/root_dev.h> | ||
27 | #include <linux/bcd.h> | ||
28 | |||
29 | #include <asm/system.h> | ||
30 | #include <asm/pgtable.h> | ||
31 | #include <asm/page.h> | ||
32 | #include <asm/dma.h> | ||
33 | #include <asm/io.h> | ||
34 | #include <asm/m48t35.h> | ||
35 | #include <platforms/gemini.h> | ||
36 | #include <asm/time.h> | ||
37 | #include <asm/open_pic.h> | ||
38 | #include <asm/bootinfo.h> | ||
39 | |||
40 | void gemini_find_bridges(void); | ||
41 | static int gemini_get_clock_speed(void); | ||
42 | extern void gemini_pcibios_fixup(void); | ||
43 | |||
44 | static char *gemini_board_families[] = { | ||
45 | "VGM", "VSS", "KGM", "VGR", "VCM", "VCS", "KCM", "VCR" | ||
46 | }; | ||
47 | static int gemini_board_count = sizeof(gemini_board_families) / | ||
48 | sizeof(gemini_board_families[0]); | ||
49 | |||
50 | static unsigned int cpu_7xx[16] = { | ||
51 | 0, 15, 14, 0, 0, 13, 5, 9, 6, 11, 8, 10, 16, 12, 7, 0 | ||
52 | }; | ||
53 | static unsigned int cpu_6xx[16] = { | ||
54 | 0, 0, 14, 0, 0, 13, 5, 9, 6, 11, 8, 10, 0, 12, 7, 0 | ||
55 | }; | ||
56 | |||
57 | /* | ||
58 | * prom_init is the Gemini version of prom.c:prom_init. We only need | ||
59 | * the BSS clearing code, so I copied that out of prom.c. This is a | ||
60 | * lot simpler than hacking prom.c so it will build with Gemini. -VAL | ||
61 | */ | ||
62 | |||
63 | #define PTRRELOC(x) ((typeof(x))((unsigned long)(x) + offset)) | ||
64 | |||
65 | unsigned long | ||
66 | prom_init(void) | ||
67 | { | ||
68 | unsigned long offset = reloc_offset(); | ||
69 | unsigned long phys; | ||
70 | extern char __bss_start, _end; | ||
71 | |||
72 | /* First zero the BSS -- use memset, some arches don't have | ||
73 | * caches on yet */ | ||
74 | memset_io(PTRRELOC(&__bss_start),0 , &_end - &__bss_start); | ||
75 | |||
76 | /* Default */ | ||
77 | phys = offset + KERNELBASE; | ||
78 | |||
79 | gemini_prom_init(); | ||
80 | |||
81 | return phys; | ||
82 | } | ||
83 | |||
84 | int | ||
85 | gemini_show_cpuinfo(struct seq_file *m) | ||
86 | { | ||
87 | unsigned char reg, rev; | ||
88 | char *family; | ||
89 | unsigned int type; | ||
90 | |||
91 | reg = readb(GEMINI_FEAT); | ||
92 | family = gemini_board_families[((reg>>4) & 0xf)]; | ||
93 | if (((reg>>4) & 0xf) > gemini_board_count) | ||
94 | printk(KERN_ERR "cpuinfo(): unable to determine board family\n"); | ||
95 | |||
96 | reg = readb(GEMINI_BREV); | ||
97 | type = (reg>>4) & 0xf; | ||
98 | rev = reg & 0xf; | ||
99 | |||
100 | reg = readb(GEMINI_BECO); | ||
101 | |||
102 | seq_printf(m, "machine\t\t: Gemini %s%d, rev %c, eco %d\n", | ||
103 | family, type, (rev + 'A'), (reg & 0xf)); | ||
104 | |||
105 | seq_printf(m, "board\t\t: Gemini %s", family); | ||
106 | if (type > 9) | ||
107 | seq_printf(m, "%c", (type - 10) + 'A'); | ||
108 | else | ||
109 | seq_printf(m, "%d", type); | ||
110 | |||
111 | seq_printf(m, ", rev %c, eco %d\n", (rev + 'A'), (reg & 0xf)); | ||
112 | |||
113 | seq_printf(m, "clock\t\t: %dMhz\n", gemini_get_clock_speed()); | ||
114 | |||
115 | return 0; | ||
116 | } | ||
117 | |||
118 | static u_char gemini_openpic_initsenses[] = { | ||
119 | 1, | ||
120 | 1, | ||
121 | 1, | ||
122 | 1, | ||
123 | 0, | ||
124 | 0, | ||
125 | 1, /* remainder are level-triggered */ | ||
126 | }; | ||
127 | |||
128 | #define GEMINI_MPIC_ADDR (0xfcfc0000) | ||
129 | #define GEMINI_MPIC_PCI_CFG (0x80005800) | ||
130 | |||
131 | void __init gemini_openpic_init(void) | ||
132 | { | ||
133 | |||
134 | OpenPIC_Addr = (volatile struct OpenPIC *) | ||
135 | grackle_read(GEMINI_MPIC_PCI_CFG + 0x10); | ||
136 | OpenPIC_InitSenses = gemini_openpic_initsenses; | ||
137 | OpenPIC_NumInitSenses = sizeof( gemini_openpic_initsenses ); | ||
138 | |||
139 | ioremap( GEMINI_MPIC_ADDR, OPENPIC_SIZE); | ||
140 | } | ||
141 | |||
142 | |||
143 | extern unsigned long loops_per_jiffy; | ||
144 | extern int root_mountflags; | ||
145 | extern char cmd_line[]; | ||
146 | |||
147 | void | ||
148 | gemini_heartbeat(void) | ||
149 | { | ||
150 | static unsigned long led = GEMINI_LEDBASE+(4*8); | ||
151 | static char direction = 8; | ||
152 | |||
153 | |||
154 | /* We only want to do this on 1 CPU */ | ||
155 | if (smp_processor_id()) | ||
156 | return; | ||
157 | *(char *)led = 0; | ||
158 | if ( (led + direction) > (GEMINI_LEDBASE+(7*8)) || | ||
159 | (led + direction) < (GEMINI_LEDBASE+(4*8)) ) | ||
160 | direction *= -1; | ||
161 | led += direction; | ||
162 | *(char *)led = 0xff; | ||
163 | ppc_md.heartbeat_count = ppc_md.heartbeat_reset; | ||
164 | } | ||
165 | |||
166 | void __init gemini_setup_arch(void) | ||
167 | { | ||
168 | extern char cmd_line[]; | ||
169 | |||
170 | |||
171 | loops_per_jiffy = 50000000/HZ; | ||
172 | |||
173 | #ifdef CONFIG_BLK_DEV_INITRD | ||
174 | /* bootable off CDROM */ | ||
175 | if (initrd_start) | ||
176 | ROOT_DEV = Root_SR0; | ||
177 | else | ||
178 | #endif | ||
179 | ROOT_DEV = Root_SDA1; | ||
180 | |||
181 | /* nothing but serial consoles... */ | ||
182 | sprintf(cmd_line, "%s console=ttyS0", cmd_line); | ||
183 | |||
184 | printk("Boot arguments: %s\n", cmd_line); | ||
185 | |||
186 | ppc_md.heartbeat = gemini_heartbeat; | ||
187 | ppc_md.heartbeat_reset = HZ/8; | ||
188 | ppc_md.heartbeat_count = 1; | ||
189 | |||
190 | /* Lookup PCI hosts */ | ||
191 | gemini_find_bridges(); | ||
192 | /* take special pains to map the MPIC, since it isn't mapped yet */ | ||
193 | gemini_openpic_init(); | ||
194 | /* start the L2 */ | ||
195 | gemini_init_l2(); | ||
196 | } | ||
197 | |||
198 | |||
199 | int | ||
200 | gemini_get_clock_speed(void) | ||
201 | { | ||
202 | unsigned long hid1, pvr; | ||
203 | int clock; | ||
204 | |||
205 | pvr = mfspr(SPRN_PVR); | ||
206 | hid1 = (mfspr(SPRN_HID1) >> 28) & 0xf; | ||
207 | if (PVR_VER(pvr) == 8 || | ||
208 | PVR_VER(pvr) == 12) | ||
209 | hid1 = cpu_7xx[hid1]; | ||
210 | else | ||
211 | hid1 = cpu_6xx[hid1]; | ||
212 | |||
213 | switch((readb(GEMINI_BSTAT) & 0xc) >> 2) { | ||
214 | |||
215 | case 0: | ||
216 | default: | ||
217 | clock = (hid1*100)/3; | ||
218 | break; | ||
219 | |||
220 | case 1: | ||
221 | clock = (hid1*125)/3; | ||
222 | break; | ||
223 | |||
224 | case 2: | ||
225 | clock = (hid1*50); | ||
226 | break; | ||
227 | } | ||
228 | |||
229 | return clock; | ||
230 | } | ||
231 | |||
232 | void __init gemini_init_l2(void) | ||
233 | { | ||
234 | unsigned char reg, brev, fam, creg; | ||
235 | unsigned long cache; | ||
236 | unsigned long pvr; | ||
237 | |||
238 | reg = readb(GEMINI_L2CFG); | ||
239 | brev = readb(GEMINI_BREV); | ||
240 | fam = readb(GEMINI_FEAT); | ||
241 | pvr = mfspr(SPRN_PVR); | ||
242 | |||
243 | switch(PVR_VER(pvr)) { | ||
244 | |||
245 | case 8: | ||
246 | if (reg & 0xc0) | ||
247 | cache = (((reg >> 6) & 0x3) << 28); | ||
248 | else | ||
249 | cache = 0x3 << 28; | ||
250 | |||
251 | #ifdef CONFIG_SMP | ||
252 | /* Pre-3.0 processor revs had snooping errata. Leave | ||
253 | their L2's disabled with SMP. -- Dan */ | ||
254 | if (PVR_CFG(pvr) < 3) { | ||
255 | printk("Pre-3.0 750; L2 left disabled!\n"); | ||
256 | return; | ||
257 | } | ||
258 | #endif /* CONFIG_SMP */ | ||
259 | |||
260 | /* Special case: VGM5-B's came before L2 ratios were set on | ||
261 | the board. Processor speed shouldn't be too high, so | ||
262 | set L2 ratio to 1:1.5. */ | ||
263 | if ((brev == 0x51) && ((fam & 0xa0) >> 4) == 0) | ||
264 | reg |= 1; | ||
265 | |||
266 | /* determine best cache ratio based upon what the board | ||
267 | tells us (which sometimes _may_ not be true) and | ||
268 | the processor speed. */ | ||
269 | else { | ||
270 | if (gemini_get_clock_speed() > 250) | ||
271 | reg = 2; | ||
272 | } | ||
273 | break; | ||
274 | case 12: | ||
275 | { | ||
276 | static unsigned long l2_size_val = 0; | ||
277 | |||
278 | if (!l2_size_val) | ||
279 | l2_size_val = _get_L2CR(); | ||
280 | cache = l2_size_val; | ||
281 | break; | ||
282 | } | ||
283 | case 4: | ||
284 | case 9: | ||
285 | creg = readb(GEMINI_CPUSTAT); | ||
286 | if (((creg & 0xc) >> 2) != 1) | ||
287 | printk("Dual-604 boards don't support the use of L2\n"); | ||
288 | else | ||
289 | writeb(1, GEMINI_L2CFG); | ||
290 | return; | ||
291 | default: | ||
292 | printk("Unknown processor; L2 left disabled\n"); | ||
293 | return; | ||
294 | } | ||
295 | |||
296 | cache |= ((1<<reg) << 25); | ||
297 | cache |= (L2CR_L2RAM_MASK|L2CR_L2CTL|L2CR_L2DO); | ||
298 | _set_L2CR(0); | ||
299 | _set_L2CR(cache | L2CR_L2E); | ||
300 | |||
301 | } | ||
302 | |||
303 | void | ||
304 | gemini_restart(char *cmd) | ||
305 | { | ||
306 | local_irq_disable(); | ||
307 | /* make a clean restart, not via the MPIC */ | ||
308 | _gemini_reboot(); | ||
309 | for(;;); | ||
310 | } | ||
311 | |||
312 | void | ||
313 | gemini_power_off(void) | ||
314 | { | ||
315 | for(;;); | ||
316 | } | ||
317 | |||
318 | void | ||
319 | gemini_halt(void) | ||
320 | { | ||
321 | gemini_restart(NULL); | ||
322 | } | ||
323 | |||
324 | void __init gemini_init_IRQ(void) | ||
325 | { | ||
326 | /* gemini has no 8259 */ | ||
327 | openpic_init(1, 0, 0, -1); | ||
328 | } | ||
329 | |||
330 | #define gemini_rtc_read(x) (readb(GEMINI_RTC+(x))) | ||
331 | #define gemini_rtc_write(val,x) (writeb((val),(GEMINI_RTC+(x)))) | ||
332 | |||
333 | /* ensure that the RTC is up and running */ | ||
334 | long __init gemini_time_init(void) | ||
335 | { | ||
336 | unsigned char reg; | ||
337 | |||
338 | reg = gemini_rtc_read(M48T35_RTC_CONTROL); | ||
339 | |||
340 | if ( reg & M48T35_RTC_STOPPED ) { | ||
341 | printk(KERN_INFO "M48T35 real-time-clock was stopped. Now starting...\n"); | ||
342 | gemini_rtc_write((reg & ~(M48T35_RTC_STOPPED)), M48T35_RTC_CONTROL); | ||
343 | gemini_rtc_write((reg | M48T35_RTC_SET), M48T35_RTC_CONTROL); | ||
344 | } | ||
345 | return 0; | ||
346 | } | ||
347 | |||
348 | #undef DEBUG_RTC | ||
349 | |||
350 | unsigned long | ||
351 | gemini_get_rtc_time(void) | ||
352 | { | ||
353 | unsigned int year, mon, day, hour, min, sec; | ||
354 | unsigned char reg; | ||
355 | |||
356 | reg = gemini_rtc_read(M48T35_RTC_CONTROL); | ||
357 | gemini_rtc_write((reg|M48T35_RTC_READ), M48T35_RTC_CONTROL); | ||
358 | #ifdef DEBUG_RTC | ||
359 | printk("get rtc: reg = %x\n", reg); | ||
360 | #endif | ||
361 | |||
362 | do { | ||
363 | sec = gemini_rtc_read(M48T35_RTC_SECONDS); | ||
364 | min = gemini_rtc_read(M48T35_RTC_MINUTES); | ||
365 | hour = gemini_rtc_read(M48T35_RTC_HOURS); | ||
366 | day = gemini_rtc_read(M48T35_RTC_DOM); | ||
367 | mon = gemini_rtc_read(M48T35_RTC_MONTH); | ||
368 | year = gemini_rtc_read(M48T35_RTC_YEAR); | ||
369 | } while( sec != gemini_rtc_read(M48T35_RTC_SECONDS)); | ||
370 | #ifdef DEBUG_RTC | ||
371 | printk("get rtc: sec=%x, min=%x, hour=%x, day=%x, mon=%x, year=%x\n", | ||
372 | sec, min, hour, day, mon, year); | ||
373 | #endif | ||
374 | |||
375 | gemini_rtc_write(reg, M48T35_RTC_CONTROL); | ||
376 | |||
377 | BCD_TO_BIN(sec); | ||
378 | BCD_TO_BIN(min); | ||
379 | BCD_TO_BIN(hour); | ||
380 | BCD_TO_BIN(day); | ||
381 | BCD_TO_BIN(mon); | ||
382 | BCD_TO_BIN(year); | ||
383 | |||
384 | if ((year += 1900) < 1970) | ||
385 | year += 100; | ||
386 | #ifdef DEBUG_RTC | ||
387 | printk("get rtc: sec=%x, min=%x, hour=%x, day=%x, mon=%x, year=%x\n", | ||
388 | sec, min, hour, day, mon, year); | ||
389 | #endif | ||
390 | |||
391 | return mktime( year, mon, day, hour, min, sec ); | ||
392 | } | ||
393 | |||
394 | |||
395 | int | ||
396 | gemini_set_rtc_time( unsigned long now ) | ||
397 | { | ||
398 | unsigned char reg; | ||
399 | struct rtc_time tm; | ||
400 | |||
401 | to_tm( now, &tm ); | ||
402 | |||
403 | reg = gemini_rtc_read(M48T35_RTC_CONTROL); | ||
404 | #ifdef DEBUG_RTC | ||
405 | printk("set rtc: reg = %x\n", reg); | ||
406 | #endif | ||
407 | |||
408 | gemini_rtc_write((reg|M48T35_RTC_SET), M48T35_RTC_CONTROL); | ||
409 | #ifdef DEBUG_RTC | ||
410 | printk("set rtc: tm vals - sec=%x, min=%x, hour=%x, mon=%x, mday=%x, year=%x\n", | ||
411 | tm.tm_sec, tm.tm_min, tm.tm_hour, tm.tm_mon, tm.tm_mday, tm.tm_year); | ||
412 | #endif | ||
413 | |||
414 | tm.tm_year -= 1900; | ||
415 | BIN_TO_BCD(tm.tm_sec); | ||
416 | BIN_TO_BCD(tm.tm_min); | ||
417 | BIN_TO_BCD(tm.tm_hour); | ||
418 | BIN_TO_BCD(tm.tm_mon); | ||
419 | BIN_TO_BCD(tm.tm_mday); | ||
420 | BIN_TO_BCD(tm.tm_year); | ||
421 | #ifdef DEBUG_RTC | ||
422 | printk("set rtc: tm vals - sec=%x, min=%x, hour=%x, mon=%x, mday=%x, year=%x\n", | ||
423 | tm.tm_sec, tm.tm_min, tm.tm_hour, tm.tm_mon, tm.tm_mday, tm.tm_year); | ||
424 | #endif | ||
425 | |||
426 | gemini_rtc_write(tm.tm_sec, M48T35_RTC_SECONDS); | ||
427 | gemini_rtc_write(tm.tm_min, M48T35_RTC_MINUTES); | ||
428 | gemini_rtc_write(tm.tm_hour, M48T35_RTC_HOURS); | ||
429 | gemini_rtc_write(tm.tm_mday, M48T35_RTC_DOM); | ||
430 | gemini_rtc_write(tm.tm_mon, M48T35_RTC_MONTH); | ||
431 | gemini_rtc_write(tm.tm_year, M48T35_RTC_YEAR); | ||
432 | |||
433 | /* done writing */ | ||
434 | gemini_rtc_write(reg, M48T35_RTC_CONTROL); | ||
435 | |||
436 | if ((time_state == TIME_ERROR) || (time_state == TIME_BAD)) | ||
437 | time_state = TIME_OK; | ||
438 | |||
439 | return 0; | ||
440 | } | ||
441 | |||
442 | /* use the RTC to determine the decrementer count */ | ||
443 | void __init gemini_calibrate_decr(void) | ||
444 | { | ||
445 | int freq, divisor; | ||
446 | unsigned char reg; | ||
447 | |||
448 | /* determine processor bus speed */ | ||
449 | reg = readb(GEMINI_BSTAT); | ||
450 | |||
451 | switch(((reg & 0x0c)>>2)&0x3) { | ||
452 | case 0: | ||
453 | default: | ||
454 | freq = 66667; | ||
455 | break; | ||
456 | case 1: | ||
457 | freq = 83000; | ||
458 | break; | ||
459 | case 2: | ||
460 | freq = 100000; | ||
461 | break; | ||
462 | } | ||
463 | |||
464 | freq *= 1000; | ||
465 | divisor = 4; | ||
466 | tb_ticks_per_jiffy = freq / HZ / divisor; | ||
467 | tb_to_us = mulhwu_scale_factor(freq/divisor, 1000000); | ||
468 | } | ||
469 | |||
470 | unsigned long __init gemini_find_end_of_memory(void) | ||
471 | { | ||
472 | unsigned long total; | ||
473 | unsigned char reg; | ||
474 | |||
475 | reg = readb(GEMINI_MEMCFG); | ||
476 | total = ((1<<((reg & 0x7) - 1)) * | ||
477 | (8<<((reg >> 3) & 0x7))); | ||
478 | total *= (1024*1024); | ||
479 | return total; | ||
480 | } | ||
481 | |||
482 | static void __init | ||
483 | gemini_map_io(void) | ||
484 | { | ||
485 | io_block_mapping(0xf0000000, 0xf0000000, 0x10000000, _PAGE_IO); | ||
486 | io_block_mapping(0x80000000, 0x80000000, 0x10000000, _PAGE_IO); | ||
487 | } | ||
488 | |||
489 | #ifdef CONFIG_SMP | ||
490 | static int | ||
491 | smp_gemini_probe(void) | ||
492 | { | ||
493 | int i, nr; | ||
494 | |||
495 | nr = (readb(GEMINI_CPUSTAT) & GEMINI_CPU_COUNT_MASK) >> 2; | ||
496 | if (nr == 0) | ||
497 | nr = 4; | ||
498 | |||
499 | if (nr > 1) { | ||
500 | openpic_request_IPIs(); | ||
501 | for (i = 1; i < nr; ++i) | ||
502 | smp_hw_index[i] = i; | ||
503 | } | ||
504 | |||
505 | return nr; | ||
506 | } | ||
507 | |||
508 | static void | ||
509 | smp_gemini_kick_cpu(int nr) | ||
510 | { | ||
511 | openpic_reset_processor_phys(1 << nr); | ||
512 | openpic_reset_processor_phys(0); | ||
513 | } | ||
514 | |||
515 | static void | ||
516 | smp_gemini_setup_cpu(int cpu_nr) | ||
517 | { | ||
518 | if (OpenPIC_Addr) | ||
519 | do_openpic_setup_cpu(); | ||
520 | if (cpu_nr > 0) | ||
521 | gemini_init_l2(); | ||
522 | } | ||
523 | |||
524 | static struct smp_ops_t gemini_smp_ops = { | ||
525 | smp_openpic_message_pass, | ||
526 | smp_gemini_probe, | ||
527 | smp_gemini_kick_cpu, | ||
528 | smp_gemini_setup_cpu, | ||
529 | .give_timebase = smp_generic_give_timebase, | ||
530 | .take_timebase = smp_generic_take_timebase, | ||
531 | }; | ||
532 | #endif /* CONFIG_SMP */ | ||
533 | |||
534 | void __init platform_init(unsigned long r3, unsigned long r4, unsigned long r5, | ||
535 | unsigned long r6, unsigned long r7) | ||
536 | { | ||
537 | int i; | ||
538 | |||
539 | /* Restore BATs for now */ | ||
540 | mtspr(SPRN_DBAT3U, 0xf0001fff); | ||
541 | mtspr(SPRN_DBAT3L, 0xf000002a); | ||
542 | |||
543 | parse_bootinfo(find_bootinfo()); | ||
544 | |||
545 | for(i = 0; i < GEMINI_LEDS; i++) | ||
546 | gemini_led_off(i); | ||
547 | |||
548 | ISA_DMA_THRESHOLD = 0; | ||
549 | DMA_MODE_READ = 0; | ||
550 | DMA_MODE_WRITE = 0; | ||
551 | |||
552 | #ifdef CONFIG_BLK_DEV_INITRD | ||
553 | if ( r4 ) | ||
554 | { | ||
555 | initrd_start = r4 + KERNELBASE; | ||
556 | initrd_end = r5 + KERNELBASE; | ||
557 | } | ||
558 | #endif | ||
559 | |||
560 | ppc_md.setup_arch = gemini_setup_arch; | ||
561 | ppc_md.show_cpuinfo = gemini_show_cpuinfo; | ||
562 | ppc_md.irq_canonicalize = NULL; | ||
563 | ppc_md.init_IRQ = gemini_init_IRQ; | ||
564 | ppc_md.get_irq = openpic_get_irq; | ||
565 | ppc_md.init = NULL; | ||
566 | |||
567 | ppc_md.restart = gemini_restart; | ||
568 | ppc_md.power_off = gemini_power_off; | ||
569 | ppc_md.halt = gemini_halt; | ||
570 | |||
571 | ppc_md.time_init = gemini_time_init; | ||
572 | ppc_md.set_rtc_time = gemini_set_rtc_time; | ||
573 | ppc_md.get_rtc_time = gemini_get_rtc_time; | ||
574 | ppc_md.calibrate_decr = gemini_calibrate_decr; | ||
575 | |||
576 | ppc_md.find_end_of_memory = gemini_find_end_of_memory; | ||
577 | ppc_md.setup_io_mappings = gemini_map_io; | ||
578 | |||
579 | ppc_md.pcibios_fixup_bus = gemini_pcibios_fixup; | ||
580 | |||
581 | #ifdef CONFIG_SMP | ||
582 | ppc_md.smp_ops = &gemini_smp_ops; | ||
583 | #endif /* CONFIG_SMP */ | ||
584 | } | ||
diff --git a/arch/ppc/platforms/hdpu.c b/arch/ppc/platforms/hdpu.c new file mode 100644 index 000000000000..b659d7b3d747 --- /dev/null +++ b/arch/ppc/platforms/hdpu.c | |||
@@ -0,0 +1,1062 @@ | |||
1 | |||
2 | /* | ||
3 | * arch/ppc/platforms/hdpu_setup.c | ||
4 | * | ||
5 | * Board setup routines for the Sky Computers HDPU Compute Blade. | ||
6 | * | ||
7 | * Written by Brian Waite <waite@skycomputers.com> | ||
8 | * | ||
9 | * Based on code done by - Mark A. Greer <mgreer@mvista.com> | ||
10 | * Rabeeh Khoury - rabeeh@galileo.co.il | ||
11 | * | ||
12 | * This program is free software; you can redistribute it and/or modify it | ||
13 | * under the terms of the GNU General Public License as published by the | ||
14 | * Free Software Foundation; either version 2 of the License, or (at your | ||
15 | * option) any later version. | ||
16 | */ | ||
17 | |||
18 | #include <linux/config.h> | ||
19 | |||
20 | #include <linux/pci.h> | ||
21 | #include <linux/delay.h> | ||
22 | #include <linux/irq.h> | ||
23 | #include <linux/ide.h> | ||
24 | #include <linux/seq_file.h> | ||
25 | |||
26 | #include <linux/initrd.h> | ||
27 | #include <linux/root_dev.h> | ||
28 | #include <linux/smp.h> | ||
29 | |||
30 | #include <asm/time.h> | ||
31 | #include <asm/machdep.h> | ||
32 | #include <asm/todc.h> | ||
33 | #include <asm/mv64x60.h> | ||
34 | #include <asm/ppcboot.h> | ||
35 | #include <platforms/hdpu.h> | ||
36 | #include <linux/mv643xx.h> | ||
37 | #include <linux/hdpu_features.h> | ||
38 | #include <linux/device.h> | ||
39 | #include <linux/mtd/physmap.h> | ||
40 | |||
41 | #define BOARD_VENDOR "Sky Computers" | ||
42 | #define BOARD_MACHINE "HDPU-CB-A" | ||
43 | |||
44 | bd_t ppcboot_bd; | ||
45 | int ppcboot_bd_valid = 0; | ||
46 | |||
47 | static mv64x60_handle_t bh; | ||
48 | |||
49 | extern char cmd_line[]; | ||
50 | |||
51 | unsigned long hdpu_find_end_of_memory(void); | ||
52 | void hdpu_mpsc_progress(char *s, unsigned short hex); | ||
53 | void hdpu_heartbeat(void); | ||
54 | |||
55 | static void parse_bootinfo(unsigned long r3, | ||
56 | unsigned long r4, unsigned long r5, | ||
57 | unsigned long r6, unsigned long r7); | ||
58 | static void hdpu_set_l1pe(void); | ||
59 | static void hdpu_cpustate_set(unsigned char new_state); | ||
60 | #ifdef CONFIG_SMP | ||
61 | static spinlock_t timebase_lock = SPIN_LOCK_UNLOCKED; | ||
62 | static unsigned int timebase_upper = 0, timebase_lower = 0; | ||
63 | extern int smp_tb_synchronized; | ||
64 | |||
65 | void __devinit hdpu_tben_give(void); | ||
66 | void __devinit hdpu_tben_take(void); | ||
67 | #endif | ||
68 | |||
69 | static int __init | ||
70 | hdpu_map_irq(struct pci_dev *dev, unsigned char idsel, unsigned char pin) | ||
71 | { | ||
72 | struct pci_controller *hose = pci_bus_to_hose(dev->bus->number); | ||
73 | |||
74 | if (hose->index == 0) { | ||
75 | static char pci_irq_table[][4] = { | ||
76 | {HDPU_PCI_0_IRQ, 0, 0, 0}, | ||
77 | {HDPU_PCI_0_IRQ, 0, 0, 0}, | ||
78 | }; | ||
79 | |||
80 | const long min_idsel = 1, max_idsel = 2, irqs_per_slot = 4; | ||
81 | return PCI_IRQ_TABLE_LOOKUP; | ||
82 | } else { | ||
83 | static char pci_irq_table[][4] = { | ||
84 | {HDPU_PCI_1_IRQ, 0, 0, 0}, | ||
85 | }; | ||
86 | |||
87 | const long min_idsel = 1, max_idsel = 1, irqs_per_slot = 4; | ||
88 | return PCI_IRQ_TABLE_LOOKUP; | ||
89 | } | ||
90 | } | ||
91 | |||
92 | static void __init hdpu_intr_setup(void) | ||
93 | { | ||
94 | mv64x60_write(&bh, MV64x60_GPP_IO_CNTL, | ||
95 | (1 | (1 << 2) | (1 << 3) | (1 << 4) | (1 << 5) | | ||
96 | (1 << 6) | (1 << 7) | (1 << 12) | (1 << 16) | | ||
97 | (1 << 18) | (1 << 19) | (1 << 20) | (1 << 21) | | ||
98 | (1 << 22) | (1 << 23) | (1 << 24) | (1 << 25) | | ||
99 | (1 << 26) | (1 << 27) | (1 << 28) | (1 << 29))); | ||
100 | |||
101 | /* XXXX Erranum FEr PCI-#8 */ | ||
102 | mv64x60_clr_bits(&bh, MV64x60_PCI0_CMD, (1 << 5) | (1 << 9)); | ||
103 | mv64x60_clr_bits(&bh, MV64x60_PCI1_CMD, (1 << 5) | (1 << 9)); | ||
104 | |||
105 | /* | ||
106 | * Dismiss and then enable interrupt on GPP interrupt cause | ||
107 | * for CPU #0 | ||
108 | */ | ||
109 | mv64x60_write(&bh, MV64x60_GPP_INTR_CAUSE, ~((1 << 8) | (1 << 13))); | ||
110 | mv64x60_set_bits(&bh, MV64x60_GPP_INTR_MASK, (1 << 8) | (1 << 13)); | ||
111 | |||
112 | /* | ||
113 | * Dismiss and then enable interrupt on CPU #0 high cause reg | ||
114 | * BIT25 summarizes GPP interrupts 8-15 | ||
115 | */ | ||
116 | mv64x60_set_bits(&bh, MV64360_IC_CPU0_INTR_MASK_HI, (1 << 25)); | ||
117 | } | ||
118 | |||
119 | static void __init hdpu_setup_peripherals(void) | ||
120 | { | ||
121 | unsigned int val; | ||
122 | |||
123 | mv64x60_set_32bit_window(&bh, MV64x60_CPU2BOOT_WIN, | ||
124 | HDPU_EMB_FLASH_BASE, HDPU_EMB_FLASH_SIZE, 0); | ||
125 | bh.ci->enable_window_32bit(&bh, MV64x60_CPU2BOOT_WIN); | ||
126 | |||
127 | mv64x60_set_32bit_window(&bh, MV64x60_CPU2DEV_0_WIN, | ||
128 | HDPU_TBEN_BASE, HDPU_TBEN_SIZE, 0); | ||
129 | bh.ci->enable_window_32bit(&bh, MV64x60_CPU2DEV_0_WIN); | ||
130 | |||
131 | mv64x60_set_32bit_window(&bh, MV64x60_CPU2DEV_1_WIN, | ||
132 | HDPU_NEXUS_ID_BASE, HDPU_NEXUS_ID_SIZE, 0); | ||
133 | bh.ci->enable_window_32bit(&bh, MV64x60_CPU2DEV_1_WIN); | ||
134 | |||
135 | mv64x60_set_32bit_window(&bh, MV64x60_CPU2SRAM_WIN, | ||
136 | HDPU_INTERNAL_SRAM_BASE, | ||
137 | HDPU_INTERNAL_SRAM_SIZE, 0); | ||
138 | bh.ci->enable_window_32bit(&bh, MV64x60_CPU2SRAM_WIN); | ||
139 | |||
140 | bh.ci->disable_window_32bit(&bh, MV64x60_ENET2MEM_4_WIN); | ||
141 | mv64x60_set_32bit_window(&bh, MV64x60_ENET2MEM_4_WIN, 0, 0, 0); | ||
142 | |||
143 | mv64x60_clr_bits(&bh, MV64x60_PCI0_PCI_DECODE_CNTL, (1 << 3)); | ||
144 | mv64x60_clr_bits(&bh, MV64x60_PCI1_PCI_DECODE_CNTL, (1 << 3)); | ||
145 | mv64x60_clr_bits(&bh, MV64x60_TIMR_CNTR_0_3_CNTL, | ||
146 | ((1 << 0) | (1 << 8) | (1 << 16) | (1 << 24))); | ||
147 | |||
148 | /* Enable pipelining */ | ||
149 | mv64x60_set_bits(&bh, MV64x60_CPU_CONFIG, (1 << 13)); | ||
150 | /* Enable Snoop Pipelineing */ | ||
151 | mv64x60_set_bits(&bh, MV64360_D_UNIT_CONTROL_HIGH, (1 << 24)); | ||
152 | |||
153 | /* | ||
154 | * Change DRAM read buffer assignment. | ||
155 | * Assign read buffer 0 dedicated only for CPU, | ||
156 | * and the rest read buffer 1. | ||
157 | */ | ||
158 | val = mv64x60_read(&bh, MV64360_SDRAM_CONFIG); | ||
159 | val = val & 0x03ffffff; | ||
160 | val = val | 0xf8000000; | ||
161 | mv64x60_write(&bh, MV64360_SDRAM_CONFIG, val); | ||
162 | |||
163 | /* | ||
164 | * Configure internal SRAM - | ||
165 | * Cache coherent write back, if CONFIG_MV64360_SRAM_CACHE_COHERENT set | ||
166 | * Parity enabled. | ||
167 | * Parity error propagation | ||
168 | * Arbitration not parked for CPU only | ||
169 | * Other bits are reserved. | ||
170 | */ | ||
171 | #ifdef CONFIG_MV64360_SRAM_CACHE_COHERENT | ||
172 | mv64x60_write(&bh, MV64360_SRAM_CONFIG, 0x001600b2); | ||
173 | #else | ||
174 | mv64x60_write(&bh, MV64360_SRAM_CONFIG, 0x001600b0); | ||
175 | #endif | ||
176 | |||
177 | hdpu_intr_setup(); | ||
178 | } | ||
179 | |||
180 | static void __init hdpu_setup_bridge(void) | ||
181 | { | ||
182 | struct mv64x60_setup_info si; | ||
183 | int i; | ||
184 | |||
185 | memset(&si, 0, sizeof(si)); | ||
186 | |||
187 | si.phys_reg_base = HDPU_BRIDGE_REG_BASE; | ||
188 | si.pci_0.enable_bus = 1; | ||
189 | si.pci_0.pci_io.cpu_base = HDPU_PCI0_IO_START_PROC_ADDR; | ||
190 | si.pci_0.pci_io.pci_base_hi = 0; | ||
191 | si.pci_0.pci_io.pci_base_lo = HDPU_PCI0_IO_START_PCI_ADDR; | ||
192 | si.pci_0.pci_io.size = HDPU_PCI0_IO_SIZE; | ||
193 | si.pci_0.pci_io.swap = MV64x60_CPU2PCI_SWAP_NONE; | ||
194 | si.pci_0.pci_mem[0].cpu_base = HDPU_PCI0_MEM_START_PROC_ADDR; | ||
195 | si.pci_0.pci_mem[0].pci_base_hi = HDPU_PCI0_MEM_START_PCI_HI_ADDR; | ||
196 | si.pci_0.pci_mem[0].pci_base_lo = HDPU_PCI0_MEM_START_PCI_LO_ADDR; | ||
197 | si.pci_0.pci_mem[0].size = HDPU_PCI0_MEM_SIZE; | ||
198 | si.pci_0.pci_mem[0].swap = MV64x60_CPU2PCI_SWAP_NONE; | ||
199 | si.pci_0.pci_cmd_bits = 0; | ||
200 | si.pci_0.latency_timer = 0x80; | ||
201 | |||
202 | si.pci_1.enable_bus = 1; | ||
203 | si.pci_1.pci_io.cpu_base = HDPU_PCI1_IO_START_PROC_ADDR; | ||
204 | si.pci_1.pci_io.pci_base_hi = 0; | ||
205 | si.pci_1.pci_io.pci_base_lo = HDPU_PCI1_IO_START_PCI_ADDR; | ||
206 | si.pci_1.pci_io.size = HDPU_PCI1_IO_SIZE; | ||
207 | si.pci_1.pci_io.swap = MV64x60_CPU2PCI_SWAP_NONE; | ||
208 | si.pci_1.pci_mem[0].cpu_base = HDPU_PCI1_MEM_START_PROC_ADDR; | ||
209 | si.pci_1.pci_mem[0].pci_base_hi = HDPU_PCI1_MEM_START_PCI_HI_ADDR; | ||
210 | si.pci_1.pci_mem[0].pci_base_lo = HDPU_PCI1_MEM_START_PCI_LO_ADDR; | ||
211 | si.pci_1.pci_mem[0].size = HDPU_PCI1_MEM_SIZE; | ||
212 | si.pci_1.pci_mem[0].swap = MV64x60_CPU2PCI_SWAP_NONE; | ||
213 | si.pci_1.pci_cmd_bits = 0; | ||
214 | si.pci_1.latency_timer = 0x80; | ||
215 | |||
216 | for (i = 0; i < MV64x60_CPU2MEM_WINDOWS; i++) { | ||
217 | #if defined(CONFIG_NOT_COHERENT_CACHE) | ||
218 | si.cpu_prot_options[i] = 0; | ||
219 | si.enet_options[i] = MV64360_ENET2MEM_SNOOP_NONE; | ||
220 | si.mpsc_options[i] = MV64360_MPSC2MEM_SNOOP_NONE; | ||
221 | si.idma_options[i] = MV64360_IDMA2MEM_SNOOP_NONE; | ||
222 | |||
223 | si.pci_1.acc_cntl_options[i] = | ||
224 | MV64360_PCI_ACC_CNTL_SNOOP_NONE | | ||
225 | MV64360_PCI_ACC_CNTL_SWAP_NONE | | ||
226 | MV64360_PCI_ACC_CNTL_MBURST_128_BYTES | | ||
227 | MV64360_PCI_ACC_CNTL_RDSIZE_256_BYTES; | ||
228 | |||
229 | si.pci_0.acc_cntl_options[i] = | ||
230 | MV64360_PCI_ACC_CNTL_SNOOP_NONE | | ||
231 | MV64360_PCI_ACC_CNTL_SWAP_NONE | | ||
232 | MV64360_PCI_ACC_CNTL_MBURST_128_BYTES | | ||
233 | MV64360_PCI_ACC_CNTL_RDSIZE_256_BYTES; | ||
234 | |||
235 | #else | ||
236 | si.cpu_prot_options[i] = 0; | ||
237 | si.enet_options[i] = MV64360_ENET2MEM_SNOOP_WB; /* errata */ | ||
238 | si.mpsc_options[i] = MV64360_MPSC2MEM_SNOOP_WB; /* errata */ | ||
239 | si.idma_options[i] = MV64360_IDMA2MEM_SNOOP_WB; /* errata */ | ||
240 | |||
241 | si.pci_0.acc_cntl_options[i] = | ||
242 | MV64360_PCI_ACC_CNTL_SNOOP_WB | | ||
243 | MV64360_PCI_ACC_CNTL_SWAP_NONE | | ||
244 | MV64360_PCI_ACC_CNTL_MBURST_32_BYTES | | ||
245 | MV64360_PCI_ACC_CNTL_RDSIZE_256_BYTES; | ||
246 | |||
247 | si.pci_1.acc_cntl_options[i] = | ||
248 | MV64360_PCI_ACC_CNTL_SNOOP_WB | | ||
249 | MV64360_PCI_ACC_CNTL_SWAP_NONE | | ||
250 | MV64360_PCI_ACC_CNTL_MBURST_32_BYTES | | ||
251 | MV64360_PCI_ACC_CNTL_RDSIZE_256_BYTES; | ||
252 | #endif | ||
253 | } | ||
254 | |||
255 | hdpu_cpustate_set(CPUSTATE_KERNEL_MAJOR | CPUSTATE_KERNEL_INIT_PCI); | ||
256 | |||
257 | /* Lookup PCI host bridges */ | ||
258 | mv64x60_init(&bh, &si); | ||
259 | pci_dram_offset = 0; /* System mem at same addr on PCI & cpu bus */ | ||
260 | ppc_md.pci_swizzle = common_swizzle; | ||
261 | ppc_md.pci_map_irq = hdpu_map_irq; | ||
262 | |||
263 | mv64x60_set_bus(&bh, 0, 0); | ||
264 | bh.hose_a->first_busno = 0; | ||
265 | bh.hose_a->last_busno = 0xff; | ||
266 | bh.hose_a->last_busno = pciauto_bus_scan(bh.hose_a, 0); | ||
267 | |||
268 | bh.hose_b->first_busno = bh.hose_a->last_busno + 1; | ||
269 | mv64x60_set_bus(&bh, 1, bh.hose_b->first_busno); | ||
270 | bh.hose_b->last_busno = 0xff; | ||
271 | bh.hose_b->last_busno = pciauto_bus_scan(bh.hose_b, | ||
272 | bh.hose_b->first_busno); | ||
273 | |||
274 | ppc_md.pci_exclude_device = mv64x60_pci_exclude_device; | ||
275 | |||
276 | hdpu_cpustate_set(CPUSTATE_KERNEL_MAJOR | CPUSTATE_KERNEL_INIT_REG); | ||
277 | /* | ||
278 | * Enabling of PCI internal-vs-external arbitration | ||
279 | * is a platform- and errata-dependent decision. | ||
280 | */ | ||
281 | return; | ||
282 | } | ||
283 | |||
284 | #if defined(CONFIG_SERIAL_MPSC_CONSOLE) | ||
285 | static void __init hdpu_early_serial_map(void) | ||
286 | { | ||
287 | #ifdef CONFIG_KGDB | ||
288 | static char first_time = 1; | ||
289 | |||
290 | #if defined(CONFIG_KGDB_TTYS0) | ||
291 | #define KGDB_PORT 0 | ||
292 | #elif defined(CONFIG_KGDB_TTYS1) | ||
293 | #define KGDB_PORT 1 | ||
294 | #else | ||
295 | #error "Invalid kgdb_tty port" | ||
296 | #endif | ||
297 | |||
298 | if (first_time) { | ||
299 | gt_early_mpsc_init(KGDB_PORT, | ||
300 | B9600 | CS8 | CREAD | HUPCL | CLOCAL); | ||
301 | first_time = 0; | ||
302 | } | ||
303 | |||
304 | return; | ||
305 | #endif | ||
306 | } | ||
307 | #endif | ||
308 | |||
309 | static void hdpu_init2(void) | ||
310 | { | ||
311 | return; | ||
312 | } | ||
313 | |||
314 | #if defined(CONFIG_MV643XX_ETH) | ||
315 | static void __init hdpu_fixup_eth_pdata(struct platform_device *pd) | ||
316 | { | ||
317 | |||
318 | struct mv643xx_eth_platform_data *eth_pd; | ||
319 | eth_pd = pd->dev.platform_data; | ||
320 | |||
321 | eth_pd->port_serial_control = | ||
322 | mv64x60_read(&bh, MV643XX_ETH_PORT_SERIAL_CONTROL_REG(pd->id) & ~1); | ||
323 | |||
324 | eth_pd->force_phy_addr = 1; | ||
325 | eth_pd->phy_addr = pd->id; | ||
326 | eth_pd->tx_queue_size = 400; | ||
327 | eth_pd->rx_queue_size = 800; | ||
328 | } | ||
329 | #endif | ||
330 | |||
331 | static void __init hdpu_fixup_mpsc_pdata(struct platform_device *pd) | ||
332 | { | ||
333 | |||
334 | struct mpsc_pdata *pdata; | ||
335 | |||
336 | pdata = (struct mpsc_pdata *)pd->dev.platform_data; | ||
337 | |||
338 | pdata->max_idle = 40; | ||
339 | if (ppcboot_bd_valid) | ||
340 | pdata->default_baud = ppcboot_bd.bi_baudrate; | ||
341 | else | ||
342 | pdata->default_baud = HDPU_DEFAULT_BAUD; | ||
343 | pdata->brg_clk_src = HDPU_MPSC_CLK_SRC; | ||
344 | pdata->brg_clk_freq = HDPU_MPSC_CLK_FREQ; | ||
345 | } | ||
346 | |||
347 | #if defined(CONFIG_HDPU_FEATURES) | ||
348 | static void __init hdpu_fixup_cpustate_pdata(struct platform_device *pd) | ||
349 | { | ||
350 | struct platform_device *pds[1]; | ||
351 | pds[0] = pd; | ||
352 | mv64x60_pd_fixup(&bh, pds, 1); | ||
353 | } | ||
354 | #endif | ||
355 | |||
356 | static int __init hdpu_platform_notify(struct device *dev) | ||
357 | { | ||
358 | static struct { | ||
359 | char *bus_id; | ||
360 | void ((*rtn) (struct platform_device * pdev)); | ||
361 | } dev_map[] = { | ||
362 | { | ||
363 | MPSC_CTLR_NAME ".0", hdpu_fixup_mpsc_pdata}, | ||
364 | #if defined(CONFIG_MV643XX_ETH) | ||
365 | { | ||
366 | MV643XX_ETH_NAME ".0", hdpu_fixup_eth_pdata}, | ||
367 | #endif | ||
368 | #if defined(CONFIG_HDPU_FEATURES) | ||
369 | { | ||
370 | HDPU_CPUSTATE_NAME ".0", hdpu_fixup_cpustate_pdata}, | ||
371 | #endif | ||
372 | }; | ||
373 | struct platform_device *pdev; | ||
374 | int i; | ||
375 | |||
376 | if (dev && dev->bus_id) | ||
377 | for (i = 0; i < ARRAY_SIZE(dev_map); i++) | ||
378 | if (!strncmp(dev->bus_id, dev_map[i].bus_id, | ||
379 | BUS_ID_SIZE)) { | ||
380 | |||
381 | pdev = container_of(dev, | ||
382 | struct platform_device, | ||
383 | dev); | ||
384 | dev_map[i].rtn(pdev); | ||
385 | } | ||
386 | |||
387 | return 0; | ||
388 | } | ||
389 | |||
390 | static void __init hdpu_setup_arch(void) | ||
391 | { | ||
392 | if (ppc_md.progress) | ||
393 | ppc_md.progress("hdpu_setup_arch: enter", 0); | ||
394 | #ifdef CONFIG_BLK_DEV_INITRD | ||
395 | if (initrd_start) | ||
396 | ROOT_DEV = Root_RAM0; | ||
397 | else | ||
398 | #endif | ||
399 | #ifdef CONFIG_ROOT_NFS | ||
400 | ROOT_DEV = Root_NFS; | ||
401 | #else | ||
402 | ROOT_DEV = Root_SDA2; | ||
403 | #endif | ||
404 | |||
405 | ppc_md.heartbeat = hdpu_heartbeat; | ||
406 | |||
407 | ppc_md.heartbeat_reset = HZ; | ||
408 | ppc_md.heartbeat_count = 1; | ||
409 | |||
410 | if (ppc_md.progress) | ||
411 | ppc_md.progress("hdpu_setup_arch: Enabling L2 cache", 0); | ||
412 | |||
413 | /* Enable L1 Parity Bits */ | ||
414 | hdpu_set_l1pe(); | ||
415 | |||
416 | /* Enable L2 and L3 caches (if 745x) */ | ||
417 | _set_L2CR(0x80080000); | ||
418 | |||
419 | if (ppc_md.progress) | ||
420 | ppc_md.progress("hdpu_setup_arch: enter", 0); | ||
421 | |||
422 | hdpu_setup_bridge(); | ||
423 | |||
424 | hdpu_setup_peripherals(); | ||
425 | |||
426 | #ifdef CONFIG_SERIAL_MPSC_CONSOLE | ||
427 | hdpu_early_serial_map(); | ||
428 | #endif | ||
429 | |||
430 | printk("SKY HDPU Compute Blade \n"); | ||
431 | |||
432 | if (ppc_md.progress) | ||
433 | ppc_md.progress("hdpu_setup_arch: exit", 0); | ||
434 | |||
435 | hdpu_cpustate_set(CPUSTATE_KERNEL_MAJOR | CPUSTATE_KERNEL_OK); | ||
436 | return; | ||
437 | } | ||
438 | static void __init hdpu_init_irq(void) | ||
439 | { | ||
440 | mv64360_init_irq(); | ||
441 | } | ||
442 | |||
443 | static void __init hdpu_set_l1pe() | ||
444 | { | ||
445 | unsigned long ictrl; | ||
446 | asm volatile ("mfspr %0, 1011":"=r" (ictrl):); | ||
447 | ictrl |= ICTRL_EICE | ICTRL_EDC | ICTRL_EICP; | ||
448 | asm volatile ("mtspr 1011, %0"::"r" (ictrl)); | ||
449 | } | ||
450 | |||
451 | /* | ||
452 | * Set BAT 1 to map 0xf1000000 to end of physical memory space. | ||
453 | */ | ||
454 | static __inline__ void hdpu_set_bat(void) | ||
455 | { | ||
456 | mb(); | ||
457 | mtspr(SPRN_DBAT1U, 0xf10001fe); | ||
458 | mtspr(SPRN_DBAT1L, 0xf100002a); | ||
459 | mb(); | ||
460 | |||
461 | return; | ||
462 | } | ||
463 | |||
464 | unsigned long __init hdpu_find_end_of_memory(void) | ||
465 | { | ||
466 | return mv64x60_get_mem_size(CONFIG_MV64X60_NEW_BASE, | ||
467 | MV64x60_TYPE_MV64360); | ||
468 | } | ||
469 | |||
470 | static void hdpu_reset_board(void) | ||
471 | { | ||
472 | volatile int infinite = 1; | ||
473 | |||
474 | hdpu_cpustate_set(CPUSTATE_KERNEL_MAJOR | CPUSTATE_KERNEL_RESET); | ||
475 | |||
476 | local_irq_disable(); | ||
477 | |||
478 | /* Clear all the LEDs */ | ||
479 | mv64x60_write(&bh, MV64x60_GPP_VALUE_CLR, ((1 << 4) | | ||
480 | (1 << 5) | (1 << 6))); | ||
481 | |||
482 | /* disable and invalidate the L2 cache */ | ||
483 | _set_L2CR(0); | ||
484 | _set_L2CR(0x200000); | ||
485 | |||
486 | /* flush and disable L1 I/D cache */ | ||
487 | __asm__ __volatile__ | ||
488 | ("\n" | ||
489 | "mfspr 3,1008\n" | ||
490 | "ori 5,5,0xcc00\n" | ||
491 | "ori 4,3,0xc00\n" | ||
492 | "andc 5,3,5\n" | ||
493 | "sync\n" | ||
494 | "mtspr 1008,4\n" | ||
495 | "isync\n" "sync\n" "mtspr 1008,5\n" "isync\n" "sync\n"); | ||
496 | |||
497 | /* Hit the reset bit */ | ||
498 | mv64x60_write(&bh, MV64x60_GPP_VALUE_CLR, (1 << 3)); | ||
499 | |||
500 | while (infinite) | ||
501 | infinite = infinite; | ||
502 | |||
503 | return; | ||
504 | } | ||
505 | |||
506 | static void hdpu_restart(char *cmd) | ||
507 | { | ||
508 | volatile ulong i = 10000000; | ||
509 | |||
510 | hdpu_reset_board(); | ||
511 | |||
512 | while (i-- > 0) ; | ||
513 | panic("restart failed\n"); | ||
514 | } | ||
515 | |||
516 | static void hdpu_halt(void) | ||
517 | { | ||
518 | local_irq_disable(); | ||
519 | |||
520 | hdpu_cpustate_set(CPUSTATE_KERNEL_MAJOR | CPUSTATE_KERNEL_HALT); | ||
521 | |||
522 | /* Clear all the LEDs */ | ||
523 | mv64x60_write(&bh, MV64x60_GPP_VALUE_CLR, ((1 << 4) | (1 << 5) | | ||
524 | (1 << 6))); | ||
525 | while (1) ; | ||
526 | /* NOTREACHED */ | ||
527 | } | ||
528 | |||
529 | static void hdpu_power_off(void) | ||
530 | { | ||
531 | hdpu_halt(); | ||
532 | /* NOTREACHED */ | ||
533 | } | ||
534 | |||
535 | static int hdpu_show_cpuinfo(struct seq_file *m) | ||
536 | { | ||
537 | uint pvid; | ||
538 | |||
539 | pvid = mfspr(SPRN_PVR); | ||
540 | seq_printf(m, "vendor\t\t: Sky Computers\n"); | ||
541 | seq_printf(m, "machine\t\t: HDPU Compute Blade\n"); | ||
542 | seq_printf(m, "PVID\t\t: 0x%x, vendor: %s\n", | ||
543 | pvid, (pvid & (1 << 15) ? "IBM" : "Motorola")); | ||
544 | |||
545 | return 0; | ||
546 | } | ||
547 | |||
548 | static void __init hdpu_calibrate_decr(void) | ||
549 | { | ||
550 | ulong freq; | ||
551 | |||
552 | if (ppcboot_bd_valid) | ||
553 | freq = ppcboot_bd.bi_busfreq / 4; | ||
554 | else | ||
555 | freq = 133000000; | ||
556 | |||
557 | printk("time_init: decrementer frequency = %lu.%.6lu MHz\n", | ||
558 | freq / 1000000, freq % 1000000); | ||
559 | |||
560 | tb_ticks_per_jiffy = freq / HZ; | ||
561 | tb_to_us = mulhwu_scale_factor(freq, 1000000); | ||
562 | |||
563 | return; | ||
564 | } | ||
565 | |||
566 | static void parse_bootinfo(unsigned long r3, | ||
567 | unsigned long r4, unsigned long r5, | ||
568 | unsigned long r6, unsigned long r7) | ||
569 | { | ||
570 | bd_t *bd = NULL; | ||
571 | char *cmdline_start = NULL; | ||
572 | int cmdline_len = 0; | ||
573 | |||
574 | if (r3) { | ||
575 | if ((r3 & 0xf0000000) == 0) | ||
576 | r3 += KERNELBASE; | ||
577 | if ((r3 & 0xf0000000) == KERNELBASE) { | ||
578 | bd = (void *)r3; | ||
579 | |||
580 | memcpy(&ppcboot_bd, bd, sizeof(ppcboot_bd)); | ||
581 | ppcboot_bd_valid = 1; | ||
582 | } | ||
583 | } | ||
584 | #ifdef CONFIG_BLK_DEV_INITRD | ||
585 | if (r4 && r5 && r5 > r4) { | ||
586 | if ((r4 & 0xf0000000) == 0) | ||
587 | r4 += KERNELBASE; | ||
588 | if ((r5 & 0xf0000000) == 0) | ||
589 | r5 += KERNELBASE; | ||
590 | if ((r4 & 0xf0000000) == KERNELBASE) { | ||
591 | initrd_start = r4; | ||
592 | initrd_end = r5; | ||
593 | initrd_below_start_ok = 1; | ||
594 | } | ||
595 | } | ||
596 | #endif /* CONFIG_BLK_DEV_INITRD */ | ||
597 | |||
598 | if (r6 && r7 && r7 > r6) { | ||
599 | if ((r6 & 0xf0000000) == 0) | ||
600 | r6 += KERNELBASE; | ||
601 | if ((r7 & 0xf0000000) == 0) | ||
602 | r7 += KERNELBASE; | ||
603 | if ((r6 & 0xf0000000) == KERNELBASE) { | ||
604 | cmdline_start = (void *)r6; | ||
605 | cmdline_len = (r7 - r6); | ||
606 | strncpy(cmd_line, cmdline_start, cmdline_len); | ||
607 | } | ||
608 | } | ||
609 | } | ||
610 | |||
611 | #if defined(CONFIG_BLK_DEV_IDE) || defined(CONFIG_BLK_DEV_IDE_MODULE) | ||
612 | static int hdpu_ide_check_region(ide_ioreg_t from, unsigned int extent) | ||
613 | { | ||
614 | return check_region(from, extent); | ||
615 | } | ||
616 | |||
617 | static void | ||
618 | hdpu_ide_request_region(ide_ioreg_t from, unsigned int extent, const char *name) | ||
619 | { | ||
620 | request_region(from, extent, name); | ||
621 | return; | ||
622 | } | ||
623 | |||
624 | static void hdpu_ide_release_region(ide_ioreg_t from, unsigned int extent) | ||
625 | { | ||
626 | release_region(from, extent); | ||
627 | return; | ||
628 | } | ||
629 | |||
630 | static void __init | ||
631 | hdpu_ide_pci_init_hwif_ports(hw_regs_t * hw, ide_ioreg_t data_port, | ||
632 | ide_ioreg_t ctrl_port, int *irq) | ||
633 | { | ||
634 | struct pci_dev *dev; | ||
635 | |||
636 | pci_for_each_dev(dev) { | ||
637 | if (((dev->class >> 8) == PCI_CLASS_STORAGE_IDE) || | ||
638 | ((dev->class >> 8) == PCI_CLASS_STORAGE_RAID)) { | ||
639 | hw->irq = dev->irq; | ||
640 | |||
641 | if (irq != NULL) { | ||
642 | *irq = dev->irq; | ||
643 | } | ||
644 | } | ||
645 | } | ||
646 | |||
647 | return; | ||
648 | } | ||
649 | #endif | ||
650 | |||
651 | void hdpu_heartbeat(void) | ||
652 | { | ||
653 | if (mv64x60_read(&bh, MV64x60_GPP_VALUE) & (1 << 5)) | ||
654 | mv64x60_write(&bh, MV64x60_GPP_VALUE_CLR, (1 << 5)); | ||
655 | else | ||
656 | mv64x60_write(&bh, MV64x60_GPP_VALUE_SET, (1 << 5)); | ||
657 | |||
658 | ppc_md.heartbeat_count = ppc_md.heartbeat_reset; | ||
659 | |||
660 | } | ||
661 | |||
662 | static void __init hdpu_map_io(void) | ||
663 | { | ||
664 | io_block_mapping(0xf1000000, 0xf1000000, 0x20000, _PAGE_IO); | ||
665 | } | ||
666 | |||
667 | #ifdef CONFIG_SMP | ||
668 | char hdpu_smp0[] = "SMP Cpu #0"; | ||
669 | char hdpu_smp1[] = "SMP Cpu #1"; | ||
670 | |||
671 | static irqreturn_t hdpu_smp_cpu0_int_handler(int irq, void *dev_id, | ||
672 | struct pt_regs *regs) | ||
673 | { | ||
674 | volatile unsigned int doorbell; | ||
675 | |||
676 | doorbell = mv64x60_read(&bh, MV64360_CPU0_DOORBELL); | ||
677 | |||
678 | /* Ack the doorbell interrupts */ | ||
679 | mv64x60_write(&bh, MV64360_CPU0_DOORBELL_CLR, doorbell); | ||
680 | |||
681 | if (doorbell & 1) { | ||
682 | smp_message_recv(0, regs); | ||
683 | } | ||
684 | if (doorbell & 2) { | ||
685 | smp_message_recv(1, regs); | ||
686 | } | ||
687 | if (doorbell & 4) { | ||
688 | smp_message_recv(2, regs); | ||
689 | } | ||
690 | if (doorbell & 8) { | ||
691 | smp_message_recv(3, regs); | ||
692 | } | ||
693 | return IRQ_HANDLED; | ||
694 | } | ||
695 | |||
696 | static irqreturn_t hdpu_smp_cpu1_int_handler(int irq, void *dev_id, | ||
697 | struct pt_regs *regs) | ||
698 | { | ||
699 | volatile unsigned int doorbell; | ||
700 | |||
701 | doorbell = mv64x60_read(&bh, MV64360_CPU1_DOORBELL); | ||
702 | |||
703 | /* Ack the doorbell interrupts */ | ||
704 | mv64x60_write(&bh, MV64360_CPU1_DOORBELL_CLR, doorbell); | ||
705 | |||
706 | if (doorbell & 1) { | ||
707 | smp_message_recv(0, regs); | ||
708 | } | ||
709 | if (doorbell & 2) { | ||
710 | smp_message_recv(1, regs); | ||
711 | } | ||
712 | if (doorbell & 4) { | ||
713 | smp_message_recv(2, regs); | ||
714 | } | ||
715 | if (doorbell & 8) { | ||
716 | smp_message_recv(3, regs); | ||
717 | } | ||
718 | return IRQ_HANDLED; | ||
719 | } | ||
720 | |||
721 | static void smp_hdpu_CPU_two(void) | ||
722 | { | ||
723 | __asm__ __volatile__ | ||
724 | ("\n" | ||
725 | "lis 3,0x0000\n" | ||
726 | "ori 3,3,0x00c0\n" | ||
727 | "mtspr 26, 3\n" "li 4,0\n" "mtspr 27,4\n" "rfi"); | ||
728 | |||
729 | } | ||
730 | |||
731 | static int smp_hdpu_probe(void) | ||
732 | { | ||
733 | int *cpu_count_reg; | ||
734 | int num_cpus = 0; | ||
735 | |||
736 | cpu_count_reg = ioremap(HDPU_NEXUS_ID_BASE, HDPU_NEXUS_ID_SIZE); | ||
737 | if (cpu_count_reg) { | ||
738 | num_cpus = (*cpu_count_reg >> 20) & 0x3; | ||
739 | iounmap(cpu_count_reg); | ||
740 | } | ||
741 | |||
742 | /* Validate the bits in the CPLD. If we could not map the reg, return 2. | ||
743 | * If the register reported 0 or 3, return 2. | ||
744 | * Older CPLD revisions set these bits to all ones (val = 3). | ||
745 | */ | ||
746 | if ((num_cpus < 1) || (num_cpus > 2)) { | ||
747 | printk | ||
748 | ("Unable to determine the number of processors %d . deafulting to 2.\n", | ||
749 | num_cpus); | ||
750 | num_cpus = 2; | ||
751 | } | ||
752 | return num_cpus; | ||
753 | } | ||
754 | |||
755 | static void | ||
756 | smp_hdpu_message_pass(int target, int msg, unsigned long data, int wait) | ||
757 | { | ||
758 | if (msg > 0x3) { | ||
759 | printk("SMP %d: smp_message_pass: unknown msg %d\n", | ||
760 | smp_processor_id(), msg); | ||
761 | return; | ||
762 | } | ||
763 | switch (target) { | ||
764 | case MSG_ALL: | ||
765 | mv64x60_write(&bh, MV64360_CPU0_DOORBELL, 1 << msg); | ||
766 | mv64x60_write(&bh, MV64360_CPU1_DOORBELL, 1 << msg); | ||
767 | break; | ||
768 | case MSG_ALL_BUT_SELF: | ||
769 | if (smp_processor_id()) | ||
770 | mv64x60_write(&bh, MV64360_CPU0_DOORBELL, 1 << msg); | ||
771 | else | ||
772 | mv64x60_write(&bh, MV64360_CPU1_DOORBELL, 1 << msg); | ||
773 | break; | ||
774 | default: | ||
775 | if (target == 0) | ||
776 | mv64x60_write(&bh, MV64360_CPU0_DOORBELL, 1 << msg); | ||
777 | else | ||
778 | mv64x60_write(&bh, MV64360_CPU1_DOORBELL, 1 << msg); | ||
779 | break; | ||
780 | } | ||
781 | } | ||
782 | |||
783 | static void smp_hdpu_kick_cpu(int nr) | ||
784 | { | ||
785 | volatile unsigned int *bootaddr; | ||
786 | |||
787 | if (ppc_md.progress) | ||
788 | ppc_md.progress("smp_hdpu_kick_cpu", 0); | ||
789 | |||
790 | hdpu_cpustate_set(CPUSTATE_KERNEL_MAJOR | CPUSTATE_KERNEL_CPU1_KICK); | ||
791 | |||
792 | /* Disable BootCS. Must also reduce the windows size to zero. */ | ||
793 | bh.ci->disable_window_32bit(&bh, MV64x60_CPU2BOOT_WIN); | ||
794 | mv64x60_set_32bit_window(&bh, MV64x60_CPU2BOOT_WIN, 0, 0, 0); | ||
795 | |||
796 | bootaddr = ioremap(HDPU_INTERNAL_SRAM_BASE, HDPU_INTERNAL_SRAM_SIZE); | ||
797 | if (!bootaddr) { | ||
798 | if (ppc_md.progress) | ||
799 | ppc_md.progress("smp_hdpu_kick_cpu: ioremap failed", 0); | ||
800 | return; | ||
801 | } | ||
802 | |||
803 | memcpy((void *)(bootaddr + 0x40), (void *)&smp_hdpu_CPU_two, 0x20); | ||
804 | |||
805 | /* map SRAM to 0xfff00000 */ | ||
806 | bh.ci->disable_window_32bit(&bh, MV64x60_CPU2SRAM_WIN); | ||
807 | |||
808 | mv64x60_set_32bit_window(&bh, MV64x60_CPU2SRAM_WIN, | ||
809 | 0xfff00000, HDPU_INTERNAL_SRAM_SIZE, 0); | ||
810 | bh.ci->enable_window_32bit(&bh, MV64x60_CPU2SRAM_WIN); | ||
811 | |||
812 | /* Enable CPU1 arbitration */ | ||
813 | mv64x60_clr_bits(&bh, MV64x60_CPU_MASTER_CNTL, (1 << 9)); | ||
814 | |||
815 | /* | ||
816 | * Wait 100mSecond until other CPU has reached __secondary_start. | ||
817 | * When it reaches, it is permittable to rever the SRAM mapping etc... | ||
818 | */ | ||
819 | mdelay(100); | ||
820 | *(unsigned long *)KERNELBASE = nr; | ||
821 | asm volatile ("dcbf 0,%0"::"r" (KERNELBASE):"memory"); | ||
822 | |||
823 | iounmap(bootaddr); | ||
824 | |||
825 | /* Set up window for internal sram (256KByte insize) */ | ||
826 | bh.ci->disable_window_32bit(&bh, MV64x60_CPU2SRAM_WIN); | ||
827 | mv64x60_set_32bit_window(&bh, MV64x60_CPU2SRAM_WIN, | ||
828 | HDPU_INTERNAL_SRAM_BASE, | ||
829 | HDPU_INTERNAL_SRAM_SIZE, 0); | ||
830 | bh.ci->enable_window_32bit(&bh, MV64x60_CPU2SRAM_WIN); | ||
831 | /* | ||
832 | * Set up windows for embedded FLASH (using boot CS window). | ||
833 | */ | ||
834 | |||
835 | bh.ci->disable_window_32bit(&bh, MV64x60_CPU2BOOT_WIN); | ||
836 | mv64x60_set_32bit_window(&bh, MV64x60_CPU2BOOT_WIN, | ||
837 | HDPU_EMB_FLASH_BASE, HDPU_EMB_FLASH_SIZE, 0); | ||
838 | bh.ci->enable_window_32bit(&bh, MV64x60_CPU2BOOT_WIN); | ||
839 | } | ||
840 | |||
841 | static void smp_hdpu_setup_cpu(int cpu_nr) | ||
842 | { | ||
843 | if (cpu_nr == 0) { | ||
844 | if (ppc_md.progress) | ||
845 | ppc_md.progress("smp_hdpu_setup_cpu 0", 0); | ||
846 | mv64x60_write(&bh, MV64360_CPU0_DOORBELL_CLR, 0xff); | ||
847 | mv64x60_write(&bh, MV64360_CPU0_DOORBELL_MASK, 0xff); | ||
848 | request_irq(60, hdpu_smp_cpu0_int_handler, | ||
849 | SA_INTERRUPT, hdpu_smp0, 0); | ||
850 | } | ||
851 | |||
852 | if (cpu_nr == 1) { | ||
853 | if (ppc_md.progress) | ||
854 | ppc_md.progress("smp_hdpu_setup_cpu 1", 0); | ||
855 | |||
856 | hdpu_cpustate_set(CPUSTATE_KERNEL_MAJOR | | ||
857 | CPUSTATE_KERNEL_CPU1_OK); | ||
858 | |||
859 | /* Enable L1 Parity Bits */ | ||
860 | hdpu_set_l1pe(); | ||
861 | |||
862 | /* Enable L2 cache */ | ||
863 | _set_L2CR(0); | ||
864 | _set_L2CR(0x80080000); | ||
865 | |||
866 | mv64x60_write(&bh, MV64360_CPU1_DOORBELL_CLR, 0x0); | ||
867 | mv64x60_write(&bh, MV64360_CPU1_DOORBELL_MASK, 0xff); | ||
868 | request_irq(28, hdpu_smp_cpu1_int_handler, | ||
869 | SA_INTERRUPT, hdpu_smp1, 0); | ||
870 | } | ||
871 | |||
872 | } | ||
873 | |||
874 | void __devinit hdpu_tben_give() | ||
875 | { | ||
876 | volatile unsigned long *val = 0; | ||
877 | |||
878 | /* By writing 0 to the TBEN_BASE, the timebases is frozen */ | ||
879 | val = ioremap(HDPU_TBEN_BASE, 4); | ||
880 | *val = 0; | ||
881 | mb(); | ||
882 | |||
883 | spin_lock(&timebase_lock); | ||
884 | timebase_upper = get_tbu(); | ||
885 | timebase_lower = get_tbl(); | ||
886 | spin_unlock(&timebase_lock); | ||
887 | |||
888 | while (timebase_upper || timebase_lower) | ||
889 | barrier(); | ||
890 | |||
891 | /* By writing 1 to the TBEN_BASE, the timebases is thawed */ | ||
892 | *val = 1; | ||
893 | mb(); | ||
894 | |||
895 | iounmap(val); | ||
896 | |||
897 | } | ||
898 | |||
899 | void __devinit hdpu_tben_take() | ||
900 | { | ||
901 | while (!(timebase_upper || timebase_lower)) | ||
902 | barrier(); | ||
903 | |||
904 | spin_lock(&timebase_lock); | ||
905 | set_tb(timebase_upper, timebase_lower); | ||
906 | timebase_upper = 0; | ||
907 | timebase_lower = 0; | ||
908 | spin_unlock(&timebase_lock); | ||
909 | } | ||
910 | |||
911 | static struct smp_ops_t hdpu_smp_ops = { | ||
912 | .message_pass = smp_hdpu_message_pass, | ||
913 | .probe = smp_hdpu_probe, | ||
914 | .kick_cpu = smp_hdpu_kick_cpu, | ||
915 | .setup_cpu = smp_hdpu_setup_cpu, | ||
916 | .give_timebase = hdpu_tben_give, | ||
917 | .take_timebase = hdpu_tben_take, | ||
918 | }; | ||
919 | #endif /* CONFIG_SMP */ | ||
920 | |||
921 | void __init | ||
922 | platform_init(unsigned long r3, unsigned long r4, unsigned long r5, | ||
923 | unsigned long r6, unsigned long r7) | ||
924 | { | ||
925 | parse_bootinfo(r3, r4, r5, r6, r7); | ||
926 | |||
927 | isa_mem_base = 0; | ||
928 | |||
929 | ppc_md.setup_arch = hdpu_setup_arch; | ||
930 | ppc_md.init = hdpu_init2; | ||
931 | ppc_md.show_cpuinfo = hdpu_show_cpuinfo; | ||
932 | ppc_md.init_IRQ = hdpu_init_irq; | ||
933 | ppc_md.get_irq = mv64360_get_irq; | ||
934 | ppc_md.restart = hdpu_restart; | ||
935 | ppc_md.power_off = hdpu_power_off; | ||
936 | ppc_md.halt = hdpu_halt; | ||
937 | ppc_md.find_end_of_memory = hdpu_find_end_of_memory; | ||
938 | ppc_md.calibrate_decr = hdpu_calibrate_decr; | ||
939 | ppc_md.setup_io_mappings = hdpu_map_io; | ||
940 | |||
941 | bh.p_base = CONFIG_MV64X60_NEW_BASE; | ||
942 | bh.v_base = (unsigned long *)bh.p_base; | ||
943 | |||
944 | hdpu_set_bat(); | ||
945 | |||
946 | #if defined(CONFIG_SERIAL_TEXT_DEBUG) | ||
947 | ppc_md.progress = hdpu_mpsc_progress; /* embedded UART */ | ||
948 | mv64x60_progress_init(bh.p_base); | ||
949 | #endif /* CONFIG_SERIAL_TEXT_DEBUG */ | ||
950 | |||
951 | #ifdef CONFIG_SMP | ||
952 | ppc_md.smp_ops = &hdpu_smp_ops; | ||
953 | #endif /* CONFIG_SMP */ | ||
954 | |||
955 | #if defined(CONFIG_SERIAL_MPSC) || defined(CONFIG_MV643XX_ETH) | ||
956 | platform_notify = hdpu_platform_notify; | ||
957 | #endif | ||
958 | return; | ||
959 | } | ||
960 | |||
961 | #if defined(CONFIG_SERIAL_TEXT_DEBUG) && defined(CONFIG_SERIAL_MPSC_CONSOLE) | ||
962 | /* SMP safe version of the serial text debug routine. Uses Semaphore 0 */ | ||
963 | void hdpu_mpsc_progress(char *s, unsigned short hex) | ||
964 | { | ||
965 | while (mv64x60_read(&bh, MV64360_WHO_AM_I) != | ||
966 | mv64x60_read(&bh, MV64360_SEMAPHORE_0)) { | ||
967 | } | ||
968 | mv64x60_mpsc_progress(s, hex); | ||
969 | mv64x60_write(&bh, MV64360_SEMAPHORE_0, 0xff); | ||
970 | } | ||
971 | #endif | ||
972 | |||
973 | static void hdpu_cpustate_set(unsigned char new_state) | ||
974 | { | ||
975 | unsigned int state = (new_state << 21); | ||
976 | mv64x60_write(&bh, MV64x60_GPP_VALUE_CLR, (0xff << 21)); | ||
977 | mv64x60_write(&bh, MV64x60_GPP_VALUE_CLR, state); | ||
978 | } | ||
979 | |||
980 | #ifdef CONFIG_MTD_PHYSMAP | ||
981 | static struct mtd_partition hdpu_partitions[] = { | ||
982 | { | ||
983 | .name = "Root FS", | ||
984 | .size = 0x03400000, | ||
985 | .offset = 0, | ||
986 | .mask_flags = 0, | ||
987 | },{ | ||
988 | .name = "User FS", | ||
989 | .size = 0x00800000, | ||
990 | .offset = 0x03400000, | ||
991 | .mask_flags = 0, | ||
992 | },{ | ||
993 | .name = "Kernel Image", | ||
994 | .size = 0x002C0000, | ||
995 | .offset = 0x03C00000, | ||
996 | .mask_flags = 0, | ||
997 | },{ | ||
998 | .name = "bootEnv", | ||
999 | .size = 0x00040000, | ||
1000 | .offset = 0x03EC0000, | ||
1001 | .mask_flags = 0, | ||
1002 | },{ | ||
1003 | .name = "bootROM", | ||
1004 | .size = 0x00100000, | ||
1005 | .offset = 0x03F00000, | ||
1006 | .mask_flags = 0, | ||
1007 | } | ||
1008 | }; | ||
1009 | |||
1010 | static int __init hdpu_setup_mtd(void) | ||
1011 | { | ||
1012 | |||
1013 | physmap_set_partitions(hdpu_partitions, 5); | ||
1014 | return 0; | ||
1015 | } | ||
1016 | |||
1017 | arch_initcall(hdpu_setup_mtd); | ||
1018 | #endif | ||
1019 | |||
1020 | #ifdef CONFIG_HDPU_FEATURES | ||
1021 | |||
1022 | static struct resource hdpu_cpustate_resources[] = { | ||
1023 | [0] = { | ||
1024 | .name = "addr base", | ||
1025 | .start = MV64x60_GPP_VALUE_SET, | ||
1026 | .end = MV64x60_GPP_VALUE_CLR + 1, | ||
1027 | .flags = IORESOURCE_MEM, | ||
1028 | }, | ||
1029 | }; | ||
1030 | |||
1031 | static struct resource hdpu_nexus_resources[] = { | ||
1032 | [0] = { | ||
1033 | .name = "nexus register", | ||
1034 | .start = HDPU_NEXUS_ID_BASE, | ||
1035 | .end = HDPU_NEXUS_ID_BASE + HDPU_NEXUS_ID_SIZE, | ||
1036 | .flags = IORESOURCE_MEM, | ||
1037 | }, | ||
1038 | }; | ||
1039 | |||
1040 | static struct platform_device hdpu_cpustate_device = { | ||
1041 | .name = HDPU_CPUSTATE_NAME, | ||
1042 | .id = 0, | ||
1043 | .num_resources = ARRAY_SIZE(hdpu_cpustate_resources), | ||
1044 | .resource = hdpu_cpustate_resources, | ||
1045 | }; | ||
1046 | |||
1047 | static struct platform_device hdpu_nexus_device = { | ||
1048 | .name = HDPU_NEXUS_NAME, | ||
1049 | .id = 0, | ||
1050 | .num_resources = ARRAY_SIZE(hdpu_nexus_resources), | ||
1051 | .resource = hdpu_nexus_resources, | ||
1052 | }; | ||
1053 | |||
1054 | static int __init hdpu_add_pds(void) | ||
1055 | { | ||
1056 | platform_device_register(&hdpu_cpustate_device); | ||
1057 | platform_device_register(&hdpu_nexus_device); | ||
1058 | return 0; | ||
1059 | } | ||
1060 | |||
1061 | arch_initcall(hdpu_add_pds); | ||
1062 | #endif | ||
diff --git a/arch/ppc/platforms/hdpu.h b/arch/ppc/platforms/hdpu.h new file mode 100644 index 000000000000..07c3cffb5c7b --- /dev/null +++ b/arch/ppc/platforms/hdpu.h | |||
@@ -0,0 +1,82 @@ | |||
1 | /* | ||
2 | * arch/ppc/platforms/hdpu.h | ||
3 | * | ||
4 | * Definitions for Sky Computers HDPU board. | ||
5 | * | ||
6 | * Brian Waite <waite@skycomputers.com> | ||
7 | * | ||
8 | * Based on code done by Rabeeh Khoury - rabeeh@galileo.co.il | ||
9 | * Based on code done by Mark A. Greer <mgreer@mvista.com> | ||
10 | * Based on code done by Tim Montgomery <timm@artesyncp.com> | ||
11 | * | ||
12 | * | ||
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. | ||
17 | */ | ||
18 | |||
19 | /* | ||
20 | * The MV64360 has 2 PCI buses each with 1 window from the CPU bus to | ||
21 | * PCI I/O space and 4 windows from the CPU bus to PCI MEM space. | ||
22 | * We'll only use one PCI MEM window on each PCI bus. | ||
23 | * | ||
24 | * This is the CPU physical memory map (windows must be at least 64K and start | ||
25 | * on a boundary that is a multiple of the window size): | ||
26 | * | ||
27 | * 0x80000000-0x8fffffff - PCI 0 MEM | ||
28 | * 0xa0000000-0xafffffff - PCI 1 MEM | ||
29 | * 0xc0000000-0xc0ffffff - PCI 0 I/O | ||
30 | * 0xc1000000-0xc1ffffff - PCI 1 I/O | ||
31 | |||
32 | * 0xf1000000-0xf100ffff - MV64360 Registers | ||
33 | * 0xf1010000-0xfb9fffff - HOLE | ||
34 | * 0xfbfa0000-0xfbfaffff - TBEN | ||
35 | * 0xfbf00000-0xfbfbffff - NEXUS | ||
36 | * 0xfbfc0000-0xfbffffff - Internal SRAM | ||
37 | * 0xfc000000-0xffffffff - Boot window | ||
38 | */ | ||
39 | |||
40 | #ifndef __PPC_PLATFORMS_HDPU_H | ||
41 | #define __PPC_PLATFORMS_HDPU_H | ||
42 | |||
43 | /* CPU Physical Memory Map setup. */ | ||
44 | #define HDPU_BRIDGE_REG_BASE 0xf1000000 | ||
45 | |||
46 | #define HDPU_TBEN_BASE 0xfbfa0000 | ||
47 | #define HDPU_TBEN_SIZE 0x00010000 | ||
48 | #define HDPU_NEXUS_ID_BASE 0xfbfb0000 | ||
49 | #define HDPU_NEXUS_ID_SIZE 0x00010000 | ||
50 | #define HDPU_INTERNAL_SRAM_BASE 0xfbfc0000 | ||
51 | #define HDPU_INTERNAL_SRAM_SIZE 0x00040000 | ||
52 | #define HDPU_EMB_FLASH_BASE 0xfc000000 | ||
53 | #define HDPU_EMB_FLASH_SIZE 0x04000000 | ||
54 | |||
55 | /* PCI Mappings */ | ||
56 | |||
57 | #define HDPU_PCI0_MEM_START_PROC_ADDR 0x80000000 | ||
58 | #define HDPU_PCI0_MEM_START_PCI_HI_ADDR 0x00000000 | ||
59 | #define HDPU_PCI0_MEM_START_PCI_LO_ADDR HDPU_PCI0_MEM_START_PROC_ADDR | ||
60 | #define HDPU_PCI0_MEM_SIZE 0x10000000 | ||
61 | |||
62 | #define HDPU_PCI1_MEM_START_PROC_ADDR 0xc0000000 | ||
63 | #define HDPU_PCI1_MEM_START_PCI_HI_ADDR 0x00000000 | ||
64 | #define HDPU_PCI1_MEM_START_PCI_LO_ADDR HDPU_PCI1_MEM_START_PROC_ADDR | ||
65 | #define HDPU_PCI1_MEM_SIZE 0x20000000 | ||
66 | |||
67 | #define HDPU_PCI0_IO_START_PROC_ADDR 0xc0000000 | ||
68 | #define HDPU_PCI0_IO_START_PCI_ADDR 0x00000000 | ||
69 | #define HDPU_PCI0_IO_SIZE 0x01000000 | ||
70 | |||
71 | #define HDPU_PCI1_IO_START_PROC_ADDR 0xc1000000 | ||
72 | #define HDPU_PCI1_IO_START_PCI_ADDR 0x01000000 | ||
73 | #define HDPU_PCI1_IO_SIZE 0x01000000 | ||
74 | |||
75 | #define HDPU_DEFAULT_BAUD 115200 | ||
76 | #define HDPU_MPSC_CLK_SRC 8 /* TCLK */ | ||
77 | #define HDPU_MPSC_CLK_FREQ 133000000 /* 133 Mhz */ | ||
78 | |||
79 | #define HDPU_PCI_0_IRQ (8+64) | ||
80 | #define HDPU_PCI_1_IRQ (13+64) | ||
81 | |||
82 | #endif /* __PPC_PLATFORMS_HDPU_H */ | ||
diff --git a/arch/ppc/platforms/hermes.h b/arch/ppc/platforms/hermes.h new file mode 100644 index 000000000000..198fc590b9f5 --- /dev/null +++ b/arch/ppc/platforms/hermes.h | |||
@@ -0,0 +1,27 @@ | |||
1 | /* | ||
2 | * Multidata HERMES-PRO ( / SL ) board specific definitions | ||
3 | * | ||
4 | * Copyright (c) 2000, 2001 Wolfgang Denk (wd@denx.de) | ||
5 | */ | ||
6 | |||
7 | #ifndef __MACH_HERMES_H | ||
8 | #define __MACH_HERMES_H | ||
9 | |||
10 | #include <linux/config.h> | ||
11 | |||
12 | #include <asm/ppcboot.h> | ||
13 | |||
14 | #define HERMES_IMMR_BASE 0xFF000000 /* phys. addr of IMMR */ | ||
15 | #define HERMES_IMAP_SIZE (64 * 1024) /* size of mapped area */ | ||
16 | |||
17 | #define IMAP_ADDR HERMES_IMMR_BASE /* physical base address of IMMR area */ | ||
18 | #define IMAP_SIZE HERMES_IMAP_SIZE /* mapped size of IMMR area */ | ||
19 | |||
20 | #define FEC_INTERRUPT 9 /* = SIU_LEVEL4 */ | ||
21 | #define CPM_INTERRUPT 11 /* = SIU_LEVEL5 (was: SIU_LEVEL2) */ | ||
22 | |||
23 | /* We don't use the 8259. | ||
24 | */ | ||
25 | #define NR_8259_INTS 0 | ||
26 | |||
27 | #endif /* __MACH_HERMES_H */ | ||
diff --git a/arch/ppc/platforms/ip860.h b/arch/ppc/platforms/ip860.h new file mode 100644 index 000000000000..8c3836c5f054 --- /dev/null +++ b/arch/ppc/platforms/ip860.h | |||
@@ -0,0 +1,36 @@ | |||
1 | /* | ||
2 | * MicroSys IP860 VMEBus board specific definitions | ||
3 | * | ||
4 | * Copyright (c) 2000, 2001 Wolfgang Denk (wd@denx.de) | ||
5 | */ | ||
6 | |||
7 | #ifndef __MACH_IP860_H | ||
8 | #define __MACH_IP860_H | ||
9 | |||
10 | #include <linux/config.h> | ||
11 | |||
12 | #include <asm/ppcboot.h> | ||
13 | |||
14 | #define IP860_IMMR_BASE 0xF1000000 /* phys. addr of IMMR */ | ||
15 | #define IP860_IMAP_SIZE (64 * 1024) /* size of mapped area */ | ||
16 | |||
17 | #define IMAP_ADDR IP860_IMMR_BASE /* physical base address of IMMR area */ | ||
18 | #define IMAP_SIZE IP860_IMAP_SIZE /* mapped size of IMMR area */ | ||
19 | |||
20 | /* | ||
21 | * MPC8xx Chip Select Usage | ||
22 | */ | ||
23 | #define IP860_BOOT_CS 0 /* Boot (VMEBus or Flash) Chip Select 0 */ | ||
24 | #define IP860_FLASH_CS 1 /* Flash is on Chip Select 1 */ | ||
25 | #define IP860_SDRAM_CS 2 /* SDRAM is on Chip Select 2 */ | ||
26 | #define IP860_SRAM_CS 3 /* SRAM is on Chip Select 3 */ | ||
27 | #define IP860_BCSR_CS 4 /* BCSR is on Chip Select 4 */ | ||
28 | #define IP860_IP_CS 5 /* IP Slots are on Chip Select 5 */ | ||
29 | #define IP860_VME_STD_CS 6 /* VME Standard I/O is on Chip Select 6 */ | ||
30 | #define IP860_VME_SHORT_CS 7 /* VME Short I/O is on Chip Select 7 */ | ||
31 | |||
32 | /* We don't use the 8259. | ||
33 | */ | ||
34 | #define NR_8259_INTS 0 | ||
35 | |||
36 | #endif /* __MACH_IP860_H */ | ||
diff --git a/arch/ppc/platforms/ivms8.h b/arch/ppc/platforms/ivms8.h new file mode 100644 index 000000000000..d4be310f8084 --- /dev/null +++ b/arch/ppc/platforms/ivms8.h | |||
@@ -0,0 +1,56 @@ | |||
1 | /* | ||
2 | * Speech Design Integrated Voicemail board specific definitions | ||
3 | * - IVMS8 (small, 8 channels) | ||
4 | * - IVML24 (large, 24 channels) | ||
5 | * | ||
6 | * In 2.5 when we force a new bootloader, we can merge these two, and add | ||
7 | * in _MACH_'s for them. -- Tom | ||
8 | * | ||
9 | * Copyright (c) 2000, 2001 Wolfgang Denk (wd@denx.de) | ||
10 | */ | ||
11 | |||
12 | #ifdef __KERNEL__ | ||
13 | #ifndef __ASM_IVMS8_H__ | ||
14 | #define __ASM_IVMS8_H__ | ||
15 | |||
16 | #include <linux/config.h> | ||
17 | |||
18 | #include <asm/ppcboot.h> | ||
19 | |||
20 | #define IVMS_IMMR_BASE 0xFFF00000 /* phys. addr of IMMR */ | ||
21 | #define IVMS_IMAP_SIZE (64 * 1024) /* size of mapped area */ | ||
22 | |||
23 | #define IMAP_ADDR IVMS_IMMR_BASE /* phys. base address of IMMR area */ | ||
24 | #define IMAP_SIZE IVMS_IMAP_SIZE /* mapped size of IMMR area */ | ||
25 | |||
26 | #define PCMCIA_MEM_ADDR ((uint)0xFE100000) | ||
27 | #define PCMCIA_MEM_SIZE ((uint)(64 * 1024)) | ||
28 | |||
29 | #define FEC_INTERRUPT 9 /* = SIU_LEVEL4 */ | ||
30 | #define IDE0_INTERRUPT 10 /* = IRQ5 */ | ||
31 | #define CPM_INTERRUPT 11 /* = SIU_LEVEL5 (was: SIU_LEVEL2) */ | ||
32 | #define PHY_INTERRUPT 12 /* = IRQ6 */ | ||
33 | |||
34 | /* override the default number of IDE hardware interfaces */ | ||
35 | #define MAX_HWIFS 1 | ||
36 | |||
37 | /* | ||
38 | * Definitions for IDE0 Interface | ||
39 | */ | ||
40 | #define IDE0_BASE_OFFSET 0x0000 /* Offset in PCMCIA memory */ | ||
41 | #define IDE0_DATA_REG_OFFSET 0x0000 | ||
42 | #define IDE0_ERROR_REG_OFFSET 0x0081 | ||
43 | #define IDE0_NSECTOR_REG_OFFSET 0x0082 | ||
44 | #define IDE0_SECTOR_REG_OFFSET 0x0083 | ||
45 | #define IDE0_LCYL_REG_OFFSET 0x0084 | ||
46 | #define IDE0_HCYL_REG_OFFSET 0x0085 | ||
47 | #define IDE0_SELECT_REG_OFFSET 0x0086 | ||
48 | #define IDE0_STATUS_REG_OFFSET 0x0087 | ||
49 | #define IDE0_CONTROL_REG_OFFSET 0x0106 | ||
50 | #define IDE0_IRQ_REG_OFFSET 0x000A /* not used */ | ||
51 | |||
52 | /* We don't use the 8259. */ | ||
53 | #define NR_8259_INTS 0 | ||
54 | |||
55 | #endif /* __ASM_IVMS8_H__ */ | ||
56 | #endif /* __KERNEL__ */ | ||
diff --git a/arch/ppc/platforms/k2.c b/arch/ppc/platforms/k2.c new file mode 100644 index 000000000000..aacb438708ff --- /dev/null +++ b/arch/ppc/platforms/k2.c | |||
@@ -0,0 +1,613 @@ | |||
1 | /* | ||
2 | * arch/ppc/platforms/k2.c | ||
3 | * | ||
4 | * Board setup routines for SBS K2 | ||
5 | * | ||
6 | * Author: Matt Porter <mporter@mvista.com> | ||
7 | * | ||
8 | * Updated by: Randy Vinson <rvinson@mvista.com. | ||
9 | * | ||
10 | * 2001-2004 (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 | #include <linux/config.h> | ||
17 | #include <linux/stddef.h> | ||
18 | #include <linux/kernel.h> | ||
19 | #include <linux/init.h> | ||
20 | #include <linux/errno.h> | ||
21 | #include <linux/reboot.h> | ||
22 | #include <linux/pci.h> | ||
23 | #include <linux/kdev_t.h> | ||
24 | #include <linux/types.h> | ||
25 | #include <linux/major.h> | ||
26 | #include <linux/initrd.h> | ||
27 | #include <linux/console.h> | ||
28 | #include <linux/delay.h> | ||
29 | #include <linux/ide.h> | ||
30 | #include <linux/irq.h> | ||
31 | #include <linux/seq_file.h> | ||
32 | #include <linux/root_dev.h> | ||
33 | |||
34 | #include <asm/system.h> | ||
35 | #include <asm/pgtable.h> | ||
36 | #include <asm/page.h> | ||
37 | #include <asm/dma.h> | ||
38 | #include <asm/io.h> | ||
39 | #include <asm/machdep.h> | ||
40 | #include <asm/time.h> | ||
41 | #include <asm/i8259.h> | ||
42 | #include <asm/todc.h> | ||
43 | #include <asm/bootinfo.h> | ||
44 | |||
45 | #include <syslib/cpc710.h> | ||
46 | #include "k2.h" | ||
47 | |||
48 | extern unsigned long loops_per_jiffy; | ||
49 | extern void gen550_progress(char *, unsigned short); | ||
50 | |||
51 | static unsigned int cpu_7xx[16] = { | ||
52 | 0, 15, 14, 0, 0, 13, 5, 9, 6, 11, 8, 10, 16, 12, 7, 0 | ||
53 | }; | ||
54 | static unsigned int cpu_6xx[16] = { | ||
55 | 0, 0, 14, 0, 0, 13, 5, 9, 6, 11, 8, 10, 0, 12, 7, 0 | ||
56 | }; | ||
57 | |||
58 | static inline int __init | ||
59 | k2_map_irq(struct pci_dev *dev, unsigned char idsel, unsigned char pin) | ||
60 | { | ||
61 | struct pci_controller *hose = pci_bus_to_hose(dev->bus->number); | ||
62 | /* | ||
63 | * Check our hose index. If we are zero then we are on the | ||
64 | * local PCI hose, otherwise we are on the cPCI hose. | ||
65 | */ | ||
66 | if (!hose->index) { | ||
67 | static char pci_irq_table[][4] = | ||
68 | /* | ||
69 | * PCI IDSEL/INTPIN->INTLINE | ||
70 | * A B C D | ||
71 | */ | ||
72 | { | ||
73 | {1, 0, 0, 0}, /* Ethernet */ | ||
74 | {5, 5, 5, 5}, /* PMC Site 1 */ | ||
75 | {6, 6, 6, 6}, /* PMC Site 2 */ | ||
76 | {0, 0, 0, 0}, /* unused */ | ||
77 | {0, 0, 0, 0}, /* unused */ | ||
78 | {0, 0, 0, 0}, /* PCI-ISA Bridge */ | ||
79 | {0, 0, 0, 0}, /* unused */ | ||
80 | {0, 0, 0, 0}, /* unused */ | ||
81 | {0, 0, 0, 0}, /* unused */ | ||
82 | {0, 0, 0, 0}, /* unused */ | ||
83 | {0, 0, 0, 0}, /* unused */ | ||
84 | {0, 0, 0, 0}, /* unused */ | ||
85 | {0, 0, 0, 0}, /* unused */ | ||
86 | {0, 0, 0, 0}, /* unused */ | ||
87 | {15, 0, 0, 0}, /* M5229 IDE */ | ||
88 | }; | ||
89 | const long min_idsel = 3, max_idsel = 17, irqs_per_slot = 4; | ||
90 | return PCI_IRQ_TABLE_LOOKUP; | ||
91 | } else { | ||
92 | static char pci_irq_table[][4] = | ||
93 | /* | ||
94 | * PCI IDSEL/INTPIN->INTLINE | ||
95 | * A B C D | ||
96 | */ | ||
97 | { | ||
98 | {10, 11, 12, 9}, /* cPCI slot 8 */ | ||
99 | {11, 12, 9, 10}, /* cPCI slot 7 */ | ||
100 | {12, 9, 10, 11}, /* cPCI slot 6 */ | ||
101 | {9, 10, 11, 12}, /* cPCI slot 5 */ | ||
102 | {10, 11, 12, 9}, /* cPCI slot 4 */ | ||
103 | {11, 12, 9, 10}, /* cPCI slot 3 */ | ||
104 | {12, 9, 10, 11}, /* cPCI slot 2 */ | ||
105 | }; | ||
106 | const long min_idsel = 15, max_idsel = 21, irqs_per_slot = 4; | ||
107 | return PCI_IRQ_TABLE_LOOKUP; | ||
108 | } | ||
109 | } | ||
110 | |||
111 | void k2_pcibios_fixup(void) | ||
112 | { | ||
113 | #if defined(CONFIG_BLK_DEV_IDE) || defined(CONFIG_BLK_DEV_IDE_MODULE) | ||
114 | struct pci_dev *ide_dev; | ||
115 | |||
116 | /* | ||
117 | * Enable DMA support on hdc | ||
118 | */ | ||
119 | ide_dev = pci_get_device(PCI_VENDOR_ID_AL, | ||
120 | PCI_DEVICE_ID_AL_M5229, NULL); | ||
121 | |||
122 | if (ide_dev) { | ||
123 | |||
124 | unsigned long ide_dma_base; | ||
125 | |||
126 | ide_dma_base = pci_resource_start(ide_dev, 4); | ||
127 | outb(0x00, ide_dma_base + 0x2); | ||
128 | outb(0x20, ide_dma_base + 0xa); | ||
129 | pci_dev_put(ide_dev); | ||
130 | } | ||
131 | #endif | ||
132 | } | ||
133 | |||
134 | void k2_pcibios_fixup_resources(struct pci_dev *dev) | ||
135 | { | ||
136 | int i; | ||
137 | |||
138 | if ((dev->vendor == PCI_VENDOR_ID_IBM) && | ||
139 | (dev->device == PCI_DEVICE_ID_IBM_CPC710_PCI64)) { | ||
140 | pr_debug("Fixup CPC710 resources\n"); | ||
141 | for (i = 0; i < DEVICE_COUNT_RESOURCE; i++) { | ||
142 | dev->resource[i].start = 0; | ||
143 | dev->resource[i].end = 0; | ||
144 | } | ||
145 | } | ||
146 | } | ||
147 | |||
148 | void k2_setup_hoses(void) | ||
149 | { | ||
150 | struct pci_controller *hose_a, *hose_b; | ||
151 | |||
152 | /* | ||
153 | * Reconfigure CPC710 memory map so | ||
154 | * we have some more PCI memory space. | ||
155 | */ | ||
156 | |||
157 | /* Set FPHB mode */ | ||
158 | __raw_writel(0x808000e0, PGCHP); /* Set FPHB mode */ | ||
159 | |||
160 | /* PCI32 mappings */ | ||
161 | __raw_writel(0x00000000, K2_PCI32_BAR + PIBAR); /* PCI I/O base */ | ||
162 | __raw_writel(0x00000000, K2_PCI32_BAR + PMBAR); /* PCI Mem base */ | ||
163 | __raw_writel(0xf0000000, K2_PCI32_BAR + MSIZE); /* 256MB */ | ||
164 | __raw_writel(0xfff00000, K2_PCI32_BAR + IOSIZE); /* 1MB */ | ||
165 | __raw_writel(0xc0000000, K2_PCI32_BAR + SMBAR); /* Base@0xc0000000 */ | ||
166 | __raw_writel(0x80000000, K2_PCI32_BAR + SIBAR); /* Base@0x80000000 */ | ||
167 | __raw_writel(0x000000c0, K2_PCI32_BAR + PSSIZE); /* 1GB space */ | ||
168 | __raw_writel(0x000000c0, K2_PCI32_BAR + PPSIZE); /* 1GB space */ | ||
169 | __raw_writel(0x00000000, K2_PCI32_BAR + BARPS); /* Base@0x00000000 */ | ||
170 | __raw_writel(0x00000000, K2_PCI32_BAR + BARPP); /* Base@0x00000000 */ | ||
171 | __raw_writel(0x00000080, K2_PCI32_BAR + PSBAR); /* Base@0x80 */ | ||
172 | __raw_writel(0x00000000, K2_PCI32_BAR + PPBAR); | ||
173 | |||
174 | __raw_writel(0xc0000000, K2_PCI32_BAR + BPMDLK); | ||
175 | __raw_writel(0xd0000000, K2_PCI32_BAR + TPMDLK); | ||
176 | __raw_writel(0x80000000, K2_PCI32_BAR + BIODLK); | ||
177 | __raw_writel(0x80100000, K2_PCI32_BAR + TIODLK); | ||
178 | __raw_writel(0xe0008000, K2_PCI32_BAR + DLKCTRL); | ||
179 | __raw_writel(0xffffffff, K2_PCI32_BAR + DLKDEV); | ||
180 | |||
181 | /* PCI64 mappings */ | ||
182 | __raw_writel(0x00100000, K2_PCI64_BAR + PIBAR); /* PCI I/O base */ | ||
183 | __raw_writel(0x10000000, K2_PCI64_BAR + PMBAR); /* PCI Mem base */ | ||
184 | __raw_writel(0xf0000000, K2_PCI64_BAR + MSIZE); /* 256MB */ | ||
185 | __raw_writel(0xfff00000, K2_PCI64_BAR + IOSIZE); /* 1MB */ | ||
186 | __raw_writel(0xd0000000, K2_PCI64_BAR + SMBAR); /* Base@0xd0000000 */ | ||
187 | __raw_writel(0x80100000, K2_PCI64_BAR + SIBAR); /* Base@0x80100000 */ | ||
188 | __raw_writel(0x000000c0, K2_PCI64_BAR + PSSIZE); /* 1GB space */ | ||
189 | __raw_writel(0x000000c0, K2_PCI64_BAR + PPSIZE); /* 1GB space */ | ||
190 | __raw_writel(0x00000000, K2_PCI64_BAR + BARPS); /* Base@0x00000000 */ | ||
191 | __raw_writel(0x00000000, K2_PCI64_BAR + BARPP); /* Base@0x00000000 */ | ||
192 | |||
193 | /* Setup PCI32 hose */ | ||
194 | hose_a = pcibios_alloc_controller(); | ||
195 | if (!hose_a) | ||
196 | return; | ||
197 | |||
198 | hose_a->first_busno = 0; | ||
199 | hose_a->last_busno = 0xff; | ||
200 | hose_a->pci_mem_offset = K2_PCI32_MEM_BASE; | ||
201 | |||
202 | pci_init_resource(&hose_a->io_resource, | ||
203 | K2_PCI32_LOWER_IO, | ||
204 | K2_PCI32_UPPER_IO, | ||
205 | IORESOURCE_IO, "PCI32 host bridge"); | ||
206 | |||
207 | pci_init_resource(&hose_a->mem_resources[0], | ||
208 | K2_PCI32_LOWER_MEM + K2_PCI32_MEM_BASE, | ||
209 | K2_PCI32_UPPER_MEM + K2_PCI32_MEM_BASE, | ||
210 | IORESOURCE_MEM, "PCI32 host bridge"); | ||
211 | |||
212 | hose_a->io_space.start = K2_PCI32_LOWER_IO; | ||
213 | hose_a->io_space.end = K2_PCI32_UPPER_IO; | ||
214 | hose_a->mem_space.start = K2_PCI32_LOWER_MEM; | ||
215 | hose_a->mem_space.end = K2_PCI32_UPPER_MEM; | ||
216 | hose_a->io_base_virt = (void *)K2_ISA_IO_BASE; | ||
217 | |||
218 | setup_indirect_pci(hose_a, K2_PCI32_CONFIG_ADDR, K2_PCI32_CONFIG_DATA); | ||
219 | |||
220 | /* Initialize PCI32 bus registers */ | ||
221 | early_write_config_byte(hose_a, | ||
222 | hose_a->first_busno, | ||
223 | PCI_DEVFN(0, 0), | ||
224 | CPC710_BUS_NUMBER, hose_a->first_busno); | ||
225 | |||
226 | early_write_config_byte(hose_a, | ||
227 | hose_a->first_busno, | ||
228 | PCI_DEVFN(0, 0), | ||
229 | CPC710_SUB_BUS_NUMBER, hose_a->last_busno); | ||
230 | |||
231 | /* Enable PCI interrupt polling */ | ||
232 | early_write_config_byte(hose_a, | ||
233 | hose_a->first_busno, | ||
234 | PCI_DEVFN(8, 0), 0x45, 0x80); | ||
235 | |||
236 | /* Route polled PCI interrupts */ | ||
237 | early_write_config_byte(hose_a, | ||
238 | hose_a->first_busno, | ||
239 | PCI_DEVFN(8, 0), 0x48, 0x58); | ||
240 | |||
241 | early_write_config_byte(hose_a, | ||
242 | hose_a->first_busno, | ||
243 | PCI_DEVFN(8, 0), 0x49, 0x07); | ||
244 | |||
245 | early_write_config_byte(hose_a, | ||
246 | hose_a->first_busno, | ||
247 | PCI_DEVFN(8, 0), 0x4a, 0x31); | ||
248 | |||
249 | early_write_config_byte(hose_a, | ||
250 | hose_a->first_busno, | ||
251 | PCI_DEVFN(8, 0), 0x4b, 0xb9); | ||
252 | |||
253 | /* route secondary IDE channel interrupt to IRQ 15 */ | ||
254 | early_write_config_byte(hose_a, | ||
255 | hose_a->first_busno, | ||
256 | PCI_DEVFN(8, 0), 0x75, 0x0f); | ||
257 | |||
258 | /* enable IDE controller IDSEL */ | ||
259 | early_write_config_byte(hose_a, | ||
260 | hose_a->first_busno, | ||
261 | PCI_DEVFN(8, 0), 0x58, 0x48); | ||
262 | |||
263 | /* Enable IDE function */ | ||
264 | early_write_config_byte(hose_a, | ||
265 | hose_a->first_busno, | ||
266 | PCI_DEVFN(17, 0), 0x50, 0x03); | ||
267 | |||
268 | /* Set M5229 IDE controller to native mode */ | ||
269 | early_write_config_byte(hose_a, | ||
270 | hose_a->first_busno, | ||
271 | PCI_DEVFN(17, 0), PCI_CLASS_PROG, 0xdf); | ||
272 | |||
273 | hose_a->last_busno = pciauto_bus_scan(hose_a, hose_a->first_busno); | ||
274 | |||
275 | /* Write out correct max subordinate bus number for hose A */ | ||
276 | early_write_config_byte(hose_a, | ||
277 | hose_a->first_busno, | ||
278 | PCI_DEVFN(0, 0), | ||
279 | CPC710_SUB_BUS_NUMBER, hose_a->last_busno); | ||
280 | |||
281 | /* Only setup PCI64 hose if we are in the system slot */ | ||
282 | if (!(readb(K2_MISC_REG) & K2_SYS_SLOT_MASK)) { | ||
283 | /* Setup PCI64 hose */ | ||
284 | hose_b = pcibios_alloc_controller(); | ||
285 | if (!hose_b) | ||
286 | return; | ||
287 | |||
288 | hose_b->first_busno = hose_a->last_busno + 1; | ||
289 | hose_b->last_busno = 0xff; | ||
290 | |||
291 | /* Reminder: quit changing the following, it is correct. */ | ||
292 | hose_b->pci_mem_offset = K2_PCI32_MEM_BASE; | ||
293 | |||
294 | pci_init_resource(&hose_b->io_resource, | ||
295 | K2_PCI64_LOWER_IO, | ||
296 | K2_PCI64_UPPER_IO, | ||
297 | IORESOURCE_IO, "PCI64 host bridge"); | ||
298 | |||
299 | pci_init_resource(&hose_b->mem_resources[0], | ||
300 | K2_PCI64_LOWER_MEM + K2_PCI32_MEM_BASE, | ||
301 | K2_PCI64_UPPER_MEM + K2_PCI32_MEM_BASE, | ||
302 | IORESOURCE_MEM, "PCI64 host bridge"); | ||
303 | |||
304 | hose_b->io_space.start = K2_PCI64_LOWER_IO; | ||
305 | hose_b->io_space.end = K2_PCI64_UPPER_IO; | ||
306 | hose_b->mem_space.start = K2_PCI64_LOWER_MEM; | ||
307 | hose_b->mem_space.end = K2_PCI64_UPPER_MEM; | ||
308 | hose_b->io_base_virt = (void *)K2_ISA_IO_BASE; | ||
309 | |||
310 | setup_indirect_pci(hose_b, | ||
311 | K2_PCI64_CONFIG_ADDR, K2_PCI64_CONFIG_DATA); | ||
312 | |||
313 | /* Initialize PCI64 bus registers */ | ||
314 | early_write_config_byte(hose_b, | ||
315 | 0, | ||
316 | PCI_DEVFN(0, 0), | ||
317 | CPC710_SUB_BUS_NUMBER, 0xff); | ||
318 | |||
319 | early_write_config_byte(hose_b, | ||
320 | 0, | ||
321 | PCI_DEVFN(0, 0), | ||
322 | CPC710_BUS_NUMBER, hose_b->first_busno); | ||
323 | |||
324 | hose_b->last_busno = pciauto_bus_scan(hose_b, | ||
325 | hose_b->first_busno); | ||
326 | |||
327 | /* Write out correct max subordinate bus number for hose B */ | ||
328 | early_write_config_byte(hose_b, | ||
329 | hose_b->first_busno, | ||
330 | PCI_DEVFN(0, 0), | ||
331 | CPC710_SUB_BUS_NUMBER, | ||
332 | hose_b->last_busno); | ||
333 | |||
334 | /* Configure PCI64 PSBAR */ | ||
335 | early_write_config_dword(hose_b, | ||
336 | hose_b->first_busno, | ||
337 | PCI_DEVFN(0, 0), | ||
338 | PCI_BASE_ADDRESS_0, | ||
339 | K2_PCI64_SYS_MEM_BASE); | ||
340 | } | ||
341 | |||
342 | /* Configure i8259 level/edge settings */ | ||
343 | outb(0x62, 0x4d0); | ||
344 | outb(0xde, 0x4d1); | ||
345 | |||
346 | #ifdef CONFIG_CPC710_DATA_GATHERING | ||
347 | { | ||
348 | unsigned int tmp; | ||
349 | tmp = __raw_readl(ABCNTL); | ||
350 | /* Enable data gathering on both PCI interfaces */ | ||
351 | __raw_writel(tmp | 0x05000000, ABCNTL); | ||
352 | } | ||
353 | #endif | ||
354 | |||
355 | ppc_md.pcibios_fixup = k2_pcibios_fixup; | ||
356 | ppc_md.pcibios_fixup_resources = k2_pcibios_fixup_resources; | ||
357 | ppc_md.pci_swizzle = common_swizzle; | ||
358 | ppc_md.pci_map_irq = k2_map_irq; | ||
359 | } | ||
360 | |||
361 | static int k2_get_bus_speed(void) | ||
362 | { | ||
363 | int bus_speed; | ||
364 | unsigned char board_id; | ||
365 | |||
366 | board_id = *(unsigned char *)K2_BOARD_ID_REG; | ||
367 | |||
368 | switch (K2_BUS_SPD(board_id)) { | ||
369 | |||
370 | case 0: | ||
371 | default: | ||
372 | bus_speed = 100000000; | ||
373 | break; | ||
374 | |||
375 | case 1: | ||
376 | bus_speed = 83333333; | ||
377 | break; | ||
378 | |||
379 | case 2: | ||
380 | bus_speed = 75000000; | ||
381 | break; | ||
382 | |||
383 | case 3: | ||
384 | bus_speed = 66666666; | ||
385 | break; | ||
386 | } | ||
387 | return bus_speed; | ||
388 | } | ||
389 | |||
390 | static int k2_get_cpu_speed(void) | ||
391 | { | ||
392 | unsigned long hid1; | ||
393 | int cpu_speed; | ||
394 | |||
395 | hid1 = mfspr(SPRN_HID1) >> 28; | ||
396 | |||
397 | if ((mfspr(SPRN_PVR) >> 16) == 8) | ||
398 | hid1 = cpu_7xx[hid1]; | ||
399 | else | ||
400 | hid1 = cpu_6xx[hid1]; | ||
401 | |||
402 | cpu_speed = k2_get_bus_speed() * hid1 / 2; | ||
403 | return cpu_speed; | ||
404 | } | ||
405 | |||
406 | static void __init k2_calibrate_decr(void) | ||
407 | { | ||
408 | int freq, divisor = 4; | ||
409 | |||
410 | /* determine processor bus speed */ | ||
411 | freq = k2_get_bus_speed(); | ||
412 | tb_ticks_per_jiffy = freq / HZ / divisor; | ||
413 | tb_to_us = mulhwu_scale_factor(freq / divisor, 1000000); | ||
414 | } | ||
415 | |||
416 | static int k2_show_cpuinfo(struct seq_file *m) | ||
417 | { | ||
418 | unsigned char k2_geo_bits, k2_system_slot; | ||
419 | |||
420 | seq_printf(m, "vendor\t\t: SBS\n"); | ||
421 | seq_printf(m, "machine\t\t: K2\n"); | ||
422 | seq_printf(m, "cpu speed\t: %dMhz\n", k2_get_cpu_speed() / 1000000); | ||
423 | seq_printf(m, "bus speed\t: %dMhz\n", k2_get_bus_speed() / 1000000); | ||
424 | seq_printf(m, "memory type\t: SDRAM\n"); | ||
425 | |||
426 | k2_geo_bits = readb(K2_MSIZ_GEO_REG) & K2_GEO_ADR_MASK; | ||
427 | k2_system_slot = !(readb(K2_MISC_REG) & K2_SYS_SLOT_MASK); | ||
428 | seq_printf(m, "backplane\t: %s slot board", | ||
429 | k2_system_slot ? "System" : "Non system"); | ||
430 | seq_printf(m, "with geographical address %x\n", k2_geo_bits); | ||
431 | |||
432 | return 0; | ||
433 | } | ||
434 | |||
435 | TODC_ALLOC(); | ||
436 | |||
437 | static void __init k2_setup_arch(void) | ||
438 | { | ||
439 | unsigned int cpu; | ||
440 | |||
441 | /* Setup TODC access */ | ||
442 | TODC_INIT(TODC_TYPE_MK48T37, 0, 0, | ||
443 | ioremap(K2_RTC_BASE_ADDRESS, K2_RTC_SIZE), 8); | ||
444 | |||
445 | /* init to some ~sane value until calibrate_delay() runs */ | ||
446 | loops_per_jiffy = 50000000 / HZ; | ||
447 | |||
448 | /* make FLASH transactions higher priority than PCI to avoid deadlock */ | ||
449 | __raw_writel(__raw_readl(SIOC1) | 0x80000000, SIOC1); | ||
450 | |||
451 | /* Set hardware to access FLASH page 2 */ | ||
452 | __raw_writel(1 << 29, GPOUT); | ||
453 | |||
454 | /* Setup PCI host bridges */ | ||
455 | k2_setup_hoses(); | ||
456 | |||
457 | #ifdef CONFIG_BLK_DEV_INITRD | ||
458 | if (initrd_start) | ||
459 | ROOT_DEV = Root_RAM0; | ||
460 | else | ||
461 | #endif | ||
462 | #ifdef CONFIG_ROOT_NFS | ||
463 | ROOT_DEV = Root_NFS; | ||
464 | #else | ||
465 | ROOT_DEV = Root_HDC1; | ||
466 | #endif | ||
467 | |||
468 | /* Identify the system */ | ||
469 | printk(KERN_INFO "System Identification: SBS K2 - PowerPC 750 @ " | ||
470 | "%d Mhz\n", k2_get_cpu_speed() / 1000000); | ||
471 | printk(KERN_INFO "Port by MontaVista Software, Inc. " | ||
472 | "(source@mvista.com)\n"); | ||
473 | |||
474 | /* Identify the CPU manufacturer */ | ||
475 | cpu = PVR_REV(mfspr(SPRN_PVR)); | ||
476 | printk(KERN_INFO "CPU manufacturer: %s [rev=%04x]\n", | ||
477 | (cpu & (1 << 15)) ? "IBM" : "Motorola", cpu); | ||
478 | } | ||
479 | |||
480 | static void k2_restart(char *cmd) | ||
481 | { | ||
482 | local_irq_disable(); | ||
483 | |||
484 | /* Flip FLASH back to page 1 to access firmware image */ | ||
485 | __raw_writel(0, GPOUT); | ||
486 | |||
487 | /* SRR0 has system reset vector, SRR1 has default MSR value */ | ||
488 | /* rfi restores MSR from SRR1 and sets the PC to the SRR0 value */ | ||
489 | mtspr(SPRN_SRR0, 0xfff00100); | ||
490 | mtspr(SPRN_SRR1, 0); | ||
491 | __asm__ __volatile__("rfi\n\t"); | ||
492 | |||
493 | /* not reached */ | ||
494 | for (;;) ; | ||
495 | } | ||
496 | |||
497 | static void k2_power_off(void) | ||
498 | { | ||
499 | for (;;) ; | ||
500 | } | ||
501 | |||
502 | static void k2_halt(void) | ||
503 | { | ||
504 | k2_restart(NULL); | ||
505 | } | ||
506 | |||
507 | /* | ||
508 | * Set BAT 3 to map PCI32 I/O space. | ||
509 | */ | ||
510 | static __inline__ void k2_set_bat(void) | ||
511 | { | ||
512 | /* wait for all outstanding memory accesses to complete */ | ||
513 | mb(); | ||
514 | |||
515 | /* setup DBATs */ | ||
516 | mtspr(SPRN_DBAT2U, 0x80001ffe); | ||
517 | mtspr(SPRN_DBAT2L, 0x8000002a); | ||
518 | mtspr(SPRN_DBAT3U, 0xf0001ffe); | ||
519 | mtspr(SPRN_DBAT3L, 0xf000002a); | ||
520 | |||
521 | /* wait for updates */ | ||
522 | mb(); | ||
523 | } | ||
524 | |||
525 | static unsigned long __init k2_find_end_of_memory(void) | ||
526 | { | ||
527 | unsigned long total; | ||
528 | unsigned char msize = 7; /* Default to 128MB */ | ||
529 | |||
530 | msize = K2_MEM_SIZE(readb(K2_MSIZ_GEO_REG)); | ||
531 | |||
532 | switch (msize) { | ||
533 | case 2: | ||
534 | /* | ||
535 | * This will break without a lowered | ||
536 | * KERNELBASE or CONFIG_HIGHMEM on. | ||
537 | * It seems non 1GB builds exist yet, | ||
538 | * though. | ||
539 | */ | ||
540 | total = K2_MEM_SIZE_1GB; | ||
541 | break; | ||
542 | case 3: | ||
543 | case 4: | ||
544 | total = K2_MEM_SIZE_512MB; | ||
545 | break; | ||
546 | case 5: | ||
547 | case 6: | ||
548 | total = K2_MEM_SIZE_256MB; | ||
549 | break; | ||
550 | case 7: | ||
551 | total = K2_MEM_SIZE_128MB; | ||
552 | break; | ||
553 | default: | ||
554 | printk | ||
555 | ("K2: Invalid memory size detected, defaulting to 128MB\n"); | ||
556 | total = K2_MEM_SIZE_128MB; | ||
557 | break; | ||
558 | } | ||
559 | return total; | ||
560 | } | ||
561 | |||
562 | static void __init k2_map_io(void) | ||
563 | { | ||
564 | io_block_mapping(K2_PCI32_IO_BASE, | ||
565 | K2_PCI32_IO_BASE, 0x00200000, _PAGE_IO); | ||
566 | io_block_mapping(0xff000000, 0xff000000, 0x01000000, _PAGE_IO); | ||
567 | } | ||
568 | |||
569 | static void __init k2_init_irq(void) | ||
570 | { | ||
571 | int i; | ||
572 | |||
573 | for (i = 0; i < 16; i++) | ||
574 | irq_desc[i].handler = &i8259_pic; | ||
575 | |||
576 | i8259_init(0); | ||
577 | } | ||
578 | |||
579 | void __init platform_init(unsigned long r3, unsigned long r4, | ||
580 | unsigned long r5, unsigned long r6, unsigned long r7) | ||
581 | { | ||
582 | parse_bootinfo((struct bi_record *)(r3 + KERNELBASE)); | ||
583 | |||
584 | k2_set_bat(); | ||
585 | |||
586 | isa_io_base = K2_ISA_IO_BASE; | ||
587 | isa_mem_base = K2_ISA_MEM_BASE; | ||
588 | pci_dram_offset = K2_PCI32_SYS_MEM_BASE; | ||
589 | |||
590 | ppc_md.setup_arch = k2_setup_arch; | ||
591 | ppc_md.show_cpuinfo = k2_show_cpuinfo; | ||
592 | ppc_md.init_IRQ = k2_init_irq; | ||
593 | ppc_md.get_irq = i8259_irq; | ||
594 | |||
595 | ppc_md.find_end_of_memory = k2_find_end_of_memory; | ||
596 | ppc_md.setup_io_mappings = k2_map_io; | ||
597 | |||
598 | ppc_md.restart = k2_restart; | ||
599 | ppc_md.power_off = k2_power_off; | ||
600 | ppc_md.halt = k2_halt; | ||
601 | |||
602 | ppc_md.time_init = todc_time_init; | ||
603 | ppc_md.set_rtc_time = todc_set_rtc_time; | ||
604 | ppc_md.get_rtc_time = todc_get_rtc_time; | ||
605 | ppc_md.calibrate_decr = k2_calibrate_decr; | ||
606 | |||
607 | ppc_md.nvram_read_val = todc_direct_read_val; | ||
608 | ppc_md.nvram_write_val = todc_direct_write_val; | ||
609 | |||
610 | #ifdef CONFIG_SERIAL_TEXT_DEBUG | ||
611 | ppc_md.progress = gen550_progress; | ||
612 | #endif | ||
613 | } | ||
diff --git a/arch/ppc/platforms/k2.h b/arch/ppc/platforms/k2.h new file mode 100644 index 000000000000..78326aba1988 --- /dev/null +++ b/arch/ppc/platforms/k2.h | |||
@@ -0,0 +1,82 @@ | |||
1 | /* | ||
2 | * arch/ppc/platforms/k2.h | ||
3 | * | ||
4 | * Definitions for SBS K2 board support | ||
5 | * | ||
6 | * Author: Matt Porter <mporter@mvista.com> | ||
7 | * | ||
8 | * 2001 (c) MontaVista, Software, Inc. This file is licensed under | ||
9 | * the terms of the GNU General Public License version 2. This program | ||
10 | * is licensed "as is" without any warranty of any kind, whether express | ||
11 | * or implied. | ||
12 | */ | ||
13 | |||
14 | #ifndef __PPC_PLATFORMS_K2_H | ||
15 | #define __PPC_PLATFORMS_K2_H | ||
16 | |||
17 | /* | ||
18 | * SBS K2 definitions | ||
19 | */ | ||
20 | |||
21 | #define K2_PCI64_BAR 0xff400000 | ||
22 | #define K2_PCI32_BAR 0xff500000 | ||
23 | |||
24 | #define K2_PCI64_CONFIG_ADDR (K2_PCI64_BAR + 0x000f8000) | ||
25 | #define K2_PCI64_CONFIG_DATA (K2_PCI64_BAR + 0x000f8010) | ||
26 | |||
27 | #define K2_PCI32_CONFIG_ADDR (K2_PCI32_BAR + 0x000f8000) | ||
28 | #define K2_PCI32_CONFIG_DATA (K2_PCI32_BAR + 0x000f8010) | ||
29 | |||
30 | #define K2_PCI64_MEM_BASE 0xd0000000 | ||
31 | #define K2_PCI64_IO_BASE 0x80100000 | ||
32 | |||
33 | #define K2_PCI32_MEM_BASE 0xc0000000 | ||
34 | #define K2_PCI32_IO_BASE 0x80000000 | ||
35 | |||
36 | #define K2_PCI32_SYS_MEM_BASE 0x80000000 | ||
37 | #define K2_PCI64_SYS_MEM_BASE K2_PCI32_SYS_MEM_BASE | ||
38 | |||
39 | #define K2_PCI32_LOWER_MEM 0x00000000 | ||
40 | #define K2_PCI32_UPPER_MEM 0x0fffffff | ||
41 | #define K2_PCI32_LOWER_IO 0x00000000 | ||
42 | #define K2_PCI32_UPPER_IO 0x000fffff | ||
43 | |||
44 | #define K2_PCI64_LOWER_MEM 0x10000000 | ||
45 | #define K2_PCI64_UPPER_MEM 0x1fffffff | ||
46 | #define K2_PCI64_LOWER_IO 0x00100000 | ||
47 | #define K2_PCI64_UPPER_IO 0x001fffff | ||
48 | |||
49 | #define K2_ISA_IO_BASE K2_PCI32_IO_BASE | ||
50 | #define K2_ISA_MEM_BASE K2_PCI32_MEM_BASE | ||
51 | |||
52 | #define K2_BOARD_ID_REG (K2_ISA_IO_BASE + 0x800) | ||
53 | #define K2_MISC_REG (K2_ISA_IO_BASE + 0x804) | ||
54 | #define K2_MSIZ_GEO_REG (K2_ISA_IO_BASE + 0x808) | ||
55 | #define K2_HOT_SWAP_REG (K2_ISA_IO_BASE + 0x80c) | ||
56 | #define K2_PLD2_REG (K2_ISA_IO_BASE + 0x80e) | ||
57 | #define K2_PLD3_REG (K2_ISA_IO_BASE + 0x80f) | ||
58 | |||
59 | #define K2_BUS_SPD(board_id) (board_id >> 2) & 3 | ||
60 | |||
61 | #define K2_RTC_BASE_OFFSET 0x90000 | ||
62 | #define K2_RTC_BASE_ADDRESS (K2_PCI32_MEM_BASE + K2_RTC_BASE_OFFSET) | ||
63 | #define K2_RTC_SIZE 0x8000 | ||
64 | |||
65 | #define K2_MEM_SIZE_MASK 0xe0 | ||
66 | #define K2_MEM_SIZE(size_reg) (size_reg & K2_MEM_SIZE_MASK) >> 5 | ||
67 | #define K2_MEM_SIZE_1GB 0x40000000 | ||
68 | #define K2_MEM_SIZE_512MB 0x20000000 | ||
69 | #define K2_MEM_SIZE_256MB 0x10000000 | ||
70 | #define K2_MEM_SIZE_128MB 0x08000000 | ||
71 | |||
72 | #define K2_L2CACHE_MASK 0x03 /* Mask for 2 L2 Cache bits */ | ||
73 | #define K2_L2CACHE_512KB 0x00 /* 512KB */ | ||
74 | #define K2_L2CACHE_256KB 0x01 /* 256KB */ | ||
75 | #define K2_L2CACHE_1MB 0x02 /* 1MB */ | ||
76 | #define K2_L2CACHE_NONE 0x03 /* None */ | ||
77 | |||
78 | #define K2_GEO_ADR_MASK 0x1f | ||
79 | |||
80 | #define K2_SYS_SLOT_MASK 0x08 | ||
81 | |||
82 | #endif /* __PPC_PLATFORMS_K2_H */ | ||
diff --git a/arch/ppc/platforms/katana.c b/arch/ppc/platforms/katana.c new file mode 100644 index 000000000000..eda922ac3167 --- /dev/null +++ b/arch/ppc/platforms/katana.c | |||
@@ -0,0 +1,795 @@ | |||
1 | /* | ||
2 | * arch/ppc/platforms/katana.c | ||
3 | * | ||
4 | * Board setup routines for the Artesyn Katana cPCI boards. | ||
5 | * | ||
6 | * Author: Tim Montgomery <timm@artesyncp.com> | ||
7 | * Maintained by: Mark A. Greer <mgreer@mvista.com> | ||
8 | * | ||
9 | * Based on code done by Rabeeh Khoury - rabeeh@galileo.co.il | ||
10 | * Based on code done by - Mark A. Greer <mgreer@mvista.com> | ||
11 | * | ||
12 | * This program is free software; you can redistribute it and/or modify it | ||
13 | * under the terms of the GNU General Public License as published by the | ||
14 | * Free Software Foundation; either version 2 of the License, or (at your | ||
15 | * option) any later version. | ||
16 | */ | ||
17 | /* | ||
18 | * Supports the Artesyn 750i, 752i, and 3750. The 752i is virtually identical | ||
19 | * to the 750i except that it has an mv64460 bridge. | ||
20 | */ | ||
21 | #include <linux/config.h> | ||
22 | #include <linux/kernel.h> | ||
23 | #include <linux/pci.h> | ||
24 | #include <linux/kdev_t.h> | ||
25 | #include <linux/console.h> | ||
26 | #include <linux/initrd.h> | ||
27 | #include <linux/root_dev.h> | ||
28 | #include <linux/delay.h> | ||
29 | #include <linux/seq_file.h> | ||
30 | #include <linux/bootmem.h> | ||
31 | #include <linux/mtd/physmap.h> | ||
32 | #include <linux/mv643xx.h> | ||
33 | #ifdef CONFIG_BOOTIMG | ||
34 | #include <linux/bootimg.h> | ||
35 | #endif | ||
36 | #include <asm/page.h> | ||
37 | #include <asm/time.h> | ||
38 | #include <asm/smp.h> | ||
39 | #include <asm/todc.h> | ||
40 | #include <asm/bootinfo.h> | ||
41 | #include <asm/ppcboot.h> | ||
42 | #include <asm/mv64x60.h> | ||
43 | #include <platforms/katana.h> | ||
44 | |||
45 | static struct mv64x60_handle bh; | ||
46 | static katana_id_t katana_id; | ||
47 | static void __iomem *cpld_base; | ||
48 | static void __iomem *sram_base; | ||
49 | |||
50 | static u32 katana_flash_size_0; | ||
51 | static u32 katana_flash_size_1; | ||
52 | |||
53 | static u32 katana_bus_frequency; | ||
54 | |||
55 | unsigned char __res[sizeof(bd_t)]; | ||
56 | |||
57 | /* PCI Interrupt routing */ | ||
58 | static int __init | ||
59 | katana_irq_lookup_750i(unsigned char idsel, unsigned char pin) | ||
60 | { | ||
61 | static char pci_irq_table[][4] = { | ||
62 | /* | ||
63 | * PCI IDSEL/INTPIN->INTLINE | ||
64 | * A B C D | ||
65 | */ | ||
66 | /* IDSEL 4 (PMC 1) */ | ||
67 | { KATANA_PCI_INTB_IRQ_750i, KATANA_PCI_INTC_IRQ_750i, | ||
68 | KATANA_PCI_INTD_IRQ_750i, KATANA_PCI_INTA_IRQ_750i }, | ||
69 | /* IDSEL 5 (PMC 2) */ | ||
70 | { KATANA_PCI_INTC_IRQ_750i, KATANA_PCI_INTD_IRQ_750i, | ||
71 | KATANA_PCI_INTA_IRQ_750i, KATANA_PCI_INTB_IRQ_750i }, | ||
72 | /* IDSEL 6 (T8110) */ | ||
73 | {KATANA_PCI_INTD_IRQ_750i, 0, 0, 0 }, | ||
74 | }; | ||
75 | const long min_idsel = 4, max_idsel = 6, irqs_per_slot = 4; | ||
76 | |||
77 | return PCI_IRQ_TABLE_LOOKUP; | ||
78 | } | ||
79 | |||
80 | static int __init | ||
81 | katana_irq_lookup_3750(unsigned char idsel, unsigned char pin) | ||
82 | { | ||
83 | static char pci_irq_table[][4] = { | ||
84 | /* | ||
85 | * PCI IDSEL/INTPIN->INTLINE | ||
86 | * A B C D | ||
87 | */ | ||
88 | { KATANA_PCI_INTA_IRQ_3750, 0, 0, 0 }, /* IDSEL 3 (BCM5691) */ | ||
89 | { KATANA_PCI_INTB_IRQ_3750, 0, 0, 0 }, /* IDSEL 4 (MV64360 #2)*/ | ||
90 | { KATANA_PCI_INTC_IRQ_3750, 0, 0, 0 }, /* IDSEL 5 (MV64360 #3)*/ | ||
91 | }; | ||
92 | const long min_idsel = 3, max_idsel = 5, irqs_per_slot = 4; | ||
93 | |||
94 | return PCI_IRQ_TABLE_LOOKUP; | ||
95 | } | ||
96 | |||
97 | static int __init | ||
98 | katana_map_irq(struct pci_dev *dev, unsigned char idsel, unsigned char pin) | ||
99 | { | ||
100 | switch (katana_id) { | ||
101 | case KATANA_ID_750I: | ||
102 | case KATANA_ID_752I: | ||
103 | return katana_irq_lookup_750i(idsel, pin); | ||
104 | |||
105 | case KATANA_ID_3750: | ||
106 | return katana_irq_lookup_3750(idsel, pin); | ||
107 | |||
108 | default: | ||
109 | printk(KERN_ERR "Bogus board ID\n"); | ||
110 | return 0; | ||
111 | } | ||
112 | } | ||
113 | |||
114 | /* Board info retrieval routines */ | ||
115 | void __init | ||
116 | katana_get_board_id(void) | ||
117 | { | ||
118 | switch (in_8(cpld_base + KATANA_CPLD_PRODUCT_ID)) { | ||
119 | case KATANA_PRODUCT_ID_3750: | ||
120 | katana_id = KATANA_ID_3750; | ||
121 | break; | ||
122 | |||
123 | case KATANA_PRODUCT_ID_750i: | ||
124 | katana_id = KATANA_ID_750I; | ||
125 | break; | ||
126 | |||
127 | case KATANA_PRODUCT_ID_752i: | ||
128 | katana_id = KATANA_ID_752I; | ||
129 | break; | ||
130 | |||
131 | default: | ||
132 | printk(KERN_ERR "Unsupported board\n"); | ||
133 | } | ||
134 | } | ||
135 | |||
136 | int __init | ||
137 | katana_get_proc_num(void) | ||
138 | { | ||
139 | u16 val; | ||
140 | u8 save_exclude; | ||
141 | static int proc = -1; | ||
142 | static u8 first_time = 1; | ||
143 | |||
144 | if (first_time) { | ||
145 | if (katana_id != KATANA_ID_3750) | ||
146 | proc = 0; | ||
147 | else { | ||
148 | save_exclude = mv64x60_pci_exclude_bridge; | ||
149 | mv64x60_pci_exclude_bridge = 0; | ||
150 | |||
151 | early_read_config_word(bh.hose_a, 0, | ||
152 | PCI_DEVFN(0,0), PCI_DEVICE_ID, &val); | ||
153 | |||
154 | mv64x60_pci_exclude_bridge = save_exclude; | ||
155 | |||
156 | switch(val) { | ||
157 | case PCI_DEVICE_ID_KATANA_3750_PROC0: | ||
158 | proc = 0; | ||
159 | break; | ||
160 | |||
161 | case PCI_DEVICE_ID_KATANA_3750_PROC1: | ||
162 | proc = 1; | ||
163 | break; | ||
164 | |||
165 | case PCI_DEVICE_ID_KATANA_3750_PROC2: | ||
166 | proc = 2; | ||
167 | break; | ||
168 | |||
169 | default: | ||
170 | printk(KERN_ERR "Bogus Device ID\n"); | ||
171 | } | ||
172 | } | ||
173 | |||
174 | first_time = 0; | ||
175 | } | ||
176 | |||
177 | return proc; | ||
178 | } | ||
179 | |||
180 | static inline int | ||
181 | katana_is_monarch(void) | ||
182 | { | ||
183 | return in_8(cpld_base + KATANA_CPLD_BD_CFG_3) & | ||
184 | KATANA_CPLD_BD_CFG_3_MONARCH; | ||
185 | } | ||
186 | |||
187 | static void __init | ||
188 | katana_setup_bridge(void) | ||
189 | { | ||
190 | struct pci_controller hose; | ||
191 | struct mv64x60_setup_info si; | ||
192 | void __iomem *vaddr; | ||
193 | int i; | ||
194 | u16 val; | ||
195 | u8 save_exclude; | ||
196 | |||
197 | /* | ||
198 | * Some versions of the Katana firmware mistakenly change the vendor | ||
199 | * & device id fields in the bridge's pci device (visible via pci | ||
200 | * config accesses). This breaks mv64x60_init() because those values | ||
201 | * are used to identify the type of bridge that's there. Artesyn | ||
202 | * claims that the subsystem vendor/device id's will have the correct | ||
203 | * Marvell values so this code puts back the correct values from there. | ||
204 | */ | ||
205 | memset(&hose, 0, sizeof(hose)); | ||
206 | vaddr = ioremap(CONFIG_MV64X60_NEW_BASE, MV64x60_INTERNAL_SPACE_SIZE); | ||
207 | setup_indirect_pci_nomap(&hose, vaddr + MV64x60_PCI0_CONFIG_ADDR, | ||
208 | vaddr + MV64x60_PCI0_CONFIG_DATA); | ||
209 | save_exclude = mv64x60_pci_exclude_bridge; | ||
210 | mv64x60_pci_exclude_bridge = 0; | ||
211 | |||
212 | early_read_config_word(&hose, 0, PCI_DEVFN(0, 0), PCI_VENDOR_ID, &val); | ||
213 | |||
214 | if (val != PCI_VENDOR_ID_MARVELL) { | ||
215 | early_read_config_word(&hose, 0, PCI_DEVFN(0, 0), | ||
216 | PCI_SUBSYSTEM_VENDOR_ID, &val); | ||
217 | early_write_config_word(&hose, 0, PCI_DEVFN(0, 0), | ||
218 | PCI_VENDOR_ID, val); | ||
219 | early_read_config_word(&hose, 0, PCI_DEVFN(0, 0), | ||
220 | PCI_SUBSYSTEM_ID, &val); | ||
221 | early_write_config_word(&hose, 0, PCI_DEVFN(0, 0), | ||
222 | PCI_DEVICE_ID, val); | ||
223 | } | ||
224 | |||
225 | mv64x60_pci_exclude_bridge = save_exclude; | ||
226 | iounmap(vaddr); | ||
227 | |||
228 | memset(&si, 0, sizeof(si)); | ||
229 | |||
230 | si.phys_reg_base = CONFIG_MV64X60_NEW_BASE; | ||
231 | |||
232 | si.pci_1.enable_bus = 1; | ||
233 | si.pci_1.pci_io.cpu_base = KATANA_PCI1_IO_START_PROC_ADDR; | ||
234 | si.pci_1.pci_io.pci_base_hi = 0; | ||
235 | si.pci_1.pci_io.pci_base_lo = KATANA_PCI1_IO_START_PCI_ADDR; | ||
236 | si.pci_1.pci_io.size = KATANA_PCI1_IO_SIZE; | ||
237 | si.pci_1.pci_io.swap = MV64x60_CPU2PCI_SWAP_NONE; | ||
238 | si.pci_1.pci_mem[0].cpu_base = KATANA_PCI1_MEM_START_PROC_ADDR; | ||
239 | si.pci_1.pci_mem[0].pci_base_hi = KATANA_PCI1_MEM_START_PCI_HI_ADDR; | ||
240 | si.pci_1.pci_mem[0].pci_base_lo = KATANA_PCI1_MEM_START_PCI_LO_ADDR; | ||
241 | si.pci_1.pci_mem[0].size = KATANA_PCI1_MEM_SIZE; | ||
242 | si.pci_1.pci_mem[0].swap = MV64x60_CPU2PCI_SWAP_NONE; | ||
243 | si.pci_1.pci_cmd_bits = 0; | ||
244 | si.pci_1.latency_timer = 0x80; | ||
245 | |||
246 | for (i = 0; i < MV64x60_CPU2MEM_WINDOWS; i++) { | ||
247 | #if defined(CONFIG_NOT_COHERENT_CACHE) | ||
248 | si.cpu_prot_options[i] = 0; | ||
249 | si.enet_options[i] = MV64360_ENET2MEM_SNOOP_NONE; | ||
250 | si.mpsc_options[i] = MV64360_MPSC2MEM_SNOOP_NONE; | ||
251 | si.idma_options[i] = MV64360_IDMA2MEM_SNOOP_NONE; | ||
252 | |||
253 | si.pci_1.acc_cntl_options[i] = | ||
254 | MV64360_PCI_ACC_CNTL_SNOOP_NONE | | ||
255 | MV64360_PCI_ACC_CNTL_SWAP_NONE | | ||
256 | MV64360_PCI_ACC_CNTL_MBURST_128_BYTES | | ||
257 | MV64360_PCI_ACC_CNTL_RDSIZE_256_BYTES; | ||
258 | #else | ||
259 | si.cpu_prot_options[i] = 0; | ||
260 | si.enet_options[i] = MV64360_ENET2MEM_SNOOP_NONE; /* errata */ | ||
261 | si.mpsc_options[i] = MV64360_MPSC2MEM_SNOOP_NONE; /* errata */ | ||
262 | si.idma_options[i] = MV64360_IDMA2MEM_SNOOP_NONE; /* errata */ | ||
263 | |||
264 | si.pci_1.acc_cntl_options[i] = | ||
265 | MV64360_PCI_ACC_CNTL_SNOOP_WB | | ||
266 | MV64360_PCI_ACC_CNTL_SWAP_NONE | | ||
267 | MV64360_PCI_ACC_CNTL_MBURST_32_BYTES | | ||
268 | MV64360_PCI_ACC_CNTL_RDSIZE_32_BYTES; | ||
269 | #endif | ||
270 | } | ||
271 | |||
272 | /* Lookup PCI host bridges */ | ||
273 | if (mv64x60_init(&bh, &si)) | ||
274 | printk(KERN_WARNING "Bridge initialization failed.\n"); | ||
275 | |||
276 | pci_dram_offset = 0; /* sys mem at same addr on PCI & cpu bus */ | ||
277 | ppc_md.pci_swizzle = common_swizzle; | ||
278 | ppc_md.pci_map_irq = katana_map_irq; | ||
279 | ppc_md.pci_exclude_device = mv64x60_pci_exclude_device; | ||
280 | |||
281 | mv64x60_set_bus(&bh, 1, 0); | ||
282 | bh.hose_b->first_busno = 0; | ||
283 | bh.hose_b->last_busno = 0xff; | ||
284 | } | ||
285 | |||
286 | /* Bridge & platform setup routines */ | ||
287 | void __init | ||
288 | katana_intr_setup(void) | ||
289 | { | ||
290 | /* MPP 8, 9, and 10 */ | ||
291 | mv64x60_clr_bits(&bh, MV64x60_MPP_CNTL_1, 0xfff); | ||
292 | |||
293 | /* MPP 14 */ | ||
294 | if ((katana_id == KATANA_ID_750I) || (katana_id == KATANA_ID_752I)) | ||
295 | mv64x60_clr_bits(&bh, MV64x60_MPP_CNTL_1, 0x0f000000); | ||
296 | |||
297 | /* | ||
298 | * Define GPP 8,9,and 10 interrupt polarity as active low | ||
299 | * input signal and level triggered | ||
300 | */ | ||
301 | mv64x60_set_bits(&bh, MV64x60_GPP_LEVEL_CNTL, 0x700); | ||
302 | mv64x60_clr_bits(&bh, MV64x60_GPP_IO_CNTL, 0x700); | ||
303 | |||
304 | if ((katana_id == KATANA_ID_750I) || (katana_id == KATANA_ID_752I)) { | ||
305 | mv64x60_set_bits(&bh, MV64x60_GPP_LEVEL_CNTL, (1<<14)); | ||
306 | mv64x60_clr_bits(&bh, MV64x60_GPP_IO_CNTL, (1<<14)); | ||
307 | } | ||
308 | |||
309 | /* Config GPP intr ctlr to respond to level trigger */ | ||
310 | mv64x60_set_bits(&bh, MV64x60_COMM_ARBITER_CNTL, (1<<10)); | ||
311 | |||
312 | /* Erranum FEr PCI-#8 */ | ||
313 | mv64x60_clr_bits(&bh, MV64x60_PCI0_CMD, (1<<5) | (1<<9)); | ||
314 | mv64x60_clr_bits(&bh, MV64x60_PCI1_CMD, (1<<5) | (1<<9)); | ||
315 | |||
316 | /* | ||
317 | * Dismiss and then enable interrupt on GPP interrupt cause | ||
318 | * for CPU #0 | ||
319 | */ | ||
320 | mv64x60_write(&bh, MV64x60_GPP_INTR_CAUSE, ~0x700); | ||
321 | mv64x60_set_bits(&bh, MV64x60_GPP_INTR_MASK, 0x700); | ||
322 | |||
323 | if ((katana_id == KATANA_ID_750I) || (katana_id == KATANA_ID_752I)) { | ||
324 | mv64x60_write(&bh, MV64x60_GPP_INTR_CAUSE, ~(1<<14)); | ||
325 | mv64x60_set_bits(&bh, MV64x60_GPP_INTR_MASK, (1<<14)); | ||
326 | } | ||
327 | |||
328 | /* | ||
329 | * Dismiss and then enable interrupt on CPU #0 high cause reg | ||
330 | * BIT25 summarizes GPP interrupts 8-15 | ||
331 | */ | ||
332 | mv64x60_set_bits(&bh, MV64360_IC_CPU0_INTR_MASK_HI, (1<<25)); | ||
333 | } | ||
334 | |||
335 | void __init | ||
336 | katana_setup_peripherals(void) | ||
337 | { | ||
338 | u32 base; | ||
339 | |||
340 | /* Set up windows for boot CS, soldered & socketed flash, and CPLD */ | ||
341 | mv64x60_set_32bit_window(&bh, MV64x60_CPU2BOOT_WIN, | ||
342 | KATANA_BOOT_WINDOW_BASE, KATANA_BOOT_WINDOW_SIZE, 0); | ||
343 | bh.ci->enable_window_32bit(&bh, MV64x60_CPU2BOOT_WIN); | ||
344 | |||
345 | /* Assume firmware set up window sizes correctly for dev 0 & 1 */ | ||
346 | mv64x60_get_32bit_window(&bh, MV64x60_CPU2DEV_0_WIN, &base, | ||
347 | &katana_flash_size_0); | ||
348 | |||
349 | if (katana_flash_size_0 > 0) { | ||
350 | mv64x60_set_32bit_window(&bh, MV64x60_CPU2DEV_0_WIN, | ||
351 | KATANA_SOLDERED_FLASH_BASE, katana_flash_size_0, 0); | ||
352 | bh.ci->enable_window_32bit(&bh, MV64x60_CPU2DEV_0_WIN); | ||
353 | } | ||
354 | |||
355 | mv64x60_get_32bit_window(&bh, MV64x60_CPU2DEV_1_WIN, &base, | ||
356 | &katana_flash_size_1); | ||
357 | |||
358 | if (katana_flash_size_1 > 0) { | ||
359 | mv64x60_set_32bit_window(&bh, MV64x60_CPU2DEV_1_WIN, | ||
360 | (KATANA_SOLDERED_FLASH_BASE + katana_flash_size_0), | ||
361 | katana_flash_size_1, 0); | ||
362 | bh.ci->enable_window_32bit(&bh, MV64x60_CPU2DEV_1_WIN); | ||
363 | } | ||
364 | |||
365 | mv64x60_set_32bit_window(&bh, MV64x60_CPU2DEV_2_WIN, | ||
366 | KATANA_SOCKET_BASE, KATANA_SOCKETED_FLASH_SIZE, 0); | ||
367 | bh.ci->enable_window_32bit(&bh, MV64x60_CPU2DEV_2_WIN); | ||
368 | |||
369 | mv64x60_set_32bit_window(&bh, MV64x60_CPU2DEV_3_WIN, | ||
370 | KATANA_CPLD_BASE, KATANA_CPLD_SIZE, 0); | ||
371 | bh.ci->enable_window_32bit(&bh, MV64x60_CPU2DEV_3_WIN); | ||
372 | cpld_base = ioremap(KATANA_CPLD_BASE, KATANA_CPLD_SIZE); | ||
373 | |||
374 | mv64x60_set_32bit_window(&bh, MV64x60_CPU2SRAM_WIN, | ||
375 | KATANA_INTERNAL_SRAM_BASE, MV64360_SRAM_SIZE, 0); | ||
376 | bh.ci->enable_window_32bit(&bh, MV64x60_CPU2SRAM_WIN); | ||
377 | sram_base = ioremap(KATANA_INTERNAL_SRAM_BASE, MV64360_SRAM_SIZE); | ||
378 | |||
379 | /* Set up Enet->SRAM window */ | ||
380 | mv64x60_set_32bit_window(&bh, MV64x60_ENET2MEM_4_WIN, | ||
381 | KATANA_INTERNAL_SRAM_BASE, MV64360_SRAM_SIZE, 0x2); | ||
382 | bh.ci->enable_window_32bit(&bh, MV64x60_ENET2MEM_4_WIN); | ||
383 | |||
384 | /* Give enet r/w access to memory region */ | ||
385 | mv64x60_set_bits(&bh, MV64360_ENET2MEM_ACC_PROT_0, (0x3 << (4 << 1))); | ||
386 | mv64x60_set_bits(&bh, MV64360_ENET2MEM_ACC_PROT_1, (0x3 << (4 << 1))); | ||
387 | mv64x60_set_bits(&bh, MV64360_ENET2MEM_ACC_PROT_2, (0x3 << (4 << 1))); | ||
388 | |||
389 | mv64x60_clr_bits(&bh, MV64x60_PCI1_PCI_DECODE_CNTL, (1 << 3)); | ||
390 | mv64x60_clr_bits(&bh, MV64x60_TIMR_CNTR_0_3_CNTL, | ||
391 | ((1 << 0) | (1 << 8) | (1 << 16) | (1 << 24))); | ||
392 | |||
393 | /* Must wait until window set up before retrieving board id */ | ||
394 | katana_get_board_id(); | ||
395 | |||
396 | /* Enumerate pci bus (must know board id before getting proc number) */ | ||
397 | if (katana_get_proc_num() == 0) | ||
398 | bh.hose_b->last_busno = pciauto_bus_scan(bh.hose_b, 0); | ||
399 | |||
400 | #if defined(CONFIG_NOT_COHERENT_CACHE) | ||
401 | mv64x60_write(&bh, MV64360_SRAM_CONFIG, 0x00160000); | ||
402 | #else | ||
403 | mv64x60_write(&bh, MV64360_SRAM_CONFIG, 0x001600b2); | ||
404 | #endif | ||
405 | |||
406 | /* | ||
407 | * Setting the SRAM to 0. Note that this generates parity errors on | ||
408 | * internal data path in SRAM since it's first time accessing it | ||
409 | * while after reset it's not configured. | ||
410 | */ | ||
411 | memset(sram_base, 0, MV64360_SRAM_SIZE); | ||
412 | |||
413 | /* Only processor zero [on 3750] is an PCI interrupt controller */ | ||
414 | if (katana_get_proc_num() == 0) | ||
415 | katana_intr_setup(); | ||
416 | } | ||
417 | |||
418 | static void __init | ||
419 | katana_enable_ipmi(void) | ||
420 | { | ||
421 | u8 reset_out; | ||
422 | |||
423 | /* Enable access to IPMI ctlr by clearing IPMI PORTSEL bit in CPLD */ | ||
424 | reset_out = in_8(cpld_base + KATANA_CPLD_RESET_OUT); | ||
425 | reset_out &= ~KATANA_CPLD_RESET_OUT_PORTSEL; | ||
426 | out_8(cpld_base + KATANA_CPLD_RESET_OUT, reset_out); | ||
427 | } | ||
428 | |||
429 | static void __init | ||
430 | katana_setup_arch(void) | ||
431 | { | ||
432 | if (ppc_md.progress) | ||
433 | ppc_md.progress("katana_setup_arch: enter", 0); | ||
434 | |||
435 | set_tb(0, 0); | ||
436 | |||
437 | #ifdef CONFIG_BLK_DEV_INITRD | ||
438 | if (initrd_start) | ||
439 | ROOT_DEV = Root_RAM0; | ||
440 | else | ||
441 | #endif | ||
442 | #ifdef CONFIG_ROOT_NFS | ||
443 | ROOT_DEV = Root_NFS; | ||
444 | #else | ||
445 | ROOT_DEV = Root_SDA2; | ||
446 | #endif | ||
447 | |||
448 | /* | ||
449 | * Set up the L2CR register. | ||
450 | * | ||
451 | * 750FX has only L2E, L2PE (bits 2-8 are reserved) | ||
452 | * DD2.0 has bug that requires the L2 to be in WRT mode | ||
453 | * avoid dirty data in cache | ||
454 | */ | ||
455 | if (PVR_REV(mfspr(SPRN_PVR)) == 0x0200) { | ||
456 | printk(KERN_INFO "DD2.0 detected. Setting L2 cache" | ||
457 | "to Writethrough mode\n"); | ||
458 | _set_L2CR(L2CR_L2E | L2CR_L2PE | L2CR_L2WT); | ||
459 | } else | ||
460 | _set_L2CR(L2CR_L2E | L2CR_L2PE); | ||
461 | |||
462 | if (ppc_md.progress) | ||
463 | ppc_md.progress("katana_setup_arch: calling setup_bridge", 0); | ||
464 | |||
465 | katana_setup_bridge(); | ||
466 | katana_setup_peripherals(); | ||
467 | katana_enable_ipmi(); | ||
468 | |||
469 | katana_bus_frequency = katana_bus_freq(cpld_base); | ||
470 | |||
471 | printk(KERN_INFO "Artesyn Communication Products, LLC - Katana(TM)\n"); | ||
472 | if (ppc_md.progress) | ||
473 | ppc_md.progress("katana_setup_arch: exit", 0); | ||
474 | } | ||
475 | |||
476 | /* Platform device data fixup routines. */ | ||
477 | #if defined(CONFIG_SERIAL_MPSC) | ||
478 | static void __init | ||
479 | katana_fixup_mpsc_pdata(struct platform_device *pdev) | ||
480 | { | ||
481 | struct mpsc_pdata *pdata; | ||
482 | |||
483 | pdata = (struct mpsc_pdata *)pdev->dev.platform_data; | ||
484 | |||
485 | pdata->max_idle = 40; | ||
486 | pdata->default_baud = KATANA_DEFAULT_BAUD; | ||
487 | pdata->brg_clk_src = KATANA_MPSC_CLK_SRC; | ||
488 | /* | ||
489 | * TCLK (not SysCLk) is routed to BRG, then to the MPSC. On most parts, | ||
490 | * TCLK == SysCLK but on 64460, they are separate pins. | ||
491 | * SysCLK can go up to 200 MHz but TCLK can only go up to 133 MHz. | ||
492 | */ | ||
493 | pdata->brg_clk_freq = min(katana_bus_frequency, MV64x60_TCLK_FREQ_MAX); | ||
494 | } | ||
495 | #endif | ||
496 | |||
497 | #if defined(CONFIG_MV643XX_ETH) | ||
498 | static void __init | ||
499 | katana_fixup_eth_pdata(struct platform_device *pdev) | ||
500 | { | ||
501 | struct mv643xx_eth_platform_data *eth_pd; | ||
502 | static u16 phy_addr[] = { | ||
503 | KATANA_ETH0_PHY_ADDR, | ||
504 | KATANA_ETH1_PHY_ADDR, | ||
505 | KATANA_ETH2_PHY_ADDR, | ||
506 | }; | ||
507 | |||
508 | eth_pd = pdev->dev.platform_data; | ||
509 | eth_pd->force_phy_addr = 1; | ||
510 | eth_pd->phy_addr = phy_addr[pdev->id]; | ||
511 | eth_pd->tx_queue_size = KATANA_ETH_TX_QUEUE_SIZE; | ||
512 | eth_pd->rx_queue_size = KATANA_ETH_RX_QUEUE_SIZE; | ||
513 | } | ||
514 | #endif | ||
515 | |||
516 | static int __init | ||
517 | katana_platform_notify(struct device *dev) | ||
518 | { | ||
519 | static struct { | ||
520 | char *bus_id; | ||
521 | void ((*rtn)(struct platform_device *pdev)); | ||
522 | } dev_map[] = { | ||
523 | #if defined(CONFIG_SERIAL_MPSC) | ||
524 | { MPSC_CTLR_NAME ".0", katana_fixup_mpsc_pdata }, | ||
525 | { MPSC_CTLR_NAME ".1", katana_fixup_mpsc_pdata }, | ||
526 | #endif | ||
527 | #if defined(CONFIG_MV643XX_ETH) | ||
528 | { MV643XX_ETH_NAME ".0", katana_fixup_eth_pdata }, | ||
529 | { MV643XX_ETH_NAME ".1", katana_fixup_eth_pdata }, | ||
530 | { MV643XX_ETH_NAME ".2", katana_fixup_eth_pdata }, | ||
531 | #endif | ||
532 | }; | ||
533 | struct platform_device *pdev; | ||
534 | int i; | ||
535 | |||
536 | if (dev && dev->bus_id) | ||
537 | for (i=0; i<ARRAY_SIZE(dev_map); i++) | ||
538 | if (!strncmp(dev->bus_id, dev_map[i].bus_id, | ||
539 | BUS_ID_SIZE)) { | ||
540 | |||
541 | pdev = container_of(dev, | ||
542 | struct platform_device, dev); | ||
543 | dev_map[i].rtn(pdev); | ||
544 | } | ||
545 | |||
546 | return 0; | ||
547 | } | ||
548 | |||
549 | #ifdef CONFIG_MTD_PHYSMAP | ||
550 | |||
551 | #ifndef MB | ||
552 | #define MB (1 << 20) | ||
553 | #endif | ||
554 | |||
555 | /* | ||
556 | * MTD Layout depends on amount of soldered FLASH in system. Sizes in MB. | ||
557 | * | ||
558 | * FLASH Amount: 128 64 32 16 | ||
559 | * ------------- --- -- -- -- | ||
560 | * Monitor: 1 1 1 1 | ||
561 | * Primary Kernel: 1.5 1.5 1.5 1.5 | ||
562 | * Primary fs: 30 30 <end> <end> | ||
563 | * Secondary Kernel: 1.5 1.5 N/A N/A | ||
564 | * Secondary fs: <end> <end> N/A N/A | ||
565 | * User: <overlays entire FLASH except for "Monitor" section> | ||
566 | */ | ||
567 | static int __init | ||
568 | katana_setup_mtd(void) | ||
569 | { | ||
570 | u32 size; | ||
571 | int ptbl_entries; | ||
572 | static struct mtd_partition *ptbl; | ||
573 | |||
574 | size = katana_flash_size_0 + katana_flash_size_1; | ||
575 | if (!size) | ||
576 | return -ENOMEM; | ||
577 | |||
578 | ptbl_entries = (size >= (64*MB)) ? 6 : 4; | ||
579 | |||
580 | if ((ptbl = kmalloc(ptbl_entries * sizeof(struct mtd_partition), | ||
581 | GFP_KERNEL)) == NULL) { | ||
582 | |||
583 | printk(KERN_WARNING "Can't alloc MTD partition table\n"); | ||
584 | return -ENOMEM; | ||
585 | } | ||
586 | memset(ptbl, 0, ptbl_entries * sizeof(struct mtd_partition)); | ||
587 | |||
588 | ptbl[0].name = "Monitor"; | ||
589 | ptbl[0].size = KATANA_MTD_MONITOR_SIZE; | ||
590 | ptbl[1].name = "Primary Kernel"; | ||
591 | ptbl[1].offset = MTDPART_OFS_NXTBLK; | ||
592 | ptbl[1].size = 0x00180000; /* 1.5 MB */ | ||
593 | ptbl[2].name = "Primary Filesystem"; | ||
594 | ptbl[2].offset = MTDPART_OFS_APPEND; | ||
595 | ptbl[2].size = MTDPART_SIZ_FULL; /* Correct for 16 & 32 MB */ | ||
596 | ptbl[ptbl_entries-1].name = "User FLASH"; | ||
597 | ptbl[ptbl_entries-1].offset = KATANA_MTD_MONITOR_SIZE; | ||
598 | ptbl[ptbl_entries-1].size = MTDPART_SIZ_FULL; | ||
599 | |||
600 | if (size >= (64*MB)) { | ||
601 | ptbl[2].size = 30*MB; | ||
602 | ptbl[3].name = "Secondary Kernel"; | ||
603 | ptbl[3].offset = MTDPART_OFS_NXTBLK; | ||
604 | ptbl[3].size = 0x00180000; /* 1.5 MB */ | ||
605 | ptbl[4].name = "Secondary Filesystem"; | ||
606 | ptbl[4].offset = MTDPART_OFS_APPEND; | ||
607 | ptbl[4].size = MTDPART_SIZ_FULL; | ||
608 | } | ||
609 | |||
610 | physmap_map.size = size; | ||
611 | physmap_set_partitions(ptbl, ptbl_entries); | ||
612 | return 0; | ||
613 | } | ||
614 | |||
615 | arch_initcall(katana_setup_mtd); | ||
616 | #endif | ||
617 | |||
618 | static void | ||
619 | katana_restart(char *cmd) | ||
620 | { | ||
621 | ulong i = 10000000; | ||
622 | |||
623 | /* issue hard reset to the reset command register */ | ||
624 | out_8(cpld_base + KATANA_CPLD_RST_CMD, KATANA_CPLD_RST_CMD_HR); | ||
625 | |||
626 | while (i-- > 0) ; | ||
627 | panic("restart failed\n"); | ||
628 | } | ||
629 | |||
630 | static void | ||
631 | katana_halt(void) | ||
632 | { | ||
633 | u8 v; | ||
634 | |||
635 | if (katana_id == KATANA_ID_752I) { | ||
636 | v = in_8(cpld_base + HSL_PLD_BASE + HSL_PLD_HOT_SWAP_OFF); | ||
637 | v |= HSL_PLD_HOT_SWAP_LED_BIT; | ||
638 | out_8(cpld_base + HSL_PLD_BASE + HSL_PLD_HOT_SWAP_OFF, v); | ||
639 | } | ||
640 | |||
641 | while (1) ; | ||
642 | /* NOTREACHED */ | ||
643 | } | ||
644 | |||
645 | static void | ||
646 | katana_power_off(void) | ||
647 | { | ||
648 | katana_halt(); | ||
649 | /* NOTREACHED */ | ||
650 | } | ||
651 | |||
652 | static int | ||
653 | katana_show_cpuinfo(struct seq_file *m) | ||
654 | { | ||
655 | seq_printf(m, "vendor\t\t: Artesyn Communication Products, LLC\n"); | ||
656 | |||
657 | seq_printf(m, "board\t\t: "); | ||
658 | |||
659 | switch (katana_id) { | ||
660 | case KATANA_ID_3750: | ||
661 | seq_printf(m, "Katana 3750\n"); | ||
662 | break; | ||
663 | |||
664 | case KATANA_ID_750I: | ||
665 | seq_printf(m, "Katana 750i\n"); | ||
666 | break; | ||
667 | |||
668 | case KATANA_ID_752I: | ||
669 | seq_printf(m, "Katana 752i\n"); | ||
670 | break; | ||
671 | |||
672 | default: | ||
673 | seq_printf(m, "Unknown\n"); | ||
674 | break; | ||
675 | } | ||
676 | |||
677 | seq_printf(m, "product ID\t: 0x%x\n", | ||
678 | in_8(cpld_base + KATANA_CPLD_PRODUCT_ID)); | ||
679 | seq_printf(m, "hardware rev\t: 0x%x\n", | ||
680 | in_8(cpld_base+KATANA_CPLD_HARDWARE_VER)); | ||
681 | seq_printf(m, "PLD rev\t\t: 0x%x\n", | ||
682 | in_8(cpld_base + KATANA_CPLD_PLD_VER)); | ||
683 | seq_printf(m, "PLB freq\t: %ldMhz\n", | ||
684 | (long)katana_bus_frequency / 1000000); | ||
685 | seq_printf(m, "PCI\t\t: %sMonarch\n", katana_is_monarch()? "" : "Non-"); | ||
686 | |||
687 | return 0; | ||
688 | } | ||
689 | |||
690 | static void __init | ||
691 | katana_calibrate_decr(void) | ||
692 | { | ||
693 | u32 freq; | ||
694 | |||
695 | freq = katana_bus_frequency / 4; | ||
696 | |||
697 | printk(KERN_INFO "time_init: decrementer frequency = %lu.%.6lu MHz\n", | ||
698 | (long)freq / 1000000, (long)freq % 1000000); | ||
699 | |||
700 | tb_ticks_per_jiffy = freq / HZ; | ||
701 | tb_to_us = mulhwu_scale_factor(freq, 1000000); | ||
702 | } | ||
703 | |||
704 | unsigned long __init | ||
705 | katana_find_end_of_memory(void) | ||
706 | { | ||
707 | return mv64x60_get_mem_size(CONFIG_MV64X60_NEW_BASE, | ||
708 | MV64x60_TYPE_MV64360); | ||
709 | } | ||
710 | |||
711 | #if defined(CONFIG_I2C_MV64XXX) && defined(CONFIG_SENSORS_M41T00) | ||
712 | extern ulong m41t00_get_rtc_time(void); | ||
713 | extern int m41t00_set_rtc_time(ulong); | ||
714 | |||
715 | static int __init | ||
716 | katana_rtc_hookup(void) | ||
717 | { | ||
718 | struct timespec tv; | ||
719 | |||
720 | ppc_md.get_rtc_time = m41t00_get_rtc_time; | ||
721 | ppc_md.set_rtc_time = m41t00_set_rtc_time; | ||
722 | |||
723 | tv.tv_nsec = 0; | ||
724 | tv.tv_sec = (ppc_md.get_rtc_time)(); | ||
725 | do_settimeofday(&tv); | ||
726 | |||
727 | return 0; | ||
728 | } | ||
729 | late_initcall(katana_rtc_hookup); | ||
730 | #endif | ||
731 | |||
732 | static inline void | ||
733 | katana_set_bat(void) | ||
734 | { | ||
735 | mb(); | ||
736 | mtspr(SPRN_DBAT2U, 0xf0001ffe); | ||
737 | mtspr(SPRN_DBAT2L, 0xf000002a); | ||
738 | mb(); | ||
739 | } | ||
740 | |||
741 | #if defined(CONFIG_SERIAL_TEXT_DEBUG) && defined(CONFIG_SERIAL_MPSC_CONSOLE) | ||
742 | static void __init | ||
743 | katana_map_io(void) | ||
744 | { | ||
745 | io_block_mapping(0xf8100000, 0xf8100000, 0x00020000, _PAGE_IO); | ||
746 | } | ||
747 | #endif | ||
748 | |||
749 | void __init | ||
750 | platform_init(unsigned long r3, unsigned long r4, unsigned long r5, | ||
751 | unsigned long r6, unsigned long r7) | ||
752 | { | ||
753 | parse_bootinfo(find_bootinfo()); | ||
754 | |||
755 | /* ASSUMPTION: If both r3 (bd_t pointer) and r6 (cmdline pointer) | ||
756 | * are non-zero, then we should use the board info from the bd_t | ||
757 | * structure and the cmdline pointed to by r6 instead of the | ||
758 | * information from birecs, if any. Otherwise, use the information | ||
759 | * from birecs as discovered by the preceeding call to | ||
760 | * parse_bootinfo(). This rule should work with both PPCBoot, which | ||
761 | * uses a bd_t board info structure, and the kernel boot wrapper, | ||
762 | * which uses birecs. | ||
763 | */ | ||
764 | if (r3 && r6) { | ||
765 | /* copy board info structure */ | ||
766 | memcpy( (void *)__res,(void *)(r3+KERNELBASE), sizeof(bd_t) ); | ||
767 | /* copy command line */ | ||
768 | *(char *)(r7+KERNELBASE) = 0; | ||
769 | strcpy(cmd_line, (char *)(r6+KERNELBASE)); | ||
770 | } | ||
771 | |||
772 | isa_mem_base = 0; | ||
773 | |||
774 | ppc_md.setup_arch = katana_setup_arch; | ||
775 | ppc_md.show_cpuinfo = katana_show_cpuinfo; | ||
776 | ppc_md.init_IRQ = mv64360_init_irq; | ||
777 | ppc_md.get_irq = mv64360_get_irq; | ||
778 | ppc_md.restart = katana_restart; | ||
779 | ppc_md.power_off = katana_power_off; | ||
780 | ppc_md.halt = katana_halt; | ||
781 | ppc_md.find_end_of_memory = katana_find_end_of_memory; | ||
782 | ppc_md.calibrate_decr = katana_calibrate_decr; | ||
783 | |||
784 | #if defined(CONFIG_SERIAL_TEXT_DEBUG) && defined(CONFIG_SERIAL_MPSC_CONSOLE) | ||
785 | ppc_md.setup_io_mappings = katana_map_io; | ||
786 | ppc_md.progress = mv64x60_mpsc_progress; | ||
787 | mv64x60_progress_init(CONFIG_MV64X60_NEW_BASE); | ||
788 | #endif | ||
789 | |||
790 | #if defined(CONFIG_SERIAL_MPSC) || defined(CONFIG_MV643XX_ETH) | ||
791 | platform_notify = katana_platform_notify; | ||
792 | #endif | ||
793 | |||
794 | katana_set_bat(); /* Need for katana_find_end_of_memory and progress */ | ||
795 | } | ||
diff --git a/arch/ppc/platforms/katana.h b/arch/ppc/platforms/katana.h new file mode 100644 index 000000000000..b82ed81950f5 --- /dev/null +++ b/arch/ppc/platforms/katana.h | |||
@@ -0,0 +1,255 @@ | |||
1 | /* | ||
2 | * arch/ppc/platforms/katana.h | ||
3 | * | ||
4 | * Definitions for Artesyn Katana750i/3750 board. | ||
5 | * | ||
6 | * Author: Tim Montgomery <timm@artesyncp.com> | ||
7 | * Maintained by: Mark A. Greer <mgreer@mvista.com> | ||
8 | * | ||
9 | * Based on code done by Rabeeh Khoury - rabeeh@galileo.co.il | ||
10 | * Based on code done by Mark A. Greer <mgreer@mvista.com> | ||
11 | * | ||
12 | * This program is free software; you can redistribute it and/or modify it | ||
13 | * under the terms of the GNU General Public License as published by the | ||
14 | * Free Software Foundation; either version 2 of the License, or (at your | ||
15 | * option) any later version. | ||
16 | */ | ||
17 | |||
18 | /* | ||
19 | * The MV64360 has 2 PCI buses each with 1 window from the CPU bus to | ||
20 | * PCI I/O space and 4 windows from the CPU bus to PCI MEM space. | ||
21 | * We'll only use one PCI MEM window on each PCI bus. | ||
22 | * | ||
23 | * This is the CPU physical memory map (windows must be at least 64 KB and start | ||
24 | * on a boundary that is a multiple of the window size): | ||
25 | * | ||
26 | * 0xff800000-0xffffffff - Boot window | ||
27 | * 0xf8400000-0xf843ffff - Internal SRAM | ||
28 | * 0xf8200000-0xf83fffff - CPLD | ||
29 | * 0xf8100000-0xf810ffff - MV64360 Registers (CONFIG_MV64X60_NEW_BASE) | ||
30 | * 0xf8000000-0xf80fffff - Socketed FLASH | ||
31 | * 0xe0000000-0xefffffff - Soldered FLASH | ||
32 | * 0xc0000000-0xc3ffffff - PCI I/O (second hose) | ||
33 | * 0x80000000-0xbfffffff - PCI MEM (second hose) | ||
34 | */ | ||
35 | |||
36 | #ifndef __PPC_PLATFORMS_KATANA_H | ||
37 | #define __PPC_PLATFORMS_KATANA_H | ||
38 | |||
39 | /* CPU Physical Memory Map setup. */ | ||
40 | #define KATANA_BOOT_WINDOW_BASE 0xff800000 | ||
41 | #define KATANA_BOOT_WINDOW_SIZE 0x00800000 /* 8 MB */ | ||
42 | #define KATANA_INTERNAL_SRAM_BASE 0xf8400000 | ||
43 | #define KATANA_CPLD_BASE 0xf8200000 | ||
44 | #define KATANA_CPLD_SIZE 0x00200000 /* 2 MB */ | ||
45 | #define KATANA_SOCKET_BASE 0xf8000000 | ||
46 | #define KATANA_SOCKETED_FLASH_SIZE 0x00100000 /* 1 MB */ | ||
47 | #define KATANA_SOLDERED_FLASH_BASE 0xe0000000 | ||
48 | #define KATANA_SOLDERED_FLASH_SIZE 0x10000000 /* 256 MB */ | ||
49 | |||
50 | #define KATANA_PCI1_MEM_START_PROC_ADDR 0x80000000 | ||
51 | #define KATANA_PCI1_MEM_START_PCI_HI_ADDR 0x00000000 | ||
52 | #define KATANA_PCI1_MEM_START_PCI_LO_ADDR 0x80000000 | ||
53 | #define KATANA_PCI1_MEM_SIZE 0x40000000 /* 1 GB */ | ||
54 | #define KATANA_PCI1_IO_START_PROC_ADDR 0xc0000000 | ||
55 | #define KATANA_PCI1_IO_START_PCI_ADDR 0x00000000 | ||
56 | #define KATANA_PCI1_IO_SIZE 0x04000000 /* 64 MB */ | ||
57 | |||
58 | /* Board-specific IRQ info */ | ||
59 | #define KATANA_PCI_INTA_IRQ_3750 64+8 | ||
60 | #define KATANA_PCI_INTB_IRQ_3750 64+9 | ||
61 | #define KATANA_PCI_INTC_IRQ_3750 64+10 | ||
62 | |||
63 | #define KATANA_PCI_INTA_IRQ_750i 64+8 | ||
64 | #define KATANA_PCI_INTB_IRQ_750i 64+9 | ||
65 | #define KATANA_PCI_INTC_IRQ_750i 64+10 | ||
66 | #define KATANA_PCI_INTD_IRQ_750i 64+14 | ||
67 | |||
68 | #define KATANA_CPLD_RST_EVENT 0x00000000 | ||
69 | #define KATANA_CPLD_RST_CMD 0x00001000 | ||
70 | #define KATANA_CPLD_PCI_ERR_INT_EN 0x00002000 | ||
71 | #define KATANA_CPLD_PCI_ERR_INT_PEND 0x00003000 | ||
72 | #define KATANA_CPLD_PRODUCT_ID 0x00004000 | ||
73 | #define KATANA_CPLD_EREADY 0x00005000 | ||
74 | |||
75 | #define KATANA_CPLD_HARDWARE_VER 0x00007000 | ||
76 | #define KATANA_CPLD_PLD_VER 0x00008000 | ||
77 | #define KATANA_CPLD_BD_CFG_0 0x00009000 | ||
78 | #define KATANA_CPLD_BD_CFG_1 0x0000a000 | ||
79 | #define KATANA_CPLD_BD_CFG_3 0x0000c000 | ||
80 | #define KATANA_CPLD_LED 0x0000d000 | ||
81 | #define KATANA_CPLD_RESET_OUT 0x0000e000 | ||
82 | |||
83 | #define KATANA_CPLD_RST_EVENT_INITACT 0x80 | ||
84 | #define KATANA_CPLD_RST_EVENT_SW 0x40 | ||
85 | #define KATANA_CPLD_RST_EVENT_WD 0x20 | ||
86 | #define KATANA_CPLD_RST_EVENT_COPS 0x10 | ||
87 | #define KATANA_CPLD_RST_EVENT_COPH 0x08 | ||
88 | #define KATANA_CPLD_RST_EVENT_CPCI 0x02 | ||
89 | #define KATANA_CPLD_RST_EVENT_FP 0x01 | ||
90 | |||
91 | #define KATANA_CPLD_RST_CMD_SCL 0x80 | ||
92 | #define KATANA_CPLD_RST_CMD_SDA 0x40 | ||
93 | #define KATANA_CPLD_RST_CMD_I2C 0x10 | ||
94 | #define KATANA_CPLD_RST_CMD_FR 0x08 | ||
95 | #define KATANA_CPLD_RST_CMD_SR 0x04 | ||
96 | #define KATANA_CPLD_RST_CMD_HR 0x01 | ||
97 | |||
98 | #define KATANA_CPLD_BD_CFG_0_SYSCLK_MASK 0xc0 | ||
99 | #define KATANA_CPLD_BD_CFG_0_SYSCLK_200 0x00 | ||
100 | #define KATANA_CPLD_BD_CFG_0_SYSCLK_166 0x80 | ||
101 | #define KATANA_CPLD_BD_CFG_0_SYSCLK_133 0xc0 | ||
102 | #define KATANA_CPLD_BD_CFG_0_SYSCLK_100 0x40 | ||
103 | |||
104 | #define KATANA_CPLD_BD_CFG_1_FL_BANK_MASK 0x03 | ||
105 | #define KATANA_CPLD_BD_CFG_1_FL_BANK_16MB 0x00 | ||
106 | #define KATANA_CPLD_BD_CFG_1_FL_BANK_32MB 0x01 | ||
107 | #define KATANA_CPLD_BD_CFG_1_FL_BANK_64MB 0x02 | ||
108 | #define KATANA_CPLD_BD_CFG_1_FL_BANK_128MB 0x03 | ||
109 | |||
110 | #define KATANA_CPLD_BD_CFG_1_FL_NUM_BANKS_MASK 0x04 | ||
111 | #define KATANA_CPLD_BD_CFG_1_FL_NUM_BANKS_ONE 0x00 | ||
112 | #define KATANA_CPLD_BD_CFG_1_FL_NUM_BANKS_TWO 0x04 | ||
113 | |||
114 | #define KATANA_CPLD_BD_CFG_3_MONARCH 0x04 | ||
115 | |||
116 | #define KATANA_CPLD_RESET_OUT_PORTSEL 0x80 | ||
117 | #define KATANA_CPLD_RESET_OUT_WD 0x20 | ||
118 | #define KATANA_CPLD_RESET_OUT_COPH 0x08 | ||
119 | #define KATANA_CPLD_RESET_OUT_PCI_RST_PCI 0x02 | ||
120 | #define KATANA_CPLD_RESET_OUT_PCI_RST_FP 0x01 | ||
121 | |||
122 | #define KATANA_MBOX_RESET_REQUEST 0xC83A | ||
123 | #define KATANA_MBOX_RESET_ACK 0xE430 | ||
124 | #define KATANA_MBOX_RESET_DONE 0x32E5 | ||
125 | |||
126 | #define HSL_PLD_BASE 0x00010000 | ||
127 | #define HSL_PLD_J4SGA_REG_OFF 0 | ||
128 | #define HSL_PLD_J4GA_REG_OFF 1 | ||
129 | #define HSL_PLD_J2GA_REG_OFF 2 | ||
130 | #define HSL_PLD_HOT_SWAP_OFF 6 | ||
131 | #define HSL_PLD_HOT_SWAP_LED_BIT 0x1 | ||
132 | #define GA_MASK 0x1f | ||
133 | #define HSL_PLD_SIZE 0x1000 | ||
134 | #define K3750_GPP_GEO_ADDR_PINS 0xf8000000 | ||
135 | #define K3750_GPP_GEO_ADDR_SHIFT 27 | ||
136 | |||
137 | #define K3750_GPP_EVENT_PROC_0 (1 << 21) | ||
138 | #define K3750_GPP_EVENT_PROC_1_2 (1 << 2) | ||
139 | |||
140 | #define PCI_VENDOR_ID_ARTESYN 0x1223 | ||
141 | #define PCI_DEVICE_ID_KATANA_3750_PROC0 0x0041 | ||
142 | #define PCI_DEVICE_ID_KATANA_3750_PROC1 0x0042 | ||
143 | #define PCI_DEVICE_ID_KATANA_3750_PROC2 0x0043 | ||
144 | |||
145 | #define COPROC_MEM_FUNCTION 0 | ||
146 | #define COPROC_MEM_BAR 0 | ||
147 | #define COPROC_REGS_FUNCTION 0 | ||
148 | #define COPROC_REGS_BAR 4 | ||
149 | #define COPROC_FLASH_FUNCTION 2 | ||
150 | #define COPROC_FLASH_BAR 4 | ||
151 | |||
152 | #define KATANA_IPMB_LOCAL_I2C_ADDR 0x08 | ||
153 | |||
154 | #define KATANA_DEFAULT_BAUD 9600 | ||
155 | #define KATANA_MPSC_CLK_SRC 8 /* TCLK */ | ||
156 | |||
157 | #define KATANA_MTD_MONITOR_SIZE (1 << 20) /* 1 MB */ | ||
158 | |||
159 | #define KATANA_ETH0_PHY_ADDR 12 | ||
160 | #define KATANA_ETH1_PHY_ADDR 11 | ||
161 | #define KATANA_ETH2_PHY_ADDR 4 | ||
162 | |||
163 | #define KATANA_PRODUCT_ID_3750 0x01 | ||
164 | #define KATANA_PRODUCT_ID_750i 0x02 | ||
165 | #define KATANA_PRODUCT_ID_752i 0x04 | ||
166 | |||
167 | #define KATANA_ETH_TX_QUEUE_SIZE 800 | ||
168 | #define KATANA_ETH_RX_QUEUE_SIZE 400 | ||
169 | |||
170 | #define KATANA_ETH_PORT_CONFIG_VALUE \ | ||
171 | ETH_UNICAST_NORMAL_MODE | \ | ||
172 | ETH_DEFAULT_RX_QUEUE_0 | \ | ||
173 | ETH_DEFAULT_RX_ARP_QUEUE_0 | \ | ||
174 | ETH_RECEIVE_BC_IF_NOT_IP_OR_ARP | \ | ||
175 | ETH_RECEIVE_BC_IF_IP | \ | ||
176 | ETH_RECEIVE_BC_IF_ARP | \ | ||
177 | ETH_CAPTURE_TCP_FRAMES_DIS | \ | ||
178 | ETH_CAPTURE_UDP_FRAMES_DIS | \ | ||
179 | ETH_DEFAULT_RX_TCP_QUEUE_0 | \ | ||
180 | ETH_DEFAULT_RX_UDP_QUEUE_0 | \ | ||
181 | ETH_DEFAULT_RX_BPDU_QUEUE_0 | ||
182 | |||
183 | #define KATANA_ETH_PORT_CONFIG_EXTEND_VALUE \ | ||
184 | ETH_SPAN_BPDU_PACKETS_AS_NORMAL | \ | ||
185 | ETH_PARTITION_DISABLE | ||
186 | |||
187 | #define GT_ETH_IPG_INT_RX(value) \ | ||
188 | ((value & 0x3fff) << 8) | ||
189 | |||
190 | #define KATANA_ETH_PORT_SDMA_CONFIG_VALUE \ | ||
191 | ETH_RX_BURST_SIZE_4_64BIT | \ | ||
192 | GT_ETH_IPG_INT_RX(0) | \ | ||
193 | ETH_TX_BURST_SIZE_4_64BIT | ||
194 | |||
195 | #define KATANA_ETH_PORT_SERIAL_CONTROL_VALUE \ | ||
196 | ETH_FORCE_LINK_PASS | \ | ||
197 | ETH_ENABLE_AUTO_NEG_FOR_DUPLX | \ | ||
198 | ETH_DISABLE_AUTO_NEG_FOR_FLOW_CTRL | \ | ||
199 | ETH_ADV_SYMMETRIC_FLOW_CTRL | \ | ||
200 | ETH_FORCE_FC_MODE_NO_PAUSE_DIS_TX | \ | ||
201 | ETH_FORCE_BP_MODE_NO_JAM | \ | ||
202 | BIT9 | \ | ||
203 | ETH_DO_NOT_FORCE_LINK_FAIL | \ | ||
204 | ETH_RETRANSMIT_16_ATTEMPTS | \ | ||
205 | ETH_ENABLE_AUTO_NEG_SPEED_GMII | \ | ||
206 | ETH_DTE_ADV_0 | \ | ||
207 | ETH_DISABLE_AUTO_NEG_BYPASS | \ | ||
208 | ETH_AUTO_NEG_NO_CHANGE | \ | ||
209 | ETH_MAX_RX_PACKET_9700BYTE | \ | ||
210 | ETH_CLR_EXT_LOOPBACK | \ | ||
211 | ETH_SET_FULL_DUPLEX_MODE | \ | ||
212 | ETH_ENABLE_FLOW_CTRL_TX_RX_IN_FULL_DUPLEX | ||
213 | |||
214 | #ifndef __ASSEMBLY__ | ||
215 | |||
216 | typedef enum { | ||
217 | KATANA_ID_3750, | ||
218 | KATANA_ID_750I, | ||
219 | KATANA_ID_752I, | ||
220 | KATANA_ID_MAX | ||
221 | } katana_id_t; | ||
222 | |||
223 | #endif | ||
224 | |||
225 | static inline u32 | ||
226 | katana_bus_freq(void __iomem *cpld_base) | ||
227 | { | ||
228 | u8 bd_cfg_0; | ||
229 | |||
230 | bd_cfg_0 = in_8(cpld_base + KATANA_CPLD_BD_CFG_0); | ||
231 | |||
232 | switch (bd_cfg_0 & KATANA_CPLD_BD_CFG_0_SYSCLK_MASK) { | ||
233 | case KATANA_CPLD_BD_CFG_0_SYSCLK_200: | ||
234 | return 200000000; | ||
235 | break; | ||
236 | |||
237 | case KATANA_CPLD_BD_CFG_0_SYSCLK_166: | ||
238 | return 166666666; | ||
239 | break; | ||
240 | |||
241 | case KATANA_CPLD_BD_CFG_0_SYSCLK_133: | ||
242 | return 133333333; | ||
243 | break; | ||
244 | |||
245 | case KATANA_CPLD_BD_CFG_0_SYSCLK_100: | ||
246 | return 100000000; | ||
247 | break; | ||
248 | |||
249 | default: | ||
250 | return 133333333; | ||
251 | break; | ||
252 | } | ||
253 | } | ||
254 | |||
255 | #endif /* __PPC_PLATFORMS_KATANA_H */ | ||
diff --git a/arch/ppc/platforms/lantec.h b/arch/ppc/platforms/lantec.h new file mode 100644 index 000000000000..8c87642c510f --- /dev/null +++ b/arch/ppc/platforms/lantec.h | |||
@@ -0,0 +1,21 @@ | |||
1 | /* | ||
2 | * LANTEC board specific definitions | ||
3 | * | ||
4 | * Copyright (c) 2001 Wolfgang Denk (wd@denx.de) | ||
5 | */ | ||
6 | |||
7 | #ifndef __MACH_LANTEC_H | ||
8 | #define __MACH_LANTEC_H | ||
9 | |||
10 | #include <linux/config.h> | ||
11 | |||
12 | #include <asm/ppcboot.h> | ||
13 | |||
14 | #define IMAP_ADDR 0xFFF00000 /* physical base address of IMMR area */ | ||
15 | #define IMAP_SIZE (64 * 1024) /* mapped size of IMMR area */ | ||
16 | |||
17 | /* We don't use the 8259. | ||
18 | */ | ||
19 | #define NR_8259_INTS 0 | ||
20 | |||
21 | #endif /* __MACH_LANTEC_H */ | ||
diff --git a/arch/ppc/platforms/lite5200.c b/arch/ppc/platforms/lite5200.c new file mode 100644 index 000000000000..b604cf8b3cae --- /dev/null +++ b/arch/ppc/platforms/lite5200.c | |||
@@ -0,0 +1,236 @@ | |||
1 | /* | ||
2 | * arch/ppc/platforms/lite5200.c | ||
3 | * | ||
4 | * Platform support file for the Freescale LITE5200 based on MPC52xx. | ||
5 | * A maximum of this file should be moved to syslib/mpc52xx_????? | ||
6 | * so that new platform based on MPC52xx need a minimal platform file | ||
7 | * ( avoid code duplication ) | ||
8 | * | ||
9 | * | ||
10 | * Maintainer : Sylvain Munaut <tnt@246tNt.com> | ||
11 | * | ||
12 | * Based on the 2.4 code written by Kent Borg, | ||
13 | * Dale Farnsworth <dale.farnsworth@mvista.com> and | ||
14 | * Wolfgang Denk <wd@denx.de> | ||
15 | * | ||
16 | * Copyright 2004-2005 Sylvain Munaut <tnt@246tNt.com> | ||
17 | * Copyright 2003 Motorola Inc. | ||
18 | * Copyright 2003 MontaVista Software Inc. | ||
19 | * Copyright 2003 DENX Software Engineering (wd@denx.de) | ||
20 | * | ||
21 | * This file is licensed under the terms of the GNU General Public License | ||
22 | * version 2. This program is licensed "as is" without any warranty of any | ||
23 | * kind, whether express or implied. | ||
24 | */ | ||
25 | |||
26 | #include <linux/config.h> | ||
27 | #include <linux/initrd.h> | ||
28 | #include <linux/seq_file.h> | ||
29 | #include <linux/kdev_t.h> | ||
30 | #include <linux/root_dev.h> | ||
31 | #include <linux/console.h> | ||
32 | #include <linux/module.h> | ||
33 | |||
34 | #include <asm/bootinfo.h> | ||
35 | #include <asm/io.h> | ||
36 | #include <asm/mpc52xx.h> | ||
37 | #include <asm/ppc_sys.h> | ||
38 | |||
39 | #include <syslib/mpc52xx_pci.h> | ||
40 | |||
41 | |||
42 | extern int powersave_nap; | ||
43 | |||
44 | /* Board data given by U-Boot */ | ||
45 | bd_t __res; | ||
46 | EXPORT_SYMBOL(__res); /* For modules */ | ||
47 | |||
48 | |||
49 | /* ======================================================================== */ | ||
50 | /* Platform specific code */ | ||
51 | /* ======================================================================== */ | ||
52 | |||
53 | /* Supported PSC function in "preference" order */ | ||
54 | struct mpc52xx_psc_func mpc52xx_psc_functions[] = { | ||
55 | { .id = 0, | ||
56 | .func = "uart", | ||
57 | }, | ||
58 | { .id = -1, /* End entry */ | ||
59 | .func = NULL, | ||
60 | } | ||
61 | }; | ||
62 | |||
63 | |||
64 | static int | ||
65 | lite5200_show_cpuinfo(struct seq_file *m) | ||
66 | { | ||
67 | seq_printf(m, "machine\t\t: Freescale LITE5200\n"); | ||
68 | return 0; | ||
69 | } | ||
70 | |||
71 | #ifdef CONFIG_PCI | ||
72 | static int | ||
73 | lite5200_map_irq(struct pci_dev *dev, unsigned char idsel, unsigned char pin) | ||
74 | { | ||
75 | return (pin == 1) && (idsel==24) ? MPC52xx_IRQ0 : -1; | ||
76 | } | ||
77 | #endif | ||
78 | |||
79 | static void __init | ||
80 | lite5200_setup_cpu(void) | ||
81 | { | ||
82 | struct mpc52xx_cdm __iomem *cdm; | ||
83 | struct mpc52xx_gpio __iomem *gpio; | ||
84 | struct mpc52xx_intr __iomem *intr; | ||
85 | struct mpc52xx_xlb __iomem *xlb; | ||
86 | |||
87 | u32 port_config; | ||
88 | u32 intr_ctrl; | ||
89 | |||
90 | /* Map zones */ | ||
91 | cdm = ioremap(MPC52xx_PA(MPC52xx_CDM_OFFSET), MPC52xx_CDM_SIZE); | ||
92 | gpio = ioremap(MPC52xx_PA(MPC52xx_GPIO_OFFSET), MPC52xx_GPIO_SIZE); | ||
93 | xlb = ioremap(MPC52xx_PA(MPC52xx_XLB_OFFSET), MPC52xx_XLB_SIZE); | ||
94 | intr = ioremap(MPC52xx_PA(MPC52xx_INTR_OFFSET), MPC52xx_INTR_SIZE); | ||
95 | |||
96 | if (!cdm || !gpio || !xlb || !intr) { | ||
97 | printk("lite5200.c: Error while mapping CDM/GPIO/XLB/INTR during" | ||
98 | "lite5200_setup_cpu\n"); | ||
99 | goto unmap_regs; | ||
100 | } | ||
101 | |||
102 | /* Use internal 48 Mhz */ | ||
103 | out_8(&cdm->ext_48mhz_en, 0x00); | ||
104 | out_8(&cdm->fd_enable, 0x01); | ||
105 | if (in_be32(&cdm->rstcfg) & 0x40) /* Assumes 33Mhz clock */ | ||
106 | out_be16(&cdm->fd_counters, 0x0001); | ||
107 | else | ||
108 | out_be16(&cdm->fd_counters, 0x5555); | ||
109 | |||
110 | /* Get port mux config */ | ||
111 | port_config = in_be32(&gpio->port_config); | ||
112 | |||
113 | /* 48Mhz internal, pin is GPIO */ | ||
114 | port_config &= ~0x00800000; | ||
115 | |||
116 | /* USB port */ | ||
117 | port_config &= ~0x00007000; /* Differential mode - USB1 only */ | ||
118 | port_config |= 0x00001000; | ||
119 | |||
120 | /* Commit port config */ | ||
121 | out_be32(&gpio->port_config, port_config); | ||
122 | |||
123 | /* Configure the XLB Arbiter */ | ||
124 | out_be32(&xlb->master_pri_enable, 0xff); | ||
125 | out_be32(&xlb->master_priority, 0x11111111); | ||
126 | |||
127 | /* Enable ram snooping for 1GB window */ | ||
128 | out_be32(&xlb->config, in_be32(&xlb->config) | MPC52xx_XLB_CFG_SNOOP); | ||
129 | out_be32(&xlb->snoop_window, MPC52xx_PCI_TARGET_MEM | 0x1d); | ||
130 | |||
131 | /* IRQ[0-3] setup : IRQ0 - Level Active Low */ | ||
132 | /* IRQ[1-3] - Level Active High */ | ||
133 | intr_ctrl = in_be32(&intr->ctrl); | ||
134 | intr_ctrl &= ~0x00ff0000; | ||
135 | intr_ctrl |= 0x00c00000; | ||
136 | out_be32(&intr->ctrl, intr_ctrl); | ||
137 | |||
138 | /* Unmap reg zone */ | ||
139 | unmap_regs: | ||
140 | if (cdm) iounmap(cdm); | ||
141 | if (gpio) iounmap(gpio); | ||
142 | if (xlb) iounmap(xlb); | ||
143 | if (intr) iounmap(intr); | ||
144 | } | ||
145 | |||
146 | static void __init | ||
147 | lite5200_setup_arch(void) | ||
148 | { | ||
149 | /* CPU & Port mux setup */ | ||
150 | lite5200_setup_cpu(); | ||
151 | |||
152 | #ifdef CONFIG_PCI | ||
153 | /* PCI Bridge setup */ | ||
154 | mpc52xx_find_bridges(); | ||
155 | #endif | ||
156 | } | ||
157 | |||
158 | void __init | ||
159 | platform_init(unsigned long r3, unsigned long r4, unsigned long r5, | ||
160 | unsigned long r6, unsigned long r7) | ||
161 | { | ||
162 | /* Generic MPC52xx platform initialization */ | ||
163 | /* TODO Create one and move a max of stuff in it. | ||
164 | Put this init in the syslib */ | ||
165 | |||
166 | struct bi_record *bootinfo = find_bootinfo(); | ||
167 | |||
168 | if (bootinfo) | ||
169 | parse_bootinfo(bootinfo); | ||
170 | else { | ||
171 | /* Load the bd_t board info structure */ | ||
172 | if (r3) | ||
173 | memcpy((void*)&__res,(void*)(r3+KERNELBASE), | ||
174 | sizeof(bd_t)); | ||
175 | |||
176 | #ifdef CONFIG_BLK_DEV_INITRD | ||
177 | /* Load the initrd */ | ||
178 | if (r4) { | ||
179 | initrd_start = r4 + KERNELBASE; | ||
180 | initrd_end = r5 + KERNELBASE; | ||
181 | } | ||
182 | #endif | ||
183 | |||
184 | /* Load the command line */ | ||
185 | if (r6) { | ||
186 | *(char *)(r7+KERNELBASE) = 0; | ||
187 | strcpy(cmd_line, (char *)(r6+KERNELBASE)); | ||
188 | } | ||
189 | } | ||
190 | |||
191 | /* PPC Sys identification */ | ||
192 | identify_ppc_sys_by_id(mfspr(SPRN_SVR)); | ||
193 | |||
194 | /* BAT setup */ | ||
195 | mpc52xx_set_bat(); | ||
196 | |||
197 | /* No ISA bus by default */ | ||
198 | isa_io_base = 0; | ||
199 | isa_mem_base = 0; | ||
200 | |||
201 | /* Powersave */ | ||
202 | /* This is provided as an example on how to do it. But you | ||
203 | need to be aware that NAP disable bus snoop and that may | ||
204 | be required for some devices to work properly, like USB ... */ | ||
205 | /* powersave_nap = 1; */ | ||
206 | |||
207 | |||
208 | /* Setup the ppc_md struct */ | ||
209 | ppc_md.setup_arch = lite5200_setup_arch; | ||
210 | ppc_md.show_cpuinfo = lite5200_show_cpuinfo; | ||
211 | ppc_md.show_percpuinfo = NULL; | ||
212 | ppc_md.init_IRQ = mpc52xx_init_irq; | ||
213 | ppc_md.get_irq = mpc52xx_get_irq; | ||
214 | |||
215 | #ifdef CONFIG_PCI | ||
216 | ppc_md.pci_map_irq = lite5200_map_irq; | ||
217 | #endif | ||
218 | |||
219 | ppc_md.find_end_of_memory = mpc52xx_find_end_of_memory; | ||
220 | ppc_md.setup_io_mappings = mpc52xx_map_io; | ||
221 | |||
222 | ppc_md.restart = mpc52xx_restart; | ||
223 | ppc_md.power_off = mpc52xx_power_off; | ||
224 | ppc_md.halt = mpc52xx_halt; | ||
225 | |||
226 | /* No time keeper on the LITE5200 */ | ||
227 | ppc_md.time_init = NULL; | ||
228 | ppc_md.get_rtc_time = NULL; | ||
229 | ppc_md.set_rtc_time = NULL; | ||
230 | |||
231 | ppc_md.calibrate_decr = mpc52xx_calibrate_decr; | ||
232 | #ifdef CONFIG_SERIAL_TEXT_DEBUG | ||
233 | ppc_md.progress = mpc52xx_progress; | ||
234 | #endif | ||
235 | } | ||
236 | |||
diff --git a/arch/ppc/platforms/lite5200.h b/arch/ppc/platforms/lite5200.h new file mode 100644 index 000000000000..c1de2aa47175 --- /dev/null +++ b/arch/ppc/platforms/lite5200.h | |||
@@ -0,0 +1,23 @@ | |||
1 | /* | ||
2 | * arch/ppc/platforms/lite5200.h | ||
3 | * | ||
4 | * Definitions for Freescale LITE5200 : MPC52xx Standard Development | ||
5 | * Platform board support | ||
6 | * | ||
7 | * Maintainer : Sylvain Munaut <tnt@246tNt.com> | ||
8 | * | ||
9 | * Copyright (C) 2004 Sylvain Munaut <tnt@246tNt.com> | ||
10 | * | ||
11 | * This file is licensed under the terms of the GNU General Public License | ||
12 | * version 2. This program is licensed "as is" without any warranty of any | ||
13 | * kind, whether express or implied. | ||
14 | */ | ||
15 | |||
16 | #ifndef __PLATFORMS_LITE5200_H__ | ||
17 | #define __PLATFORMS_LITE5200_H__ | ||
18 | |||
19 | /* Serial port used for low-level debug */ | ||
20 | #define MPC52xx_PF_CONSOLE_PORT 1 /* PSC1 */ | ||
21 | |||
22 | |||
23 | #endif /* __PLATFORMS_LITE5200_H__ */ | ||
diff --git a/arch/ppc/platforms/lopec.c b/arch/ppc/platforms/lopec.c new file mode 100644 index 000000000000..a5569525e0af --- /dev/null +++ b/arch/ppc/platforms/lopec.c | |||
@@ -0,0 +1,411 @@ | |||
1 | /* | ||
2 | * arch/ppc/platforms/lopec.c | ||
3 | * | ||
4 | * Setup routines for the Motorola LoPEC. | ||
5 | * | ||
6 | * Author: Dan Cox | ||
7 | * Maintainer: Tom Rini <trini@kernel.crashing.org> | ||
8 | * | ||
9 | * 2001-2004 (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/config.h> | ||
16 | #include <linux/types.h> | ||
17 | #include <linux/delay.h> | ||
18 | #include <linux/pci_ids.h> | ||
19 | #include <linux/ioport.h> | ||
20 | #include <linux/init.h> | ||
21 | #include <linux/ide.h> | ||
22 | #include <linux/seq_file.h> | ||
23 | #include <linux/initrd.h> | ||
24 | #include <linux/console.h> | ||
25 | #include <linux/root_dev.h> | ||
26 | #include <linux/pci.h> | ||
27 | |||
28 | #include <asm/machdep.h> | ||
29 | #include <asm/pci-bridge.h> | ||
30 | #include <asm/io.h> | ||
31 | #include <asm/open_pic.h> | ||
32 | #include <asm/i8259.h> | ||
33 | #include <asm/todc.h> | ||
34 | #include <asm/bootinfo.h> | ||
35 | #include <asm/mpc10x.h> | ||
36 | #include <asm/hw_irq.h> | ||
37 | #include <asm/prep_nvram.h> | ||
38 | #include <asm/kgdb.h> | ||
39 | |||
40 | /* | ||
41 | * Define all of the IRQ senses and polarities. Taken from the | ||
42 | * LoPEC Programmer's Reference Guide. | ||
43 | */ | ||
44 | static u_char lopec_openpic_initsenses[16] __initdata = { | ||
45 | (IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE), /* IRQ 0 */ | ||
46 | (IRQ_SENSE_LEVEL | IRQ_POLARITY_NEGATIVE), /* IRQ 1 */ | ||
47 | (IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE), /* IRQ 2 */ | ||
48 | (IRQ_SENSE_LEVEL | IRQ_POLARITY_NEGATIVE), /* IRQ 3 */ | ||
49 | (IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE), /* IRQ 4 */ | ||
50 | (IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE), /* IRQ 5 */ | ||
51 | (IRQ_SENSE_LEVEL | IRQ_POLARITY_NEGATIVE), /* IRQ 6 */ | ||
52 | (IRQ_SENSE_LEVEL | IRQ_POLARITY_NEGATIVE), /* IRQ 7 */ | ||
53 | (IRQ_SENSE_LEVEL | IRQ_POLARITY_NEGATIVE), /* IRQ 8 */ | ||
54 | (IRQ_SENSE_LEVEL | IRQ_POLARITY_NEGATIVE), /* IRQ 9 */ | ||
55 | (IRQ_SENSE_LEVEL | IRQ_POLARITY_NEGATIVE), /* IRQ 10 */ | ||
56 | (IRQ_SENSE_LEVEL | IRQ_POLARITY_NEGATIVE), /* IRQ 11 */ | ||
57 | (IRQ_SENSE_LEVEL | IRQ_POLARITY_NEGATIVE), /* IRQ 12 */ | ||
58 | (IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE), /* IRQ 13 */ | ||
59 | (IRQ_SENSE_EDGE | IRQ_POLARITY_NEGATIVE), /* IRQ 14 */ | ||
60 | (IRQ_SENSE_LEVEL | IRQ_POLARITY_NEGATIVE) /* IRQ 15 */ | ||
61 | }; | ||
62 | |||
63 | static inline int __init | ||
64 | lopec_map_irq(struct pci_dev *dev, unsigned char idsel, unsigned char pin) | ||
65 | { | ||
66 | int irq; | ||
67 | static char pci_irq_table[][4] = { | ||
68 | {16, 0, 0, 0}, /* ID 11 - Winbond */ | ||
69 | {22, 0, 0, 0}, /* ID 12 - SCSI */ | ||
70 | {0, 0, 0, 0}, /* ID 13 - nothing */ | ||
71 | {17, 0, 0, 0}, /* ID 14 - 82559 Ethernet */ | ||
72 | {27, 0, 0, 0}, /* ID 15 - USB */ | ||
73 | {23, 0, 0, 0}, /* ID 16 - PMC slot 1 */ | ||
74 | {24, 0, 0, 0}, /* ID 17 - PMC slot 2 */ | ||
75 | {25, 0, 0, 0}, /* ID 18 - PCI slot */ | ||
76 | {0, 0, 0, 0}, /* ID 19 - nothing */ | ||
77 | {0, 0, 0, 0}, /* ID 20 - nothing */ | ||
78 | {0, 0, 0, 0}, /* ID 21 - nothing */ | ||
79 | {0, 0, 0, 0}, /* ID 22 - nothing */ | ||
80 | {0, 0, 0, 0}, /* ID 23 - nothing */ | ||
81 | {0, 0, 0, 0}, /* ID 24 - PMC slot 1b */ | ||
82 | {0, 0, 0, 0}, /* ID 25 - nothing */ | ||
83 | {0, 0, 0, 0} /* ID 26 - PMC Slot 2b */ | ||
84 | }; | ||
85 | const long min_idsel = 11, max_idsel = 26, irqs_per_slot = 4; | ||
86 | |||
87 | irq = PCI_IRQ_TABLE_LOOKUP; | ||
88 | if (!irq) | ||
89 | return 0; | ||
90 | |||
91 | return irq; | ||
92 | } | ||
93 | |||
94 | static void __init | ||
95 | lopec_setup_winbond_83553(struct pci_controller *hose) | ||
96 | { | ||
97 | int devfn; | ||
98 | |||
99 | devfn = PCI_DEVFN(11,0); | ||
100 | |||
101 | /* IDE interrupt routing (primary 14, secondary 15) */ | ||
102 | early_write_config_byte(hose, 0, devfn, 0x43, 0xef); | ||
103 | /* PCI interrupt routing */ | ||
104 | early_write_config_word(hose, 0, devfn, 0x44, 0x0000); | ||
105 | |||
106 | /* ISA-PCI address decoder */ | ||
107 | early_write_config_byte(hose, 0, devfn, 0x48, 0xf0); | ||
108 | |||
109 | /* RTC, kb, not used in PPC */ | ||
110 | early_write_config_byte(hose, 0, devfn, 0x4d, 0x00); | ||
111 | early_write_config_byte(hose, 0, devfn, 0x4e, 0x04); | ||
112 | devfn = PCI_DEVFN(11, 1); | ||
113 | early_write_config_byte(hose, 0, devfn, 0x09, 0x8f); | ||
114 | early_write_config_dword(hose, 0, devfn, 0x40, 0x00ff0011); | ||
115 | } | ||
116 | |||
117 | static void __init | ||
118 | lopec_find_bridges(void) | ||
119 | { | ||
120 | struct pci_controller *hose; | ||
121 | |||
122 | hose = pcibios_alloc_controller(); | ||
123 | if (!hose) | ||
124 | return; | ||
125 | |||
126 | hose->first_busno = 0; | ||
127 | hose->last_busno = 0xff; | ||
128 | |||
129 | if (mpc10x_bridge_init(hose, MPC10X_MEM_MAP_B, MPC10X_MEM_MAP_B, | ||
130 | MPC10X_MAPB_EUMB_BASE) == 0) { | ||
131 | |||
132 | hose->mem_resources[0].end = 0xffffffff; | ||
133 | lopec_setup_winbond_83553(hose); | ||
134 | hose->last_busno = pciauto_bus_scan(hose, hose->first_busno); | ||
135 | ppc_md.pci_swizzle = common_swizzle; | ||
136 | ppc_md.pci_map_irq = lopec_map_irq; | ||
137 | } | ||
138 | } | ||
139 | |||
140 | static int | ||
141 | lopec_show_cpuinfo(struct seq_file *m) | ||
142 | { | ||
143 | seq_printf(m, "machine\t\t: Motorola LoPEC\n"); | ||
144 | return 0; | ||
145 | } | ||
146 | |||
147 | static u32 | ||
148 | lopec_irq_canonicalize(u32 irq) | ||
149 | { | ||
150 | if (irq == 2) | ||
151 | return 9; | ||
152 | else | ||
153 | return irq; | ||
154 | } | ||
155 | |||
156 | static void | ||
157 | lopec_restart(char *cmd) | ||
158 | { | ||
159 | #define LOPEC_SYSSTAT1 0xffe00000 | ||
160 | /* force a hard reset, if possible */ | ||
161 | unsigned char reg = *((unsigned char *) LOPEC_SYSSTAT1); | ||
162 | reg |= 0x80; | ||
163 | *((unsigned char *) LOPEC_SYSSTAT1) = reg; | ||
164 | |||
165 | local_irq_disable(); | ||
166 | while(1); | ||
167 | #undef LOPEC_SYSSTAT1 | ||
168 | } | ||
169 | |||
170 | static void | ||
171 | lopec_halt(void) | ||
172 | { | ||
173 | local_irq_disable(); | ||
174 | while(1); | ||
175 | } | ||
176 | |||
177 | static void | ||
178 | lopec_power_off(void) | ||
179 | { | ||
180 | lopec_halt(); | ||
181 | } | ||
182 | |||
183 | #if defined(CONFIG_BLK_DEV_IDE) || defined(CONFIG_BLK_DEV_IDE_MODULE) | ||
184 | int lopec_ide_ports_known = 0; | ||
185 | static unsigned long lopec_ide_regbase[MAX_HWIFS]; | ||
186 | static unsigned long lopec_ide_ctl_regbase[MAX_HWIFS]; | ||
187 | static unsigned long lopec_idedma_regbase; | ||
188 | |||
189 | static void | ||
190 | lopec_ide_probe(void) | ||
191 | { | ||
192 | struct pci_dev *dev = pci_get_device(PCI_VENDOR_ID_WINBOND, | ||
193 | PCI_DEVICE_ID_WINBOND_82C105, | ||
194 | NULL); | ||
195 | lopec_ide_ports_known = 1; | ||
196 | |||
197 | if (dev) { | ||
198 | lopec_ide_regbase[0] = dev->resource[0].start; | ||
199 | lopec_ide_regbase[1] = dev->resource[2].start; | ||
200 | lopec_ide_ctl_regbase[0] = dev->resource[1].start; | ||
201 | lopec_ide_ctl_regbase[1] = dev->resource[3].start; | ||
202 | lopec_idedma_regbase = dev->resource[4].start; | ||
203 | pci_dev_put(dev); | ||
204 | } | ||
205 | } | ||
206 | |||
207 | static int | ||
208 | lopec_ide_default_irq(unsigned long base) | ||
209 | { | ||
210 | if (lopec_ide_ports_known == 0) | ||
211 | lopec_ide_probe(); | ||
212 | |||
213 | if (base == lopec_ide_regbase[0]) | ||
214 | return 14; | ||
215 | else if (base == lopec_ide_regbase[1]) | ||
216 | return 15; | ||
217 | else | ||
218 | return 0; | ||
219 | } | ||
220 | |||
221 | static unsigned long | ||
222 | lopec_ide_default_io_base(int index) | ||
223 | { | ||
224 | if (lopec_ide_ports_known == 0) | ||
225 | lopec_ide_probe(); | ||
226 | return lopec_ide_regbase[index]; | ||
227 | } | ||
228 | |||
229 | static void __init | ||
230 | lopec_ide_init_hwif_ports(hw_regs_t *hw, unsigned long data, | ||
231 | unsigned long ctl, int *irq) | ||
232 | { | ||
233 | unsigned long reg = data; | ||
234 | uint alt_status_base; | ||
235 | int i; | ||
236 | |||
237 | for (i = IDE_DATA_OFFSET; i <= IDE_STATUS_OFFSET; i++) | ||
238 | hw->io_ports[i] = reg++; | ||
239 | |||
240 | if (data == lopec_ide_regbase[0]) { | ||
241 | alt_status_base = lopec_ide_ctl_regbase[0] + 2; | ||
242 | hw->irq = 14; | ||
243 | } else if (data == lopec_ide_regbase[1]) { | ||
244 | alt_status_base = lopec_ide_ctl_regbase[1] + 2; | ||
245 | hw->irq = 15; | ||
246 | } else { | ||
247 | alt_status_base = 0; | ||
248 | hw->irq = 0; | ||
249 | } | ||
250 | |||
251 | if (ctl) | ||
252 | hw->io_ports[IDE_CONTROL_OFFSET] = ctl; | ||
253 | else | ||
254 | hw->io_ports[IDE_CONTROL_OFFSET] = alt_status_base; | ||
255 | |||
256 | if (irq != NULL) | ||
257 | *irq = hw->irq; | ||
258 | |||
259 | } | ||
260 | #endif /* BLK_DEV_IDE */ | ||
261 | |||
262 | static void __init | ||
263 | lopec_init_IRQ(void) | ||
264 | { | ||
265 | int i; | ||
266 | |||
267 | /* | ||
268 | * Provide the open_pic code with the correct table of interrupts. | ||
269 | */ | ||
270 | OpenPIC_InitSenses = lopec_openpic_initsenses; | ||
271 | OpenPIC_NumInitSenses = sizeof(lopec_openpic_initsenses); | ||
272 | |||
273 | mpc10x_set_openpic(); | ||
274 | |||
275 | /* We have a cascade on OpenPIC IRQ 0, Linux IRQ 16 */ | ||
276 | openpic_hookup_cascade(NUM_8259_INTERRUPTS, "82c59 cascade", | ||
277 | &i8259_irq); | ||
278 | |||
279 | /* Map i8259 interrupts */ | ||
280 | for(i = 0; i < NUM_8259_INTERRUPTS; i++) | ||
281 | irq_desc[i].handler = &i8259_pic; | ||
282 | |||
283 | /* | ||
284 | * The EPIC allows for a read in the range of 0xFEF00000 -> | ||
285 | * 0xFEFFFFFF to generate a PCI interrupt-acknowledge transaction. | ||
286 | */ | ||
287 | i8259_init(0xfef00000); | ||
288 | } | ||
289 | |||
290 | static int __init | ||
291 | lopec_request_io(void) | ||
292 | { | ||
293 | outb(0x00, 0x4d0); | ||
294 | outb(0xc0, 0x4d1); | ||
295 | |||
296 | request_region(0x00, 0x20, "dma1"); | ||
297 | request_region(0x20, 0x20, "pic1"); | ||
298 | request_region(0x40, 0x20, "timer"); | ||
299 | request_region(0x80, 0x10, "dma page reg"); | ||
300 | request_region(0xa0, 0x20, "pic2"); | ||
301 | request_region(0xc0, 0x20, "dma2"); | ||
302 | |||
303 | return 0; | ||
304 | } | ||
305 | |||
306 | device_initcall(lopec_request_io); | ||
307 | |||
308 | static void __init | ||
309 | lopec_map_io(void) | ||
310 | { | ||
311 | io_block_mapping(0xf0000000, 0xf0000000, 0x10000000, _PAGE_IO); | ||
312 | io_block_mapping(0xb0000000, 0xb0000000, 0x10000000, _PAGE_IO); | ||
313 | } | ||
314 | |||
315 | /* | ||
316 | * Set BAT 3 to map 0xf8000000 to end of physical memory space 1-to-1. | ||
317 | */ | ||
318 | static __inline__ void | ||
319 | lopec_set_bat(void) | ||
320 | { | ||
321 | mb(); | ||
322 | mtspr(SPRN_DBAT1U, 0xf8000ffe); | ||
323 | mtspr(SPRN_DBAT1L, 0xf800002a); | ||
324 | mb(); | ||
325 | } | ||
326 | |||
327 | TODC_ALLOC(); | ||
328 | |||
329 | static void __init | ||
330 | lopec_setup_arch(void) | ||
331 | { | ||
332 | |||
333 | TODC_INIT(TODC_TYPE_MK48T37, 0, 0, | ||
334 | ioremap(0xffe80000, 0x8000), 8); | ||
335 | |||
336 | loops_per_jiffy = 100000000/HZ; | ||
337 | |||
338 | lopec_find_bridges(); | ||
339 | |||
340 | #ifdef CONFIG_BLK_DEV_INITRD | ||
341 | if (initrd_start) | ||
342 | ROOT_DEV = Root_RAM0; | ||
343 | else | ||
344 | #elif defined(CONFIG_ROOT_NFS) | ||
345 | ROOT_DEV = Root_NFS; | ||
346 | #elif defined(CONFIG_BLK_DEV_IDEDISK) | ||
347 | ROOT_DEV = Root_HDA1; | ||
348 | #else | ||
349 | ROOT_DEV = Root_SDA1; | ||
350 | #endif | ||
351 | |||
352 | #ifdef CONFIG_PPCBUG_NVRAM | ||
353 | /* Read in NVRAM data */ | ||
354 | init_prep_nvram(); | ||
355 | |||
356 | /* if no bootargs, look in NVRAM */ | ||
357 | if ( cmd_line[0] == '\0' ) { | ||
358 | char *bootargs; | ||
359 | bootargs = prep_nvram_get_var("bootargs"); | ||
360 | if (bootargs != NULL) { | ||
361 | strcpy(cmd_line, bootargs); | ||
362 | /* again.. */ | ||
363 | strcpy(saved_command_line, cmd_line); | ||
364 | } | ||
365 | } | ||
366 | #endif | ||
367 | } | ||
368 | |||
369 | void __init | ||
370 | platform_init(unsigned long r3, unsigned long r4, unsigned long r5, | ||
371 | unsigned long r6, unsigned long r7) | ||
372 | { | ||
373 | parse_bootinfo(find_bootinfo()); | ||
374 | lopec_set_bat(); | ||
375 | |||
376 | isa_io_base = MPC10X_MAPB_ISA_IO_BASE; | ||
377 | isa_mem_base = MPC10X_MAPB_ISA_MEM_BASE; | ||
378 | pci_dram_offset = MPC10X_MAPB_DRAM_OFFSET; | ||
379 | ISA_DMA_THRESHOLD = 0x00ffffff; | ||
380 | DMA_MODE_READ = 0x44; | ||
381 | DMA_MODE_WRITE = 0x48; | ||
382 | |||
383 | ppc_md.setup_arch = lopec_setup_arch; | ||
384 | ppc_md.show_cpuinfo = lopec_show_cpuinfo; | ||
385 | ppc_md.irq_canonicalize = lopec_irq_canonicalize; | ||
386 | ppc_md.init_IRQ = lopec_init_IRQ; | ||
387 | ppc_md.get_irq = openpic_get_irq; | ||
388 | |||
389 | ppc_md.restart = lopec_restart; | ||
390 | ppc_md.power_off = lopec_power_off; | ||
391 | ppc_md.halt = lopec_halt; | ||
392 | |||
393 | ppc_md.setup_io_mappings = lopec_map_io; | ||
394 | |||
395 | ppc_md.time_init = todc_time_init; | ||
396 | ppc_md.set_rtc_time = todc_set_rtc_time; | ||
397 | ppc_md.get_rtc_time = todc_get_rtc_time; | ||
398 | ppc_md.calibrate_decr = todc_calibrate_decr; | ||
399 | |||
400 | ppc_md.nvram_read_val = todc_direct_read_val; | ||
401 | ppc_md.nvram_write_val = todc_direct_write_val; | ||
402 | |||
403 | #if defined(CONFIG_BLK_DEV_IDE) || defined(CONFIG_BLK_DEV_IDE_MODULE) | ||
404 | ppc_ide_md.default_irq = lopec_ide_default_irq; | ||
405 | ppc_ide_md.default_io_base = lopec_ide_default_io_base; | ||
406 | ppc_ide_md.ide_init_hwif = lopec_ide_init_hwif_ports; | ||
407 | #endif | ||
408 | #ifdef CONFIG_SERIAL_TEXT_DEBUG | ||
409 | ppc_md.progress = gen550_progress; | ||
410 | #endif | ||
411 | } | ||
diff --git a/arch/ppc/platforms/lopec.h b/arch/ppc/platforms/lopec.h new file mode 100644 index 000000000000..5490edb2d263 --- /dev/null +++ b/arch/ppc/platforms/lopec.h | |||
@@ -0,0 +1,39 @@ | |||
1 | /* | ||
2 | * include/asm-ppc/lopec_serial.h | ||
3 | * | ||
4 | * Definitions for Motorola LoPEC board. | ||
5 | * | ||
6 | * Author: Dan Cox | ||
7 | * danc@mvista.com (or, alternately, source@mvista.com) | ||
8 | * | ||
9 | * 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 | #ifndef __H_LOPEC_SERIAL | ||
16 | #define __H_LOPEC_SERIAL | ||
17 | |||
18 | #define RS_TABLE_SIZE 3 | ||
19 | |||
20 | #define BASE_BAUD (1843200 / 16) | ||
21 | |||
22 | #ifdef CONFIG_SERIAL_DETECT_IRQ | ||
23 | #define STD_COM_FLAGS (ASYNC_BOOT_AUTOCONF|ASYNC_SKIP_TEST|ASYNC_AUTO_IRQ) | ||
24 | #else | ||
25 | #define STD_COM_FLAGS (ASYNC_BOOT_AUTOCONF|ASYNC_SKIP_TEST) | ||
26 | #endif | ||
27 | |||
28 | #define SERIAL_PORT_DFNS \ | ||
29 | { 0, BASE_BAUD, 0xffe10000, 29, STD_COM_FLAGS, \ | ||
30 | iomem_base: (u8 *) 0xffe10000, \ | ||
31 | io_type: SERIAL_IO_MEM }, \ | ||
32 | { 0, BASE_BAUD, 0xffe11000, 20, STD_COM_FLAGS, \ | ||
33 | iomem_base: (u8 *) 0xffe11000, \ | ||
34 | io_type: SERIAL_IO_MEM }, \ | ||
35 | { 0, BASE_BAUD, 0xffe12000, 21, STD_COM_FLAGS, \ | ||
36 | iomem_base: (u8 *) 0xffe12000, \ | ||
37 | io_type: SERIAL_IO_MEM } | ||
38 | |||
39 | #endif | ||
diff --git a/arch/ppc/platforms/lwmon.h b/arch/ppc/platforms/lwmon.h new file mode 100644 index 000000000000..995bf5112df0 --- /dev/null +++ b/arch/ppc/platforms/lwmon.h | |||
@@ -0,0 +1,60 @@ | |||
1 | /* | ||
2 | * Liebherr LWMON board specific definitions | ||
3 | * | ||
4 | * Copyright (c) 2001 Wolfgang Denk (wd@denx.de) | ||
5 | */ | ||
6 | |||
7 | #ifndef __MACH_LWMON_H | ||
8 | #define __MACH_LWMON_H | ||
9 | |||
10 | #include <linux/config.h> | ||
11 | |||
12 | #include <asm/ppcboot.h> | ||
13 | |||
14 | #define IMAP_ADDR 0xFFF00000 /* physical base address of IMMR area */ | ||
15 | #define IMAP_SIZE (64 * 1024) /* mapped size of IMMR area */ | ||
16 | |||
17 | /*----------------------------------------------------------------------- | ||
18 | * PCMCIA stuff | ||
19 | *----------------------------------------------------------------------- | ||
20 | * | ||
21 | */ | ||
22 | #define PCMCIA_MEM_SIZE ( 64 << 20 ) | ||
23 | |||
24 | #define MAX_HWIFS 1 /* overwrite default in include/asm-ppc/ide.h */ | ||
25 | |||
26 | /* | ||
27 | * Definitions for IDE0 Interface | ||
28 | */ | ||
29 | #define IDE0_BASE_OFFSET 0 | ||
30 | #define IDE0_DATA_REG_OFFSET (PCMCIA_MEM_SIZE + 0x320) | ||
31 | #define IDE0_ERROR_REG_OFFSET (2 * PCMCIA_MEM_SIZE + 0x320 + 1) | ||
32 | #define IDE0_NSECTOR_REG_OFFSET (2 * PCMCIA_MEM_SIZE + 0x320 + 2) | ||
33 | #define IDE0_SECTOR_REG_OFFSET (2 * PCMCIA_MEM_SIZE + 0x320 + 3) | ||
34 | #define IDE0_LCYL_REG_OFFSET (2 * PCMCIA_MEM_SIZE + 0x320 + 4) | ||
35 | #define IDE0_HCYL_REG_OFFSET (2 * PCMCIA_MEM_SIZE + 0x320 + 5) | ||
36 | #define IDE0_SELECT_REG_OFFSET (2 * PCMCIA_MEM_SIZE + 0x320 + 6) | ||
37 | #define IDE0_STATUS_REG_OFFSET (2 * PCMCIA_MEM_SIZE + 0x320 + 7) | ||
38 | #define IDE0_CONTROL_REG_OFFSET 0x0106 | ||
39 | #define IDE0_IRQ_REG_OFFSET 0x000A /* not used */ | ||
40 | |||
41 | #define IDE0_INTERRUPT 13 | ||
42 | |||
43 | /* | ||
44 | * Definitions for I2C devices | ||
45 | */ | ||
46 | #define I2C_ADDR_AUDIO 0x28 /* Audio volume control */ | ||
47 | #define I2C_ADDR_SYSMON 0x2E /* LM87 System Monitor */ | ||
48 | #define I2C_ADDR_RTC 0x51 /* PCF8563 RTC */ | ||
49 | #define I2C_ADDR_POWER_A 0x52 /* PCMCIA/USB power switch, channel A */ | ||
50 | #define I2C_ADDR_POWER_B 0x53 /* PCMCIA/USB power switch, channel B */ | ||
51 | #define I2C_ADDR_KEYBD 0x56 /* PIC LWE keyboard */ | ||
52 | #define I2C_ADDR_PICIO 0x57 /* PIC IO Expander */ | ||
53 | #define I2C_ADDR_EEPROM 0x58 /* EEPROM AT24C164 */ | ||
54 | |||
55 | |||
56 | /* We don't use the 8259. | ||
57 | */ | ||
58 | #define NR_8259_INTS 0 | ||
59 | |||
60 | #endif /* __MACH_LWMON_H */ | ||
diff --git a/arch/ppc/platforms/mbx.h b/arch/ppc/platforms/mbx.h new file mode 100644 index 000000000000..fe81ca4ea0a2 --- /dev/null +++ b/arch/ppc/platforms/mbx.h | |||
@@ -0,0 +1,117 @@ | |||
1 | /* | ||
2 | * A collection of structures, addresses, and values associated with | ||
3 | * the Motorola MBX boards. This was originally created for the | ||
4 | * MBX860, and probably needs revisions for other boards (like the 821). | ||
5 | * When this file gets out of control, we can split it up into more | ||
6 | * meaningful pieces. | ||
7 | * | ||
8 | * Copyright (c) 1997 Dan Malek (dmalek@jlc.net) | ||
9 | */ | ||
10 | #ifdef __KERNEL__ | ||
11 | #ifndef __MACH_MBX_DEFS | ||
12 | #define __MACH_MBX_DEFS | ||
13 | |||
14 | #ifndef __ASSEMBLY__ | ||
15 | /* A Board Information structure that is given to a program when | ||
16 | * EPPC-Bug starts it up. | ||
17 | */ | ||
18 | typedef struct bd_info { | ||
19 | unsigned int bi_tag; /* Should be 0x42444944 "BDID" */ | ||
20 | unsigned int bi_size; /* Size of this structure */ | ||
21 | unsigned int bi_revision; /* revision of this structure */ | ||
22 | unsigned int bi_bdate; /* EPPCbug date, i.e. 0x11061997 */ | ||
23 | unsigned int bi_memstart; /* Memory start address */ | ||
24 | unsigned int bi_memsize; /* Memory (end) size in bytes */ | ||
25 | unsigned int bi_intfreq; /* Internal Freq, in Hz */ | ||
26 | unsigned int bi_busfreq; /* Bus Freq, in Hz */ | ||
27 | unsigned int bi_clun; /* Boot device controller */ | ||
28 | unsigned int bi_dlun; /* Boot device logical dev */ | ||
29 | |||
30 | /* These fields are not part of the board information structure | ||
31 | * provided by the boot rom. They are filled in by embed_config.c | ||
32 | * so we have the information consistent with other platforms. | ||
33 | */ | ||
34 | unsigned char bi_enetaddr[6]; | ||
35 | unsigned int bi_baudrate; | ||
36 | } bd_t; | ||
37 | |||
38 | /* Memory map for the MBX as configured by EPPC-Bug. We could reprogram | ||
39 | * The SIU and PCI bridge, and try to use larger MMU pages, but the | ||
40 | * performance gain is not measureable and it certainly complicates the | ||
41 | * generic MMU model. | ||
42 | * | ||
43 | * In a effort to minimize memory usage for embedded applications, any | ||
44 | * PCI driver or ISA driver must request or map the region required by | ||
45 | * the device. For convenience (and since we can map up to 4 Mbytes with | ||
46 | * a single page table page), the MMU initialization will map the | ||
47 | * NVRAM, Status/Control registers, CPM Dual Port RAM, and the PCI | ||
48 | * Bridge CSRs 1:1 into the kernel address space. | ||
49 | */ | ||
50 | #define PCI_ISA_IO_ADDR ((unsigned)0x80000000) | ||
51 | #define PCI_ISA_IO_SIZE ((uint)(512 * 1024 * 1024)) | ||
52 | #define PCI_IDE_ADDR ((unsigned)0x81000000) | ||
53 | #define PCI_ISA_MEM_ADDR ((unsigned)0xc0000000) | ||
54 | #define PCI_ISA_MEM_SIZE ((uint)(512 * 1024 * 1024)) | ||
55 | #define PCMCIA_MEM_ADDR ((uint)0xe0000000) | ||
56 | #define PCMCIA_MEM_SIZE ((uint)(64 * 1024 * 1024)) | ||
57 | #define PCMCIA_DMA_ADDR ((uint)0xe4000000) | ||
58 | #define PCMCIA_DMA_SIZE ((uint)(64 * 1024 * 1024)) | ||
59 | #define PCMCIA_ATTRB_ADDR ((uint)0xe8000000) | ||
60 | #define PCMCIA_ATTRB_SIZE ((uint)(64 * 1024 * 1024)) | ||
61 | #define PCMCIA_IO_ADDR ((uint)0xec000000) | ||
62 | #define PCMCIA_IO_SIZE ((uint)(64 * 1024 * 1024)) | ||
63 | #define NVRAM_ADDR ((uint)0xfa000000) | ||
64 | #define NVRAM_SIZE ((uint)(1 * 1024 * 1024)) | ||
65 | #define MBX_CSR_ADDR ((uint)0xfa100000) | ||
66 | #define MBX_CSR_SIZE ((uint)(1 * 1024 * 1024)) | ||
67 | #define IMAP_ADDR ((uint)0xfa200000) | ||
68 | #define IMAP_SIZE ((uint)(64 * 1024)) | ||
69 | #define PCI_CSR_ADDR ((uint)0xfa210000) | ||
70 | #define PCI_CSR_SIZE ((uint)(64 * 1024)) | ||
71 | |||
72 | /* Map additional physical space into well known virtual addresses. Due | ||
73 | * to virtual address mapping, these physical addresses are not accessible | ||
74 | * in a 1:1 virtual to physical mapping. | ||
75 | */ | ||
76 | #define ISA_IO_VIRT_ADDR ((uint)0xfa220000) | ||
77 | #define ISA_IO_VIRT_SIZE ((uint)64 * 1024) | ||
78 | |||
79 | /* Interrupt assignments. | ||
80 | * These are defined (and fixed) by the MBX hardware implementation. | ||
81 | */ | ||
82 | #define POWER_FAIL_INT SIU_IRQ0 /* Power fail */ | ||
83 | #define TEMP_HILO_INT SIU_IRQ1 /* Temperature sensor */ | ||
84 | #define QSPAN_INT SIU_IRQ2 /* PCI Bridge (DMA CTLR?) */ | ||
85 | #define ISA_BRIDGE_INT SIU_IRQ3 /* All those PC things */ | ||
86 | #define COMM_L_INT SIU_IRQ6 /* MBX Comm expansion connector pin */ | ||
87 | #define STOP_ABRT_INT SIU_IRQ7 /* Stop/Abort header pin */ | ||
88 | |||
89 | /* CPM Ethernet through SCCx. | ||
90 | * | ||
91 | * Bits in parallel I/O port registers that have to be set/cleared | ||
92 | * to configure the pins for SCC1 use. The TCLK and RCLK seem unique | ||
93 | * to the MBX860 board. Any two of the four available clocks could be | ||
94 | * used, and the MPC860 cookbook manual has an example using different | ||
95 | * clock pins. | ||
96 | */ | ||
97 | #define PA_ENET_RXD ((ushort)0x0001) | ||
98 | #define PA_ENET_TXD ((ushort)0x0002) | ||
99 | #define PA_ENET_TCLK ((ushort)0x0200) | ||
100 | #define PA_ENET_RCLK ((ushort)0x0800) | ||
101 | #define PC_ENET_TENA ((ushort)0x0001) | ||
102 | #define PC_ENET_CLSN ((ushort)0x0010) | ||
103 | #define PC_ENET_RENA ((ushort)0x0020) | ||
104 | |||
105 | /* Control bits in the SICR to route TCLK (CLK2) and RCLK (CLK4) to | ||
106 | * SCC1. Also, make sure GR1 (bit 24) and SC1 (bit 25) are zero. | ||
107 | */ | ||
108 | #define SICR_ENET_MASK ((uint)0x000000ff) | ||
109 | #define SICR_ENET_CLKRT ((uint)0x0000003d) | ||
110 | |||
111 | /* The MBX uses the 8259. | ||
112 | */ | ||
113 | #define NR_8259_INTS 16 | ||
114 | |||
115 | #endif /* !__ASSEMBLY__ */ | ||
116 | #endif /* __MACH_MBX_DEFS */ | ||
117 | #endif /* __KERNEL__ */ | ||
diff --git a/arch/ppc/platforms/mcpn765.c b/arch/ppc/platforms/mcpn765.c new file mode 100644 index 000000000000..e88d294ea593 --- /dev/null +++ b/arch/ppc/platforms/mcpn765.c | |||
@@ -0,0 +1,527 @@ | |||
1 | /* | ||
2 | * arch/ppc/platforms/mcpn765.c | ||
3 | * | ||
4 | * Board setup routines for the Motorola MCG MCPN765 cPCI Board. | ||
5 | * | ||
6 | * Author: Mark A. Greer | ||
7 | * mgreer@mvista.com | ||
8 | * | ||
9 | * Modified by Randy Vinson (rvinson@mvista.com) | ||
10 | * | ||
11 | * 2001-2002 (c) MontaVista, Software, Inc. This file is licensed under | ||
12 | * the terms of the GNU General Public License version 2. This program | ||
13 | * is licensed "as is" without any warranty of any kind, whether express | ||
14 | * or implied. | ||
15 | */ | ||
16 | |||
17 | /* | ||
18 | * This file adds support for the Motorola MCG MCPN765. | ||
19 | */ | ||
20 | #include <linux/config.h> | ||
21 | #include <linux/stddef.h> | ||
22 | #include <linux/kernel.h> | ||
23 | #include <linux/init.h> | ||
24 | #include <linux/errno.h> | ||
25 | #include <linux/reboot.h> | ||
26 | #include <linux/pci.h> | ||
27 | #include <linux/kdev_t.h> | ||
28 | #include <linux/major.h> | ||
29 | #include <linux/initrd.h> | ||
30 | #include <linux/console.h> | ||
31 | #include <linux/delay.h> | ||
32 | #include <linux/irq.h> | ||
33 | #include <linux/seq_file.h> | ||
34 | #include <linux/root_dev.h> | ||
35 | #include <linux/serial.h> | ||
36 | #include <linux/tty.h> /* for linux/serial_core.h */ | ||
37 | #include <linux/serial_core.h> | ||
38 | #include <linux/slab.h> | ||
39 | |||
40 | #include <asm/system.h> | ||
41 | #include <asm/pgtable.h> | ||
42 | #include <asm/page.h> | ||
43 | #include <asm/time.h> | ||
44 | #include <asm/dma.h> | ||
45 | #include <asm/byteorder.h> | ||
46 | #include <asm/io.h> | ||
47 | #include <asm/machdep.h> | ||
48 | #include <asm/prom.h> | ||
49 | #include <asm/smp.h> | ||
50 | #include <asm/open_pic.h> | ||
51 | #include <asm/i8259.h> | ||
52 | #include <asm/todc.h> | ||
53 | #include <asm/pci-bridge.h> | ||
54 | #include <asm/irq.h> | ||
55 | #include <asm/uaccess.h> | ||
56 | #include <asm/bootinfo.h> | ||
57 | #include <asm/hawk.h> | ||
58 | #include <asm/kgdb.h> | ||
59 | |||
60 | #include "mcpn765.h" | ||
61 | |||
62 | static u_char mcpn765_openpic_initsenses[] __initdata = { | ||
63 | (IRQ_SENSE_EDGE | IRQ_POLARITY_POSITIVE),/* 16: i8259 cascade */ | ||
64 | (IRQ_SENSE_LEVEL | IRQ_POLARITY_NEGATIVE),/* 17: COM1,2,3,4 */ | ||
65 | (IRQ_SENSE_LEVEL | IRQ_POLARITY_NEGATIVE),/* 18: Enet 1 (front) */ | ||
66 | (IRQ_SENSE_LEVEL | IRQ_POLARITY_NEGATIVE),/* 19: HAWK WDT XXXX */ | ||
67 | (IRQ_SENSE_LEVEL | IRQ_POLARITY_NEGATIVE),/* 20: 21554 bridge */ | ||
68 | (IRQ_SENSE_LEVEL | IRQ_POLARITY_NEGATIVE),/* 21: cPCI INTA# */ | ||
69 | (IRQ_SENSE_LEVEL | IRQ_POLARITY_NEGATIVE),/* 22: cPCI INTB# */ | ||
70 | (IRQ_SENSE_LEVEL | IRQ_POLARITY_NEGATIVE),/* 23: cPCI INTC# */ | ||
71 | (IRQ_SENSE_LEVEL | IRQ_POLARITY_NEGATIVE),/* 24: cPCI INTD# */ | ||
72 | (IRQ_SENSE_LEVEL | IRQ_POLARITY_NEGATIVE),/* 25: PMC1 INTA#,PMC2 INTB#*/ | ||
73 | (IRQ_SENSE_LEVEL | IRQ_POLARITY_NEGATIVE),/* 26: PMC1 INTB#,PMC2 INTC#*/ | ||
74 | (IRQ_SENSE_LEVEL | IRQ_POLARITY_NEGATIVE),/* 27: PMC1 INTC#,PMC2 INTD#*/ | ||
75 | (IRQ_SENSE_LEVEL | IRQ_POLARITY_NEGATIVE),/* 28: PMC1 INTD#,PMC2 INTA#*/ | ||
76 | (IRQ_SENSE_LEVEL | IRQ_POLARITY_NEGATIVE),/* 29: Enet 2 (J3) */ | ||
77 | (IRQ_SENSE_LEVEL | IRQ_POLARITY_NEGATIVE),/* 30: Abort Switch */ | ||
78 | (IRQ_SENSE_LEVEL | IRQ_POLARITY_NEGATIVE),/* 31: RTC Alarm */ | ||
79 | }; | ||
80 | |||
81 | extern void mcpn765_set_VIA_IDE_native(void); | ||
82 | |||
83 | extern u_int openpic_irq(void); | ||
84 | extern char cmd_line[]; | ||
85 | |||
86 | extern void gen550_progress(char *, unsigned short); | ||
87 | extern void gen550_init(int, struct uart_port *); | ||
88 | |||
89 | int use_of_interrupt_tree = 0; | ||
90 | |||
91 | static void mcpn765_halt(void); | ||
92 | |||
93 | TODC_ALLOC(); | ||
94 | |||
95 | /* | ||
96 | * Motorola MCG MCPN765 interrupt routing. | ||
97 | */ | ||
98 | static inline int | ||
99 | mcpn765_map_irq(struct pci_dev *dev, unsigned char idsel, unsigned char pin) | ||
100 | { | ||
101 | static char pci_irq_table[][4] = | ||
102 | /* | ||
103 | * PCI IDSEL/INTPIN->INTLINE | ||
104 | * A B C D | ||
105 | */ | ||
106 | { | ||
107 | { 14, 0, 0, 0 }, /* IDSEL 11 - have to manually set */ | ||
108 | { 0, 0, 0, 0 }, /* IDSEL 12 - unused */ | ||
109 | { 0, 0, 0, 0 }, /* IDSEL 13 - unused */ | ||
110 | { 18, 0, 0, 0 }, /* IDSEL 14 - Enet 0 */ | ||
111 | { 0, 0, 0, 0 }, /* IDSEL 15 - unused */ | ||
112 | { 25, 26, 27, 28 }, /* IDSEL 16 - PMC Slot 1 */ | ||
113 | { 28, 25, 26, 27 }, /* IDSEL 17 - PMC Slot 2 */ | ||
114 | { 0, 0, 0, 0 }, /* IDSEL 18 - PMC 2B Connector XXXX */ | ||
115 | { 29, 0, 0, 0 }, /* IDSEL 19 - Enet 1 */ | ||
116 | { 20, 0, 0, 0 }, /* IDSEL 20 - 21554 cPCI bridge */ | ||
117 | }; | ||
118 | |||
119 | const long min_idsel = 11, max_idsel = 20, irqs_per_slot = 4; | ||
120 | return PCI_IRQ_TABLE_LOOKUP; | ||
121 | } | ||
122 | |||
123 | void __init | ||
124 | mcpn765_set_VIA_IDE_legacy(void) | ||
125 | { | ||
126 | unsigned short vend, dev; | ||
127 | |||
128 | early_read_config_word(0, 0, PCI_DEVFN(0xb, 1), PCI_VENDOR_ID, &vend); | ||
129 | early_read_config_word(0, 0, PCI_DEVFN(0xb, 1), PCI_DEVICE_ID, &dev); | ||
130 | |||
131 | if ((vend == PCI_VENDOR_ID_VIA) && | ||
132 | (dev == PCI_DEVICE_ID_VIA_82C586_1)) { | ||
133 | |||
134 | unsigned char temp; | ||
135 | |||
136 | /* put back original "standard" port base addresses */ | ||
137 | early_write_config_dword(0, 0, PCI_DEVFN(0xb, 1), | ||
138 | PCI_BASE_ADDRESS_0, 0x1f1); | ||
139 | early_write_config_dword(0, 0, PCI_DEVFN(0xb, 1), | ||
140 | PCI_BASE_ADDRESS_1, 0x3f5); | ||
141 | early_write_config_dword(0, 0, PCI_DEVFN(0xb, 1), | ||
142 | PCI_BASE_ADDRESS_2, 0x171); | ||
143 | early_write_config_dword(0, 0, PCI_DEVFN(0xb, 1), | ||
144 | PCI_BASE_ADDRESS_3, 0x375); | ||
145 | early_write_config_dword(0, 0, PCI_DEVFN(0xb, 1), | ||
146 | PCI_BASE_ADDRESS_4, 0xcc01); | ||
147 | |||
148 | /* put into legacy mode */ | ||
149 | early_read_config_byte(0, 0, PCI_DEVFN(0xb, 1), PCI_CLASS_PROG, | ||
150 | &temp); | ||
151 | temp &= ~0x05; | ||
152 | early_write_config_byte(0, 0, PCI_DEVFN(0xb, 1), PCI_CLASS_PROG, | ||
153 | temp); | ||
154 | } | ||
155 | } | ||
156 | |||
157 | void | ||
158 | mcpn765_set_VIA_IDE_native(void) | ||
159 | { | ||
160 | unsigned short vend, dev; | ||
161 | |||
162 | early_read_config_word(0, 0, PCI_DEVFN(0xb, 1), PCI_VENDOR_ID, &vend); | ||
163 | early_read_config_word(0, 0, PCI_DEVFN(0xb, 1), PCI_DEVICE_ID, &dev); | ||
164 | |||
165 | if ((vend == PCI_VENDOR_ID_VIA) && | ||
166 | (dev == PCI_DEVICE_ID_VIA_82C586_1)) { | ||
167 | |||
168 | unsigned char temp; | ||
169 | |||
170 | /* put into native mode */ | ||
171 | early_read_config_byte(0, 0, PCI_DEVFN(0xb, 1), PCI_CLASS_PROG, | ||
172 | &temp); | ||
173 | temp |= 0x05; | ||
174 | early_write_config_byte(0, 0, PCI_DEVFN(0xb, 1), PCI_CLASS_PROG, | ||
175 | temp); | ||
176 | } | ||
177 | } | ||
178 | |||
179 | /* | ||
180 | * Initialize the VIA 82c586b. | ||
181 | */ | ||
182 | static void __init | ||
183 | mcpn765_setup_via_82c586b(void) | ||
184 | { | ||
185 | struct pci_dev *dev; | ||
186 | u_char c; | ||
187 | |||
188 | if ((dev = pci_get_device(PCI_VENDOR_ID_VIA, | ||
189 | PCI_DEVICE_ID_VIA_82C586_0, | ||
190 | NULL)) == NULL) { | ||
191 | printk("No VIA ISA bridge found\n"); | ||
192 | mcpn765_halt(); | ||
193 | /* NOTREACHED */ | ||
194 | } | ||
195 | |||
196 | /* | ||
197 | * If the firmware left the EISA 4d0/4d1 ports enabled, make sure | ||
198 | * IRQ 14 is set for edge. | ||
199 | */ | ||
200 | pci_read_config_byte(dev, 0x47, &c); | ||
201 | |||
202 | if (c & (1<<5)) { | ||
203 | c = inb(0x4d1); | ||
204 | c &= ~(1<<6); | ||
205 | outb(c, 0x4d1); | ||
206 | } | ||
207 | |||
208 | /* Disable PNP IRQ routing since we use the Hawk's MPIC */ | ||
209 | pci_write_config_dword(dev, 0x54, 0); | ||
210 | pci_write_config_byte(dev, 0x58, 0); | ||
211 | |||
212 | pci_dev_put(dev); | ||
213 | if ((dev = pci_get_device(PCI_VENDOR_ID_VIA, | ||
214 | PCI_DEVICE_ID_VIA_82C586_1, | ||
215 | NULL)) == NULL) { | ||
216 | printk("No VIA ISA bridge found\n"); | ||
217 | mcpn765_halt(); | ||
218 | /* NOTREACHED */ | ||
219 | } | ||
220 | |||
221 | /* | ||
222 | * PPCBug doesn't set the enable bits for the IDE device. | ||
223 | * Turn them on now. | ||
224 | */ | ||
225 | pci_read_config_byte(dev, 0x40, &c); | ||
226 | c |= 0x03; | ||
227 | pci_write_config_byte(dev, 0x40, c); | ||
228 | pci_dev_put(dev); | ||
229 | |||
230 | return; | ||
231 | } | ||
232 | |||
233 | void __init | ||
234 | mcpn765_pcibios_fixup(void) | ||
235 | { | ||
236 | /* Do MCPN765 board specific initialization. */ | ||
237 | mcpn765_setup_via_82c586b(); | ||
238 | } | ||
239 | |||
240 | void __init | ||
241 | mcpn765_find_bridges(void) | ||
242 | { | ||
243 | struct pci_controller *hose; | ||
244 | |||
245 | hose = pcibios_alloc_controller(); | ||
246 | |||
247 | if (!hose) | ||
248 | return; | ||
249 | |||
250 | hose->first_busno = 0; | ||
251 | hose->last_busno = 0xff; | ||
252 | hose->pci_mem_offset = MCPN765_PCI_PHY_MEM_OFFSET; | ||
253 | |||
254 | pci_init_resource(&hose->io_resource, | ||
255 | MCPN765_PCI_IO_START, | ||
256 | MCPN765_PCI_IO_END, | ||
257 | IORESOURCE_IO, | ||
258 | "PCI host bridge"); | ||
259 | |||
260 | pci_init_resource(&hose->mem_resources[0], | ||
261 | MCPN765_PCI_MEM_START, | ||
262 | MCPN765_PCI_MEM_END, | ||
263 | IORESOURCE_MEM, | ||
264 | "PCI host bridge"); | ||
265 | |||
266 | hose->io_space.start = MCPN765_PCI_IO_START; | ||
267 | hose->io_space.end = MCPN765_PCI_IO_END; | ||
268 | hose->mem_space.start = MCPN765_PCI_MEM_START; | ||
269 | hose->mem_space.end = MCPN765_PCI_MEM_END - HAWK_MPIC_SIZE; | ||
270 | |||
271 | if (hawk_init(hose, | ||
272 | MCPN765_HAWK_PPC_REG_BASE, | ||
273 | MCPN765_PROC_PCI_MEM_START, | ||
274 | MCPN765_PROC_PCI_MEM_END - HAWK_MPIC_SIZE, | ||
275 | MCPN765_PROC_PCI_IO_START, | ||
276 | MCPN765_PROC_PCI_IO_END, | ||
277 | MCPN765_PCI_MEM_END - HAWK_MPIC_SIZE + 1) != 0) { | ||
278 | printk("Could not initialize HAWK bridge\n"); | ||
279 | } | ||
280 | |||
281 | /* VIA IDE BAR decoders are only 16-bits wide. PCI Auto Config | ||
282 | * will reassign the bars outside of 16-bit I/O space, which will | ||
283 | * "break" things. To prevent this, we'll set the IDE chip into | ||
284 | * legacy mode and seed the bars with their legacy addresses (in 16-bit | ||
285 | * I/O space). The Auto Config code will skip the IDE contoller in | ||
286 | * legacy mode, so our bar values will stick. | ||
287 | */ | ||
288 | mcpn765_set_VIA_IDE_legacy(); | ||
289 | |||
290 | hose->last_busno = pciauto_bus_scan(hose, hose->first_busno); | ||
291 | |||
292 | /* Now that we've got 16-bit addresses in the bars, we can switch the | ||
293 | * IDE controller back into native mode so we can do "modern" resource | ||
294 | * and interrupt management. | ||
295 | */ | ||
296 | mcpn765_set_VIA_IDE_native(); | ||
297 | |||
298 | ppc_md.pcibios_fixup = mcpn765_pcibios_fixup; | ||
299 | ppc_md.pcibios_fixup_bus = NULL; | ||
300 | ppc_md.pci_swizzle = common_swizzle; | ||
301 | ppc_md.pci_map_irq = mcpn765_map_irq; | ||
302 | |||
303 | return; | ||
304 | } | ||
305 | static void __init | ||
306 | mcpn765_setup_arch(void) | ||
307 | { | ||
308 | struct pci_controller *hose; | ||
309 | |||
310 | if ( ppc_md.progress ) | ||
311 | ppc_md.progress("mcpn765_setup_arch: enter", 0); | ||
312 | |||
313 | loops_per_jiffy = 50000000 / HZ; | ||
314 | |||
315 | #ifdef CONFIG_BLK_DEV_INITRD | ||
316 | if (initrd_start) | ||
317 | ROOT_DEV = Root_RAM0; | ||
318 | else | ||
319 | #endif | ||
320 | #ifdef CONFIG_ROOT_NFS | ||
321 | ROOT_DEV = Root_NFS; | ||
322 | #else | ||
323 | ROOT_DEV = Root_SDA2; | ||
324 | #endif | ||
325 | |||
326 | if ( ppc_md.progress ) | ||
327 | ppc_md.progress("mcpn765_setup_arch: find_bridges", 0); | ||
328 | |||
329 | /* Lookup PCI host bridges */ | ||
330 | mcpn765_find_bridges(); | ||
331 | |||
332 | hose = pci_bus_to_hose(0); | ||
333 | isa_io_base = (ulong)hose->io_base_virt; | ||
334 | |||
335 | TODC_INIT(TODC_TYPE_MK48T37, | ||
336 | (MCPN765_PHYS_NVRAM_AS0 - isa_io_base), | ||
337 | (MCPN765_PHYS_NVRAM_AS1 - isa_io_base), | ||
338 | (MCPN765_PHYS_NVRAM_DATA - isa_io_base), | ||
339 | 8); | ||
340 | |||
341 | OpenPIC_InitSenses = mcpn765_openpic_initsenses; | ||
342 | OpenPIC_NumInitSenses = sizeof(mcpn765_openpic_initsenses); | ||
343 | |||
344 | printk("Motorola MCG MCPN765 cPCI Non-System Board\n"); | ||
345 | printk("MCPN765 port (MontaVista Software, Inc. (source@mvista.com))\n"); | ||
346 | |||
347 | if ( ppc_md.progress ) | ||
348 | ppc_md.progress("mcpn765_setup_arch: exit", 0); | ||
349 | |||
350 | return; | ||
351 | } | ||
352 | |||
353 | static void __init | ||
354 | mcpn765_init2(void) | ||
355 | { | ||
356 | |||
357 | request_region(0x00,0x20,"dma1"); | ||
358 | request_region(0x20,0x20,"pic1"); | ||
359 | request_region(0x40,0x20,"timer"); | ||
360 | request_region(0x80,0x10,"dma page reg"); | ||
361 | request_region(0xa0,0x20,"pic2"); | ||
362 | request_region(0xc0,0x20,"dma2"); | ||
363 | |||
364 | return; | ||
365 | } | ||
366 | |||
367 | /* | ||
368 | * Interrupt setup and service. | ||
369 | * Have MPIC on HAWK and cascaded 8259s on VIA 82586 cascaded to MPIC. | ||
370 | */ | ||
371 | static void __init | ||
372 | mcpn765_init_IRQ(void) | ||
373 | { | ||
374 | int i; | ||
375 | |||
376 | if ( ppc_md.progress ) | ||
377 | ppc_md.progress("init_irq: enter", 0); | ||
378 | |||
379 | openpic_init(NUM_8259_INTERRUPTS); | ||
380 | openpic_hookup_cascade(NUM_8259_INTERRUPTS, "82c59 cascade", | ||
381 | i8259_irq); | ||
382 | |||
383 | for(i=0; i < NUM_8259_INTERRUPTS; i++) | ||
384 | irq_desc[i].handler = &i8259_pic; | ||
385 | |||
386 | i8259_init(0); | ||
387 | |||
388 | if ( ppc_md.progress ) | ||
389 | ppc_md.progress("init_irq: exit", 0); | ||
390 | |||
391 | return; | ||
392 | } | ||
393 | |||
394 | static u32 | ||
395 | mcpn765_irq_canonicalize(u32 irq) | ||
396 | { | ||
397 | if (irq == 2) | ||
398 | return 9; | ||
399 | else | ||
400 | return irq; | ||
401 | } | ||
402 | |||
403 | static unsigned long __init | ||
404 | mcpn765_find_end_of_memory(void) | ||
405 | { | ||
406 | return hawk_get_mem_size(MCPN765_HAWK_SMC_BASE); | ||
407 | } | ||
408 | |||
409 | static void __init | ||
410 | mcpn765_map_io(void) | ||
411 | { | ||
412 | io_block_mapping(0xfe800000, 0xfe800000, 0x00800000, _PAGE_IO); | ||
413 | } | ||
414 | |||
415 | static void | ||
416 | mcpn765_reset_board(void) | ||
417 | { | ||
418 | local_irq_disable(); | ||
419 | |||
420 | /* set VIA IDE controller into native mode */ | ||
421 | mcpn765_set_VIA_IDE_native(); | ||
422 | |||
423 | /* Set exception prefix high - to the firmware */ | ||
424 | _nmask_and_or_msr(0, MSR_IP); | ||
425 | |||
426 | out_8((u_char *)MCPN765_BOARD_MODRST_REG, 0x01); | ||
427 | |||
428 | return; | ||
429 | } | ||
430 | |||
431 | static void | ||
432 | mcpn765_restart(char *cmd) | ||
433 | { | ||
434 | volatile ulong i = 10000000; | ||
435 | |||
436 | mcpn765_reset_board(); | ||
437 | |||
438 | while (i-- > 0); | ||
439 | panic("restart failed\n"); | ||
440 | } | ||
441 | |||
442 | static void | ||
443 | mcpn765_power_off(void) | ||
444 | { | ||
445 | mcpn765_halt(); | ||
446 | /* NOTREACHED */ | ||
447 | } | ||
448 | |||
449 | static void | ||
450 | mcpn765_halt(void) | ||
451 | { | ||
452 | local_irq_disable(); | ||
453 | while (1); | ||
454 | /* NOTREACHED */ | ||
455 | } | ||
456 | |||
457 | static int | ||
458 | mcpn765_show_cpuinfo(struct seq_file *m) | ||
459 | { | ||
460 | seq_printf(m, "vendor\t\t: Motorola MCG\n"); | ||
461 | seq_printf(m, "machine\t\t: MCPN765\n"); | ||
462 | |||
463 | return 0; | ||
464 | } | ||
465 | |||
466 | /* | ||
467 | * Set BAT 3 to map 0xf0000000 to end of physical memory space. | ||
468 | */ | ||
469 | static __inline__ void | ||
470 | mcpn765_set_bat(void) | ||
471 | { | ||
472 | mb(); | ||
473 | mtspr(SPRN_DBAT1U, 0xfe8000fe); | ||
474 | mtspr(SPRN_DBAT1L, 0xfe80002a); | ||
475 | mb(); | ||
476 | } | ||
477 | |||
478 | void __init | ||
479 | platform_init(unsigned long r3, unsigned long r4, unsigned long r5, | ||
480 | unsigned long r6, unsigned long r7) | ||
481 | { | ||
482 | parse_bootinfo(find_bootinfo()); | ||
483 | |||
484 | /* Map in board regs, etc. */ | ||
485 | mcpn765_set_bat(); | ||
486 | |||
487 | isa_mem_base = MCPN765_ISA_MEM_BASE; | ||
488 | pci_dram_offset = MCPN765_PCI_DRAM_OFFSET; | ||
489 | ISA_DMA_THRESHOLD = 0x00ffffff; | ||
490 | DMA_MODE_READ = 0x44; | ||
491 | DMA_MODE_WRITE = 0x48; | ||
492 | |||
493 | ppc_md.setup_arch = mcpn765_setup_arch; | ||
494 | ppc_md.show_cpuinfo = mcpn765_show_cpuinfo; | ||
495 | ppc_md.irq_canonicalize = mcpn765_irq_canonicalize; | ||
496 | ppc_md.init_IRQ = mcpn765_init_IRQ; | ||
497 | ppc_md.get_irq = openpic_get_irq; | ||
498 | ppc_md.init = mcpn765_init2; | ||
499 | |||
500 | ppc_md.restart = mcpn765_restart; | ||
501 | ppc_md.power_off = mcpn765_power_off; | ||
502 | ppc_md.halt = mcpn765_halt; | ||
503 | |||
504 | ppc_md.find_end_of_memory = mcpn765_find_end_of_memory; | ||
505 | ppc_md.setup_io_mappings = mcpn765_map_io; | ||
506 | |||
507 | ppc_md.time_init = todc_time_init; | ||
508 | ppc_md.set_rtc_time = todc_set_rtc_time; | ||
509 | ppc_md.get_rtc_time = todc_get_rtc_time; | ||
510 | ppc_md.calibrate_decr = todc_calibrate_decr; | ||
511 | |||
512 | ppc_md.nvram_read_val = todc_m48txx_read_val; | ||
513 | ppc_md.nvram_write_val = todc_m48txx_write_val; | ||
514 | |||
515 | ppc_md.heartbeat = NULL; | ||
516 | ppc_md.heartbeat_reset = 0; | ||
517 | ppc_md.heartbeat_count = 0; | ||
518 | |||
519 | #ifdef CONFIG_SERIAL_TEXT_DEBUG | ||
520 | ppc_md.progress = gen550_progress; | ||
521 | #endif | ||
522 | #ifdef CONFIG_KGDB | ||
523 | ppc_md.kgdb_map_scc = gen550_kgdb_map_scc; | ||
524 | #endif | ||
525 | |||
526 | return; | ||
527 | } | ||
diff --git a/arch/ppc/platforms/mcpn765.h b/arch/ppc/platforms/mcpn765.h new file mode 100644 index 000000000000..4d35ecad097b --- /dev/null +++ b/arch/ppc/platforms/mcpn765.h | |||
@@ -0,0 +1,122 @@ | |||
1 | /* | ||
2 | * arch/ppc/platforms/mcpn765.h | ||
3 | * | ||
4 | * Definitions for Motorola MCG MCPN765 cPCI Board. | ||
5 | * | ||
6 | * Author: Mark A. Greer | ||
7 | * mgreer@mvista.com | ||
8 | * | ||
9 | * 2001-2004 (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 | /* | ||
16 | * From Processor to PCI: | ||
17 | * PCI Mem Space: 0x80000000 - 0xc0000000 -> 0x80000000 - 0xc0000000 (1 GB) | ||
18 | * PCI I/O Space: 0xfd800000 - 0xfe000000 -> 0x00000000 - 0x00800000 (8 MB) | ||
19 | * Note: Must skip 0xfe000000-0xfe400000 for CONFIG_HIGHMEM/PKMAP area | ||
20 | * MPIC in PCI Mem Space: 0xfe800000 - 0xfe830000 (not all used by MPIC) | ||
21 | * | ||
22 | * From PCI to Processor: | ||
23 | * System Memory: 0x00000000 -> 0x00000000 | ||
24 | */ | ||
25 | |||
26 | #ifndef __PPC_PLATFORMS_MCPN765_H | ||
27 | #define __PPC_PLATFORMS_MCPN765_H | ||
28 | #include <linux/config.h> | ||
29 | |||
30 | /* PCI Memory space mapping info */ | ||
31 | #define MCPN765_PCI_MEM_SIZE 0x40000000U | ||
32 | #define MCPN765_PROC_PCI_MEM_START 0x80000000U | ||
33 | #define MCPN765_PROC_PCI_MEM_END (MCPN765_PROC_PCI_MEM_START + \ | ||
34 | MCPN765_PCI_MEM_SIZE - 1) | ||
35 | #define MCPN765_PCI_MEM_START 0x80000000U | ||
36 | #define MCPN765_PCI_MEM_END (MCPN765_PCI_MEM_START + \ | ||
37 | MCPN765_PCI_MEM_SIZE - 1) | ||
38 | |||
39 | /* PCI I/O space mapping info */ | ||
40 | #define MCPN765_PCI_IO_SIZE 0x00800000U | ||
41 | #define MCPN765_PROC_PCI_IO_START 0xfd800000U | ||
42 | #define MCPN765_PROC_PCI_IO_END (MCPN765_PROC_PCI_IO_START + \ | ||
43 | MCPN765_PCI_IO_SIZE - 1) | ||
44 | #define MCPN765_PCI_IO_START 0x00000000U | ||
45 | #define MCPN765_PCI_IO_END (MCPN765_PCI_IO_START + \ | ||
46 | MCPN765_PCI_IO_SIZE - 1) | ||
47 | |||
48 | /* System memory mapping info */ | ||
49 | #define MCPN765_PCI_DRAM_OFFSET 0x00000000U | ||
50 | #define MCPN765_PCI_PHY_MEM_OFFSET 0x00000000U | ||
51 | |||
52 | #define MCPN765_ISA_MEM_BASE 0x00000000U | ||
53 | #define MCPN765_ISA_IO_BASE MCPN765_PROC_PCI_IO_START | ||
54 | |||
55 | /* Define base addresses for important sets of registers */ | ||
56 | #define MCPN765_HAWK_MPIC_BASE 0xfe800000U | ||
57 | #define MCPN765_HAWK_SMC_BASE 0xfef80000U | ||
58 | #define MCPN765_HAWK_PPC_REG_BASE 0xfeff0000U | ||
59 | |||
60 | /* Define MCPN765 board register addresses. */ | ||
61 | #define MCPN765_BOARD_STATUS_REG 0xfef88080U | ||
62 | #define MCPN765_BOARD_MODFAIL_REG 0xfef88090U | ||
63 | #define MCPN765_BOARD_MODRST_REG 0xfef880a0U | ||
64 | #define MCPN765_BOARD_TBEN_REG 0xfef880c0U | ||
65 | #define MCPN765_BOARD_GEOGRAPHICAL_REG 0xfef880e8U | ||
66 | #define MCPN765_BOARD_EXT_FEATURE_REG 0xfef880f0U | ||
67 | #define MCPN765_BOARD_LAST_RESET_REG 0xfef880f8U | ||
68 | |||
69 | /* Defines for UART */ | ||
70 | |||
71 | /* Define the UART base addresses */ | ||
72 | #define MCPN765_SERIAL_1 0xfef88000 | ||
73 | #define MCPN765_SERIAL_2 0xfef88200 | ||
74 | #define MCPN765_SERIAL_3 0xfef88400 | ||
75 | #define MCPN765_SERIAL_4 0xfef88600 | ||
76 | |||
77 | #ifdef CONFIG_SERIAL_MANY_PORTS | ||
78 | #define RS_TABLE_SIZE 64 | ||
79 | #else | ||
80 | #define RS_TABLE_SIZE 4 | ||
81 | #endif | ||
82 | |||
83 | /* Rate for the 1.8432 Mhz clock for the onboard serial chip */ | ||
84 | #define BASE_BAUD ( 1843200 / 16 ) | ||
85 | #define UART_CLK 1843200 | ||
86 | |||
87 | #ifdef CONFIG_SERIAL_DETECT_IRQ | ||
88 | #define STD_COM_FLAGS (ASYNC_BOOT_AUTOCONF|ASYNC_SKIP_TEST|ASYNC_AUTO_IRQ) | ||
89 | #else | ||
90 | #define STD_COM_FLAGS (ASYNC_BOOT_AUTOCONF|ASYNC_SKIP_TEST) | ||
91 | #endif | ||
92 | |||
93 | /* All UART IRQ's are wire-OR'd to IRQ 17 */ | ||
94 | #define STD_SERIAL_PORT_DFNS \ | ||
95 | { 0, BASE_BAUD, MCPN765_SERIAL_1, 17, STD_COM_FLAGS, /* ttyS0 */\ | ||
96 | iomem_base: (u8 *)MCPN765_SERIAL_1, \ | ||
97 | iomem_reg_shift: 4, \ | ||
98 | io_type: SERIAL_IO_MEM }, \ | ||
99 | { 0, BASE_BAUD, MCPN765_SERIAL_2, 17, STD_COM_FLAGS, /* ttyS1 */\ | ||
100 | iomem_base: (u8 *)MCPN765_SERIAL_2, \ | ||
101 | iomem_reg_shift: 4, \ | ||
102 | io_type: SERIAL_IO_MEM }, \ | ||
103 | { 0, BASE_BAUD, MCPN765_SERIAL_3, 17, STD_COM_FLAGS, /* ttyS2 */\ | ||
104 | iomem_base: (u8 *)MCPN765_SERIAL_3, \ | ||
105 | iomem_reg_shift: 4, \ | ||
106 | io_type: SERIAL_IO_MEM }, \ | ||
107 | { 0, BASE_BAUD, MCPN765_SERIAL_4, 17, STD_COM_FLAGS, /* ttyS3 */\ | ||
108 | iomem_base: (u8 *)MCPN765_SERIAL_4, \ | ||
109 | iomem_reg_shift: 4, \ | ||
110 | io_type: SERIAL_IO_MEM }, | ||
111 | |||
112 | #define SERIAL_PORT_DFNS \ | ||
113 | STD_SERIAL_PORT_DFNS | ||
114 | |||
115 | /* Define the NVRAM/RTC address strobe & data registers */ | ||
116 | #define MCPN765_PHYS_NVRAM_AS0 0xfef880c8U | ||
117 | #define MCPN765_PHYS_NVRAM_AS1 0xfef880d0U | ||
118 | #define MCPN765_PHYS_NVRAM_DATA 0xfef880d8U | ||
119 | |||
120 | extern void mcpn765_find_bridges(void); | ||
121 | |||
122 | #endif /* __PPC_PLATFORMS_MCPN765_H */ | ||
diff --git a/arch/ppc/platforms/mpc5200.c b/arch/ppc/platforms/mpc5200.c new file mode 100644 index 000000000000..a58db438c162 --- /dev/null +++ b/arch/ppc/platforms/mpc5200.c | |||
@@ -0,0 +1,53 @@ | |||
1 | /* | ||
2 | * arch/ppc/platforms/mpc5200.c | ||
3 | * | ||
4 | * OCP Definitions for the boards based on MPC5200 processor. Contains | ||
5 | * definitions for every common peripherals. (Mostly all but PSCs) | ||
6 | * | ||
7 | * Maintainer : Sylvain Munaut <tnt@246tNt.com> | ||
8 | * | ||
9 | * Copyright 2004 Sylvain Munaut <tnt@246tNt.com> | ||
10 | * | ||
11 | * This file is licensed under the terms of the GNU General Public License | ||
12 | * version 2. This program is licensed "as is" without any warranty of any | ||
13 | * kind, whether express or implied. | ||
14 | */ | ||
15 | |||
16 | #include <asm/ocp.h> | ||
17 | #include <asm/mpc52xx.h> | ||
18 | |||
19 | |||
20 | static struct ocp_fs_i2c_data mpc5200_i2c_def = { | ||
21 | .flags = FS_I2C_CLOCK_5200, | ||
22 | }; | ||
23 | |||
24 | |||
25 | /* Here is the core_ocp struct. | ||
26 | * With all the devices common to all board. Even if port multiplexing is | ||
27 | * not setup for them (if the user don't want them, just don't select the | ||
28 | * config option). The potentially conflicting devices (like PSCs) goes in | ||
29 | * board specific file. | ||
30 | */ | ||
31 | struct ocp_def core_ocp[] = { | ||
32 | { | ||
33 | .vendor = OCP_VENDOR_FREESCALE, | ||
34 | .function = OCP_FUNC_IIC, | ||
35 | .index = 0, | ||
36 | .paddr = MPC52xx_I2C1, | ||
37 | .irq = OCP_IRQ_NA, /* MPC52xx_IRQ_I2C1 - Buggy */ | ||
38 | .pm = OCP_CPM_NA, | ||
39 | .additions = &mpc5200_i2c_def, | ||
40 | }, | ||
41 | { | ||
42 | .vendor = OCP_VENDOR_FREESCALE, | ||
43 | .function = OCP_FUNC_IIC, | ||
44 | .index = 1, | ||
45 | .paddr = MPC52xx_I2C2, | ||
46 | .irq = OCP_IRQ_NA, /* MPC52xx_IRQ_I2C2 - Buggy */ | ||
47 | .pm = OCP_CPM_NA, | ||
48 | .additions = &mpc5200_i2c_def, | ||
49 | }, | ||
50 | { /* Terminating entry */ | ||
51 | .vendor = OCP_VENDOR_INVALID | ||
52 | } | ||
53 | }; | ||
diff --git a/arch/ppc/platforms/mvme5100.c b/arch/ppc/platforms/mvme5100.c new file mode 100644 index 000000000000..b292b44b760c --- /dev/null +++ b/arch/ppc/platforms/mvme5100.c | |||
@@ -0,0 +1,349 @@ | |||
1 | /* | ||
2 | * arch/ppc/platforms/mvme5100.c | ||
3 | * | ||
4 | * Board setup routines for the Motorola MVME5100. | ||
5 | * | ||
6 | * Author: Matt Porter <mporter@mvista.com> | ||
7 | * | ||
8 | * 2001-2004 (c) MontaVista, Software, Inc. This file is licensed under | ||
9 | * the terms of the GNU General Public License version 2. This program | ||
10 | * is licensed "as is" without any warranty of any kind, whether express | ||
11 | * or implied. | ||
12 | */ | ||
13 | |||
14 | #include <linux/config.h> | ||
15 | #include <linux/stddef.h> | ||
16 | #include <linux/kernel.h> | ||
17 | #include <linux/init.h> | ||
18 | #include <linux/errno.h> | ||
19 | #include <linux/pci.h> | ||
20 | #include <linux/initrd.h> | ||
21 | #include <linux/console.h> | ||
22 | #include <linux/delay.h> | ||
23 | #include <linux/irq.h> | ||
24 | #include <linux/ide.h> | ||
25 | #include <linux/seq_file.h> | ||
26 | #include <linux/kdev_t.h> | ||
27 | #include <linux/root_dev.h> | ||
28 | |||
29 | #include <asm/system.h> | ||
30 | #include <asm/pgtable.h> | ||
31 | #include <asm/page.h> | ||
32 | #include <asm/dma.h> | ||
33 | #include <asm/io.h> | ||
34 | #include <asm/machdep.h> | ||
35 | #include <asm/open_pic.h> | ||
36 | #include <asm/i8259.h> | ||
37 | #include <asm/todc.h> | ||
38 | #include <asm/pci-bridge.h> | ||
39 | #include <asm/bootinfo.h> | ||
40 | #include <asm/hawk.h> | ||
41 | |||
42 | #include <platforms/pplus.h> | ||
43 | #include <platforms/mvme5100.h> | ||
44 | |||
45 | static u_char mvme5100_openpic_initsenses[16] __initdata = { | ||
46 | (IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE), /* i8259 cascade */ | ||
47 | (IRQ_SENSE_LEVEL | IRQ_POLARITY_NEGATIVE), /* TL16C550 UART 1,2 */ | ||
48 | (IRQ_SENSE_LEVEL | IRQ_POLARITY_NEGATIVE), /* Enet1 front panel or P2 */ | ||
49 | (IRQ_SENSE_LEVEL | IRQ_POLARITY_NEGATIVE), /* Hawk Watchdog 1,2 */ | ||
50 | (IRQ_SENSE_LEVEL | IRQ_POLARITY_NEGATIVE), /* DS1621 thermal alarm */ | ||
51 | (IRQ_SENSE_LEVEL | IRQ_POLARITY_NEGATIVE), /* Universe II LINT0# */ | ||
52 | (IRQ_SENSE_LEVEL | IRQ_POLARITY_NEGATIVE), /* Universe II LINT1# */ | ||
53 | (IRQ_SENSE_LEVEL | IRQ_POLARITY_NEGATIVE), /* Universe II LINT2# */ | ||
54 | (IRQ_SENSE_LEVEL | IRQ_POLARITY_NEGATIVE), /* Universe II LINT3# */ | ||
55 | (IRQ_SENSE_LEVEL | IRQ_POLARITY_NEGATIVE), /* PMC1 INTA#, PMC2 INTB# */ | ||
56 | (IRQ_SENSE_LEVEL | IRQ_POLARITY_NEGATIVE), /* PMC1 INTB#, PMC2 INTC# */ | ||
57 | (IRQ_SENSE_LEVEL | IRQ_POLARITY_NEGATIVE), /* PMC1 INTC#, PMC2 INTD# */ | ||
58 | (IRQ_SENSE_LEVEL | IRQ_POLARITY_NEGATIVE), /* PMC1 INTD#, PMC2 INTA# */ | ||
59 | (IRQ_SENSE_LEVEL | IRQ_POLARITY_NEGATIVE), /* Enet 2 (front panel) */ | ||
60 | (IRQ_SENSE_LEVEL | IRQ_POLARITY_NEGATIVE), /* Abort Switch */ | ||
61 | (IRQ_SENSE_LEVEL | IRQ_POLARITY_NEGATIVE), /* RTC Alarm */ | ||
62 | }; | ||
63 | |||
64 | static inline int | ||
65 | mvme5100_map_irq(struct pci_dev *dev, unsigned char idsel, unsigned char pin) | ||
66 | { | ||
67 | int irq; | ||
68 | |||
69 | static char pci_irq_table[][4] = | ||
70 | /* | ||
71 | * PCI IDSEL/INTPIN->INTLINE | ||
72 | * A B C D | ||
73 | */ | ||
74 | { | ||
75 | { 0, 0, 0, 0 }, /* IDSEL 11 - Winbond */ | ||
76 | { 0, 0, 0, 0 }, /* IDSEL 12 - unused */ | ||
77 | { 21, 22, 23, 24 }, /* IDSEL 13 - Universe II */ | ||
78 | { 18, 0, 0, 0 }, /* IDSEL 14 - Enet 1 */ | ||
79 | { 0, 0, 0, 0 }, /* IDSEL 15 - unused */ | ||
80 | { 25, 26, 27, 28 }, /* IDSEL 16 - PMC Slot 1 */ | ||
81 | { 28, 25, 26, 27 }, /* IDSEL 17 - PMC Slot 2 */ | ||
82 | { 0, 0, 0, 0 }, /* IDSEL 18 - unused */ | ||
83 | { 29, 0, 0, 0 }, /* IDSEL 19 - Enet 2 */ | ||
84 | { 0, 0, 0, 0 }, /* IDSEL 20 - PMCSPAN */ | ||
85 | }; | ||
86 | |||
87 | const long min_idsel = 11, max_idsel = 20, irqs_per_slot = 4; | ||
88 | irq = PCI_IRQ_TABLE_LOOKUP; | ||
89 | /* If lookup is zero, always return 0 */ | ||
90 | if (!irq) | ||
91 | return 0; | ||
92 | else | ||
93 | #ifdef CONFIG_MVME5100_IPMC761_PRESENT | ||
94 | /* If IPMC761 present, return table value */ | ||
95 | return irq; | ||
96 | #else | ||
97 | /* If IPMC761 not present, we don't have an i8259 so adjust */ | ||
98 | return (irq - NUM_8259_INTERRUPTS); | ||
99 | #endif | ||
100 | } | ||
101 | |||
102 | static void | ||
103 | mvme5100_pcibios_fixup_resources(struct pci_dev *dev) | ||
104 | { | ||
105 | int i; | ||
106 | |||
107 | if ((dev->vendor == PCI_VENDOR_ID_MOTOROLA) && | ||
108 | (dev->device == PCI_DEVICE_ID_MOTOROLA_HAWK)) | ||
109 | for (i=0; i<DEVICE_COUNT_RESOURCE; i++) | ||
110 | { | ||
111 | dev->resource[i].start = 0; | ||
112 | dev->resource[i].end = 0; | ||
113 | } | ||
114 | } | ||
115 | |||
116 | static void __init | ||
117 | mvme5100_setup_bridge(void) | ||
118 | { | ||
119 | struct pci_controller* hose; | ||
120 | |||
121 | hose = pcibios_alloc_controller(); | ||
122 | |||
123 | if (!hose) | ||
124 | return; | ||
125 | |||
126 | hose->first_busno = 0; | ||
127 | hose->last_busno = 0xff; | ||
128 | hose->pci_mem_offset = MVME5100_PCI_MEM_OFFSET; | ||
129 | |||
130 | pci_init_resource(&hose->io_resource, MVME5100_PCI_LOWER_IO, | ||
131 | MVME5100_PCI_UPPER_IO, IORESOURCE_IO, | ||
132 | "PCI host bridge"); | ||
133 | |||
134 | pci_init_resource(&hose->mem_resources[0], MVME5100_PCI_LOWER_MEM, | ||
135 | MVME5100_PCI_UPPER_MEM, IORESOURCE_MEM, | ||
136 | "PCI host bridge"); | ||
137 | |||
138 | hose->io_space.start = MVME5100_PCI_LOWER_IO; | ||
139 | hose->io_space.end = MVME5100_PCI_UPPER_IO; | ||
140 | hose->mem_space.start = MVME5100_PCI_LOWER_MEM; | ||
141 | hose->mem_space.end = MVME5100_PCI_UPPER_MEM; | ||
142 | hose->io_base_virt = (void *)MVME5100_ISA_IO_BASE; | ||
143 | |||
144 | /* Use indirect method of Hawk */ | ||
145 | setup_indirect_pci(hose, MVME5100_PCI_CONFIG_ADDR, | ||
146 | MVME5100_PCI_CONFIG_DATA); | ||
147 | |||
148 | hose->last_busno = pciauto_bus_scan(hose, hose->first_busno); | ||
149 | |||
150 | ppc_md.pcibios_fixup_resources = mvme5100_pcibios_fixup_resources; | ||
151 | ppc_md.pci_swizzle = common_swizzle; | ||
152 | ppc_md.pci_map_irq = mvme5100_map_irq; | ||
153 | } | ||
154 | |||
155 | static void __init | ||
156 | mvme5100_setup_arch(void) | ||
157 | { | ||
158 | if ( ppc_md.progress ) | ||
159 | ppc_md.progress("mvme5100_setup_arch: enter", 0); | ||
160 | |||
161 | loops_per_jiffy = 50000000 / HZ; | ||
162 | |||
163 | #ifdef CONFIG_BLK_DEV_INITRD | ||
164 | if (initrd_start) | ||
165 | ROOT_DEV = Root_RAM0; | ||
166 | else | ||
167 | #endif | ||
168 | #ifdef CONFIG_ROOT_NFS | ||
169 | ROOT_DEV = Root_NFS; | ||
170 | #else | ||
171 | ROOT_DEV = Root_SDA2; | ||
172 | #endif | ||
173 | |||
174 | if ( ppc_md.progress ) | ||
175 | ppc_md.progress("mvme5100_setup_arch: find_bridges", 0); | ||
176 | |||
177 | /* Setup PCI host bridge */ | ||
178 | mvme5100_setup_bridge(); | ||
179 | |||
180 | /* Find and map our OpenPIC */ | ||
181 | hawk_mpic_init(MVME5100_PCI_MEM_OFFSET); | ||
182 | OpenPIC_InitSenses = mvme5100_openpic_initsenses; | ||
183 | OpenPIC_NumInitSenses = sizeof(mvme5100_openpic_initsenses); | ||
184 | |||
185 | printk("MVME5100 port (C) 2001 MontaVista Software, Inc. (source@mvista.com)\n"); | ||
186 | |||
187 | if ( ppc_md.progress ) | ||
188 | ppc_md.progress("mvme5100_setup_arch: exit", 0); | ||
189 | |||
190 | return; | ||
191 | } | ||
192 | |||
193 | static void __init | ||
194 | mvme5100_init2(void) | ||
195 | { | ||
196 | #ifdef CONFIG_MVME5100_IPMC761_PRESENT | ||
197 | request_region(0x00,0x20,"dma1"); | ||
198 | request_region(0x20,0x20,"pic1"); | ||
199 | request_region(0x40,0x20,"timer"); | ||
200 | request_region(0x80,0x10,"dma page reg"); | ||
201 | request_region(0xa0,0x20,"pic2"); | ||
202 | request_region(0xc0,0x20,"dma2"); | ||
203 | #endif | ||
204 | return; | ||
205 | } | ||
206 | |||
207 | /* | ||
208 | * Interrupt setup and service. | ||
209 | * Have MPIC on HAWK and cascaded 8259s on Winbond cascaded to MPIC. | ||
210 | */ | ||
211 | static void __init | ||
212 | mvme5100_init_IRQ(void) | ||
213 | { | ||
214 | #ifdef CONFIG_MVME5100_IPMC761_PRESENT | ||
215 | int i; | ||
216 | #endif | ||
217 | |||
218 | if ( ppc_md.progress ) | ||
219 | ppc_md.progress("init_irq: enter", 0); | ||
220 | |||
221 | openpic_set_sources(0, 16, OpenPIC_Addr + 0x10000); | ||
222 | #ifdef CONFIG_MVME5100_IPMC761_PRESENT | ||
223 | openpic_init(NUM_8259_INTERRUPTS); | ||
224 | openpic_hookup_cascade(NUM_8259_INTERRUPTS, "82c59 cascade", | ||
225 | &i8259_irq); | ||
226 | |||
227 | /* Map i8259 interrupts. */ | ||
228 | for (i = 0; i < NUM_8259_INTERRUPTS; i++) | ||
229 | irq_desc[i].handler = &i8259_pic; | ||
230 | |||
231 | i8259_init(0); | ||
232 | #else | ||
233 | openpic_init(0); | ||
234 | #endif | ||
235 | |||
236 | if ( ppc_md.progress ) | ||
237 | ppc_md.progress("init_irq: exit", 0); | ||
238 | |||
239 | return; | ||
240 | } | ||
241 | |||
242 | /* | ||
243 | * Set BAT 3 to map 0xf0000000 to end of physical memory space. | ||
244 | */ | ||
245 | static __inline__ void | ||
246 | mvme5100_set_bat(void) | ||
247 | { | ||
248 | mb(); | ||
249 | mtspr(SPRN_DBAT1U, 0xf0001ffe); | ||
250 | mtspr(SPRN_DBAT1L, 0xf000002a); | ||
251 | mb(); | ||
252 | } | ||
253 | |||
254 | static unsigned long __init | ||
255 | mvme5100_find_end_of_memory(void) | ||
256 | { | ||
257 | return hawk_get_mem_size(MVME5100_HAWK_SMC_BASE); | ||
258 | } | ||
259 | |||
260 | static void __init | ||
261 | mvme5100_map_io(void) | ||
262 | { | ||
263 | io_block_mapping(0xfe000000, 0xfe000000, 0x02000000, _PAGE_IO); | ||
264 | ioremap_base = 0xfe000000; | ||
265 | } | ||
266 | |||
267 | static void | ||
268 | mvme5100_reset_board(void) | ||
269 | { | ||
270 | local_irq_disable(); | ||
271 | |||
272 | /* Set exception prefix high - to the firmware */ | ||
273 | _nmask_and_or_msr(0, MSR_IP); | ||
274 | |||
275 | out_8((u_char *)MVME5100_BOARD_MODRST_REG, 0x01); | ||
276 | |||
277 | return; | ||
278 | } | ||
279 | |||
280 | static void | ||
281 | mvme5100_restart(char *cmd) | ||
282 | { | ||
283 | volatile ulong i = 10000000; | ||
284 | |||
285 | mvme5100_reset_board(); | ||
286 | |||
287 | while (i-- > 0); | ||
288 | panic("restart failed\n"); | ||
289 | } | ||
290 | |||
291 | static void | ||
292 | mvme5100_halt(void) | ||
293 | { | ||
294 | local_irq_disable(); | ||
295 | while (1); | ||
296 | } | ||
297 | |||
298 | static void | ||
299 | mvme5100_power_off(void) | ||
300 | { | ||
301 | mvme5100_halt(); | ||
302 | } | ||
303 | |||
304 | static int | ||
305 | mvme5100_show_cpuinfo(struct seq_file *m) | ||
306 | { | ||
307 | seq_printf(m, "vendor\t\t: Motorola\n"); | ||
308 | seq_printf(m, "machine\t\t: MVME5100\n"); | ||
309 | |||
310 | return 0; | ||
311 | } | ||
312 | |||
313 | TODC_ALLOC(); | ||
314 | |||
315 | void __init | ||
316 | platform_init(unsigned long r3, unsigned long r4, unsigned long r5, | ||
317 | unsigned long r6, unsigned long r7) | ||
318 | { | ||
319 | parse_bootinfo(find_bootinfo()); | ||
320 | mvme5100_set_bat(); | ||
321 | |||
322 | isa_io_base = MVME5100_ISA_IO_BASE; | ||
323 | isa_mem_base = MVME5100_ISA_MEM_BASE; | ||
324 | pci_dram_offset = MVME5100_PCI_DRAM_OFFSET; | ||
325 | |||
326 | ppc_md.setup_arch = mvme5100_setup_arch; | ||
327 | ppc_md.show_cpuinfo = mvme5100_show_cpuinfo; | ||
328 | ppc_md.init_IRQ = mvme5100_init_IRQ; | ||
329 | ppc_md.get_irq = openpic_get_irq; | ||
330 | ppc_md.init = mvme5100_init2; | ||
331 | |||
332 | ppc_md.restart = mvme5100_restart; | ||
333 | ppc_md.power_off = mvme5100_power_off; | ||
334 | ppc_md.halt = mvme5100_halt; | ||
335 | |||
336 | ppc_md.find_end_of_memory = mvme5100_find_end_of_memory; | ||
337 | ppc_md.setup_io_mappings = mvme5100_map_io; | ||
338 | |||
339 | TODC_INIT(TODC_TYPE_MK48T37, MVME5100_NVRAM_AS0, MVME5100_NVRAM_AS1, | ||
340 | MVME5100_NVRAM_DATA, 8); | ||
341 | |||
342 | ppc_md.time_init = todc_time_init; | ||
343 | ppc_md.set_rtc_time = todc_set_rtc_time; | ||
344 | ppc_md.get_rtc_time = todc_get_rtc_time; | ||
345 | ppc_md.calibrate_decr = todc_calibrate_decr; | ||
346 | |||
347 | ppc_md.nvram_read_val = todc_m48txx_read_val; | ||
348 | ppc_md.nvram_write_val = todc_m48txx_write_val; | ||
349 | } | ||
diff --git a/arch/ppc/platforms/mvme5100.h b/arch/ppc/platforms/mvme5100.h new file mode 100644 index 000000000000..edd479439a4e --- /dev/null +++ b/arch/ppc/platforms/mvme5100.h | |||
@@ -0,0 +1,91 @@ | |||
1 | /* | ||
2 | * include/asm-ppc/platforms/mvme5100.h | ||
3 | * | ||
4 | * Definitions for Motorola MVME5100. | ||
5 | * | ||
6 | * Author: Matt Porter <mporter@mvista.com> | ||
7 | * | ||
8 | * 2001 (c) MontaVista, Software, Inc. This file is licensed under | ||
9 | * the terms of the GNU General Public License version 2. This program | ||
10 | * is licensed "as is" without any warranty of any kind, whether express | ||
11 | * or implied. | ||
12 | */ | ||
13 | |||
14 | #ifdef __KERNEL__ | ||
15 | #ifndef __ASM_MVME5100_H__ | ||
16 | #define __ASM_MVME5100_H__ | ||
17 | |||
18 | #define MVME5100_HAWK_SMC_BASE 0xfef80000 | ||
19 | |||
20 | #define MVME5100_PCI_CONFIG_ADDR 0xfe000cf8 | ||
21 | #define MVME5100_PCI_CONFIG_DATA 0xfe000cfc | ||
22 | |||
23 | #define MVME5100_PCI_IO_BASE 0xfe000000 | ||
24 | #define MVME5100_PCI_MEM_BASE 0x80000000 | ||
25 | |||
26 | #define MVME5100_PCI_MEM_OFFSET 0x00000000 | ||
27 | |||
28 | #define MVME5100_PCI_DRAM_OFFSET 0x00000000 | ||
29 | #define MVME5100_ISA_MEM_BASE 0x00000000 | ||
30 | #define MVME5100_ISA_IO_BASE MVME5100_PCI_IO_BASE | ||
31 | |||
32 | #define MVME5100_PCI_LOWER_MEM 0x80000000 | ||
33 | #define MVME5100_PCI_UPPER_MEM 0xf3f7ffff | ||
34 | #define MVME5100_PCI_LOWER_IO 0x00000000 | ||
35 | #define MVME5100_PCI_UPPER_IO 0x0077ffff | ||
36 | |||
37 | /* MVME5100 board register addresses. */ | ||
38 | #define MVME5100_BOARD_STATUS_REG 0xfef88080 | ||
39 | #define MVME5100_BOARD_MODFAIL_REG 0xfef88090 | ||
40 | #define MVME5100_BOARD_MODRST_REG 0xfef880a0 | ||
41 | #define MVME5100_BOARD_TBEN_REG 0xfef880c0 | ||
42 | #define MVME5100_BOARD_SW_READ_REG 0xfef880e0 | ||
43 | #define MVME5100_BOARD_GEO_ADDR_REG 0xfef880e8 | ||
44 | #define MVME5100_BOARD_EXT_FEATURE1_REG 0xfef880f0 | ||
45 | #define MVME5100_BOARD_EXT_FEATURE2_REG 0xfef88100 | ||
46 | |||
47 | /* Define the NVRAM/RTC address strobe & data registers */ | ||
48 | #define MVME5100_PHYS_NVRAM_AS0 0xfef880c8 | ||
49 | #define MVME5100_PHYS_NVRAM_AS1 0xfef880d0 | ||
50 | #define MVME5100_PHYS_NVRAM_DATA 0xfef880d8 | ||
51 | |||
52 | #define MVME5100_NVRAM_AS0 (MVME5100_PHYS_NVRAM_AS0 - MVME5100_ISA_IO_BASE) | ||
53 | #define MVME5100_NVRAM_AS1 (MVME5100_PHYS_NVRAM_AS1 - MVME5100_ISA_IO_BASE) | ||
54 | #define MVME5100_NVRAM_DATA (MVME5100_PHYS_NVRAM_DATA - MVME5100_ISA_IO_BASE) | ||
55 | |||
56 | /* UART clock, addresses, and irq */ | ||
57 | #define MVME5100_BASE_BAUD 1843200 | ||
58 | #define MVME5100_SERIAL_1 0xfef88000 | ||
59 | #define MVME5100_SERIAL_2 0xfef88200 | ||
60 | #ifdef CONFIG_MVME5100_IPMC761_PRESENT | ||
61 | #define MVME5100_SERIAL_IRQ 17 | ||
62 | #else | ||
63 | #define MVME5100_SERIAL_IRQ 1 | ||
64 | #endif | ||
65 | |||
66 | #define RS_TABLE_SIZE 4 | ||
67 | |||
68 | #define BASE_BAUD ( MVME5100_BASE_BAUD / 16 ) | ||
69 | |||
70 | #define STD_COM_FLAGS ASYNC_BOOT_AUTOCONF | ||
71 | |||
72 | /* All UART IRQ's are wire-OR'd to one MPIC IRQ */ | ||
73 | #define STD_SERIAL_PORT_DFNS \ | ||
74 | { 0, BASE_BAUD, MVME5100_SERIAL_1, \ | ||
75 | MVME5100_SERIAL_IRQ, \ | ||
76 | STD_COM_FLAGS, /* ttyS0 */ \ | ||
77 | iomem_base: (unsigned char *)MVME5100_SERIAL_1, \ | ||
78 | iomem_reg_shift: 4, \ | ||
79 | io_type: SERIAL_IO_MEM }, \ | ||
80 | { 0, BASE_BAUD, MVME5100_SERIAL_2, \ | ||
81 | MVME5100_SERIAL_IRQ, \ | ||
82 | STD_COM_FLAGS, /* ttyS1 */ \ | ||
83 | iomem_base: (unsigned char *)MVME5100_SERIAL_2, \ | ||
84 | iomem_reg_shift: 4, \ | ||
85 | io_type: SERIAL_IO_MEM }, | ||
86 | |||
87 | #define SERIAL_PORT_DFNS \ | ||
88 | STD_SERIAL_PORT_DFNS | ||
89 | |||
90 | #endif /* __ASM_MVME5100_H__ */ | ||
91 | #endif /* __KERNEL__ */ | ||
diff --git a/arch/ppc/platforms/pal4.h b/arch/ppc/platforms/pal4.h new file mode 100644 index 000000000000..641a11a31657 --- /dev/null +++ b/arch/ppc/platforms/pal4.h | |||
@@ -0,0 +1,42 @@ | |||
1 | /* | ||
2 | * arch/ppc/platforms/pal4.h | ||
3 | * | ||
4 | * Definitions for SBS Palomar IV board | ||
5 | * | ||
6 | * Author: Dan Cox | ||
7 | * | ||
8 | * 2002 (c) MontaVista, Software, Inc. This file is licensed under | ||
9 | * the terms of the GNU General Public License version 2. This program | ||
10 | * is licensed "as is" without any warranty of any kind, whether express | ||
11 | * or implied. | ||
12 | */ | ||
13 | |||
14 | #ifndef __PPC_PLATFORMS_PAL4_H | ||
15 | #define __PPC_PLATFORMS_PAL4_H | ||
16 | |||
17 | #define PAL4_NVRAM 0xfffc0000 | ||
18 | #define PAL4_NVRAM_SIZE 0x8000 | ||
19 | |||
20 | #define PAL4_DRAM 0xfff80000 | ||
21 | #define PAL4_DRAM_BR_MASK 0xc0 | ||
22 | #define PAL4_DRAM_BR_SHIFT 6 | ||
23 | #define PAL4_DRAM_RESET 0x10 | ||
24 | #define PAL4_DRAM_EREADY 0x40 | ||
25 | |||
26 | #define PAL4_MISC 0xfff80004 | ||
27 | #define PAL4_MISC_FB_MASK 0xc0 | ||
28 | #define PAL4_MISC_FLASH 0x20 /* StratFlash mapping: 1->0xff80, 0->0xfff0 */ | ||
29 | #define PAL4_MISC_MISC 0x08 | ||
30 | #define PAL4_MISC_BITF 0x02 | ||
31 | #define PAL4_MISC_NVKS 0x01 | ||
32 | |||
33 | #define PAL4_L2 0xfff80008 | ||
34 | #define PAL4_L2_MASK 0x07 | ||
35 | |||
36 | #define PAL4_PLDR 0xfff8000c | ||
37 | |||
38 | /* Only two Ethernet devices on the board... */ | ||
39 | #define PAL4_ETH 31 | ||
40 | #define PAL4_INTA 20 | ||
41 | |||
42 | #endif /* __PPC_PLATFORMS_PAL4_H */ | ||
diff --git a/arch/ppc/platforms/pal4_pci.c b/arch/ppc/platforms/pal4_pci.c new file mode 100644 index 000000000000..c3b1b757a48b --- /dev/null +++ b/arch/ppc/platforms/pal4_pci.c | |||
@@ -0,0 +1,77 @@ | |||
1 | /* | ||
2 | * arch/ppc/platforms/pal4_pci.c | ||
3 | * | ||
4 | * PCI support for SBS Palomar IV | ||
5 | * | ||
6 | * Author: Dan Cox | ||
7 | * | ||
8 | * 2002 (c) MontaVista, Software, Inc. This file is licensed under | ||
9 | * the terms of the GNU General Public License version 2. This program | ||
10 | * is licensed "as is" without any warranty of any kind, whether express | ||
11 | * or implied. | ||
12 | */ | ||
13 | |||
14 | #include <linux/kernel.h> | ||
15 | #include <linux/init.h> | ||
16 | #include <linux/pci.h> | ||
17 | |||
18 | #include <asm/byteorder.h> | ||
19 | #include <asm/machdep.h> | ||
20 | #include <asm/io.h> | ||
21 | #include <asm/pci-bridge.h> | ||
22 | #include <asm/uaccess.h> | ||
23 | |||
24 | #include <syslib/cpc700.h> | ||
25 | |||
26 | #include "pal4.h" | ||
27 | |||
28 | /* not much to this.... */ | ||
29 | static inline int __init | ||
30 | pal4_map_irq(struct pci_dev *dev, unsigned char idsel, unsigned char pin) | ||
31 | { | ||
32 | if (idsel == 9) | ||
33 | return PAL4_ETH; | ||
34 | else | ||
35 | return PAL4_INTA + (idsel - 3); | ||
36 | } | ||
37 | |||
38 | void __init | ||
39 | pal4_find_bridges(void) | ||
40 | { | ||
41 | struct pci_controller *hose; | ||
42 | |||
43 | hose = pcibios_alloc_controller(); | ||
44 | if (!hose) | ||
45 | return; | ||
46 | |||
47 | hose->first_busno = 0; | ||
48 | hose->last_busno = 0xff; | ||
49 | hose->pci_mem_offset = 0; | ||
50 | |||
51 | /* Could snatch these from the CPC700.... */ | ||
52 | pci_init_resource(&hose->io_resource, | ||
53 | 0x0, | ||
54 | 0x03ffffff, | ||
55 | IORESOURCE_IO, | ||
56 | "PCI host bridge"); | ||
57 | |||
58 | pci_init_resource(&hose->mem_resources[0], | ||
59 | 0x90000000, | ||
60 | 0x9fffffff, | ||
61 | IORESOURCE_MEM, | ||
62 | "PCI host bridge"); | ||
63 | |||
64 | hose->io_space.start = 0x00800000; | ||
65 | hose->io_space.end = 0x03ffffff; | ||
66 | hose->mem_space.start = 0x90000000; | ||
67 | hose->mem_space.end = 0x9fffffff; | ||
68 | hose->io_base_virt = (void *) 0xf8000000; | ||
69 | |||
70 | setup_indirect_pci(hose, CPC700_PCI_CONFIG_ADDR, | ||
71 | CPC700_PCI_CONFIG_DATA); | ||
72 | |||
73 | hose->last_busno = pciauto_bus_scan(hose, hose->first_busno); | ||
74 | |||
75 | ppc_md.pci_swizzle = common_swizzle; | ||
76 | ppc_md.pci_map_irq = pal4_map_irq; | ||
77 | } | ||
diff --git a/arch/ppc/platforms/pal4_serial.h b/arch/ppc/platforms/pal4_serial.h new file mode 100644 index 000000000000..a715c66e1adf --- /dev/null +++ b/arch/ppc/platforms/pal4_serial.h | |||
@@ -0,0 +1,39 @@ | |||
1 | /* | ||
2 | * arch/ppc/platforms/pal4_serial.h | ||
3 | * | ||
4 | * Definitions for SBS PalomarIV serial support | ||
5 | * | ||
6 | * Author: Dan Cox | ||
7 | * | ||
8 | * 2002 (c) MontaVista, Software, Inc. This file is licensed under | ||
9 | * the terms of the GNU General Public License version 2. This program | ||
10 | * is licensed "as is" without any warranty of any kind, whether express | ||
11 | * or implied. | ||
12 | */ | ||
13 | |||
14 | #ifndef __PPC_PAL4_SERIAL_H | ||
15 | #define __PPC_PAL4_SERIAL_H | ||
16 | |||
17 | #define CPC700_SERIAL_1 0xff600300 | ||
18 | #define CPC700_SERIAL_2 0xff600400 | ||
19 | |||
20 | #define RS_TABLE_SIZE 2 | ||
21 | #define BASE_BAUD (33333333 / 4 / 16) | ||
22 | |||
23 | #ifdef CONFIG_SERIAL_DETECT_IRQ | ||
24 | #define STD_COM_FLAGS (ASYNC_BOOT_AUTOCONF|ASYNC_SKIP_TEST|ASYNC_AUTO_IRQ) | ||
25 | #define STD_COM4_FLAGS (ASYNC_BOOT_AUTOCONF|ASYNC_AUTO_IRQ) | ||
26 | #else | ||
27 | #define STD_COM_FLAGS (ASYNC_BOOT_AUTOCONF|ASYNC_SKIP_TEST) | ||
28 | #define STD_COM4_FLAGS (ASYNC_BOOT_AUTOCONF) | ||
29 | #endif | ||
30 | |||
31 | #define SERIAL_PORT_DFNS \ | ||
32 | {0, BASE_BAUD, CPC700_SERIAL_1, 3, STD_COM_FLAGS, \ | ||
33 | iomem_base: (unsigned char *) CPC700_SERIAL_1, \ | ||
34 | io_type: SERIAL_IO_MEM}, /* ttyS0 */ \ | ||
35 | {0, BASE_BAUD, CPC700_SERIAL_2, 4, STD_COM_FLAGS, \ | ||
36 | iomem_base: (unsigned char *) CPC700_SERIAL_2, \ | ||
37 | io_type: SERIAL_IO_MEM} | ||
38 | |||
39 | #endif | ||
diff --git a/arch/ppc/platforms/pal4_setup.c b/arch/ppc/platforms/pal4_setup.c new file mode 100644 index 000000000000..12446b93e38c --- /dev/null +++ b/arch/ppc/platforms/pal4_setup.c | |||
@@ -0,0 +1,175 @@ | |||
1 | /* | ||
2 | * arch/ppc/platforms/pal4_setup.c | ||
3 | * | ||
4 | * Board setup routines for the SBS PalomarIV. | ||
5 | * | ||
6 | * Author: Dan Cox | ||
7 | * | ||
8 | * 2002 (c) MontaVista, Software, Inc. This file is licensed under | ||
9 | * the terms of the GNU General Public License version 2. This program | ||
10 | * is licensed "as is" without any warranty of any kind, whether express | ||
11 | * or implied. | ||
12 | */ | ||
13 | |||
14 | #include <linux/config.h> | ||
15 | #include <linux/kernel.h> | ||
16 | #include <linux/init.h> | ||
17 | #include <linux/types.h> | ||
18 | #include <linux/errno.h> | ||
19 | #include <linux/reboot.h> | ||
20 | #include <linux/time.h> | ||
21 | #include <linux/irq.h> | ||
22 | #include <linux/kdev_t.h> | ||
23 | #include <linux/initrd.h> | ||
24 | #include <linux/console.h> | ||
25 | #include <linux/seq_file.h> | ||
26 | #include <linux/root_dev.h> | ||
27 | |||
28 | #include <asm/io.h> | ||
29 | #include <asm/todc.h> | ||
30 | #include <asm/bootinfo.h> | ||
31 | |||
32 | #include <syslib/cpc700.h> | ||
33 | |||
34 | #include "pal4.h" | ||
35 | |||
36 | extern void pal4_find_bridges(void); | ||
37 | |||
38 | unsigned int cpc700_irq_assigns[][2] = { | ||
39 | {1, 1}, /* IRQ 0: ECC correctable error */ | ||
40 | {1, 1}, /* IRQ 1: PCI write to memory range */ | ||
41 | {0, 1}, /* IRQ 2: PCI write to command register */ | ||
42 | {0, 1}, /* IRQ 3: UART 0 */ | ||
43 | {0, 1}, /* IRQ 4: UART 1 */ | ||
44 | {0, 1}, /* IRQ 5: ICC 0 */ | ||
45 | {0, 1}, /* IRQ 6: ICC 1 */ | ||
46 | {0, 1}, /* IRQ 7: GPT compare 0 */ | ||
47 | {0, 1}, /* IRQ 8: GPT compare 1 */ | ||
48 | {0, 1}, /* IRQ 9: GPT compare 2 */ | ||
49 | {0, 1}, /* IRQ 10: GPT compare 3 */ | ||
50 | {0, 1}, /* IRQ 11: GPT compare 4 */ | ||
51 | {0, 1}, /* IRQ 12: GPT capture 0 */ | ||
52 | {0, 1}, /* IRQ 13: GPT capture 1 */ | ||
53 | {0, 1}, /* IRQ 14: GPT capture 2 */ | ||
54 | {0, 1}, /* IRQ 15: GPT capture 3 */ | ||
55 | {0, 1}, /* IRQ 16: GPT capture 4 */ | ||
56 | {0, 0}, /* IRQ 17: reserved */ | ||
57 | {0, 0}, /* IRQ 18: reserved */ | ||
58 | {0, 0}, /* IRQ 19: reserved */ | ||
59 | {0, 0}, /* IRQ 20: reserved */ | ||
60 | {0, 1}, /* IRQ 21: Ethernet */ | ||
61 | {0, 0}, /* IRQ 22: reserved */ | ||
62 | {0, 0}, /* IRQ 23: reserved */ | ||
63 | {0, 0}, /* IRQ 24: resreved */ | ||
64 | {0, 0}, /* IRQ 25: reserved */ | ||
65 | {0, 0}, /* IRQ 26: reserved */ | ||
66 | {0, 0}, /* IRQ 27: reserved */ | ||
67 | {0, 0}, /* IRQ 28: reserved */ | ||
68 | {0, 0}, /* IRQ 29: reserved */ | ||
69 | {0, 0}, /* IRQ 30: reserved */ | ||
70 | {0, 0}, /* IRQ 31: reserved */ | ||
71 | }; | ||
72 | |||
73 | static int | ||
74 | pal4_show_cpuinfo(struct seq_file *m) | ||
75 | { | ||
76 | seq_printf(m, "board\t\t: SBS Palomar IV\n"); | ||
77 | |||
78 | return 0; | ||
79 | } | ||
80 | |||
81 | static void | ||
82 | pal4_restart(char *cmd) | ||
83 | { | ||
84 | local_irq_disable(); | ||
85 | __asm__ __volatile__("lis 3,0xfff0\n \ | ||
86 | ori 3,3,0x100\n \ | ||
87 | mtspr 26,3\n \ | ||
88 | li 3,0\n \ | ||
89 | mtspr 27,3\n \ | ||
90 | rfi"); | ||
91 | |||
92 | for(;;); | ||
93 | } | ||
94 | |||
95 | static void | ||
96 | pal4_power_off(void) | ||
97 | { | ||
98 | local_irq_disable(); | ||
99 | for(;;); | ||
100 | } | ||
101 | |||
102 | static void | ||
103 | pal4_halt(void) | ||
104 | { | ||
105 | pal4_power_off(); | ||
106 | } | ||
107 | |||
108 | TODC_ALLOC(); | ||
109 | |||
110 | static void __init | ||
111 | pal4_setup_arch(void) | ||
112 | { | ||
113 | unsigned long l2; | ||
114 | |||
115 | TODC_INIT(TODC_TYPE_MK48T37, 0, 0, | ||
116 | ioremap(PAL4_NVRAM, PAL4_NVRAM_SIZE), 8); | ||
117 | |||
118 | pal4_find_bridges(); | ||
119 | |||
120 | #ifdef CONFIG_BLK_DEV_INITRD | ||
121 | if (initrd_start) | ||
122 | ROOT_DEV = Root_RAM0; | ||
123 | else | ||
124 | #endif | ||
125 | ROOT_DEV = Root_NFS; | ||
126 | |||
127 | /* The L2 gets disabled in the bootloader, but all the proper | ||
128 | bits should be present from the fw, so just re-enable it */ | ||
129 | l2 = _get_L2CR(); | ||
130 | if (!(l2 & L2CR_L2E)) { | ||
131 | /* presume that it was initially set if the size is | ||
132 | still present. */ | ||
133 | if (l2 ^ L2CR_L2SIZ_MASK) | ||
134 | _set_L2CR(l2 | L2CR_L2E); | ||
135 | else | ||
136 | printk("L2 not set by firmware; left disabled.\n"); | ||
137 | } | ||
138 | } | ||
139 | |||
140 | static void __init | ||
141 | pal4_map_io(void) | ||
142 | { | ||
143 | io_block_mapping(0xf0000000, 0xf0000000, 0x10000000, _PAGE_IO); | ||
144 | } | ||
145 | |||
146 | void __init | ||
147 | platform_init(unsigned long r3, unsigned long r4, unsigned long r5, | ||
148 | unsigned long r6, unsigned long r7) | ||
149 | { | ||
150 | parse_bootinfo(find_bootinfo()); | ||
151 | |||
152 | isa_io_base = 0 /*PAL4_ISA_IO_BASE*/; | ||
153 | pci_dram_offset = 0 /*PAL4_PCI_SYS_MEM_BASE*/; | ||
154 | |||
155 | ppc_md.setup_arch = pal4_setup_arch; | ||
156 | ppc_md.show_cpuinfo = pal4_show_cpuinfo; | ||
157 | |||
158 | ppc_md.setup_io_mappings = pal4_map_io; | ||
159 | |||
160 | ppc_md.init_IRQ = cpc700_init_IRQ; | ||
161 | ppc_md.get_irq = cpc700_get_irq; | ||
162 | |||
163 | ppc_md.restart = pal4_restart; | ||
164 | ppc_md.halt = pal4_halt; | ||
165 | ppc_md.power_off = pal4_power_off; | ||
166 | |||
167 | ppc_md.time_init = todc_time_init; | ||
168 | ppc_md.set_rtc_time = todc_set_rtc_time; | ||
169 | ppc_md.get_rtc_time = todc_get_rtc_time; | ||
170 | ppc_md.calibrate_decr = todc_calibrate_decr; | ||
171 | |||
172 | ppc_md.nvram_read_val = todc_direct_read_val; | ||
173 | ppc_md.nvram_write_val = todc_direct_write_val; | ||
174 | } | ||
175 | |||
diff --git a/arch/ppc/platforms/pcore.c b/arch/ppc/platforms/pcore.c new file mode 100644 index 000000000000..d7191630a650 --- /dev/null +++ b/arch/ppc/platforms/pcore.c | |||
@@ -0,0 +1,352 @@ | |||
1 | /* | ||
2 | * arch/ppc/platforms/pcore_setup.c | ||
3 | * | ||
4 | * Setup routines for Force PCORE boards | ||
5 | * | ||
6 | * Author: Matt Porter <mporter@mvista.com> | ||
7 | * | ||
8 | * 2001 (c) MontaVista, Software, Inc. This file is licensed under | ||
9 | * the terms of the GNU General Public License version 2. This program | ||
10 | * is licensed "as is" without any warranty of any kind, whether express | ||
11 | * or implied. | ||
12 | */ | ||
13 | |||
14 | #include <linux/config.h> | ||
15 | #include <linux/stddef.h> | ||
16 | #include <linux/kernel.h> | ||
17 | #include <linux/init.h> | ||
18 | #include <linux/errno.h> | ||
19 | #include <linux/reboot.h> | ||
20 | #include <linux/pci.h> | ||
21 | #include <linux/kdev_t.h> | ||
22 | #include <linux/types.h> | ||
23 | #include <linux/major.h> | ||
24 | #include <linux/initrd.h> | ||
25 | #include <linux/console.h> | ||
26 | #include <linux/irq.h> | ||
27 | #include <linux/seq_file.h> | ||
28 | #include <linux/root_dev.h> | ||
29 | |||
30 | #include <asm/io.h> | ||
31 | #include <asm/machdep.h> | ||
32 | #include <asm/time.h> | ||
33 | #include <asm/i8259.h> | ||
34 | #include <asm/mpc10x.h> | ||
35 | #include <asm/todc.h> | ||
36 | #include <asm/bootinfo.h> | ||
37 | #include <asm/kgdb.h> | ||
38 | |||
39 | #include "pcore.h" | ||
40 | |||
41 | extern unsigned long loops_per_jiffy; | ||
42 | |||
43 | static int board_type; | ||
44 | |||
45 | static inline int __init | ||
46 | pcore_6750_map_irq(struct pci_dev *dev, unsigned char idsel, unsigned char pin) | ||
47 | { | ||
48 | static char pci_irq_table[][4] = | ||
49 | /* | ||
50 | * PCI IDSEL/INTPIN->INTLINE | ||
51 | * A B C D | ||
52 | */ | ||
53 | { | ||
54 | {9, 10, 11, 12}, /* IDSEL 24 - DEC 21554 */ | ||
55 | {10, 0, 0, 0}, /* IDSEL 25 - DEC 21143 */ | ||
56 | {11, 12, 9, 10}, /* IDSEL 26 - PMC I */ | ||
57 | {12, 9, 10, 11}, /* IDSEL 27 - PMC II */ | ||
58 | {0, 0, 0, 0}, /* IDSEL 28 - unused */ | ||
59 | {0, 0, 9, 0}, /* IDSEL 29 - unused */ | ||
60 | {0, 0, 0, 0}, /* IDSEL 30 - Winbond */ | ||
61 | }; | ||
62 | const long min_idsel = 24, max_idsel = 30, irqs_per_slot = 4; | ||
63 | return PCI_IRQ_TABLE_LOOKUP; | ||
64 | }; | ||
65 | |||
66 | static inline int __init | ||
67 | pcore_680_map_irq(struct pci_dev *dev, unsigned char idsel, unsigned char pin) | ||
68 | { | ||
69 | static char pci_irq_table[][4] = | ||
70 | /* | ||
71 | * PCI IDSEL/INTPIN->INTLINE | ||
72 | * A B C D | ||
73 | */ | ||
74 | { | ||
75 | {9, 10, 11, 12}, /* IDSEL 24 - Sentinel */ | ||
76 | {10, 0, 0, 0}, /* IDSEL 25 - i82559 #1 */ | ||
77 | {11, 12, 9, 10}, /* IDSEL 26 - PMC I */ | ||
78 | {12, 9, 10, 11}, /* IDSEL 27 - PMC II */ | ||
79 | {9, 0, 0, 0}, /* IDSEL 28 - i82559 #2 */ | ||
80 | {0, 0, 0, 0}, /* IDSEL 29 - unused */ | ||
81 | {0, 0, 0, 0}, /* IDSEL 30 - Winbond */ | ||
82 | }; | ||
83 | const long min_idsel = 24, max_idsel = 30, irqs_per_slot = 4; | ||
84 | return PCI_IRQ_TABLE_LOOKUP; | ||
85 | }; | ||
86 | |||
87 | void __init | ||
88 | pcore_pcibios_fixup(void) | ||
89 | { | ||
90 | struct pci_dev *dev; | ||
91 | |||
92 | if ((dev = pci_get_device(PCI_VENDOR_ID_WINBOND, | ||
93 | PCI_DEVICE_ID_WINBOND_83C553, | ||
94 | 0))) | ||
95 | { | ||
96 | /* Reroute interrupts both IDE channels to 15 */ | ||
97 | pci_write_config_byte(dev, | ||
98 | PCORE_WINBOND_IDE_INT, | ||
99 | 0xff); | ||
100 | |||
101 | /* Route INTA-D to IRQ9-12, respectively */ | ||
102 | pci_write_config_word(dev, | ||
103 | PCORE_WINBOND_PCI_INT, | ||
104 | 0x9abc); | ||
105 | |||
106 | /* | ||
107 | * Set up 8259 edge/level triggering | ||
108 | */ | ||
109 | outb(0x00, PCORE_WINBOND_PRI_EDG_LVL); | ||
110 | outb(0x1e, PCORE_WINBOND_SEC_EDG_LVL); | ||
111 | pci_dev_put(dev); | ||
112 | } | ||
113 | } | ||
114 | |||
115 | int __init | ||
116 | pcore_find_bridges(void) | ||
117 | { | ||
118 | struct pci_controller* hose; | ||
119 | int host_bridge, board_type; | ||
120 | |||
121 | hose = pcibios_alloc_controller(); | ||
122 | if (!hose) | ||
123 | return 0; | ||
124 | |||
125 | mpc10x_bridge_init(hose, | ||
126 | MPC10X_MEM_MAP_B, | ||
127 | MPC10X_MEM_MAP_B, | ||
128 | MPC10X_MAPB_EUMB_BASE); | ||
129 | |||
130 | /* Determine board type */ | ||
131 | early_read_config_dword(hose, | ||
132 | 0, | ||
133 | PCI_DEVFN(0,0), | ||
134 | PCI_VENDOR_ID, | ||
135 | &host_bridge); | ||
136 | if (host_bridge == MPC10X_BRIDGE_106) | ||
137 | board_type = PCORE_TYPE_6750; | ||
138 | else /* MPC10X_BRIDGE_107 */ | ||
139 | board_type = PCORE_TYPE_680; | ||
140 | |||
141 | hose->last_busno = pciauto_bus_scan(hose, hose->first_busno); | ||
142 | |||
143 | ppc_md.pcibios_fixup = pcore_pcibios_fixup; | ||
144 | ppc_md.pci_swizzle = common_swizzle; | ||
145 | |||
146 | if (board_type == PCORE_TYPE_6750) | ||
147 | ppc_md.pci_map_irq = pcore_6750_map_irq; | ||
148 | else /* PCORE_TYPE_680 */ | ||
149 | ppc_md.pci_map_irq = pcore_680_map_irq; | ||
150 | |||
151 | return board_type; | ||
152 | } | ||
153 | |||
154 | /* Dummy variable to satisfy mpc10x_common.o */ | ||
155 | void *OpenPIC_Addr; | ||
156 | |||
157 | static int | ||
158 | pcore_show_cpuinfo(struct seq_file *m) | ||
159 | { | ||
160 | seq_printf(m, "vendor\t\t: Force Computers\n"); | ||
161 | |||
162 | if (board_type == PCORE_TYPE_6750) | ||
163 | seq_printf(m, "machine\t\t: PowerCore 6750\n"); | ||
164 | else /* PCORE_TYPE_680 */ | ||
165 | seq_printf(m, "machine\t\t: PowerCore 680\n"); | ||
166 | |||
167 | seq_printf(m, "L2\t\t: " ); | ||
168 | if (board_type == PCORE_TYPE_6750) | ||
169 | switch (readb(PCORE_DCCR_REG) & PCORE_DCCR_L2_MASK) | ||
170 | { | ||
171 | case PCORE_DCCR_L2_0KB: | ||
172 | seq_printf(m, "nocache"); | ||
173 | break; | ||
174 | case PCORE_DCCR_L2_256KB: | ||
175 | seq_printf(m, "256KB"); | ||
176 | break; | ||
177 | case PCORE_DCCR_L2_1MB: | ||
178 | seq_printf(m, "1MB"); | ||
179 | break; | ||
180 | case PCORE_DCCR_L2_512KB: | ||
181 | seq_printf(m, "512KB"); | ||
182 | break; | ||
183 | default: | ||
184 | seq_printf(m, "error"); | ||
185 | break; | ||
186 | } | ||
187 | else /* PCORE_TYPE_680 */ | ||
188 | switch (readb(PCORE_DCCR_REG) & PCORE_DCCR_L2_MASK) | ||
189 | { | ||
190 | case PCORE_DCCR_L2_2MB: | ||
191 | seq_printf(m, "2MB"); | ||
192 | break; | ||
193 | case PCORE_DCCR_L2_256KB: | ||
194 | seq_printf(m, "reserved"); | ||
195 | break; | ||
196 | case PCORE_DCCR_L2_1MB: | ||
197 | seq_printf(m, "1MB"); | ||
198 | break; | ||
199 | case PCORE_DCCR_L2_512KB: | ||
200 | seq_printf(m, "512KB"); | ||
201 | break; | ||
202 | default: | ||
203 | seq_printf(m, "error"); | ||
204 | break; | ||
205 | } | ||
206 | |||
207 | seq_printf(m, "\n"); | ||
208 | |||
209 | return 0; | ||
210 | } | ||
211 | |||
212 | static void __init | ||
213 | pcore_setup_arch(void) | ||
214 | { | ||
215 | /* init to some ~sane value until calibrate_delay() runs */ | ||
216 | loops_per_jiffy = 50000000/HZ; | ||
217 | |||
218 | /* Lookup PCI host bridges */ | ||
219 | board_type = pcore_find_bridges(); | ||
220 | |||
221 | #ifdef CONFIG_BLK_DEV_INITRD | ||
222 | if (initrd_start) | ||
223 | ROOT_DEV = Root_RAM0; | ||
224 | else | ||
225 | #endif | ||
226 | #ifdef CONFIG_ROOT_NFS | ||
227 | ROOT_DEV = Root_NFS; | ||
228 | #else | ||
229 | ROOT_DEV = Root_SDA2; | ||
230 | #endif | ||
231 | |||
232 | printk(KERN_INFO "Force PowerCore "); | ||
233 | if (board_type == PCORE_TYPE_6750) | ||
234 | printk("6750\n"); | ||
235 | else | ||
236 | printk("680\n"); | ||
237 | printk(KERN_INFO "Port by MontaVista Software, Inc. (source@mvista.com)\n"); | ||
238 | _set_L2CR(L2CR_L2E | _get_L2CR()); | ||
239 | |||
240 | } | ||
241 | |||
242 | static void | ||
243 | pcore_restart(char *cmd) | ||
244 | { | ||
245 | local_irq_disable(); | ||
246 | /* Hard reset */ | ||
247 | writeb(0x11, 0xfe000332); | ||
248 | while(1); | ||
249 | } | ||
250 | |||
251 | static void | ||
252 | pcore_halt(void) | ||
253 | { | ||
254 | local_irq_disable(); | ||
255 | /* Turn off user LEDs */ | ||
256 | writeb(0x00, 0xfe000300); | ||
257 | while (1); | ||
258 | } | ||
259 | |||
260 | static void | ||
261 | pcore_power_off(void) | ||
262 | { | ||
263 | pcore_halt(); | ||
264 | } | ||
265 | |||
266 | |||
267 | static void __init | ||
268 | pcore_init_IRQ(void) | ||
269 | { | ||
270 | int i; | ||
271 | |||
272 | for ( i = 0 ; i < 16 ; i++ ) | ||
273 | irq_desc[i].handler = &i8259_pic; | ||
274 | |||
275 | i8259_init(0); | ||
276 | } | ||
277 | |||
278 | /* | ||
279 | * Set BAT 3 to map 0xf0000000 to end of physical memory space. | ||
280 | */ | ||
281 | static __inline__ void | ||
282 | pcore_set_bat(void) | ||
283 | { | ||
284 | mb(); | ||
285 | mtspr(SPRN_DBAT3U, 0xf0001ffe); | ||
286 | mtspr(SPRN_DBAT3L, 0xfe80002a); | ||
287 | mb(); | ||
288 | |||
289 | } | ||
290 | |||
291 | static unsigned long __init | ||
292 | pcore_find_end_of_memory(void) | ||
293 | { | ||
294 | |||
295 | return mpc10x_get_mem_size(MPC10X_MEM_MAP_B); | ||
296 | } | ||
297 | |||
298 | static void __init | ||
299 | pcore_map_io(void) | ||
300 | { | ||
301 | io_block_mapping(0xfe000000, 0xfe000000, 0x02000000, _PAGE_IO); | ||
302 | } | ||
303 | |||
304 | TODC_ALLOC(); | ||
305 | |||
306 | void __init | ||
307 | platform_init(unsigned long r3, unsigned long r4, unsigned long r5, | ||
308 | unsigned long r6, unsigned long r7) | ||
309 | { | ||
310 | parse_bootinfo(find_bootinfo()); | ||
311 | |||
312 | /* Cover I/O space with a BAT */ | ||
313 | /* yuck, better hope your ram size is a power of 2 -- paulus */ | ||
314 | pcore_set_bat(); | ||
315 | |||
316 | isa_io_base = MPC10X_MAPB_ISA_IO_BASE; | ||
317 | isa_mem_base = MPC10X_MAPB_ISA_MEM_BASE; | ||
318 | pci_dram_offset = MPC10X_MAPB_DRAM_OFFSET; | ||
319 | |||
320 | ppc_md.setup_arch = pcore_setup_arch; | ||
321 | ppc_md.show_cpuinfo = pcore_show_cpuinfo; | ||
322 | ppc_md.init_IRQ = pcore_init_IRQ; | ||
323 | ppc_md.get_irq = i8259_irq; | ||
324 | |||
325 | ppc_md.find_end_of_memory = pcore_find_end_of_memory; | ||
326 | ppc_md.setup_io_mappings = pcore_map_io; | ||
327 | |||
328 | ppc_md.restart = pcore_restart; | ||
329 | ppc_md.power_off = pcore_power_off; | ||
330 | ppc_md.halt = pcore_halt; | ||
331 | |||
332 | TODC_INIT(TODC_TYPE_MK48T59, | ||
333 | PCORE_NVRAM_AS0, | ||
334 | PCORE_NVRAM_AS1, | ||
335 | PCORE_NVRAM_DATA, | ||
336 | 8); | ||
337 | |||
338 | ppc_md.time_init = todc_time_init; | ||
339 | ppc_md.get_rtc_time = todc_get_rtc_time; | ||
340 | ppc_md.set_rtc_time = todc_set_rtc_time; | ||
341 | ppc_md.calibrate_decr = todc_calibrate_decr; | ||
342 | |||
343 | ppc_md.nvram_read_val = todc_m48txx_read_val; | ||
344 | ppc_md.nvram_write_val = todc_m48txx_write_val; | ||
345 | |||
346 | #ifdef CONFIG_SERIAL_TEXT_DEBUG | ||
347 | ppc_md.progress = gen550_progress; | ||
348 | #endif | ||
349 | #ifdef CONFIG_KGDB | ||
350 | ppc_md.kgdb_map_scc = gen550_kgdb_map_scc; | ||
351 | #endif | ||
352 | } | ||
diff --git a/arch/ppc/platforms/pcore.h b/arch/ppc/platforms/pcore.h new file mode 100644 index 000000000000..c6a26e764926 --- /dev/null +++ b/arch/ppc/platforms/pcore.h | |||
@@ -0,0 +1,39 @@ | |||
1 | /* | ||
2 | * arch/ppc/platforms/pcore.h | ||
3 | * | ||
4 | * Definitions for Force PowerCore board support | ||
5 | * | ||
6 | * Author: Matt Porter <mporter@mvista.com> | ||
7 | * | ||
8 | * 2001 (c) MontaVista, Software, Inc. This file is licensed under | ||
9 | * the terms of the GNU General Public License version 2. This program | ||
10 | * is licensed "as is" without any warranty of any kind, whether express | ||
11 | * or implied. | ||
12 | */ | ||
13 | |||
14 | #ifndef __PPC_PLATFORMS_PCORE_H | ||
15 | #define __PPC_PLATFORMS_PCORE_H | ||
16 | |||
17 | #include <asm/mpc10x.h> | ||
18 | |||
19 | #define PCORE_TYPE_6750 1 | ||
20 | #define PCORE_TYPE_680 2 | ||
21 | |||
22 | #define PCORE_NVRAM_AS0 0x73 | ||
23 | #define PCORE_NVRAM_AS1 0x75 | ||
24 | #define PCORE_NVRAM_DATA 0x77 | ||
25 | |||
26 | #define PCORE_DCCR_REG (MPC10X_MAPB_ISA_IO_BASE + 0x308) | ||
27 | #define PCORE_DCCR_L2_MASK 0xc0 | ||
28 | #define PCORE_DCCR_L2_0KB 0x00 | ||
29 | #define PCORE_DCCR_L2_256KB 0x40 | ||
30 | #define PCORE_DCCR_L2_512KB 0xc0 | ||
31 | #define PCORE_DCCR_L2_1MB 0x80 | ||
32 | #define PCORE_DCCR_L2_2MB 0x00 | ||
33 | |||
34 | #define PCORE_WINBOND_IDE_INT 0x43 | ||
35 | #define PCORE_WINBOND_PCI_INT 0x44 | ||
36 | #define PCORE_WINBOND_PRI_EDG_LVL 0x4d0 | ||
37 | #define PCORE_WINBOND_SEC_EDG_LVL 0x4d1 | ||
38 | |||
39 | #endif /* __PPC_PLATFORMS_PCORE_H */ | ||
diff --git a/arch/ppc/platforms/pcu_e.h b/arch/ppc/platforms/pcu_e.h new file mode 100644 index 000000000000..91a820a6fbc4 --- /dev/null +++ b/arch/ppc/platforms/pcu_e.h | |||
@@ -0,0 +1,28 @@ | |||
1 | /* | ||
2 | * Siemens PCU E board specific definitions | ||
3 | * | ||
4 | * Copyright (c) 2001 Wolfgang Denk (wd@denx.de) | ||
5 | */ | ||
6 | |||
7 | #ifndef __MACH_PCU_E_H | ||
8 | #define __MACH_PCU_E_H | ||
9 | |||
10 | #include <linux/config.h> | ||
11 | |||
12 | #include <asm/ppcboot.h> | ||
13 | |||
14 | #define PCU_E_IMMR_BASE 0xFE000000 /* phys. addr of IMMR */ | ||
15 | #define PCU_E_IMAP_SIZE (64 * 1024) /* size of mapped area */ | ||
16 | |||
17 | #define IMAP_ADDR PCU_E_IMMR_BASE /* physical base address of IMMR area */ | ||
18 | #define IMAP_SIZE PCU_E_IMAP_SIZE /* mapped size of IMMR area */ | ||
19 | |||
20 | #define FEC_INTERRUPT 15 /* = SIU_LEVEL7 */ | ||
21 | #define DEC_INTERRUPT 13 /* = SIU_LEVEL6 */ | ||
22 | #define CPM_INTERRUPT 11 /* = SIU_LEVEL5 (was: SIU_LEVEL2) */ | ||
23 | |||
24 | /* We don't use the 8259. | ||
25 | */ | ||
26 | #define NR_8259_INTS 0 | ||
27 | |||
28 | #endif /* __MACH_PCU_E_H */ | ||
diff --git a/arch/ppc/platforms/pmac_backlight.c b/arch/ppc/platforms/pmac_backlight.c new file mode 100644 index 000000000000..ed2b1cebc19a --- /dev/null +++ b/arch/ppc/platforms/pmac_backlight.c | |||
@@ -0,0 +1,202 @@ | |||
1 | /* | ||
2 | * Miscellaneous procedures for dealing with the PowerMac hardware. | ||
3 | * Contains support for the backlight. | ||
4 | * | ||
5 | * Copyright (C) 2000 Benjamin Herrenschmidt | ||
6 | * | ||
7 | */ | ||
8 | |||
9 | #include <linux/config.h> | ||
10 | #include <linux/kernel.h> | ||
11 | #include <linux/module.h> | ||
12 | #include <linux/stddef.h> | ||
13 | #include <linux/reboot.h> | ||
14 | #include <linux/nvram.h> | ||
15 | #include <linux/console.h> | ||
16 | #include <asm/sections.h> | ||
17 | #include <asm/ptrace.h> | ||
18 | #include <asm/io.h> | ||
19 | #include <asm/pgtable.h> | ||
20 | #include <asm/system.h> | ||
21 | #include <asm/prom.h> | ||
22 | #include <asm/machdep.h> | ||
23 | #include <asm/nvram.h> | ||
24 | #include <asm/backlight.h> | ||
25 | |||
26 | #include <linux/adb.h> | ||
27 | #include <linux/pmu.h> | ||
28 | |||
29 | static struct backlight_controller *backlighter; | ||
30 | static void* backlighter_data; | ||
31 | static int backlight_autosave; | ||
32 | static int backlight_level = BACKLIGHT_MAX; | ||
33 | static int backlight_enabled = 1; | ||
34 | static int backlight_req_level = -1; | ||
35 | static int backlight_req_enable = -1; | ||
36 | |||
37 | static void backlight_callback(void *); | ||
38 | static DECLARE_WORK(backlight_work, backlight_callback, NULL); | ||
39 | |||
40 | void __pmac register_backlight_controller(struct backlight_controller *ctrler, | ||
41 | void *data, char *type) | ||
42 | { | ||
43 | struct device_node* bk_node; | ||
44 | char *prop; | ||
45 | int valid = 0; | ||
46 | |||
47 | /* There's already a matching controller, bail out */ | ||
48 | if (backlighter != NULL) | ||
49 | return; | ||
50 | |||
51 | bk_node = find_devices("backlight"); | ||
52 | |||
53 | #ifdef CONFIG_ADB_PMU | ||
54 | /* Special case for the old PowerBook since I can't test on it */ | ||
55 | backlight_autosave = machine_is_compatible("AAPL,3400/2400") | ||
56 | || machine_is_compatible("AAPL,3500"); | ||
57 | if ((backlight_autosave | ||
58 | || machine_is_compatible("AAPL,PowerBook1998") | ||
59 | || machine_is_compatible("PowerBook1,1")) | ||
60 | && !strcmp(type, "pmu")) | ||
61 | valid = 1; | ||
62 | #endif | ||
63 | if (bk_node) { | ||
64 | prop = get_property(bk_node, "backlight-control", NULL); | ||
65 | if (prop && !strncmp(prop, type, strlen(type))) | ||
66 | valid = 1; | ||
67 | } | ||
68 | if (!valid) | ||
69 | return; | ||
70 | backlighter = ctrler; | ||
71 | backlighter_data = data; | ||
72 | |||
73 | if (bk_node && !backlight_autosave) | ||
74 | prop = get_property(bk_node, "bklt", NULL); | ||
75 | else | ||
76 | prop = NULL; | ||
77 | if (prop) { | ||
78 | backlight_level = ((*prop)+1) >> 1; | ||
79 | if (backlight_level > BACKLIGHT_MAX) | ||
80 | backlight_level = BACKLIGHT_MAX; | ||
81 | } | ||
82 | |||
83 | #ifdef CONFIG_ADB_PMU | ||
84 | if (backlight_autosave) { | ||
85 | struct adb_request req; | ||
86 | pmu_request(&req, NULL, 2, 0xd9, 0); | ||
87 | while (!req.complete) | ||
88 | pmu_poll(); | ||
89 | backlight_level = req.reply[0] >> 4; | ||
90 | } | ||
91 | #endif | ||
92 | acquire_console_sem(); | ||
93 | if (!backlighter->set_enable(1, backlight_level, data)) | ||
94 | backlight_enabled = 1; | ||
95 | release_console_sem(); | ||
96 | |||
97 | printk(KERN_INFO "Registered \"%s\" backlight controller," | ||
98 | "level: %d/15\n", type, backlight_level); | ||
99 | } | ||
100 | EXPORT_SYMBOL(register_backlight_controller); | ||
101 | |||
102 | void __pmac unregister_backlight_controller(struct backlight_controller | ||
103 | *ctrler, void *data) | ||
104 | { | ||
105 | /* We keep the current backlight level (for now) */ | ||
106 | if (ctrler == backlighter && data == backlighter_data) | ||
107 | backlighter = NULL; | ||
108 | } | ||
109 | EXPORT_SYMBOL(unregister_backlight_controller); | ||
110 | |||
111 | static int __pmac __set_backlight_enable(int enable) | ||
112 | { | ||
113 | int rc; | ||
114 | |||
115 | if (!backlighter) | ||
116 | return -ENODEV; | ||
117 | acquire_console_sem(); | ||
118 | rc = backlighter->set_enable(enable, backlight_level, | ||
119 | backlighter_data); | ||
120 | if (!rc) | ||
121 | backlight_enabled = enable; | ||
122 | release_console_sem(); | ||
123 | return rc; | ||
124 | } | ||
125 | int __pmac set_backlight_enable(int enable) | ||
126 | { | ||
127 | if (!backlighter) | ||
128 | return -ENODEV; | ||
129 | backlight_req_enable = enable; | ||
130 | schedule_work(&backlight_work); | ||
131 | return 0; | ||
132 | } | ||
133 | |||
134 | EXPORT_SYMBOL(set_backlight_enable); | ||
135 | |||
136 | int __pmac get_backlight_enable(void) | ||
137 | { | ||
138 | if (!backlighter) | ||
139 | return -ENODEV; | ||
140 | return backlight_enabled; | ||
141 | } | ||
142 | EXPORT_SYMBOL(get_backlight_enable); | ||
143 | |||
144 | static int __pmac __set_backlight_level(int level) | ||
145 | { | ||
146 | int rc = 0; | ||
147 | |||
148 | if (!backlighter) | ||
149 | return -ENODEV; | ||
150 | if (level < BACKLIGHT_MIN) | ||
151 | level = BACKLIGHT_OFF; | ||
152 | if (level > BACKLIGHT_MAX) | ||
153 | level = BACKLIGHT_MAX; | ||
154 | acquire_console_sem(); | ||
155 | if (backlight_enabled) | ||
156 | rc = backlighter->set_level(level, backlighter_data); | ||
157 | if (!rc) | ||
158 | backlight_level = level; | ||
159 | release_console_sem(); | ||
160 | if (!rc && !backlight_autosave) { | ||
161 | level <<=1; | ||
162 | if (level & 0x10) | ||
163 | level |= 0x01; | ||
164 | // -- todo: save to property "bklt" | ||
165 | } | ||
166 | return rc; | ||
167 | } | ||
168 | int __pmac set_backlight_level(int level) | ||
169 | { | ||
170 | if (!backlighter) | ||
171 | return -ENODEV; | ||
172 | backlight_req_level = level; | ||
173 | schedule_work(&backlight_work); | ||
174 | return 0; | ||
175 | } | ||
176 | |||
177 | EXPORT_SYMBOL(set_backlight_level); | ||
178 | |||
179 | int __pmac get_backlight_level(void) | ||
180 | { | ||
181 | if (!backlighter) | ||
182 | return -ENODEV; | ||
183 | return backlight_level; | ||
184 | } | ||
185 | EXPORT_SYMBOL(get_backlight_level); | ||
186 | |||
187 | static void backlight_callback(void *dummy) | ||
188 | { | ||
189 | int level, enable; | ||
190 | |||
191 | do { | ||
192 | level = backlight_req_level; | ||
193 | enable = backlight_req_enable; | ||
194 | mb(); | ||
195 | |||
196 | if (level >= 0) | ||
197 | __set_backlight_level(level); | ||
198 | if (enable >= 0) | ||
199 | __set_backlight_enable(enable); | ||
200 | } while(cmpxchg(&backlight_req_level, level, -1) != level || | ||
201 | cmpxchg(&backlight_req_enable, enable, -1) != enable); | ||
202 | } | ||
diff --git a/arch/ppc/platforms/pmac_cache.S b/arch/ppc/platforms/pmac_cache.S new file mode 100644 index 000000000000..c00e0352044d --- /dev/null +++ b/arch/ppc/platforms/pmac_cache.S | |||
@@ -0,0 +1,325 @@ | |||
1 | /* | ||
2 | * This file contains low-level cache management functions | ||
3 | * used for sleep and CPU speed changes on Apple machines. | ||
4 | * (In fact the only thing that is Apple-specific is that we assume | ||
5 | * that we can read from ROM at physical address 0xfff00000.) | ||
6 | * | ||
7 | * Copyright (C) 2004 Paul Mackerras (paulus@samba.org) and | ||
8 | * Benjamin Herrenschmidt (benh@kernel.crashing.org) | ||
9 | * | ||
10 | * This program is free software; you can redistribute it and/or | ||
11 | * modify it under the terms of the GNU General Public License | ||
12 | * as published by the Free Software Foundation; either version | ||
13 | * 2 of the License, or (at your option) any later version. | ||
14 | * | ||
15 | */ | ||
16 | |||
17 | #include <linux/config.h> | ||
18 | #include <asm/processor.h> | ||
19 | #include <asm/ppc_asm.h> | ||
20 | #include <asm/cputable.h> | ||
21 | |||
22 | /* | ||
23 | * Flush and disable all data caches (dL1, L2, L3). This is used | ||
24 | * when going to sleep, when doing a PMU based cpufreq transition, | ||
25 | * or when "offlining" a CPU on SMP machines. This code is over | ||
26 | * paranoid, but I've had enough issues with various CPU revs and | ||
27 | * bugs that I decided it was worth beeing over cautious | ||
28 | */ | ||
29 | |||
30 | _GLOBAL(flush_disable_caches) | ||
31 | BEGIN_FTR_SECTION | ||
32 | b flush_disable_745x | ||
33 | END_FTR_SECTION_IFSET(CPU_FTR_SPEC7450) | ||
34 | BEGIN_FTR_SECTION | ||
35 | b flush_disable_75x | ||
36 | END_FTR_SECTION_IFSET(CPU_FTR_L2CR) | ||
37 | b __flush_disable_L1 | ||
38 | |||
39 | /* This is the code for G3 and 74[01]0 */ | ||
40 | flush_disable_75x: | ||
41 | mflr r10 | ||
42 | |||
43 | /* Turn off EE and DR in MSR */ | ||
44 | mfmsr r11 | ||
45 | rlwinm r0,r11,0,~MSR_EE | ||
46 | rlwinm r0,r0,0,~MSR_DR | ||
47 | sync | ||
48 | mtmsr r0 | ||
49 | isync | ||
50 | |||
51 | /* Stop DST streams */ | ||
52 | BEGIN_FTR_SECTION | ||
53 | DSSALL | ||
54 | sync | ||
55 | END_FTR_SECTION_IFSET(CPU_FTR_ALTIVEC) | ||
56 | |||
57 | /* Stop DPM */ | ||
58 | mfspr r8,SPRN_HID0 /* Save SPRN_HID0 in r8 */ | ||
59 | rlwinm r4,r8,0,12,10 /* Turn off HID0[DPM] */ | ||
60 | sync | ||
61 | mtspr SPRN_HID0,r4 /* Disable DPM */ | ||
62 | sync | ||
63 | |||
64 | /* disp-flush L1 */ | ||
65 | li r4,0x4000 | ||
66 | mtctr r4 | ||
67 | lis r4,0xfff0 | ||
68 | 1: lwzx r0,r0,r4 | ||
69 | addi r4,r4,32 | ||
70 | bdnz 1b | ||
71 | sync | ||
72 | isync | ||
73 | |||
74 | /* disable / invalidate / enable L1 data */ | ||
75 | mfspr r3,SPRN_HID0 | ||
76 | rlwinm r0,r0,0,~HID0_DCE | ||
77 | mtspr SPRN_HID0,r3 | ||
78 | sync | ||
79 | isync | ||
80 | ori r3,r3,HID0_DCE|HID0_DCI | ||
81 | sync | ||
82 | isync | ||
83 | mtspr SPRN_HID0,r3 | ||
84 | xori r3,r3,HID0_DCI | ||
85 | mtspr SPRN_HID0,r3 | ||
86 | sync | ||
87 | |||
88 | /* Get the current enable bit of the L2CR into r4 */ | ||
89 | mfspr r5,SPRN_L2CR | ||
90 | /* Set to data-only (pre-745x bit) */ | ||
91 | oris r3,r5,L2CR_L2DO@h | ||
92 | b 2f | ||
93 | /* When disabling L2, code must be in L1 */ | ||
94 | .balign 32 | ||
95 | 1: mtspr SPRN_L2CR,r3 | ||
96 | 3: sync | ||
97 | isync | ||
98 | b 1f | ||
99 | 2: b 3f | ||
100 | 3: sync | ||
101 | isync | ||
102 | b 1b | ||
103 | 1: /* disp-flush L2. The interesting thing here is that the L2 can be | ||
104 | * up to 2Mb ... so using the ROM, we'll end up wrapping back to memory | ||
105 | * but that is probbaly fine. We disp-flush over 4Mb to be safe | ||
106 | */ | ||
107 | lis r4,2 | ||
108 | mtctr r4 | ||
109 | lis r4,0xfff0 | ||
110 | 1: lwzx r0,r0,r4 | ||
111 | addi r4,r4,32 | ||
112 | bdnz 1b | ||
113 | sync | ||
114 | isync | ||
115 | /* now disable L2 */ | ||
116 | rlwinm r5,r5,0,~L2CR_L2E | ||
117 | b 2f | ||
118 | /* When disabling L2, code must be in L1 */ | ||
119 | .balign 32 | ||
120 | 1: mtspr SPRN_L2CR,r5 | ||
121 | 3: sync | ||
122 | isync | ||
123 | b 1f | ||
124 | 2: b 3f | ||
125 | 3: sync | ||
126 | isync | ||
127 | b 1b | ||
128 | 1: sync | ||
129 | isync | ||
130 | /* Invalidate L2. This is pre-745x, we clear the L2I bit ourselves */ | ||
131 | oris r4,r5,L2CR_L2I@h | ||
132 | mtspr SPRN_L2CR,r4 | ||
133 | sync | ||
134 | isync | ||
135 | xoris r4,r4,L2CR_L2I@h | ||
136 | sync | ||
137 | mtspr SPRN_L2CR,r4 | ||
138 | sync | ||
139 | |||
140 | /* now disable the L1 data cache */ | ||
141 | mfspr r0,SPRN_HID0 | ||
142 | rlwinm r0,r0,0,~HID0_DCE | ||
143 | mtspr SPRN_HID0,r0 | ||
144 | sync | ||
145 | isync | ||
146 | |||
147 | /* Restore HID0[DPM] to whatever it was before */ | ||
148 | sync | ||
149 | mtspr SPRN_HID0,r8 | ||
150 | sync | ||
151 | |||
152 | /* restore DR and EE */ | ||
153 | sync | ||
154 | mtmsr r11 | ||
155 | isync | ||
156 | |||
157 | mtlr r10 | ||
158 | blr | ||
159 | |||
160 | /* This code is for 745x processors */ | ||
161 | flush_disable_745x: | ||
162 | /* Turn off EE and DR in MSR */ | ||
163 | mfmsr r11 | ||
164 | rlwinm r0,r11,0,~MSR_EE | ||
165 | rlwinm r0,r0,0,~MSR_DR | ||
166 | sync | ||
167 | mtmsr r0 | ||
168 | isync | ||
169 | |||
170 | /* Stop prefetch streams */ | ||
171 | DSSALL | ||
172 | sync | ||
173 | |||
174 | /* Disable L2 prefetching */ | ||
175 | mfspr r0,SPRN_MSSCR0 | ||
176 | rlwinm r0,r0,0,0,29 | ||
177 | mtspr SPRN_MSSCR0,r0 | ||
178 | sync | ||
179 | isync | ||
180 | lis r4,0 | ||
181 | dcbf 0,r4 | ||
182 | dcbf 0,r4 | ||
183 | dcbf 0,r4 | ||
184 | dcbf 0,r4 | ||
185 | dcbf 0,r4 | ||
186 | dcbf 0,r4 | ||
187 | dcbf 0,r4 | ||
188 | dcbf 0,r4 | ||
189 | |||
190 | /* Due to a bug with the HW flush on some CPU revs, we occasionally | ||
191 | * experience data corruption. I'm adding a displacement flush along | ||
192 | * with a dcbf loop over a few Mb to "help". The problem isn't totally | ||
193 | * fixed by this in theory, but at least, in practice, I couldn't reproduce | ||
194 | * it even with a big hammer... | ||
195 | */ | ||
196 | |||
197 | lis r4,0x0002 | ||
198 | mtctr r4 | ||
199 | li r4,0 | ||
200 | 1: | ||
201 | lwzx r0,r0,r4 | ||
202 | addi r4,r4,32 /* Go to start of next cache line */ | ||
203 | bdnz 1b | ||
204 | isync | ||
205 | |||
206 | /* Now, flush the first 4MB of memory */ | ||
207 | lis r4,0x0002 | ||
208 | mtctr r4 | ||
209 | li r4,0 | ||
210 | sync | ||
211 | 1: | ||
212 | dcbf 0,r4 | ||
213 | addi r4,r4,32 /* Go to start of next cache line */ | ||
214 | bdnz 1b | ||
215 | |||
216 | /* Flush and disable the L1 data cache */ | ||
217 | mfspr r6,SPRN_LDSTCR | ||
218 | lis r3,0xfff0 /* read from ROM for displacement flush */ | ||
219 | li r4,0xfe /* start with only way 0 unlocked */ | ||
220 | li r5,128 /* 128 lines in each way */ | ||
221 | 1: mtctr r5 | ||
222 | rlwimi r6,r4,0,24,31 | ||
223 | mtspr SPRN_LDSTCR,r6 | ||
224 | sync | ||
225 | isync | ||
226 | 2: lwz r0,0(r3) /* touch each cache line */ | ||
227 | addi r3,r3,32 | ||
228 | bdnz 2b | ||
229 | rlwinm r4,r4,1,24,30 /* move on to the next way */ | ||
230 | ori r4,r4,1 | ||
231 | cmpwi r4,0xff /* all done? */ | ||
232 | bne 1b | ||
233 | /* now unlock the L1 data cache */ | ||
234 | li r4,0 | ||
235 | rlwimi r6,r4,0,24,31 | ||
236 | sync | ||
237 | mtspr SPRN_LDSTCR,r6 | ||
238 | sync | ||
239 | isync | ||
240 | |||
241 | /* Flush the L2 cache using the hardware assist */ | ||
242 | mfspr r3,SPRN_L2CR | ||
243 | cmpwi r3,0 /* check if it is enabled first */ | ||
244 | bge 4f | ||
245 | oris r0,r3,(L2CR_L2IO_745x|L2CR_L2DO_745x)@h | ||
246 | b 2f | ||
247 | /* When disabling/locking L2, code must be in L1 */ | ||
248 | .balign 32 | ||
249 | 1: mtspr SPRN_L2CR,r0 /* lock the L2 cache */ | ||
250 | 3: sync | ||
251 | isync | ||
252 | b 1f | ||
253 | 2: b 3f | ||
254 | 3: sync | ||
255 | isync | ||
256 | b 1b | ||
257 | 1: sync | ||
258 | isync | ||
259 | ori r0,r3,L2CR_L2HWF_745x | ||
260 | sync | ||
261 | mtspr SPRN_L2CR,r0 /* set the hardware flush bit */ | ||
262 | 3: mfspr r0,SPRN_L2CR /* wait for it to go to 0 */ | ||
263 | andi. r0,r0,L2CR_L2HWF_745x | ||
264 | bne 3b | ||
265 | sync | ||
266 | rlwinm r3,r3,0,~L2CR_L2E | ||
267 | b 2f | ||
268 | /* When disabling L2, code must be in L1 */ | ||
269 | .balign 32 | ||
270 | 1: mtspr SPRN_L2CR,r3 /* disable the L2 cache */ | ||
271 | 3: sync | ||
272 | isync | ||
273 | b 1f | ||
274 | 2: b 3f | ||
275 | 3: sync | ||
276 | isync | ||
277 | b 1b | ||
278 | 1: sync | ||
279 | isync | ||
280 | oris r4,r3,L2CR_L2I@h | ||
281 | mtspr SPRN_L2CR,r4 | ||
282 | sync | ||
283 | isync | ||
284 | 1: mfspr r4,SPRN_L2CR | ||
285 | andis. r0,r4,L2CR_L2I@h | ||
286 | bne 1b | ||
287 | sync | ||
288 | |||
289 | BEGIN_FTR_SECTION | ||
290 | /* Flush the L3 cache using the hardware assist */ | ||
291 | 4: mfspr r3,SPRN_L3CR | ||
292 | cmpwi r3,0 /* check if it is enabled */ | ||
293 | bge 6f | ||
294 | oris r0,r3,L3CR_L3IO@h | ||
295 | ori r0,r0,L3CR_L3DO | ||
296 | sync | ||
297 | mtspr SPRN_L3CR,r0 /* lock the L3 cache */ | ||
298 | sync | ||
299 | isync | ||
300 | ori r0,r0,L3CR_L3HWF | ||
301 | sync | ||
302 | mtspr SPRN_L3CR,r0 /* set the hardware flush bit */ | ||
303 | 5: mfspr r0,SPRN_L3CR /* wait for it to go to zero */ | ||
304 | andi. r0,r0,L3CR_L3HWF | ||
305 | bne 5b | ||
306 | rlwinm r3,r3,0,~L3CR_L3E | ||
307 | sync | ||
308 | mtspr SPRN_L3CR,r3 /* disable the L3 cache */ | ||
309 | sync | ||
310 | ori r4,r3,L3CR_L3I | ||
311 | mtspr SPRN_L3CR,r4 | ||
312 | 1: mfspr r4,SPRN_L3CR | ||
313 | andi. r0,r4,L3CR_L3I | ||
314 | bne 1b | ||
315 | sync | ||
316 | END_FTR_SECTION_IFSET(CPU_FTR_L3CR) | ||
317 | |||
318 | 6: mfspr r0,SPRN_HID0 /* now disable the L1 data cache */ | ||
319 | rlwinm r0,r0,0,~HID0_DCE | ||
320 | mtspr SPRN_HID0,r0 | ||
321 | sync | ||
322 | isync | ||
323 | mtmsr r11 /* restore DR and EE */ | ||
324 | isync | ||
325 | blr | ||
diff --git a/arch/ppc/platforms/pmac_cpufreq.c b/arch/ppc/platforms/pmac_cpufreq.c new file mode 100644 index 000000000000..9c85f9ca1cfb --- /dev/null +++ b/arch/ppc/platforms/pmac_cpufreq.c | |||
@@ -0,0 +1,571 @@ | |||
1 | /* | ||
2 | * arch/ppc/platforms/pmac_cpufreq.c | ||
3 | * | ||
4 | * Copyright (C) 2002 - 2004 Benjamin Herrenschmidt <benh@kernel.crashing.org> | ||
5 | * Copyright (C) 2004 John Steele Scott <toojays@toojays.net> | ||
6 | * | ||
7 | * This program is free software; you can redistribute it and/or modify | ||
8 | * it under the terms of the GNU General Public License version 2 as | ||
9 | * published by the Free Software Foundation. | ||
10 | * | ||
11 | */ | ||
12 | |||
13 | #include <linux/config.h> | ||
14 | #include <linux/module.h> | ||
15 | #include <linux/types.h> | ||
16 | #include <linux/errno.h> | ||
17 | #include <linux/kernel.h> | ||
18 | #include <linux/delay.h> | ||
19 | #include <linux/sched.h> | ||
20 | #include <linux/adb.h> | ||
21 | #include <linux/pmu.h> | ||
22 | #include <linux/slab.h> | ||
23 | #include <linux/cpufreq.h> | ||
24 | #include <linux/init.h> | ||
25 | #include <linux/sysdev.h> | ||
26 | #include <linux/i2c.h> | ||
27 | #include <linux/hardirq.h> | ||
28 | #include <asm/prom.h> | ||
29 | #include <asm/machdep.h> | ||
30 | #include <asm/irq.h> | ||
31 | #include <asm/pmac_feature.h> | ||
32 | #include <asm/mmu_context.h> | ||
33 | #include <asm/sections.h> | ||
34 | #include <asm/cputable.h> | ||
35 | #include <asm/time.h> | ||
36 | #include <asm/system.h> | ||
37 | #include <asm/open_pic.h> | ||
38 | |||
39 | /* WARNING !!! This will cause calibrate_delay() to be called, | ||
40 | * but this is an __init function ! So you MUST go edit | ||
41 | * init/main.c to make it non-init before enabling DEBUG_FREQ | ||
42 | */ | ||
43 | #undef DEBUG_FREQ | ||
44 | |||
45 | /* | ||
46 | * There is a problem with the core cpufreq code on SMP kernels, | ||
47 | * it won't recalculate the Bogomips properly | ||
48 | */ | ||
49 | #ifdef CONFIG_SMP | ||
50 | #warning "WARNING, CPUFREQ not recommended on SMP kernels" | ||
51 | #endif | ||
52 | |||
53 | extern void low_choose_7447a_dfs(int dfs); | ||
54 | extern void low_choose_750fx_pll(int pll); | ||
55 | extern void low_sleep_handler(void); | ||
56 | |||
57 | /* | ||
58 | * Currently, PowerMac cpufreq supports only high & low frequencies | ||
59 | * that are set by the firmware | ||
60 | */ | ||
61 | static unsigned int low_freq; | ||
62 | static unsigned int hi_freq; | ||
63 | static unsigned int cur_freq; | ||
64 | |||
65 | /* | ||
66 | * Different models uses different mecanisms to switch the frequency | ||
67 | */ | ||
68 | static int (*set_speed_proc)(int low_speed); | ||
69 | |||
70 | /* | ||
71 | * Some definitions used by the various speedprocs | ||
72 | */ | ||
73 | static u32 voltage_gpio; | ||
74 | static u32 frequency_gpio; | ||
75 | static u32 slew_done_gpio; | ||
76 | |||
77 | |||
78 | #define PMAC_CPU_LOW_SPEED 1 | ||
79 | #define PMAC_CPU_HIGH_SPEED 0 | ||
80 | |||
81 | /* There are only two frequency states for each processor. Values | ||
82 | * are in kHz for the time being. | ||
83 | */ | ||
84 | #define CPUFREQ_HIGH PMAC_CPU_HIGH_SPEED | ||
85 | #define CPUFREQ_LOW PMAC_CPU_LOW_SPEED | ||
86 | |||
87 | static struct cpufreq_frequency_table pmac_cpu_freqs[] = { | ||
88 | {CPUFREQ_HIGH, 0}, | ||
89 | {CPUFREQ_LOW, 0}, | ||
90 | {0, CPUFREQ_TABLE_END}, | ||
91 | }; | ||
92 | |||
93 | static inline void wakeup_decrementer(void) | ||
94 | { | ||
95 | set_dec(tb_ticks_per_jiffy); | ||
96 | /* No currently-supported powerbook has a 601, | ||
97 | * so use get_tbl, not native | ||
98 | */ | ||
99 | last_jiffy_stamp(0) = tb_last_stamp = get_tbl(); | ||
100 | } | ||
101 | |||
102 | #ifdef DEBUG_FREQ | ||
103 | static inline void debug_calc_bogomips(void) | ||
104 | { | ||
105 | /* This will cause a recalc of bogomips and display the | ||
106 | * result. We backup/restore the value to avoid affecting the | ||
107 | * core cpufreq framework's own calculation. | ||
108 | */ | ||
109 | extern void calibrate_delay(void); | ||
110 | |||
111 | unsigned long save_lpj = loops_per_jiffy; | ||
112 | calibrate_delay(); | ||
113 | loops_per_jiffy = save_lpj; | ||
114 | } | ||
115 | #endif /* DEBUG_FREQ */ | ||
116 | |||
117 | /* Switch CPU speed under 750FX CPU control | ||
118 | */ | ||
119 | static int __pmac cpu_750fx_cpu_speed(int low_speed) | ||
120 | { | ||
121 | #ifdef DEBUG_FREQ | ||
122 | printk(KERN_DEBUG "HID1, before: %x\n", mfspr(SPRN_HID1)); | ||
123 | #endif | ||
124 | #ifdef CONFIG_6xx | ||
125 | low_choose_750fx_pll(low_speed); | ||
126 | #endif | ||
127 | #ifdef DEBUG_FREQ | ||
128 | printk(KERN_DEBUG "HID1, after: %x\n", mfspr(SPRN_HID1)); | ||
129 | debug_calc_bogomips(); | ||
130 | #endif | ||
131 | |||
132 | return 0; | ||
133 | } | ||
134 | |||
135 | /* Switch CPU speed using DFS */ | ||
136 | static int __pmac dfs_set_cpu_speed(int low_speed) | ||
137 | { | ||
138 | if (low_speed == 0) { | ||
139 | /* ramping up, set voltage first */ | ||
140 | pmac_call_feature(PMAC_FTR_WRITE_GPIO, NULL, voltage_gpio, 0x05); | ||
141 | /* Make sure we sleep for at least 1ms */ | ||
142 | msleep(1); | ||
143 | } | ||
144 | |||
145 | /* set frequency */ | ||
146 | low_choose_7447a_dfs(low_speed); | ||
147 | |||
148 | if (low_speed == 1) { | ||
149 | /* ramping down, set voltage last */ | ||
150 | pmac_call_feature(PMAC_FTR_WRITE_GPIO, NULL, voltage_gpio, 0x04); | ||
151 | msleep(1); | ||
152 | } | ||
153 | |||
154 | return 0; | ||
155 | } | ||
156 | |||
157 | static unsigned int __pmac dfs_get_cpu_speed(unsigned int cpu) | ||
158 | { | ||
159 | if (mfspr(SPRN_HID1) & HID1_DFS) | ||
160 | return low_freq; | ||
161 | else | ||
162 | return hi_freq; | ||
163 | } | ||
164 | |||
165 | |||
166 | /* Switch CPU speed using slewing GPIOs | ||
167 | */ | ||
168 | static int __pmac gpios_set_cpu_speed(int low_speed) | ||
169 | { | ||
170 | int gpio; | ||
171 | |||
172 | /* If ramping up, set voltage first */ | ||
173 | if (low_speed == 0) { | ||
174 | pmac_call_feature(PMAC_FTR_WRITE_GPIO, NULL, voltage_gpio, 0x05); | ||
175 | /* Delay is way too big but it's ok, we schedule */ | ||
176 | msleep(10); | ||
177 | } | ||
178 | |||
179 | /* Set frequency */ | ||
180 | pmac_call_feature(PMAC_FTR_WRITE_GPIO, NULL, frequency_gpio, | ||
181 | low_speed ? 0x04 : 0x05); | ||
182 | udelay(200); | ||
183 | do { | ||
184 | set_current_state(TASK_UNINTERRUPTIBLE); | ||
185 | schedule_timeout(1); | ||
186 | gpio = pmac_call_feature(PMAC_FTR_READ_GPIO, NULL, slew_done_gpio, 0); | ||
187 | } while((gpio & 0x02) == 0); | ||
188 | |||
189 | /* If ramping down, set voltage last */ | ||
190 | if (low_speed == 1) { | ||
191 | pmac_call_feature(PMAC_FTR_WRITE_GPIO, NULL, voltage_gpio, 0x04); | ||
192 | /* Delay is way too big but it's ok, we schedule */ | ||
193 | msleep(10); | ||
194 | } | ||
195 | |||
196 | #ifdef DEBUG_FREQ | ||
197 | debug_calc_bogomips(); | ||
198 | #endif | ||
199 | |||
200 | return 0; | ||
201 | } | ||
202 | |||
203 | /* Switch CPU speed under PMU control | ||
204 | */ | ||
205 | static int __pmac pmu_set_cpu_speed(int low_speed) | ||
206 | { | ||
207 | struct adb_request req; | ||
208 | unsigned long save_l2cr; | ||
209 | unsigned long save_l3cr; | ||
210 | |||
211 | preempt_disable(); | ||
212 | |||
213 | #ifdef DEBUG_FREQ | ||
214 | printk(KERN_DEBUG "HID1, before: %x\n", mfspr(SPRN_HID1)); | ||
215 | #endif | ||
216 | /* Disable all interrupt sources on openpic */ | ||
217 | openpic_set_priority(0xf); | ||
218 | |||
219 | /* Make sure the decrementer won't interrupt us */ | ||
220 | asm volatile("mtdec %0" : : "r" (0x7fffffff)); | ||
221 | /* Make sure any pending DEC interrupt occuring while we did | ||
222 | * the above didn't re-enable the DEC */ | ||
223 | mb(); | ||
224 | asm volatile("mtdec %0" : : "r" (0x7fffffff)); | ||
225 | |||
226 | /* We can now disable MSR_EE */ | ||
227 | local_irq_disable(); | ||
228 | |||
229 | /* Giveup the FPU & vec */ | ||
230 | enable_kernel_fp(); | ||
231 | |||
232 | #ifdef CONFIG_ALTIVEC | ||
233 | if (cpu_has_feature(CPU_FTR_ALTIVEC)) | ||
234 | enable_kernel_altivec(); | ||
235 | #endif /* CONFIG_ALTIVEC */ | ||
236 | |||
237 | /* Save & disable L2 and L3 caches */ | ||
238 | save_l3cr = _get_L3CR(); /* (returns -1 if not available) */ | ||
239 | save_l2cr = _get_L2CR(); /* (returns -1 if not available) */ | ||
240 | |||
241 | /* Send the new speed command. My assumption is that this command | ||
242 | * will cause PLL_CFG[0..3] to be changed next time CPU goes to sleep | ||
243 | */ | ||
244 | pmu_request(&req, NULL, 6, PMU_CPU_SPEED, 'W', 'O', 'O', 'F', low_speed); | ||
245 | while (!req.complete) | ||
246 | pmu_poll(); | ||
247 | |||
248 | /* Prepare the northbridge for the speed transition */ | ||
249 | pmac_call_feature(PMAC_FTR_SLEEP_STATE,NULL,1,1); | ||
250 | |||
251 | /* Call low level code to backup CPU state and recover from | ||
252 | * hardware reset | ||
253 | */ | ||
254 | low_sleep_handler(); | ||
255 | |||
256 | /* Restore the northbridge */ | ||
257 | pmac_call_feature(PMAC_FTR_SLEEP_STATE,NULL,1,0); | ||
258 | |||
259 | /* Restore L2 cache */ | ||
260 | if (save_l2cr != 0xffffffff && (save_l2cr & L2CR_L2E) != 0) | ||
261 | _set_L2CR(save_l2cr); | ||
262 | /* Restore L3 cache */ | ||
263 | if (save_l3cr != 0xffffffff && (save_l3cr & L3CR_L3E) != 0) | ||
264 | _set_L3CR(save_l3cr); | ||
265 | |||
266 | /* Restore userland MMU context */ | ||
267 | set_context(current->active_mm->context, current->active_mm->pgd); | ||
268 | |||
269 | #ifdef DEBUG_FREQ | ||
270 | printk(KERN_DEBUG "HID1, after: %x\n", mfspr(SPRN_HID1)); | ||
271 | #endif | ||
272 | |||
273 | /* Restore low level PMU operations */ | ||
274 | pmu_unlock(); | ||
275 | |||
276 | /* Restore decrementer */ | ||
277 | wakeup_decrementer(); | ||
278 | |||
279 | /* Restore interrupts */ | ||
280 | openpic_set_priority(0); | ||
281 | |||
282 | /* Let interrupts flow again ... */ | ||
283 | local_irq_enable(); | ||
284 | |||
285 | #ifdef DEBUG_FREQ | ||
286 | debug_calc_bogomips(); | ||
287 | #endif | ||
288 | |||
289 | preempt_enable(); | ||
290 | |||
291 | return 0; | ||
292 | } | ||
293 | |||
294 | static int __pmac do_set_cpu_speed(int speed_mode) | ||
295 | { | ||
296 | struct cpufreq_freqs freqs; | ||
297 | |||
298 | freqs.old = cur_freq; | ||
299 | freqs.new = (speed_mode == PMAC_CPU_HIGH_SPEED) ? hi_freq : low_freq; | ||
300 | freqs.cpu = smp_processor_id(); | ||
301 | |||
302 | if (freqs.old == freqs.new) | ||
303 | return 0; | ||
304 | |||
305 | cpufreq_notify_transition(&freqs, CPUFREQ_PRECHANGE); | ||
306 | set_speed_proc(speed_mode == PMAC_CPU_LOW_SPEED); | ||
307 | cpufreq_notify_transition(&freqs, CPUFREQ_POSTCHANGE); | ||
308 | cur_freq = (speed_mode == PMAC_CPU_HIGH_SPEED) ? hi_freq : low_freq; | ||
309 | |||
310 | return 0; | ||
311 | } | ||
312 | |||
313 | static int __pmac pmac_cpufreq_verify(struct cpufreq_policy *policy) | ||
314 | { | ||
315 | return cpufreq_frequency_table_verify(policy, pmac_cpu_freqs); | ||
316 | } | ||
317 | |||
318 | static int __pmac pmac_cpufreq_target( struct cpufreq_policy *policy, | ||
319 | unsigned int target_freq, | ||
320 | unsigned int relation) | ||
321 | { | ||
322 | unsigned int newstate = 0; | ||
323 | |||
324 | if (cpufreq_frequency_table_target(policy, pmac_cpu_freqs, | ||
325 | target_freq, relation, &newstate)) | ||
326 | return -EINVAL; | ||
327 | |||
328 | return do_set_cpu_speed(newstate); | ||
329 | } | ||
330 | |||
331 | unsigned int __pmac pmac_get_one_cpufreq(int i) | ||
332 | { | ||
333 | /* Supports only one CPU for now */ | ||
334 | return (i == 0) ? cur_freq : 0; | ||
335 | } | ||
336 | |||
337 | static int __pmac pmac_cpufreq_cpu_init(struct cpufreq_policy *policy) | ||
338 | { | ||
339 | if (policy->cpu != 0) | ||
340 | return -ENODEV; | ||
341 | |||
342 | policy->governor = CPUFREQ_DEFAULT_GOVERNOR; | ||
343 | policy->cpuinfo.transition_latency = CPUFREQ_ETERNAL; | ||
344 | policy->cur = cur_freq; | ||
345 | |||
346 | return cpufreq_frequency_table_cpuinfo(policy, &pmac_cpu_freqs[0]); | ||
347 | } | ||
348 | |||
349 | static u32 __pmac read_gpio(struct device_node *np) | ||
350 | { | ||
351 | u32 *reg = (u32 *)get_property(np, "reg", NULL); | ||
352 | |||
353 | if (reg == NULL) | ||
354 | return 0; | ||
355 | /* That works for all keylargos but shall be fixed properly | ||
356 | * some day... | ||
357 | */ | ||
358 | return 0x50 + (*reg); | ||
359 | } | ||
360 | |||
361 | static struct cpufreq_driver pmac_cpufreq_driver = { | ||
362 | .verify = pmac_cpufreq_verify, | ||
363 | .target = pmac_cpufreq_target, | ||
364 | .init = pmac_cpufreq_cpu_init, | ||
365 | .name = "powermac", | ||
366 | .owner = THIS_MODULE, | ||
367 | }; | ||
368 | |||
369 | |||
370 | static int __pmac pmac_cpufreq_init_MacRISC3(struct device_node *cpunode) | ||
371 | { | ||
372 | struct device_node *volt_gpio_np = of_find_node_by_name(NULL, | ||
373 | "voltage-gpio"); | ||
374 | struct device_node *freq_gpio_np = of_find_node_by_name(NULL, | ||
375 | "frequency-gpio"); | ||
376 | struct device_node *slew_done_gpio_np = of_find_node_by_name(NULL, | ||
377 | "slewing-done"); | ||
378 | u32 *value; | ||
379 | |||
380 | /* | ||
381 | * Check to see if it's GPIO driven or PMU only | ||
382 | * | ||
383 | * The way we extract the GPIO address is slightly hackish, but it | ||
384 | * works well enough for now. We need to abstract the whole GPIO | ||
385 | * stuff sooner or later anyway | ||
386 | */ | ||
387 | |||
388 | if (volt_gpio_np) | ||
389 | voltage_gpio = read_gpio(volt_gpio_np); | ||
390 | if (freq_gpio_np) | ||
391 | frequency_gpio = read_gpio(freq_gpio_np); | ||
392 | if (slew_done_gpio_np) | ||
393 | slew_done_gpio = read_gpio(slew_done_gpio_np); | ||
394 | |||
395 | /* If we use the frequency GPIOs, calculate the min/max speeds based | ||
396 | * on the bus frequencies | ||
397 | */ | ||
398 | if (frequency_gpio && slew_done_gpio) { | ||
399 | int lenp, rc; | ||
400 | u32 *freqs, *ratio; | ||
401 | |||
402 | freqs = (u32 *)get_property(cpunode, "bus-frequencies", &lenp); | ||
403 | lenp /= sizeof(u32); | ||
404 | if (freqs == NULL || lenp != 2) { | ||
405 | printk(KERN_ERR "cpufreq: bus-frequencies incorrect or missing\n"); | ||
406 | return 1; | ||
407 | } | ||
408 | ratio = (u32 *)get_property(cpunode, "processor-to-bus-ratio*2", NULL); | ||
409 | if (ratio == NULL) { | ||
410 | printk(KERN_ERR "cpufreq: processor-to-bus-ratio*2 missing\n"); | ||
411 | return 1; | ||
412 | } | ||
413 | |||
414 | /* Get the min/max bus frequencies */ | ||
415 | low_freq = min(freqs[0], freqs[1]); | ||
416 | hi_freq = max(freqs[0], freqs[1]); | ||
417 | |||
418 | /* Grrrr.. It _seems_ that the device-tree is lying on the low bus | ||
419 | * frequency, it claims it to be around 84Mhz on some models while | ||
420 | * it appears to be approx. 101Mhz on all. Let's hack around here... | ||
421 | * fortunately, we don't need to be too precise | ||
422 | */ | ||
423 | if (low_freq < 98000000) | ||
424 | low_freq = 101000000; | ||
425 | |||
426 | /* Convert those to CPU core clocks */ | ||
427 | low_freq = (low_freq * (*ratio)) / 2000; | ||
428 | hi_freq = (hi_freq * (*ratio)) / 2000; | ||
429 | |||
430 | /* Now we get the frequencies, we read the GPIO to see what is out current | ||
431 | * speed | ||
432 | */ | ||
433 | rc = pmac_call_feature(PMAC_FTR_READ_GPIO, NULL, frequency_gpio, 0); | ||
434 | cur_freq = (rc & 0x01) ? hi_freq : low_freq; | ||
435 | |||
436 | set_speed_proc = gpios_set_cpu_speed; | ||
437 | return 1; | ||
438 | } | ||
439 | |||
440 | /* If we use the PMU, look for the min & max frequencies in the | ||
441 | * device-tree | ||
442 | */ | ||
443 | value = (u32 *)get_property(cpunode, "min-clock-frequency", NULL); | ||
444 | if (!value) | ||
445 | return 1; | ||
446 | low_freq = (*value) / 1000; | ||
447 | /* The PowerBook G4 12" (PowerBook6,1) has an error in the device-tree | ||
448 | * here */ | ||
449 | if (low_freq < 100000) | ||
450 | low_freq *= 10; | ||
451 | |||
452 | value = (u32 *)get_property(cpunode, "max-clock-frequency", NULL); | ||
453 | if (!value) | ||
454 | return 1; | ||
455 | hi_freq = (*value) / 1000; | ||
456 | set_speed_proc = pmu_set_cpu_speed; | ||
457 | |||
458 | return 0; | ||
459 | } | ||
460 | |||
461 | static int __pmac pmac_cpufreq_init_7447A(struct device_node *cpunode) | ||
462 | { | ||
463 | struct device_node *volt_gpio_np; | ||
464 | u32 *reg; | ||
465 | struct cpufreq_driver *driver = &pmac_cpufreq_driver; | ||
466 | |||
467 | /* Look for voltage GPIO */ | ||
468 | volt_gpio_np = of_find_node_by_name(NULL, "cpu-vcore-select"); | ||
469 | reg = (u32 *)get_property(volt_gpio_np, "reg", NULL); | ||
470 | voltage_gpio = *reg; | ||
471 | if (!volt_gpio_np){ | ||
472 | printk(KERN_ERR "cpufreq: missing cpu-vcore-select gpio\n"); | ||
473 | return 1; | ||
474 | } | ||
475 | |||
476 | /* OF only reports the high frequency */ | ||
477 | hi_freq = cur_freq; | ||
478 | low_freq = cur_freq/2; | ||
479 | |||
480 | /* Read actual frequency from CPU */ | ||
481 | driver->get = dfs_get_cpu_speed; | ||
482 | cur_freq = driver->get(0); | ||
483 | set_speed_proc = dfs_set_cpu_speed; | ||
484 | |||
485 | return 0; | ||
486 | } | ||
487 | |||
488 | /* Currently, we support the following machines: | ||
489 | * | ||
490 | * - Titanium PowerBook 1Ghz (PMU based, 667Mhz & 1Ghz) | ||
491 | * - Titanium PowerBook 800 (PMU based, 667Mhz & 800Mhz) | ||
492 | * - Titanium PowerBook 400 (PMU based, 300Mhz & 400Mhz) | ||
493 | * - Titanium PowerBook 500 (PMU based, 300Mhz & 500Mhz) | ||
494 | * - iBook2 500/600 (PMU based, 400Mhz & 500/600Mhz) | ||
495 | * - iBook2 700 (CPU based, 400Mhz & 700Mhz, support low voltage) | ||
496 | * - Recent MacRISC3 laptops | ||
497 | * - All new machines with 7447A CPUs | ||
498 | */ | ||
499 | static int __init pmac_cpufreq_setup(void) | ||
500 | { | ||
501 | struct device_node *cpunode; | ||
502 | u32 *value; | ||
503 | |||
504 | if (strstr(cmd_line, "nocpufreq")) | ||
505 | return 0; | ||
506 | |||
507 | /* Assume only one CPU */ | ||
508 | cpunode = find_type_devices("cpu"); | ||
509 | if (!cpunode) | ||
510 | goto out; | ||
511 | |||
512 | /* Get current cpu clock freq */ | ||
513 | value = (u32 *)get_property(cpunode, "clock-frequency", NULL); | ||
514 | if (!value) | ||
515 | goto out; | ||
516 | cur_freq = (*value) / 1000; | ||
517 | |||
518 | /* Check for 7447A based MacRISC3 */ | ||
519 | if (machine_is_compatible("MacRISC3") && | ||
520 | get_property(cpunode, "dynamic-power-step", NULL) && | ||
521 | PVR_VER(mfspr(SPRN_PVR)) == 0x8003) { | ||
522 | pmac_cpufreq_init_7447A(cpunode); | ||
523 | /* Check for other MacRISC3 machines */ | ||
524 | } else if (machine_is_compatible("PowerBook3,4") || | ||
525 | machine_is_compatible("PowerBook3,5") || | ||
526 | machine_is_compatible("MacRISC3")) { | ||
527 | pmac_cpufreq_init_MacRISC3(cpunode); | ||
528 | /* Else check for iBook2 500/600 */ | ||
529 | } else if (machine_is_compatible("PowerBook4,1")) { | ||
530 | hi_freq = cur_freq; | ||
531 | low_freq = 400000; | ||
532 | set_speed_proc = pmu_set_cpu_speed; | ||
533 | } | ||
534 | /* Else check for TiPb 400 & 500 */ | ||
535 | else if (machine_is_compatible("PowerBook3,2")) { | ||
536 | /* We only know about the 400 MHz and the 500Mhz model | ||
537 | * they both have 300 MHz as low frequency | ||
538 | */ | ||
539 | if (cur_freq < 350000 || cur_freq > 550000) | ||
540 | goto out; | ||
541 | hi_freq = cur_freq; | ||
542 | low_freq = 300000; | ||
543 | set_speed_proc = pmu_set_cpu_speed; | ||
544 | } | ||
545 | /* Else check for 750FX */ | ||
546 | else if (PVR_VER(mfspr(SPRN_PVR)) == 0x7000) { | ||
547 | if (get_property(cpunode, "dynamic-power-step", NULL) == NULL) | ||
548 | goto out; | ||
549 | hi_freq = cur_freq; | ||
550 | value = (u32 *)get_property(cpunode, "reduced-clock-frequency", NULL); | ||
551 | if (!value) | ||
552 | goto out; | ||
553 | low_freq = (*value) / 1000; | ||
554 | set_speed_proc = cpu_750fx_cpu_speed; | ||
555 | } | ||
556 | out: | ||
557 | if (set_speed_proc == NULL) | ||
558 | return -ENODEV; | ||
559 | |||
560 | pmac_cpu_freqs[CPUFREQ_LOW].frequency = low_freq; | ||
561 | pmac_cpu_freqs[CPUFREQ_HIGH].frequency = hi_freq; | ||
562 | |||
563 | printk(KERN_INFO "Registering PowerMac CPU frequency driver\n"); | ||
564 | printk(KERN_INFO "Low: %d Mhz, High: %d Mhz, Boot: %d Mhz\n", | ||
565 | low_freq/1000, hi_freq/1000, cur_freq/1000); | ||
566 | |||
567 | return cpufreq_register_driver(&pmac_cpufreq_driver); | ||
568 | } | ||
569 | |||
570 | module_init(pmac_cpufreq_setup); | ||
571 | |||
diff --git a/arch/ppc/platforms/pmac_feature.c b/arch/ppc/platforms/pmac_feature.c new file mode 100644 index 000000000000..8e60550863a6 --- /dev/null +++ b/arch/ppc/platforms/pmac_feature.c | |||
@@ -0,0 +1,2972 @@ | |||
1 | /* | ||
2 | * arch/ppc/platforms/pmac_feature.c | ||
3 | * | ||
4 | * Copyright (C) 1996-2001 Paul Mackerras (paulus@cs.anu.edu.au) | ||
5 | * Ben. Herrenschmidt (benh@kernel.crashing.org) | ||
6 | * | ||
7 | * This program is free software; you can redistribute it and/or | ||
8 | * modify it under the terms of the GNU General Public License | ||
9 | * as published by the Free Software Foundation; either version | ||
10 | * 2 of the License, or (at your option) any later version. | ||
11 | * | ||
12 | * TODO: | ||
13 | * | ||
14 | * - Replace mdelay with some schedule loop if possible | ||
15 | * - Shorten some obfuscated delays on some routines (like modem | ||
16 | * power) | ||
17 | * - Refcount some clocks (see darwin) | ||
18 | * - Split split split... | ||
19 | * | ||
20 | */ | ||
21 | #include <linux/config.h> | ||
22 | #include <linux/types.h> | ||
23 | #include <linux/init.h> | ||
24 | #include <linux/delay.h> | ||
25 | #include <linux/kernel.h> | ||
26 | #include <linux/sched.h> | ||
27 | #include <linux/spinlock.h> | ||
28 | #include <linux/adb.h> | ||
29 | #include <linux/pmu.h> | ||
30 | #include <linux/ioport.h> | ||
31 | #include <linux/pci.h> | ||
32 | #include <asm/sections.h> | ||
33 | #include <asm/errno.h> | ||
34 | #include <asm/ohare.h> | ||
35 | #include <asm/heathrow.h> | ||
36 | #include <asm/keylargo.h> | ||
37 | #include <asm/uninorth.h> | ||
38 | #include <asm/io.h> | ||
39 | #include <asm/prom.h> | ||
40 | #include <asm/machdep.h> | ||
41 | #include <asm/pmac_feature.h> | ||
42 | #include <asm/dbdma.h> | ||
43 | #include <asm/pci-bridge.h> | ||
44 | #include <asm/pmac_low_i2c.h> | ||
45 | |||
46 | #undef DEBUG_FEATURE | ||
47 | |||
48 | #ifdef DEBUG_FEATURE | ||
49 | #define DBG(fmt,...) printk(KERN_DEBUG fmt) | ||
50 | #else | ||
51 | #define DBG(fmt,...) | ||
52 | #endif | ||
53 | |||
54 | #ifdef CONFIG_6xx | ||
55 | extern int powersave_lowspeed; | ||
56 | #endif | ||
57 | |||
58 | extern int powersave_nap; | ||
59 | extern struct device_node *k2_skiplist[2]; | ||
60 | |||
61 | |||
62 | /* | ||
63 | * We use a single global lock to protect accesses. Each driver has | ||
64 | * to take care of its own locking | ||
65 | */ | ||
66 | static DEFINE_SPINLOCK(feature_lock __pmacdata); | ||
67 | |||
68 | #define LOCK(flags) spin_lock_irqsave(&feature_lock, flags); | ||
69 | #define UNLOCK(flags) spin_unlock_irqrestore(&feature_lock, flags); | ||
70 | |||
71 | |||
72 | /* | ||
73 | * Instance of some macio stuffs | ||
74 | */ | ||
75 | struct macio_chip macio_chips[MAX_MACIO_CHIPS] __pmacdata; | ||
76 | |||
77 | struct macio_chip* __pmac | ||
78 | macio_find(struct device_node* child, int type) | ||
79 | { | ||
80 | while(child) { | ||
81 | int i; | ||
82 | |||
83 | for (i=0; i < MAX_MACIO_CHIPS && macio_chips[i].of_node; i++) | ||
84 | if (child == macio_chips[i].of_node && | ||
85 | (!type || macio_chips[i].type == type)) | ||
86 | return &macio_chips[i]; | ||
87 | child = child->parent; | ||
88 | } | ||
89 | return NULL; | ||
90 | } | ||
91 | |||
92 | static const char* macio_names[] __pmacdata = | ||
93 | { | ||
94 | "Unknown", | ||
95 | "Grand Central", | ||
96 | "OHare", | ||
97 | "OHareII", | ||
98 | "Heathrow", | ||
99 | "Gatwick", | ||
100 | "Paddington", | ||
101 | "Keylargo", | ||
102 | "Pangea", | ||
103 | "Intrepid", | ||
104 | "K2" | ||
105 | }; | ||
106 | |||
107 | |||
108 | |||
109 | /* | ||
110 | * Uninorth reg. access. Note that Uni-N regs are big endian | ||
111 | */ | ||
112 | |||
113 | #define UN_REG(r) (uninorth_base + ((r) >> 2)) | ||
114 | #define UN_IN(r) (in_be32(UN_REG(r))) | ||
115 | #define UN_OUT(r,v) (out_be32(UN_REG(r), (v))) | ||
116 | #define UN_BIS(r,v) (UN_OUT((r), UN_IN(r) | (v))) | ||
117 | #define UN_BIC(r,v) (UN_OUT((r), UN_IN(r) & ~(v))) | ||
118 | |||
119 | static struct device_node* uninorth_node __pmacdata; | ||
120 | static u32 __iomem * uninorth_base __pmacdata; | ||
121 | static u32 uninorth_rev __pmacdata; | ||
122 | static int uninorth_u3 __pmacdata; | ||
123 | static void __iomem *u3_ht; | ||
124 | |||
125 | /* | ||
126 | * For each motherboard family, we have a table of functions pointers | ||
127 | * that handle the various features. | ||
128 | */ | ||
129 | |||
130 | typedef long (*feature_call)(struct device_node* node, long param, long value); | ||
131 | |||
132 | struct feature_table_entry { | ||
133 | unsigned int selector; | ||
134 | feature_call function; | ||
135 | }; | ||
136 | |||
137 | struct pmac_mb_def | ||
138 | { | ||
139 | const char* model_string; | ||
140 | const char* model_name; | ||
141 | int model_id; | ||
142 | struct feature_table_entry* features; | ||
143 | unsigned long board_flags; | ||
144 | }; | ||
145 | static struct pmac_mb_def pmac_mb __pmacdata; | ||
146 | |||
147 | /* | ||
148 | * Here are the chip specific feature functions | ||
149 | */ | ||
150 | |||
151 | static inline int __pmac | ||
152 | simple_feature_tweak(struct device_node* node, int type, int reg, u32 mask, int value) | ||
153 | { | ||
154 | struct macio_chip* macio; | ||
155 | unsigned long flags; | ||
156 | |||
157 | macio = macio_find(node, type); | ||
158 | if (!macio) | ||
159 | return -ENODEV; | ||
160 | LOCK(flags); | ||
161 | if (value) | ||
162 | MACIO_BIS(reg, mask); | ||
163 | else | ||
164 | MACIO_BIC(reg, mask); | ||
165 | (void)MACIO_IN32(reg); | ||
166 | UNLOCK(flags); | ||
167 | |||
168 | return 0; | ||
169 | } | ||
170 | |||
171 | #ifndef CONFIG_POWER4 | ||
172 | |||
173 | static long __pmac | ||
174 | ohare_htw_scc_enable(struct device_node* node, long param, long value) | ||
175 | { | ||
176 | struct macio_chip* macio; | ||
177 | unsigned long chan_mask; | ||
178 | unsigned long fcr; | ||
179 | unsigned long flags; | ||
180 | int htw, trans; | ||
181 | unsigned long rmask; | ||
182 | |||
183 | macio = macio_find(node, 0); | ||
184 | if (!macio) | ||
185 | return -ENODEV; | ||
186 | if (!strcmp(node->name, "ch-a")) | ||
187 | chan_mask = MACIO_FLAG_SCCA_ON; | ||
188 | else if (!strcmp(node->name, "ch-b")) | ||
189 | chan_mask = MACIO_FLAG_SCCB_ON; | ||
190 | else | ||
191 | return -ENODEV; | ||
192 | |||
193 | htw = (macio->type == macio_heathrow || macio->type == macio_paddington | ||
194 | || macio->type == macio_gatwick); | ||
195 | /* On these machines, the HRW_SCC_TRANS_EN_N bit mustn't be touched */ | ||
196 | trans = (pmac_mb.model_id != PMAC_TYPE_YOSEMITE && | ||
197 | pmac_mb.model_id != PMAC_TYPE_YIKES); | ||
198 | if (value) { | ||
199 | #ifdef CONFIG_ADB_PMU | ||
200 | if ((param & 0xfff) == PMAC_SCC_IRDA) | ||
201 | pmu_enable_irled(1); | ||
202 | #endif /* CONFIG_ADB_PMU */ | ||
203 | LOCK(flags); | ||
204 | fcr = MACIO_IN32(OHARE_FCR); | ||
205 | /* Check if scc cell need enabling */ | ||
206 | if (!(fcr & OH_SCC_ENABLE)) { | ||
207 | fcr |= OH_SCC_ENABLE; | ||
208 | if (htw) { | ||
209 | /* Side effect: this will also power up the | ||
210 | * modem, but it's too messy to figure out on which | ||
211 | * ports this controls the tranceiver and on which | ||
212 | * it controls the modem | ||
213 | */ | ||
214 | if (trans) | ||
215 | fcr &= ~HRW_SCC_TRANS_EN_N; | ||
216 | MACIO_OUT32(OHARE_FCR, fcr); | ||
217 | fcr |= (rmask = HRW_RESET_SCC); | ||
218 | MACIO_OUT32(OHARE_FCR, fcr); | ||
219 | } else { | ||
220 | fcr |= (rmask = OH_SCC_RESET); | ||
221 | MACIO_OUT32(OHARE_FCR, fcr); | ||
222 | } | ||
223 | UNLOCK(flags); | ||
224 | (void)MACIO_IN32(OHARE_FCR); | ||
225 | mdelay(15); | ||
226 | LOCK(flags); | ||
227 | fcr &= ~rmask; | ||
228 | MACIO_OUT32(OHARE_FCR, fcr); | ||
229 | } | ||
230 | if (chan_mask & MACIO_FLAG_SCCA_ON) | ||
231 | fcr |= OH_SCCA_IO; | ||
232 | if (chan_mask & MACIO_FLAG_SCCB_ON) | ||
233 | fcr |= OH_SCCB_IO; | ||
234 | MACIO_OUT32(OHARE_FCR, fcr); | ||
235 | macio->flags |= chan_mask; | ||
236 | UNLOCK(flags); | ||
237 | if (param & PMAC_SCC_FLAG_XMON) | ||
238 | macio->flags |= MACIO_FLAG_SCC_LOCKED; | ||
239 | } else { | ||
240 | if (macio->flags & MACIO_FLAG_SCC_LOCKED) | ||
241 | return -EPERM; | ||
242 | LOCK(flags); | ||
243 | fcr = MACIO_IN32(OHARE_FCR); | ||
244 | if (chan_mask & MACIO_FLAG_SCCA_ON) | ||
245 | fcr &= ~OH_SCCA_IO; | ||
246 | if (chan_mask & MACIO_FLAG_SCCB_ON) | ||
247 | fcr &= ~OH_SCCB_IO; | ||
248 | MACIO_OUT32(OHARE_FCR, fcr); | ||
249 | if ((fcr & (OH_SCCA_IO | OH_SCCB_IO)) == 0) { | ||
250 | fcr &= ~OH_SCC_ENABLE; | ||
251 | if (htw && trans) | ||
252 | fcr |= HRW_SCC_TRANS_EN_N; | ||
253 | MACIO_OUT32(OHARE_FCR, fcr); | ||
254 | } | ||
255 | macio->flags &= ~(chan_mask); | ||
256 | UNLOCK(flags); | ||
257 | mdelay(10); | ||
258 | #ifdef CONFIG_ADB_PMU | ||
259 | if ((param & 0xfff) == PMAC_SCC_IRDA) | ||
260 | pmu_enable_irled(0); | ||
261 | #endif /* CONFIG_ADB_PMU */ | ||
262 | } | ||
263 | return 0; | ||
264 | } | ||
265 | |||
266 | static long __pmac | ||
267 | ohare_floppy_enable(struct device_node* node, long param, long value) | ||
268 | { | ||
269 | return simple_feature_tweak(node, macio_ohare, | ||
270 | OHARE_FCR, OH_FLOPPY_ENABLE, value); | ||
271 | } | ||
272 | |||
273 | static long __pmac | ||
274 | ohare_mesh_enable(struct device_node* node, long param, long value) | ||
275 | { | ||
276 | return simple_feature_tweak(node, macio_ohare, | ||
277 | OHARE_FCR, OH_MESH_ENABLE, value); | ||
278 | } | ||
279 | |||
280 | static long __pmac | ||
281 | ohare_ide_enable(struct device_node* node, long param, long value) | ||
282 | { | ||
283 | switch(param) { | ||
284 | case 0: | ||
285 | /* For some reason, setting the bit in set_initial_features() | ||
286 | * doesn't stick. I'm still investigating... --BenH. | ||
287 | */ | ||
288 | if (value) | ||
289 | simple_feature_tweak(node, macio_ohare, | ||
290 | OHARE_FCR, OH_IOBUS_ENABLE, 1); | ||
291 | return simple_feature_tweak(node, macio_ohare, | ||
292 | OHARE_FCR, OH_IDE0_ENABLE, value); | ||
293 | case 1: | ||
294 | return simple_feature_tweak(node, macio_ohare, | ||
295 | OHARE_FCR, OH_BAY_IDE_ENABLE, value); | ||
296 | default: | ||
297 | return -ENODEV; | ||
298 | } | ||
299 | } | ||
300 | |||
301 | static long __pmac | ||
302 | ohare_ide_reset(struct device_node* node, long param, long value) | ||
303 | { | ||
304 | switch(param) { | ||
305 | case 0: | ||
306 | return simple_feature_tweak(node, macio_ohare, | ||
307 | OHARE_FCR, OH_IDE0_RESET_N, !value); | ||
308 | case 1: | ||
309 | return simple_feature_tweak(node, macio_ohare, | ||
310 | OHARE_FCR, OH_IDE1_RESET_N, !value); | ||
311 | default: | ||
312 | return -ENODEV; | ||
313 | } | ||
314 | } | ||
315 | |||
316 | static long __pmac | ||
317 | ohare_sleep_state(struct device_node* node, long param, long value) | ||
318 | { | ||
319 | struct macio_chip* macio = &macio_chips[0]; | ||
320 | |||
321 | if ((pmac_mb.board_flags & PMAC_MB_CAN_SLEEP) == 0) | ||
322 | return -EPERM; | ||
323 | if (value == 1) { | ||
324 | MACIO_BIC(OHARE_FCR, OH_IOBUS_ENABLE); | ||
325 | } else if (value == 0) { | ||
326 | MACIO_BIS(OHARE_FCR, OH_IOBUS_ENABLE); | ||
327 | } | ||
328 | |||
329 | return 0; | ||
330 | } | ||
331 | |||
332 | static long __pmac | ||
333 | heathrow_modem_enable(struct device_node* node, long param, long value) | ||
334 | { | ||
335 | struct macio_chip* macio; | ||
336 | u8 gpio; | ||
337 | unsigned long flags; | ||
338 | |||
339 | macio = macio_find(node, macio_unknown); | ||
340 | if (!macio) | ||
341 | return -ENODEV; | ||
342 | gpio = MACIO_IN8(HRW_GPIO_MODEM_RESET) & ~1; | ||
343 | if (!value) { | ||
344 | LOCK(flags); | ||
345 | MACIO_OUT8(HRW_GPIO_MODEM_RESET, gpio); | ||
346 | UNLOCK(flags); | ||
347 | (void)MACIO_IN8(HRW_GPIO_MODEM_RESET); | ||
348 | mdelay(250); | ||
349 | } | ||
350 | if (pmac_mb.model_id != PMAC_TYPE_YOSEMITE && | ||
351 | pmac_mb.model_id != PMAC_TYPE_YIKES) { | ||
352 | LOCK(flags); | ||
353 | if (value) | ||
354 | MACIO_BIC(HEATHROW_FCR, HRW_SCC_TRANS_EN_N); | ||
355 | else | ||
356 | MACIO_BIS(HEATHROW_FCR, HRW_SCC_TRANS_EN_N); | ||
357 | UNLOCK(flags); | ||
358 | (void)MACIO_IN32(HEATHROW_FCR); | ||
359 | mdelay(250); | ||
360 | } | ||
361 | if (value) { | ||
362 | LOCK(flags); | ||
363 | MACIO_OUT8(HRW_GPIO_MODEM_RESET, gpio | 1); | ||
364 | (void)MACIO_IN8(HRW_GPIO_MODEM_RESET); | ||
365 | UNLOCK(flags); mdelay(250); LOCK(flags); | ||
366 | MACIO_OUT8(HRW_GPIO_MODEM_RESET, gpio); | ||
367 | (void)MACIO_IN8(HRW_GPIO_MODEM_RESET); | ||
368 | UNLOCK(flags); mdelay(250); LOCK(flags); | ||
369 | MACIO_OUT8(HRW_GPIO_MODEM_RESET, gpio | 1); | ||
370 | (void)MACIO_IN8(HRW_GPIO_MODEM_RESET); | ||
371 | UNLOCK(flags); mdelay(250); | ||
372 | } | ||
373 | return 0; | ||
374 | } | ||
375 | |||
376 | static long __pmac | ||
377 | heathrow_floppy_enable(struct device_node* node, long param, long value) | ||
378 | { | ||
379 | return simple_feature_tweak(node, macio_unknown, | ||
380 | HEATHROW_FCR, | ||
381 | HRW_SWIM_ENABLE|HRW_BAY_FLOPPY_ENABLE, | ||
382 | value); | ||
383 | } | ||
384 | |||
385 | static long __pmac | ||
386 | heathrow_mesh_enable(struct device_node* node, long param, long value) | ||
387 | { | ||
388 | struct macio_chip* macio; | ||
389 | unsigned long flags; | ||
390 | |||
391 | macio = macio_find(node, macio_unknown); | ||
392 | if (!macio) | ||
393 | return -ENODEV; | ||
394 | LOCK(flags); | ||
395 | /* Set clear mesh cell enable */ | ||
396 | if (value) | ||
397 | MACIO_BIS(HEATHROW_FCR, HRW_MESH_ENABLE); | ||
398 | else | ||
399 | MACIO_BIC(HEATHROW_FCR, HRW_MESH_ENABLE); | ||
400 | (void)MACIO_IN32(HEATHROW_FCR); | ||
401 | udelay(10); | ||
402 | /* Set/Clear termination power */ | ||
403 | if (value) | ||
404 | MACIO_BIC(HEATHROW_MBCR, 0x04000000); | ||
405 | else | ||
406 | MACIO_BIS(HEATHROW_MBCR, 0x04000000); | ||
407 | (void)MACIO_IN32(HEATHROW_MBCR); | ||
408 | udelay(10); | ||
409 | UNLOCK(flags); | ||
410 | |||
411 | return 0; | ||
412 | } | ||
413 | |||
414 | static long __pmac | ||
415 | heathrow_ide_enable(struct device_node* node, long param, long value) | ||
416 | { | ||
417 | switch(param) { | ||
418 | case 0: | ||
419 | return simple_feature_tweak(node, macio_unknown, | ||
420 | HEATHROW_FCR, HRW_IDE0_ENABLE, value); | ||
421 | case 1: | ||
422 | return simple_feature_tweak(node, macio_unknown, | ||
423 | HEATHROW_FCR, HRW_BAY_IDE_ENABLE, value); | ||
424 | default: | ||
425 | return -ENODEV; | ||
426 | } | ||
427 | } | ||
428 | |||
429 | static long __pmac | ||
430 | heathrow_ide_reset(struct device_node* node, long param, long value) | ||
431 | { | ||
432 | switch(param) { | ||
433 | case 0: | ||
434 | return simple_feature_tweak(node, macio_unknown, | ||
435 | HEATHROW_FCR, HRW_IDE0_RESET_N, !value); | ||
436 | case 1: | ||
437 | return simple_feature_tweak(node, macio_unknown, | ||
438 | HEATHROW_FCR, HRW_IDE1_RESET_N, !value); | ||
439 | default: | ||
440 | return -ENODEV; | ||
441 | } | ||
442 | } | ||
443 | |||
444 | static long __pmac | ||
445 | heathrow_bmac_enable(struct device_node* node, long param, long value) | ||
446 | { | ||
447 | struct macio_chip* macio; | ||
448 | unsigned long flags; | ||
449 | |||
450 | macio = macio_find(node, 0); | ||
451 | if (!macio) | ||
452 | return -ENODEV; | ||
453 | if (value) { | ||
454 | LOCK(flags); | ||
455 | MACIO_BIS(HEATHROW_FCR, HRW_BMAC_IO_ENABLE); | ||
456 | MACIO_BIS(HEATHROW_FCR, HRW_BMAC_RESET); | ||
457 | UNLOCK(flags); | ||
458 | (void)MACIO_IN32(HEATHROW_FCR); | ||
459 | mdelay(10); | ||
460 | LOCK(flags); | ||
461 | MACIO_BIC(HEATHROW_FCR, HRW_BMAC_RESET); | ||
462 | UNLOCK(flags); | ||
463 | (void)MACIO_IN32(HEATHROW_FCR); | ||
464 | mdelay(10); | ||
465 | } else { | ||
466 | LOCK(flags); | ||
467 | MACIO_BIC(HEATHROW_FCR, HRW_BMAC_IO_ENABLE); | ||
468 | UNLOCK(flags); | ||
469 | } | ||
470 | return 0; | ||
471 | } | ||
472 | |||
473 | static long __pmac | ||
474 | heathrow_sound_enable(struct device_node* node, long param, long value) | ||
475 | { | ||
476 | struct macio_chip* macio; | ||
477 | unsigned long flags; | ||
478 | |||
479 | /* B&W G3 and Yikes don't support that properly (the | ||
480 | * sound appear to never come back after beeing shut down). | ||
481 | */ | ||
482 | if (pmac_mb.model_id == PMAC_TYPE_YOSEMITE || | ||
483 | pmac_mb.model_id == PMAC_TYPE_YIKES) | ||
484 | return 0; | ||
485 | |||
486 | macio = macio_find(node, 0); | ||
487 | if (!macio) | ||
488 | return -ENODEV; | ||
489 | if (value) { | ||
490 | LOCK(flags); | ||
491 | MACIO_BIS(HEATHROW_FCR, HRW_SOUND_CLK_ENABLE); | ||
492 | MACIO_BIC(HEATHROW_FCR, HRW_SOUND_POWER_N); | ||
493 | UNLOCK(flags); | ||
494 | (void)MACIO_IN32(HEATHROW_FCR); | ||
495 | } else { | ||
496 | LOCK(flags); | ||
497 | MACIO_BIS(HEATHROW_FCR, HRW_SOUND_POWER_N); | ||
498 | MACIO_BIC(HEATHROW_FCR, HRW_SOUND_CLK_ENABLE); | ||
499 | UNLOCK(flags); | ||
500 | } | ||
501 | return 0; | ||
502 | } | ||
503 | |||
504 | static u32 save_fcr[6] __pmacdata; | ||
505 | static u32 save_mbcr __pmacdata; | ||
506 | static u32 save_gpio_levels[2] __pmacdata; | ||
507 | static u8 save_gpio_extint[KEYLARGO_GPIO_EXTINT_CNT] __pmacdata; | ||
508 | static u8 save_gpio_normal[KEYLARGO_GPIO_CNT] __pmacdata; | ||
509 | static u32 save_unin_clock_ctl __pmacdata; | ||
510 | static struct dbdma_regs save_dbdma[13] __pmacdata; | ||
511 | static struct dbdma_regs save_alt_dbdma[13] __pmacdata; | ||
512 | |||
513 | static void __pmac | ||
514 | dbdma_save(struct macio_chip* macio, struct dbdma_regs* save) | ||
515 | { | ||
516 | int i; | ||
517 | |||
518 | /* Save state & config of DBDMA channels */ | ||
519 | for (i=0; i<13; i++) { | ||
520 | volatile struct dbdma_regs __iomem * chan = (void __iomem *) | ||
521 | (macio->base + ((0x8000+i*0x100)>>2)); | ||
522 | save[i].cmdptr_hi = in_le32(&chan->cmdptr_hi); | ||
523 | save[i].cmdptr = in_le32(&chan->cmdptr); | ||
524 | save[i].intr_sel = in_le32(&chan->intr_sel); | ||
525 | save[i].br_sel = in_le32(&chan->br_sel); | ||
526 | save[i].wait_sel = in_le32(&chan->wait_sel); | ||
527 | } | ||
528 | } | ||
529 | |||
530 | static void __pmac | ||
531 | dbdma_restore(struct macio_chip* macio, struct dbdma_regs* save) | ||
532 | { | ||
533 | int i; | ||
534 | |||
535 | /* Save state & config of DBDMA channels */ | ||
536 | for (i=0; i<13; i++) { | ||
537 | volatile struct dbdma_regs __iomem * chan = (void __iomem *) | ||
538 | (macio->base + ((0x8000+i*0x100)>>2)); | ||
539 | out_le32(&chan->control, (ACTIVE|DEAD|WAKE|FLUSH|PAUSE|RUN)<<16); | ||
540 | while (in_le32(&chan->status) & ACTIVE) | ||
541 | mb(); | ||
542 | out_le32(&chan->cmdptr_hi, save[i].cmdptr_hi); | ||
543 | out_le32(&chan->cmdptr, save[i].cmdptr); | ||
544 | out_le32(&chan->intr_sel, save[i].intr_sel); | ||
545 | out_le32(&chan->br_sel, save[i].br_sel); | ||
546 | out_le32(&chan->wait_sel, save[i].wait_sel); | ||
547 | } | ||
548 | } | ||
549 | |||
550 | static void __pmac | ||
551 | heathrow_sleep(struct macio_chip* macio, int secondary) | ||
552 | { | ||
553 | if (secondary) { | ||
554 | dbdma_save(macio, save_alt_dbdma); | ||
555 | save_fcr[2] = MACIO_IN32(0x38); | ||
556 | save_fcr[3] = MACIO_IN32(0x3c); | ||
557 | } else { | ||
558 | dbdma_save(macio, save_dbdma); | ||
559 | save_fcr[0] = MACIO_IN32(0x38); | ||
560 | save_fcr[1] = MACIO_IN32(0x3c); | ||
561 | save_mbcr = MACIO_IN32(0x34); | ||
562 | /* Make sure sound is shut down */ | ||
563 | MACIO_BIS(HEATHROW_FCR, HRW_SOUND_POWER_N); | ||
564 | MACIO_BIC(HEATHROW_FCR, HRW_SOUND_CLK_ENABLE); | ||
565 | /* This seems to be necessary as well or the fan | ||
566 | * keeps coming up and battery drains fast */ | ||
567 | MACIO_BIC(HEATHROW_FCR, HRW_IOBUS_ENABLE); | ||
568 | MACIO_BIC(HEATHROW_FCR, HRW_IDE0_RESET_N); | ||
569 | /* Make sure eth is down even if module or sleep | ||
570 | * won't work properly */ | ||
571 | MACIO_BIC(HEATHROW_FCR, HRW_BMAC_IO_ENABLE | HRW_BMAC_RESET); | ||
572 | } | ||
573 | /* Make sure modem is shut down */ | ||
574 | MACIO_OUT8(HRW_GPIO_MODEM_RESET, | ||
575 | MACIO_IN8(HRW_GPIO_MODEM_RESET) & ~1); | ||
576 | MACIO_BIS(HEATHROW_FCR, HRW_SCC_TRANS_EN_N); | ||
577 | MACIO_BIC(HEATHROW_FCR, OH_SCCA_IO|OH_SCCB_IO|HRW_SCC_ENABLE); | ||
578 | |||
579 | /* Let things settle */ | ||
580 | (void)MACIO_IN32(HEATHROW_FCR); | ||
581 | } | ||
582 | |||
583 | static void __pmac | ||
584 | heathrow_wakeup(struct macio_chip* macio, int secondary) | ||
585 | { | ||
586 | if (secondary) { | ||
587 | MACIO_OUT32(0x38, save_fcr[2]); | ||
588 | (void)MACIO_IN32(0x38); | ||
589 | mdelay(1); | ||
590 | MACIO_OUT32(0x3c, save_fcr[3]); | ||
591 | (void)MACIO_IN32(0x38); | ||
592 | mdelay(10); | ||
593 | dbdma_restore(macio, save_alt_dbdma); | ||
594 | } else { | ||
595 | MACIO_OUT32(0x38, save_fcr[0] | HRW_IOBUS_ENABLE); | ||
596 | (void)MACIO_IN32(0x38); | ||
597 | mdelay(1); | ||
598 | MACIO_OUT32(0x3c, save_fcr[1]); | ||
599 | (void)MACIO_IN32(0x38); | ||
600 | mdelay(1); | ||
601 | MACIO_OUT32(0x34, save_mbcr); | ||
602 | (void)MACIO_IN32(0x38); | ||
603 | mdelay(10); | ||
604 | dbdma_restore(macio, save_dbdma); | ||
605 | } | ||
606 | } | ||
607 | |||
608 | static long __pmac | ||
609 | heathrow_sleep_state(struct device_node* node, long param, long value) | ||
610 | { | ||
611 | if ((pmac_mb.board_flags & PMAC_MB_CAN_SLEEP) == 0) | ||
612 | return -EPERM; | ||
613 | if (value == 1) { | ||
614 | if (macio_chips[1].type == macio_gatwick) | ||
615 | heathrow_sleep(&macio_chips[0], 1); | ||
616 | heathrow_sleep(&macio_chips[0], 0); | ||
617 | } else if (value == 0) { | ||
618 | heathrow_wakeup(&macio_chips[0], 0); | ||
619 | if (macio_chips[1].type == macio_gatwick) | ||
620 | heathrow_wakeup(&macio_chips[0], 1); | ||
621 | } | ||
622 | return 0; | ||
623 | } | ||
624 | |||
625 | static long __pmac | ||
626 | core99_scc_enable(struct device_node* node, long param, long value) | ||
627 | { | ||
628 | struct macio_chip* macio; | ||
629 | unsigned long flags; | ||
630 | unsigned long chan_mask; | ||
631 | u32 fcr; | ||
632 | |||
633 | macio = macio_find(node, 0); | ||
634 | if (!macio) | ||
635 | return -ENODEV; | ||
636 | if (!strcmp(node->name, "ch-a")) | ||
637 | chan_mask = MACIO_FLAG_SCCA_ON; | ||
638 | else if (!strcmp(node->name, "ch-b")) | ||
639 | chan_mask = MACIO_FLAG_SCCB_ON; | ||
640 | else | ||
641 | return -ENODEV; | ||
642 | |||
643 | if (value) { | ||
644 | int need_reset_scc = 0; | ||
645 | int need_reset_irda = 0; | ||
646 | |||
647 | LOCK(flags); | ||
648 | fcr = MACIO_IN32(KEYLARGO_FCR0); | ||
649 | /* Check if scc cell need enabling */ | ||
650 | if (!(fcr & KL0_SCC_CELL_ENABLE)) { | ||
651 | fcr |= KL0_SCC_CELL_ENABLE; | ||
652 | need_reset_scc = 1; | ||
653 | } | ||
654 | if (chan_mask & MACIO_FLAG_SCCA_ON) { | ||
655 | fcr |= KL0_SCCA_ENABLE; | ||
656 | /* Don't enable line drivers for I2S modem */ | ||
657 | if ((param & 0xfff) == PMAC_SCC_I2S1) | ||
658 | fcr &= ~KL0_SCC_A_INTF_ENABLE; | ||
659 | else | ||
660 | fcr |= KL0_SCC_A_INTF_ENABLE; | ||
661 | } | ||
662 | if (chan_mask & MACIO_FLAG_SCCB_ON) { | ||
663 | fcr |= KL0_SCCB_ENABLE; | ||
664 | /* Perform irda specific inits */ | ||
665 | if ((param & 0xfff) == PMAC_SCC_IRDA) { | ||
666 | fcr &= ~KL0_SCC_B_INTF_ENABLE; | ||
667 | fcr |= KL0_IRDA_ENABLE; | ||
668 | fcr |= KL0_IRDA_CLK32_ENABLE | KL0_IRDA_CLK19_ENABLE; | ||
669 | fcr |= KL0_IRDA_SOURCE1_SEL; | ||
670 | fcr &= ~(KL0_IRDA_FAST_CONNECT|KL0_IRDA_DEFAULT1|KL0_IRDA_DEFAULT0); | ||
671 | fcr &= ~(KL0_IRDA_SOURCE2_SEL|KL0_IRDA_HIGH_BAND); | ||
672 | need_reset_irda = 1; | ||
673 | } else | ||
674 | fcr |= KL0_SCC_B_INTF_ENABLE; | ||
675 | } | ||
676 | MACIO_OUT32(KEYLARGO_FCR0, fcr); | ||
677 | macio->flags |= chan_mask; | ||
678 | if (need_reset_scc) { | ||
679 | MACIO_BIS(KEYLARGO_FCR0, KL0_SCC_RESET); | ||
680 | (void)MACIO_IN32(KEYLARGO_FCR0); | ||
681 | UNLOCK(flags); | ||
682 | mdelay(15); | ||
683 | LOCK(flags); | ||
684 | MACIO_BIC(KEYLARGO_FCR0, KL0_SCC_RESET); | ||
685 | } | ||
686 | if (need_reset_irda) { | ||
687 | MACIO_BIS(KEYLARGO_FCR0, KL0_IRDA_RESET); | ||
688 | (void)MACIO_IN32(KEYLARGO_FCR0); | ||
689 | UNLOCK(flags); | ||
690 | mdelay(15); | ||
691 | LOCK(flags); | ||
692 | MACIO_BIC(KEYLARGO_FCR0, KL0_IRDA_RESET); | ||
693 | } | ||
694 | UNLOCK(flags); | ||
695 | if (param & PMAC_SCC_FLAG_XMON) | ||
696 | macio->flags |= MACIO_FLAG_SCC_LOCKED; | ||
697 | } else { | ||
698 | if (macio->flags & MACIO_FLAG_SCC_LOCKED) | ||
699 | return -EPERM; | ||
700 | LOCK(flags); | ||
701 | fcr = MACIO_IN32(KEYLARGO_FCR0); | ||
702 | if (chan_mask & MACIO_FLAG_SCCA_ON) | ||
703 | fcr &= ~KL0_SCCA_ENABLE; | ||
704 | if (chan_mask & MACIO_FLAG_SCCB_ON) { | ||
705 | fcr &= ~KL0_SCCB_ENABLE; | ||
706 | /* Perform irda specific clears */ | ||
707 | if ((param & 0xfff) == PMAC_SCC_IRDA) { | ||
708 | fcr &= ~KL0_IRDA_ENABLE; | ||
709 | fcr &= ~(KL0_IRDA_CLK32_ENABLE | KL0_IRDA_CLK19_ENABLE); | ||
710 | fcr &= ~(KL0_IRDA_FAST_CONNECT|KL0_IRDA_DEFAULT1|KL0_IRDA_DEFAULT0); | ||
711 | fcr &= ~(KL0_IRDA_SOURCE1_SEL|KL0_IRDA_SOURCE2_SEL|KL0_IRDA_HIGH_BAND); | ||
712 | } | ||
713 | } | ||
714 | MACIO_OUT32(KEYLARGO_FCR0, fcr); | ||
715 | if ((fcr & (KL0_SCCA_ENABLE | KL0_SCCB_ENABLE)) == 0) { | ||
716 | fcr &= ~KL0_SCC_CELL_ENABLE; | ||
717 | MACIO_OUT32(KEYLARGO_FCR0, fcr); | ||
718 | } | ||
719 | macio->flags &= ~(chan_mask); | ||
720 | UNLOCK(flags); | ||
721 | mdelay(10); | ||
722 | } | ||
723 | return 0; | ||
724 | } | ||
725 | |||
726 | static long __pmac | ||
727 | core99_modem_enable(struct device_node* node, long param, long value) | ||
728 | { | ||
729 | struct macio_chip* macio; | ||
730 | u8 gpio; | ||
731 | unsigned long flags; | ||
732 | |||
733 | /* Hack for internal USB modem */ | ||
734 | if (node == NULL) { | ||
735 | if (macio_chips[0].type != macio_keylargo) | ||
736 | return -ENODEV; | ||
737 | node = macio_chips[0].of_node; | ||
738 | } | ||
739 | macio = macio_find(node, 0); | ||
740 | if (!macio) | ||
741 | return -ENODEV; | ||
742 | gpio = MACIO_IN8(KL_GPIO_MODEM_RESET); | ||
743 | gpio |= KEYLARGO_GPIO_OUTPUT_ENABLE; | ||
744 | gpio &= ~KEYLARGO_GPIO_OUTOUT_DATA; | ||
745 | |||
746 | if (!value) { | ||
747 | LOCK(flags); | ||
748 | MACIO_OUT8(KL_GPIO_MODEM_RESET, gpio); | ||
749 | UNLOCK(flags); | ||
750 | (void)MACIO_IN8(KL_GPIO_MODEM_RESET); | ||
751 | mdelay(250); | ||
752 | } | ||
753 | LOCK(flags); | ||
754 | if (value) { | ||
755 | MACIO_BIC(KEYLARGO_FCR2, KL2_ALT_DATA_OUT); | ||
756 | UNLOCK(flags); | ||
757 | (void)MACIO_IN32(KEYLARGO_FCR2); | ||
758 | mdelay(250); | ||
759 | } else { | ||
760 | MACIO_BIS(KEYLARGO_FCR2, KL2_ALT_DATA_OUT); | ||
761 | UNLOCK(flags); | ||
762 | } | ||
763 | if (value) { | ||
764 | LOCK(flags); | ||
765 | MACIO_OUT8(KL_GPIO_MODEM_RESET, gpio | KEYLARGO_GPIO_OUTOUT_DATA); | ||
766 | (void)MACIO_IN8(KL_GPIO_MODEM_RESET); | ||
767 | UNLOCK(flags); mdelay(250); LOCK(flags); | ||
768 | MACIO_OUT8(KL_GPIO_MODEM_RESET, gpio); | ||
769 | (void)MACIO_IN8(KL_GPIO_MODEM_RESET); | ||
770 | UNLOCK(flags); mdelay(250); LOCK(flags); | ||
771 | MACIO_OUT8(KL_GPIO_MODEM_RESET, gpio | KEYLARGO_GPIO_OUTOUT_DATA); | ||
772 | (void)MACIO_IN8(KL_GPIO_MODEM_RESET); | ||
773 | UNLOCK(flags); mdelay(250); | ||
774 | } | ||
775 | return 0; | ||
776 | } | ||
777 | |||
778 | static long __pmac | ||
779 | pangea_modem_enable(struct device_node* node, long param, long value) | ||
780 | { | ||
781 | struct macio_chip* macio; | ||
782 | u8 gpio; | ||
783 | unsigned long flags; | ||
784 | |||
785 | /* Hack for internal USB modem */ | ||
786 | if (node == NULL) { | ||
787 | if (macio_chips[0].type != macio_pangea && | ||
788 | macio_chips[0].type != macio_intrepid) | ||
789 | return -ENODEV; | ||
790 | node = macio_chips[0].of_node; | ||
791 | } | ||
792 | macio = macio_find(node, 0); | ||
793 | if (!macio) | ||
794 | return -ENODEV; | ||
795 | gpio = MACIO_IN8(KL_GPIO_MODEM_RESET); | ||
796 | gpio |= KEYLARGO_GPIO_OUTPUT_ENABLE; | ||
797 | gpio &= ~KEYLARGO_GPIO_OUTOUT_DATA; | ||
798 | |||
799 | if (!value) { | ||
800 | LOCK(flags); | ||
801 | MACIO_OUT8(KL_GPIO_MODEM_RESET, gpio); | ||
802 | UNLOCK(flags); | ||
803 | (void)MACIO_IN8(KL_GPIO_MODEM_RESET); | ||
804 | mdelay(250); | ||
805 | } | ||
806 | LOCK(flags); | ||
807 | if (value) { | ||
808 | MACIO_OUT8(KL_GPIO_MODEM_POWER, | ||
809 | KEYLARGO_GPIO_OUTPUT_ENABLE); | ||
810 | UNLOCK(flags); | ||
811 | (void)MACIO_IN32(KEYLARGO_FCR2); | ||
812 | mdelay(250); | ||
813 | } else { | ||
814 | MACIO_OUT8(KL_GPIO_MODEM_POWER, | ||
815 | KEYLARGO_GPIO_OUTPUT_ENABLE | KEYLARGO_GPIO_OUTOUT_DATA); | ||
816 | UNLOCK(flags); | ||
817 | } | ||
818 | if (value) { | ||
819 | LOCK(flags); | ||
820 | MACIO_OUT8(KL_GPIO_MODEM_RESET, gpio | KEYLARGO_GPIO_OUTOUT_DATA); | ||
821 | (void)MACIO_IN8(KL_GPIO_MODEM_RESET); | ||
822 | UNLOCK(flags); mdelay(250); LOCK(flags); | ||
823 | MACIO_OUT8(KL_GPIO_MODEM_RESET, gpio); | ||
824 | (void)MACIO_IN8(KL_GPIO_MODEM_RESET); | ||
825 | UNLOCK(flags); mdelay(250); LOCK(flags); | ||
826 | MACIO_OUT8(KL_GPIO_MODEM_RESET, gpio | KEYLARGO_GPIO_OUTOUT_DATA); | ||
827 | (void)MACIO_IN8(KL_GPIO_MODEM_RESET); | ||
828 | UNLOCK(flags); mdelay(250); | ||
829 | } | ||
830 | return 0; | ||
831 | } | ||
832 | |||
833 | static long __pmac | ||
834 | core99_ata100_enable(struct device_node* node, long value) | ||
835 | { | ||
836 | unsigned long flags; | ||
837 | struct pci_dev *pdev = NULL; | ||
838 | u8 pbus, pid; | ||
839 | |||
840 | if (uninorth_rev < 0x24) | ||
841 | return -ENODEV; | ||
842 | |||
843 | LOCK(flags); | ||
844 | if (value) | ||
845 | UN_BIS(UNI_N_CLOCK_CNTL, UNI_N_CLOCK_CNTL_ATA100); | ||
846 | else | ||
847 | UN_BIC(UNI_N_CLOCK_CNTL, UNI_N_CLOCK_CNTL_ATA100); | ||
848 | (void)UN_IN(UNI_N_CLOCK_CNTL); | ||
849 | UNLOCK(flags); | ||
850 | udelay(20); | ||
851 | |||
852 | if (value) { | ||
853 | if (pci_device_from_OF_node(node, &pbus, &pid) == 0) | ||
854 | pdev = pci_find_slot(pbus, pid); | ||
855 | if (pdev == NULL) | ||
856 | return 0; | ||
857 | pci_enable_device(pdev); | ||
858 | pci_set_master(pdev); | ||
859 | } | ||
860 | return 0; | ||
861 | } | ||
862 | |||
863 | static long __pmac | ||
864 | core99_ide_enable(struct device_node* node, long param, long value) | ||
865 | { | ||
866 | /* Bus ID 0 to 2 are KeyLargo based IDE, busID 3 is U2 | ||
867 | * based ata-100 | ||
868 | */ | ||
869 | switch(param) { | ||
870 | case 0: | ||
871 | return simple_feature_tweak(node, macio_unknown, | ||
872 | KEYLARGO_FCR1, KL1_EIDE0_ENABLE, value); | ||
873 | case 1: | ||
874 | return simple_feature_tweak(node, macio_unknown, | ||
875 | KEYLARGO_FCR1, KL1_EIDE1_ENABLE, value); | ||
876 | case 2: | ||
877 | return simple_feature_tweak(node, macio_unknown, | ||
878 | KEYLARGO_FCR1, KL1_UIDE_ENABLE, value); | ||
879 | case 3: | ||
880 | return core99_ata100_enable(node, value); | ||
881 | default: | ||
882 | return -ENODEV; | ||
883 | } | ||
884 | } | ||
885 | |||
886 | static long __pmac | ||
887 | core99_ide_reset(struct device_node* node, long param, long value) | ||
888 | { | ||
889 | switch(param) { | ||
890 | case 0: | ||
891 | return simple_feature_tweak(node, macio_unknown, | ||
892 | KEYLARGO_FCR1, KL1_EIDE0_RESET_N, !value); | ||
893 | case 1: | ||
894 | return simple_feature_tweak(node, macio_unknown, | ||
895 | KEYLARGO_FCR1, KL1_EIDE1_RESET_N, !value); | ||
896 | case 2: | ||
897 | return simple_feature_tweak(node, macio_unknown, | ||
898 | KEYLARGO_FCR1, KL1_UIDE_RESET_N, !value); | ||
899 | default: | ||
900 | return -ENODEV; | ||
901 | } | ||
902 | } | ||
903 | |||
904 | static long __pmac | ||
905 | core99_gmac_enable(struct device_node* node, long param, long value) | ||
906 | { | ||
907 | unsigned long flags; | ||
908 | |||
909 | LOCK(flags); | ||
910 | if (value) | ||
911 | UN_BIS(UNI_N_CLOCK_CNTL, UNI_N_CLOCK_CNTL_GMAC); | ||
912 | else | ||
913 | UN_BIC(UNI_N_CLOCK_CNTL, UNI_N_CLOCK_CNTL_GMAC); | ||
914 | (void)UN_IN(UNI_N_CLOCK_CNTL); | ||
915 | UNLOCK(flags); | ||
916 | udelay(20); | ||
917 | |||
918 | return 0; | ||
919 | } | ||
920 | |||
921 | static long __pmac | ||
922 | core99_gmac_phy_reset(struct device_node* node, long param, long value) | ||
923 | { | ||
924 | unsigned long flags; | ||
925 | struct macio_chip* macio; | ||
926 | |||
927 | macio = &macio_chips[0]; | ||
928 | if (macio->type != macio_keylargo && macio->type != macio_pangea && | ||
929 | macio->type != macio_intrepid) | ||
930 | return -ENODEV; | ||
931 | |||
932 | LOCK(flags); | ||
933 | MACIO_OUT8(KL_GPIO_ETH_PHY_RESET, KEYLARGO_GPIO_OUTPUT_ENABLE); | ||
934 | (void)MACIO_IN8(KL_GPIO_ETH_PHY_RESET); | ||
935 | UNLOCK(flags); | ||
936 | mdelay(10); | ||
937 | LOCK(flags); | ||
938 | MACIO_OUT8(KL_GPIO_ETH_PHY_RESET, /*KEYLARGO_GPIO_OUTPUT_ENABLE | */ | ||
939 | KEYLARGO_GPIO_OUTOUT_DATA); | ||
940 | UNLOCK(flags); | ||
941 | mdelay(10); | ||
942 | |||
943 | return 0; | ||
944 | } | ||
945 | |||
946 | static long __pmac | ||
947 | core99_sound_chip_enable(struct device_node* node, long param, long value) | ||
948 | { | ||
949 | struct macio_chip* macio; | ||
950 | unsigned long flags; | ||
951 | |||
952 | macio = macio_find(node, 0); | ||
953 | if (!macio) | ||
954 | return -ENODEV; | ||
955 | |||
956 | /* Do a better probe code, screamer G4 desktops & | ||
957 | * iMacs can do that too, add a recalibrate in | ||
958 | * the driver as well | ||
959 | */ | ||
960 | if (pmac_mb.model_id == PMAC_TYPE_PISMO || | ||
961 | pmac_mb.model_id == PMAC_TYPE_TITANIUM) { | ||
962 | LOCK(flags); | ||
963 | if (value) | ||
964 | MACIO_OUT8(KL_GPIO_SOUND_POWER, | ||
965 | KEYLARGO_GPIO_OUTPUT_ENABLE | | ||
966 | KEYLARGO_GPIO_OUTOUT_DATA); | ||
967 | else | ||
968 | MACIO_OUT8(KL_GPIO_SOUND_POWER, | ||
969 | KEYLARGO_GPIO_OUTPUT_ENABLE); | ||
970 | (void)MACIO_IN8(KL_GPIO_SOUND_POWER); | ||
971 | UNLOCK(flags); | ||
972 | } | ||
973 | return 0; | ||
974 | } | ||
975 | |||
976 | static long __pmac | ||
977 | core99_airport_enable(struct device_node* node, long param, long value) | ||
978 | { | ||
979 | struct macio_chip* macio; | ||
980 | unsigned long flags; | ||
981 | int state; | ||
982 | |||
983 | macio = macio_find(node, 0); | ||
984 | if (!macio) | ||
985 | return -ENODEV; | ||
986 | |||
987 | /* Hint: we allow passing of macio itself for the sake of the | ||
988 | * sleep code | ||
989 | */ | ||
990 | if (node != macio->of_node && | ||
991 | (!node->parent || node->parent != macio->of_node)) | ||
992 | return -ENODEV; | ||
993 | state = (macio->flags & MACIO_FLAG_AIRPORT_ON) != 0; | ||
994 | if (value == state) | ||
995 | return 0; | ||
996 | if (value) { | ||
997 | /* This code is a reproduction of OF enable-cardslot | ||
998 | * and init-wireless methods, slightly hacked until | ||
999 | * I got it working. | ||
1000 | */ | ||
1001 | LOCK(flags); | ||
1002 | MACIO_OUT8(KEYLARGO_GPIO_0+0xf, 5); | ||
1003 | (void)MACIO_IN8(KEYLARGO_GPIO_0+0xf); | ||
1004 | UNLOCK(flags); | ||
1005 | mdelay(10); | ||
1006 | LOCK(flags); | ||
1007 | MACIO_OUT8(KEYLARGO_GPIO_0+0xf, 4); | ||
1008 | (void)MACIO_IN8(KEYLARGO_GPIO_0+0xf); | ||
1009 | UNLOCK(flags); | ||
1010 | |||
1011 | mdelay(10); | ||
1012 | |||
1013 | LOCK(flags); | ||
1014 | MACIO_BIC(KEYLARGO_FCR2, KL2_CARDSEL_16); | ||
1015 | (void)MACIO_IN32(KEYLARGO_FCR2); | ||
1016 | udelay(10); | ||
1017 | MACIO_OUT8(KEYLARGO_GPIO_EXTINT_0+0xb, 0); | ||
1018 | (void)MACIO_IN8(KEYLARGO_GPIO_EXTINT_0+0xb); | ||
1019 | udelay(10); | ||
1020 | MACIO_OUT8(KEYLARGO_GPIO_EXTINT_0+0xa, 0x28); | ||
1021 | (void)MACIO_IN8(KEYLARGO_GPIO_EXTINT_0+0xa); | ||
1022 | udelay(10); | ||
1023 | MACIO_OUT8(KEYLARGO_GPIO_EXTINT_0+0xd, 0x28); | ||
1024 | (void)MACIO_IN8(KEYLARGO_GPIO_EXTINT_0+0xd); | ||
1025 | udelay(10); | ||
1026 | MACIO_OUT8(KEYLARGO_GPIO_0+0xd, 0x28); | ||
1027 | (void)MACIO_IN8(KEYLARGO_GPIO_0+0xd); | ||
1028 | udelay(10); | ||
1029 | MACIO_OUT8(KEYLARGO_GPIO_0+0xe, 0x28); | ||
1030 | (void)MACIO_IN8(KEYLARGO_GPIO_0+0xe); | ||
1031 | UNLOCK(flags); | ||
1032 | udelay(10); | ||
1033 | MACIO_OUT32(0x1c000, 0); | ||
1034 | mdelay(1); | ||
1035 | MACIO_OUT8(0x1a3e0, 0x41); | ||
1036 | (void)MACIO_IN8(0x1a3e0); | ||
1037 | udelay(10); | ||
1038 | LOCK(flags); | ||
1039 | MACIO_BIS(KEYLARGO_FCR2, KL2_CARDSEL_16); | ||
1040 | (void)MACIO_IN32(KEYLARGO_FCR2); | ||
1041 | UNLOCK(flags); | ||
1042 | mdelay(100); | ||
1043 | |||
1044 | macio->flags |= MACIO_FLAG_AIRPORT_ON; | ||
1045 | } else { | ||
1046 | LOCK(flags); | ||
1047 | MACIO_BIC(KEYLARGO_FCR2, KL2_CARDSEL_16); | ||
1048 | (void)MACIO_IN32(KEYLARGO_FCR2); | ||
1049 | MACIO_OUT8(KL_GPIO_AIRPORT_0, 0); | ||
1050 | MACIO_OUT8(KL_GPIO_AIRPORT_1, 0); | ||
1051 | MACIO_OUT8(KL_GPIO_AIRPORT_2, 0); | ||
1052 | MACIO_OUT8(KL_GPIO_AIRPORT_3, 0); | ||
1053 | MACIO_OUT8(KL_GPIO_AIRPORT_4, 0); | ||
1054 | (void)MACIO_IN8(KL_GPIO_AIRPORT_4); | ||
1055 | UNLOCK(flags); | ||
1056 | |||
1057 | macio->flags &= ~MACIO_FLAG_AIRPORT_ON; | ||
1058 | } | ||
1059 | return 0; | ||
1060 | } | ||
1061 | |||
1062 | #ifdef CONFIG_SMP | ||
1063 | static long __pmac | ||
1064 | core99_reset_cpu(struct device_node* node, long param, long value) | ||
1065 | { | ||
1066 | unsigned int reset_io = 0; | ||
1067 | unsigned long flags; | ||
1068 | struct macio_chip* macio; | ||
1069 | struct device_node* np; | ||
1070 | const int dflt_reset_lines[] = { KL_GPIO_RESET_CPU0, | ||
1071 | KL_GPIO_RESET_CPU1, | ||
1072 | KL_GPIO_RESET_CPU2, | ||
1073 | KL_GPIO_RESET_CPU3 }; | ||
1074 | |||
1075 | macio = &macio_chips[0]; | ||
1076 | if (macio->type != macio_keylargo) | ||
1077 | return -ENODEV; | ||
1078 | |||
1079 | np = find_path_device("/cpus"); | ||
1080 | if (np == NULL) | ||
1081 | return -ENODEV; | ||
1082 | for (np = np->child; np != NULL; np = np->sibling) { | ||
1083 | u32* num = (u32 *)get_property(np, "reg", NULL); | ||
1084 | u32* rst = (u32 *)get_property(np, "soft-reset", NULL); | ||
1085 | if (num == NULL || rst == NULL) | ||
1086 | continue; | ||
1087 | if (param == *num) { | ||
1088 | reset_io = *rst; | ||
1089 | break; | ||
1090 | } | ||
1091 | } | ||
1092 | if (np == NULL || reset_io == 0) | ||
1093 | reset_io = dflt_reset_lines[param]; | ||
1094 | |||
1095 | LOCK(flags); | ||
1096 | MACIO_OUT8(reset_io, KEYLARGO_GPIO_OUTPUT_ENABLE); | ||
1097 | (void)MACIO_IN8(reset_io); | ||
1098 | udelay(1); | ||
1099 | MACIO_OUT8(reset_io, 0); | ||
1100 | (void)MACIO_IN8(reset_io); | ||
1101 | UNLOCK(flags); | ||
1102 | |||
1103 | return 0; | ||
1104 | } | ||
1105 | #endif /* CONFIG_SMP */ | ||
1106 | |||
1107 | static long __pmac | ||
1108 | core99_usb_enable(struct device_node* node, long param, long value) | ||
1109 | { | ||
1110 | struct macio_chip* macio; | ||
1111 | unsigned long flags; | ||
1112 | char* prop; | ||
1113 | int number; | ||
1114 | u32 reg; | ||
1115 | |||
1116 | macio = &macio_chips[0]; | ||
1117 | if (macio->type != macio_keylargo && macio->type != macio_pangea && | ||
1118 | macio->type != macio_intrepid) | ||
1119 | return -ENODEV; | ||
1120 | |||
1121 | prop = (char *)get_property(node, "AAPL,clock-id", NULL); | ||
1122 | if (!prop) | ||
1123 | return -ENODEV; | ||
1124 | if (strncmp(prop, "usb0u048", 8) == 0) | ||
1125 | number = 0; | ||
1126 | else if (strncmp(prop, "usb1u148", 8) == 0) | ||
1127 | number = 2; | ||
1128 | else if (strncmp(prop, "usb2u248", 8) == 0) | ||
1129 | number = 4; | ||
1130 | else | ||
1131 | return -ENODEV; | ||
1132 | |||
1133 | /* Sorry for the brute-force locking, but this is only used during | ||
1134 | * sleep and the timing seem to be critical | ||
1135 | */ | ||
1136 | LOCK(flags); | ||
1137 | if (value) { | ||
1138 | /* Turn ON */ | ||
1139 | if (number == 0) { | ||
1140 | MACIO_BIC(KEYLARGO_FCR0, (KL0_USB0_PAD_SUSPEND0 | KL0_USB0_PAD_SUSPEND1)); | ||
1141 | (void)MACIO_IN32(KEYLARGO_FCR0); | ||
1142 | UNLOCK(flags); | ||
1143 | mdelay(1); | ||
1144 | LOCK(flags); | ||
1145 | MACIO_BIS(KEYLARGO_FCR0, KL0_USB0_CELL_ENABLE); | ||
1146 | } else if (number == 2) { | ||
1147 | MACIO_BIC(KEYLARGO_FCR0, (KL0_USB1_PAD_SUSPEND0 | KL0_USB1_PAD_SUSPEND1)); | ||
1148 | UNLOCK(flags); | ||
1149 | (void)MACIO_IN32(KEYLARGO_FCR0); | ||
1150 | mdelay(1); | ||
1151 | LOCK(flags); | ||
1152 | MACIO_BIS(KEYLARGO_FCR0, KL0_USB1_CELL_ENABLE); | ||
1153 | } else if (number == 4) { | ||
1154 | MACIO_BIC(KEYLARGO_FCR1, (KL1_USB2_PAD_SUSPEND0 | KL1_USB2_PAD_SUSPEND1)); | ||
1155 | UNLOCK(flags); | ||
1156 | (void)MACIO_IN32(KEYLARGO_FCR1); | ||
1157 | mdelay(1); | ||
1158 | LOCK(flags); | ||
1159 | MACIO_BIS(KEYLARGO_FCR1, KL1_USB2_CELL_ENABLE); | ||
1160 | } | ||
1161 | if (number < 4) { | ||
1162 | reg = MACIO_IN32(KEYLARGO_FCR4); | ||
1163 | reg &= ~(KL4_PORT_WAKEUP_ENABLE(number) | KL4_PORT_RESUME_WAKE_EN(number) | | ||
1164 | KL4_PORT_CONNECT_WAKE_EN(number) | KL4_PORT_DISCONNECT_WAKE_EN(number)); | ||
1165 | reg &= ~(KL4_PORT_WAKEUP_ENABLE(number+1) | KL4_PORT_RESUME_WAKE_EN(number+1) | | ||
1166 | KL4_PORT_CONNECT_WAKE_EN(number+1) | KL4_PORT_DISCONNECT_WAKE_EN(number+1)); | ||
1167 | MACIO_OUT32(KEYLARGO_FCR4, reg); | ||
1168 | (void)MACIO_IN32(KEYLARGO_FCR4); | ||
1169 | udelay(10); | ||
1170 | } else { | ||
1171 | reg = MACIO_IN32(KEYLARGO_FCR3); | ||
1172 | reg &= ~(KL3_IT_PORT_WAKEUP_ENABLE(0) | KL3_IT_PORT_RESUME_WAKE_EN(0) | | ||
1173 | KL3_IT_PORT_CONNECT_WAKE_EN(0) | KL3_IT_PORT_DISCONNECT_WAKE_EN(0)); | ||
1174 | reg &= ~(KL3_IT_PORT_WAKEUP_ENABLE(1) | KL3_IT_PORT_RESUME_WAKE_EN(1) | | ||
1175 | KL3_IT_PORT_CONNECT_WAKE_EN(1) | KL3_IT_PORT_DISCONNECT_WAKE_EN(1)); | ||
1176 | MACIO_OUT32(KEYLARGO_FCR3, reg); | ||
1177 | (void)MACIO_IN32(KEYLARGO_FCR3); | ||
1178 | udelay(10); | ||
1179 | } | ||
1180 | if (macio->type == macio_intrepid) { | ||
1181 | /* wait for clock stopped bits to clear */ | ||
1182 | u32 test0 = 0, test1 = 0; | ||
1183 | u32 status0, status1; | ||
1184 | int timeout = 1000; | ||
1185 | |||
1186 | UNLOCK(flags); | ||
1187 | switch (number) { | ||
1188 | case 0: | ||
1189 | test0 = UNI_N_CLOCK_STOPPED_USB0; | ||
1190 | test1 = UNI_N_CLOCK_STOPPED_USB0PCI; | ||
1191 | break; | ||
1192 | case 2: | ||
1193 | test0 = UNI_N_CLOCK_STOPPED_USB1; | ||
1194 | test1 = UNI_N_CLOCK_STOPPED_USB1PCI; | ||
1195 | break; | ||
1196 | case 4: | ||
1197 | test0 = UNI_N_CLOCK_STOPPED_USB2; | ||
1198 | test1 = UNI_N_CLOCK_STOPPED_USB2PCI; | ||
1199 | break; | ||
1200 | } | ||
1201 | do { | ||
1202 | if (--timeout <= 0) { | ||
1203 | printk(KERN_ERR "core99_usb_enable: " | ||
1204 | "Timeout waiting for clocks\n"); | ||
1205 | break; | ||
1206 | } | ||
1207 | mdelay(1); | ||
1208 | status0 = UN_IN(UNI_N_CLOCK_STOP_STATUS0); | ||
1209 | status1 = UN_IN(UNI_N_CLOCK_STOP_STATUS1); | ||
1210 | } while ((status0 & test0) | (status1 & test1)); | ||
1211 | LOCK(flags); | ||
1212 | } | ||
1213 | } else { | ||
1214 | /* Turn OFF */ | ||
1215 | if (number < 4) { | ||
1216 | reg = MACIO_IN32(KEYLARGO_FCR4); | ||
1217 | reg |= KL4_PORT_WAKEUP_ENABLE(number) | KL4_PORT_RESUME_WAKE_EN(number) | | ||
1218 | KL4_PORT_CONNECT_WAKE_EN(number) | KL4_PORT_DISCONNECT_WAKE_EN(number); | ||
1219 | reg |= KL4_PORT_WAKEUP_ENABLE(number+1) | KL4_PORT_RESUME_WAKE_EN(number+1) | | ||
1220 | KL4_PORT_CONNECT_WAKE_EN(number+1) | KL4_PORT_DISCONNECT_WAKE_EN(number+1); | ||
1221 | MACIO_OUT32(KEYLARGO_FCR4, reg); | ||
1222 | (void)MACIO_IN32(KEYLARGO_FCR4); | ||
1223 | udelay(1); | ||
1224 | } else { | ||
1225 | reg = MACIO_IN32(KEYLARGO_FCR3); | ||
1226 | reg |= KL3_IT_PORT_WAKEUP_ENABLE(0) | KL3_IT_PORT_RESUME_WAKE_EN(0) | | ||
1227 | KL3_IT_PORT_CONNECT_WAKE_EN(0) | KL3_IT_PORT_DISCONNECT_WAKE_EN(0); | ||
1228 | reg |= KL3_IT_PORT_WAKEUP_ENABLE(1) | KL3_IT_PORT_RESUME_WAKE_EN(1) | | ||
1229 | KL3_IT_PORT_CONNECT_WAKE_EN(1) | KL3_IT_PORT_DISCONNECT_WAKE_EN(1); | ||
1230 | MACIO_OUT32(KEYLARGO_FCR3, reg); | ||
1231 | (void)MACIO_IN32(KEYLARGO_FCR3); | ||
1232 | udelay(1); | ||
1233 | } | ||
1234 | if (number == 0) { | ||
1235 | if (macio->type != macio_intrepid) | ||
1236 | MACIO_BIC(KEYLARGO_FCR0, KL0_USB0_CELL_ENABLE); | ||
1237 | (void)MACIO_IN32(KEYLARGO_FCR0); | ||
1238 | udelay(1); | ||
1239 | MACIO_BIS(KEYLARGO_FCR0, (KL0_USB0_PAD_SUSPEND0 | KL0_USB0_PAD_SUSPEND1)); | ||
1240 | (void)MACIO_IN32(KEYLARGO_FCR0); | ||
1241 | } else if (number == 2) { | ||
1242 | if (macio->type != macio_intrepid) | ||
1243 | MACIO_BIC(KEYLARGO_FCR0, KL0_USB1_CELL_ENABLE); | ||
1244 | (void)MACIO_IN32(KEYLARGO_FCR0); | ||
1245 | udelay(1); | ||
1246 | MACIO_BIS(KEYLARGO_FCR0, (KL0_USB1_PAD_SUSPEND0 | KL0_USB1_PAD_SUSPEND1)); | ||
1247 | (void)MACIO_IN32(KEYLARGO_FCR0); | ||
1248 | } else if (number == 4) { | ||
1249 | udelay(1); | ||
1250 | MACIO_BIS(KEYLARGO_FCR1, (KL1_USB2_PAD_SUSPEND0 | KL1_USB2_PAD_SUSPEND1)); | ||
1251 | (void)MACIO_IN32(KEYLARGO_FCR1); | ||
1252 | } | ||
1253 | udelay(1); | ||
1254 | } | ||
1255 | UNLOCK(flags); | ||
1256 | |||
1257 | return 0; | ||
1258 | } | ||
1259 | |||
1260 | static long __pmac | ||
1261 | core99_firewire_enable(struct device_node* node, long param, long value) | ||
1262 | { | ||
1263 | unsigned long flags; | ||
1264 | struct macio_chip* macio; | ||
1265 | |||
1266 | macio = &macio_chips[0]; | ||
1267 | if (macio->type != macio_keylargo && macio->type != macio_pangea && | ||
1268 | macio->type != macio_intrepid) | ||
1269 | return -ENODEV; | ||
1270 | if (!(macio->flags & MACIO_FLAG_FW_SUPPORTED)) | ||
1271 | return -ENODEV; | ||
1272 | |||
1273 | LOCK(flags); | ||
1274 | if (value) { | ||
1275 | UN_BIS(UNI_N_CLOCK_CNTL, UNI_N_CLOCK_CNTL_FW); | ||
1276 | (void)UN_IN(UNI_N_CLOCK_CNTL); | ||
1277 | } else { | ||
1278 | UN_BIC(UNI_N_CLOCK_CNTL, UNI_N_CLOCK_CNTL_FW); | ||
1279 | (void)UN_IN(UNI_N_CLOCK_CNTL); | ||
1280 | } | ||
1281 | UNLOCK(flags); | ||
1282 | mdelay(1); | ||
1283 | |||
1284 | return 0; | ||
1285 | } | ||
1286 | |||
1287 | static long __pmac | ||
1288 | core99_firewire_cable_power(struct device_node* node, long param, long value) | ||
1289 | { | ||
1290 | unsigned long flags; | ||
1291 | struct macio_chip* macio; | ||
1292 | |||
1293 | /* Trick: we allow NULL node */ | ||
1294 | if ((pmac_mb.board_flags & PMAC_MB_HAS_FW_POWER) == 0) | ||
1295 | return -ENODEV; | ||
1296 | macio = &macio_chips[0]; | ||
1297 | if (macio->type != macio_keylargo && macio->type != macio_pangea && | ||
1298 | macio->type != macio_intrepid) | ||
1299 | return -ENODEV; | ||
1300 | if (!(macio->flags & MACIO_FLAG_FW_SUPPORTED)) | ||
1301 | return -ENODEV; | ||
1302 | |||
1303 | LOCK(flags); | ||
1304 | if (value) { | ||
1305 | MACIO_OUT8(KL_GPIO_FW_CABLE_POWER , 0); | ||
1306 | MACIO_IN8(KL_GPIO_FW_CABLE_POWER); | ||
1307 | udelay(10); | ||
1308 | } else { | ||
1309 | MACIO_OUT8(KL_GPIO_FW_CABLE_POWER , 4); | ||
1310 | MACIO_IN8(KL_GPIO_FW_CABLE_POWER); udelay(10); | ||
1311 | } | ||
1312 | UNLOCK(flags); | ||
1313 | mdelay(1); | ||
1314 | |||
1315 | return 0; | ||
1316 | } | ||
1317 | |||
1318 | static long __pmac | ||
1319 | intrepid_aack_delay_enable(struct device_node* node, long param, long value) | ||
1320 | { | ||
1321 | unsigned long flags; | ||
1322 | |||
1323 | if (uninorth_rev < 0xd2) | ||
1324 | return -ENODEV; | ||
1325 | |||
1326 | LOCK(flags); | ||
1327 | if (param) | ||
1328 | UN_BIS(UNI_N_AACK_DELAY, UNI_N_AACK_DELAY_ENABLE); | ||
1329 | else | ||
1330 | UN_BIC(UNI_N_AACK_DELAY, UNI_N_AACK_DELAY_ENABLE); | ||
1331 | UNLOCK(flags); | ||
1332 | |||
1333 | return 0; | ||
1334 | } | ||
1335 | |||
1336 | |||
1337 | #endif /* CONFIG_POWER4 */ | ||
1338 | |||
1339 | static long __pmac | ||
1340 | core99_read_gpio(struct device_node* node, long param, long value) | ||
1341 | { | ||
1342 | struct macio_chip* macio = &macio_chips[0]; | ||
1343 | |||
1344 | return MACIO_IN8(param); | ||
1345 | } | ||
1346 | |||
1347 | |||
1348 | static long __pmac | ||
1349 | core99_write_gpio(struct device_node* node, long param, long value) | ||
1350 | { | ||
1351 | struct macio_chip* macio = &macio_chips[0]; | ||
1352 | |||
1353 | MACIO_OUT8(param, (u8)(value & 0xff)); | ||
1354 | return 0; | ||
1355 | } | ||
1356 | |||
1357 | #ifdef CONFIG_POWER4 | ||
1358 | |||
1359 | static long __pmac | ||
1360 | g5_gmac_enable(struct device_node* node, long param, long value) | ||
1361 | { | ||
1362 | struct macio_chip* macio = &macio_chips[0]; | ||
1363 | unsigned long flags; | ||
1364 | u8 pbus, pid; | ||
1365 | |||
1366 | LOCK(flags); | ||
1367 | if (value) { | ||
1368 | MACIO_BIS(KEYLARGO_FCR1, K2_FCR1_GMAC_CLK_ENABLE); | ||
1369 | mb(); | ||
1370 | k2_skiplist[0] = NULL; | ||
1371 | } else { | ||
1372 | k2_skiplist[0] = node; | ||
1373 | mb(); | ||
1374 | MACIO_BIC(KEYLARGO_FCR1, K2_FCR1_GMAC_CLK_ENABLE); | ||
1375 | } | ||
1376 | |||
1377 | UNLOCK(flags); | ||
1378 | mdelay(1); | ||
1379 | |||
1380 | return 0; | ||
1381 | } | ||
1382 | |||
1383 | static long __pmac | ||
1384 | g5_fw_enable(struct device_node* node, long param, long value) | ||
1385 | { | ||
1386 | struct macio_chip* macio = &macio_chips[0]; | ||
1387 | unsigned long flags; | ||
1388 | |||
1389 | LOCK(flags); | ||
1390 | if (value) { | ||
1391 | MACIO_BIS(KEYLARGO_FCR1, K2_FCR1_FW_CLK_ENABLE); | ||
1392 | mb(); | ||
1393 | k2_skiplist[1] = NULL; | ||
1394 | } else { | ||
1395 | k2_skiplist[1] = node; | ||
1396 | mb(); | ||
1397 | MACIO_BIC(KEYLARGO_FCR1, K2_FCR1_FW_CLK_ENABLE); | ||
1398 | } | ||
1399 | |||
1400 | UNLOCK(flags); | ||
1401 | mdelay(1); | ||
1402 | |||
1403 | return 0; | ||
1404 | } | ||
1405 | |||
1406 | static long __pmac | ||
1407 | g5_mpic_enable(struct device_node* node, long param, long value) | ||
1408 | { | ||
1409 | unsigned long flags; | ||
1410 | |||
1411 | if (node->parent == NULL || strcmp(node->parent->name, "u3")) | ||
1412 | return 0; | ||
1413 | |||
1414 | LOCK(flags); | ||
1415 | UN_BIS(U3_TOGGLE_REG, U3_MPIC_RESET | U3_MPIC_OUTPUT_ENABLE); | ||
1416 | UNLOCK(flags); | ||
1417 | |||
1418 | return 0; | ||
1419 | } | ||
1420 | |||
1421 | #ifdef CONFIG_SMP | ||
1422 | static long __pmac | ||
1423 | g5_reset_cpu(struct device_node* node, long param, long value) | ||
1424 | { | ||
1425 | unsigned int reset_io = 0; | ||
1426 | unsigned long flags; | ||
1427 | struct macio_chip* macio; | ||
1428 | struct device_node* np; | ||
1429 | |||
1430 | macio = &macio_chips[0]; | ||
1431 | if (macio->type != macio_keylargo2) | ||
1432 | return -ENODEV; | ||
1433 | |||
1434 | np = find_path_device("/cpus"); | ||
1435 | if (np == NULL) | ||
1436 | return -ENODEV; | ||
1437 | for (np = np->child; np != NULL; np = np->sibling) { | ||
1438 | u32* num = (u32 *)get_property(np, "reg", NULL); | ||
1439 | u32* rst = (u32 *)get_property(np, "soft-reset", NULL); | ||
1440 | if (num == NULL || rst == NULL) | ||
1441 | continue; | ||
1442 | if (param == *num) { | ||
1443 | reset_io = *rst; | ||
1444 | break; | ||
1445 | } | ||
1446 | } | ||
1447 | if (np == NULL || reset_io == 0) | ||
1448 | return -ENODEV; | ||
1449 | |||
1450 | LOCK(flags); | ||
1451 | MACIO_OUT8(reset_io, KEYLARGO_GPIO_OUTPUT_ENABLE); | ||
1452 | (void)MACIO_IN8(reset_io); | ||
1453 | udelay(1); | ||
1454 | MACIO_OUT8(reset_io, 0); | ||
1455 | (void)MACIO_IN8(reset_io); | ||
1456 | UNLOCK(flags); | ||
1457 | |||
1458 | return 0; | ||
1459 | } | ||
1460 | #endif /* CONFIG_SMP */ | ||
1461 | |||
1462 | /* | ||
1463 | * This can be called from pmac_smp so isn't static | ||
1464 | * | ||
1465 | * This takes the second CPU off the bus on dual CPU machines | ||
1466 | * running UP | ||
1467 | */ | ||
1468 | void __pmac g5_phy_disable_cpu1(void) | ||
1469 | { | ||
1470 | UN_OUT(U3_API_PHY_CONFIG_1, 0); | ||
1471 | } | ||
1472 | |||
1473 | #endif /* CONFIG_POWER4 */ | ||
1474 | |||
1475 | #ifndef CONFIG_POWER4 | ||
1476 | |||
1477 | static void __pmac | ||
1478 | keylargo_shutdown(struct macio_chip* macio, int sleep_mode) | ||
1479 | { | ||
1480 | u32 temp; | ||
1481 | |||
1482 | if (sleep_mode) { | ||
1483 | mdelay(1); | ||
1484 | MACIO_BIS(KEYLARGO_FCR0, KL0_USB_REF_SUSPEND); | ||
1485 | (void)MACIO_IN32(KEYLARGO_FCR0); | ||
1486 | mdelay(1); | ||
1487 | } | ||
1488 | |||
1489 | MACIO_BIC(KEYLARGO_FCR0,KL0_SCCA_ENABLE | KL0_SCCB_ENABLE | | ||
1490 | KL0_SCC_CELL_ENABLE | | ||
1491 | KL0_IRDA_ENABLE | KL0_IRDA_CLK32_ENABLE | | ||
1492 | KL0_IRDA_CLK19_ENABLE); | ||
1493 | |||
1494 | MACIO_BIC(KEYLARGO_MBCR, KL_MBCR_MB0_DEV_MASK); | ||
1495 | MACIO_BIS(KEYLARGO_MBCR, KL_MBCR_MB0_IDE_ENABLE); | ||
1496 | |||
1497 | MACIO_BIC(KEYLARGO_FCR1, | ||
1498 | KL1_AUDIO_SEL_22MCLK | KL1_AUDIO_CLK_ENABLE_BIT | | ||
1499 | KL1_AUDIO_CLK_OUT_ENABLE | KL1_AUDIO_CELL_ENABLE | | ||
1500 | KL1_I2S0_CELL_ENABLE | KL1_I2S0_CLK_ENABLE_BIT | | ||
1501 | KL1_I2S0_ENABLE | KL1_I2S1_CELL_ENABLE | | ||
1502 | KL1_I2S1_CLK_ENABLE_BIT | KL1_I2S1_ENABLE | | ||
1503 | KL1_EIDE0_ENABLE | KL1_EIDE0_RESET_N | | ||
1504 | KL1_EIDE1_ENABLE | KL1_EIDE1_RESET_N | | ||
1505 | KL1_UIDE_ENABLE); | ||
1506 | |||
1507 | MACIO_BIS(KEYLARGO_FCR2, KL2_ALT_DATA_OUT); | ||
1508 | MACIO_BIC(KEYLARGO_FCR2, KL2_IOBUS_ENABLE); | ||
1509 | |||
1510 | temp = MACIO_IN32(KEYLARGO_FCR3); | ||
1511 | if (macio->rev >= 2) { | ||
1512 | temp |= KL3_SHUTDOWN_PLL2X; | ||
1513 | if (sleep_mode) | ||
1514 | temp |= KL3_SHUTDOWN_PLL_TOTAL; | ||
1515 | } | ||
1516 | |||
1517 | temp |= KL3_SHUTDOWN_PLLKW6 | KL3_SHUTDOWN_PLLKW4 | | ||
1518 | KL3_SHUTDOWN_PLLKW35; | ||
1519 | if (sleep_mode) | ||
1520 | temp |= KL3_SHUTDOWN_PLLKW12; | ||
1521 | temp &= ~(KL3_CLK66_ENABLE | KL3_CLK49_ENABLE | KL3_CLK45_ENABLE | ||
1522 | | KL3_CLK31_ENABLE | KL3_I2S1_CLK18_ENABLE | KL3_I2S0_CLK18_ENABLE); | ||
1523 | if (sleep_mode) | ||
1524 | temp &= ~(KL3_TIMER_CLK18_ENABLE | KL3_VIA_CLK16_ENABLE); | ||
1525 | MACIO_OUT32(KEYLARGO_FCR3, temp); | ||
1526 | |||
1527 | /* Flush posted writes & wait a bit */ | ||
1528 | (void)MACIO_IN32(KEYLARGO_FCR0); mdelay(1); | ||
1529 | } | ||
1530 | |||
1531 | static void __pmac | ||
1532 | pangea_shutdown(struct macio_chip* macio, int sleep_mode) | ||
1533 | { | ||
1534 | u32 temp; | ||
1535 | |||
1536 | MACIO_BIC(KEYLARGO_FCR0,KL0_SCCA_ENABLE | KL0_SCCB_ENABLE | | ||
1537 | KL0_SCC_CELL_ENABLE | | ||
1538 | KL0_USB0_CELL_ENABLE | KL0_USB1_CELL_ENABLE); | ||
1539 | |||
1540 | MACIO_BIC(KEYLARGO_FCR1, | ||
1541 | KL1_AUDIO_SEL_22MCLK | KL1_AUDIO_CLK_ENABLE_BIT | | ||
1542 | KL1_AUDIO_CLK_OUT_ENABLE | KL1_AUDIO_CELL_ENABLE | | ||
1543 | KL1_I2S0_CELL_ENABLE | KL1_I2S0_CLK_ENABLE_BIT | | ||
1544 | KL1_I2S0_ENABLE | KL1_I2S1_CELL_ENABLE | | ||
1545 | KL1_I2S1_CLK_ENABLE_BIT | KL1_I2S1_ENABLE | | ||
1546 | KL1_UIDE_ENABLE); | ||
1547 | if (pmac_mb.board_flags & PMAC_MB_MOBILE) | ||
1548 | MACIO_BIC(KEYLARGO_FCR1, KL1_UIDE_RESET_N); | ||
1549 | |||
1550 | MACIO_BIS(KEYLARGO_FCR2, KL2_ALT_DATA_OUT); | ||
1551 | |||
1552 | temp = MACIO_IN32(KEYLARGO_FCR3); | ||
1553 | temp |= KL3_SHUTDOWN_PLLKW6 | KL3_SHUTDOWN_PLLKW4 | | ||
1554 | KL3_SHUTDOWN_PLLKW35; | ||
1555 | temp &= ~(KL3_CLK49_ENABLE | KL3_CLK45_ENABLE | KL3_CLK31_ENABLE | ||
1556 | | KL3_I2S0_CLK18_ENABLE | KL3_I2S1_CLK18_ENABLE); | ||
1557 | if (sleep_mode) | ||
1558 | temp &= ~(KL3_VIA_CLK16_ENABLE | KL3_TIMER_CLK18_ENABLE); | ||
1559 | MACIO_OUT32(KEYLARGO_FCR3, temp); | ||
1560 | |||
1561 | /* Flush posted writes & wait a bit */ | ||
1562 | (void)MACIO_IN32(KEYLARGO_FCR0); mdelay(1); | ||
1563 | } | ||
1564 | |||
1565 | static void __pmac | ||
1566 | intrepid_shutdown(struct macio_chip* macio, int sleep_mode) | ||
1567 | { | ||
1568 | u32 temp; | ||
1569 | |||
1570 | MACIO_BIC(KEYLARGO_FCR0,KL0_SCCA_ENABLE | KL0_SCCB_ENABLE | | ||
1571 | KL0_SCC_CELL_ENABLE); | ||
1572 | |||
1573 | MACIO_BIC(KEYLARGO_FCR1, | ||
1574 | /*KL1_USB2_CELL_ENABLE |*/ | ||
1575 | KL1_I2S0_CELL_ENABLE | KL1_I2S0_CLK_ENABLE_BIT | | ||
1576 | KL1_I2S0_ENABLE | KL1_I2S1_CELL_ENABLE | | ||
1577 | KL1_I2S1_CLK_ENABLE_BIT | KL1_I2S1_ENABLE); | ||
1578 | if (pmac_mb.board_flags & PMAC_MB_MOBILE) | ||
1579 | MACIO_BIC(KEYLARGO_FCR1, KL1_UIDE_RESET_N); | ||
1580 | |||
1581 | temp = MACIO_IN32(KEYLARGO_FCR3); | ||
1582 | temp &= ~(KL3_CLK49_ENABLE | KL3_CLK45_ENABLE | | ||
1583 | KL3_I2S1_CLK18_ENABLE | KL3_I2S0_CLK18_ENABLE); | ||
1584 | if (sleep_mode) | ||
1585 | temp &= ~(KL3_TIMER_CLK18_ENABLE | KL3_IT_VIA_CLK32_ENABLE); | ||
1586 | MACIO_OUT32(KEYLARGO_FCR3, temp); | ||
1587 | |||
1588 | /* Flush posted writes & wait a bit */ | ||
1589 | (void)MACIO_IN32(KEYLARGO_FCR0); | ||
1590 | mdelay(10); | ||
1591 | } | ||
1592 | |||
1593 | static int __pmac | ||
1594 | core99_sleep(void) | ||
1595 | { | ||
1596 | struct macio_chip* macio; | ||
1597 | int i; | ||
1598 | |||
1599 | macio = &macio_chips[0]; | ||
1600 | if (macio->type != macio_keylargo && macio->type != macio_pangea && | ||
1601 | macio->type != macio_intrepid) | ||
1602 | return -ENODEV; | ||
1603 | |||
1604 | /* The device-tree contains that in the hwclock node */ | ||
1605 | if (macio->type == macio_intrepid) { | ||
1606 | UN_OUT(UNI_N_CLOCK_SPREADING, 0); | ||
1607 | mdelay(40); | ||
1608 | } | ||
1609 | |||
1610 | /* We power off the wireless slot in case it was not done | ||
1611 | * by the driver. We don't power it on automatically however | ||
1612 | */ | ||
1613 | if (macio->flags & MACIO_FLAG_AIRPORT_ON) | ||
1614 | core99_airport_enable(macio->of_node, 0, 0); | ||
1615 | |||
1616 | /* We power off the FW cable. Should be done by the driver... */ | ||
1617 | if (macio->flags & MACIO_FLAG_FW_SUPPORTED) { | ||
1618 | core99_firewire_enable(NULL, 0, 0); | ||
1619 | core99_firewire_cable_power(NULL, 0, 0); | ||
1620 | } | ||
1621 | |||
1622 | /* We make sure int. modem is off (in case driver lost it) */ | ||
1623 | if (macio->type == macio_keylargo) | ||
1624 | core99_modem_enable(macio->of_node, 0, 0); | ||
1625 | else | ||
1626 | pangea_modem_enable(macio->of_node, 0, 0); | ||
1627 | |||
1628 | /* We make sure the sound is off as well */ | ||
1629 | core99_sound_chip_enable(macio->of_node, 0, 0); | ||
1630 | |||
1631 | /* | ||
1632 | * Save various bits of KeyLargo | ||
1633 | */ | ||
1634 | |||
1635 | /* Save the state of the various GPIOs */ | ||
1636 | save_gpio_levels[0] = MACIO_IN32(KEYLARGO_GPIO_LEVELS0); | ||
1637 | save_gpio_levels[1] = MACIO_IN32(KEYLARGO_GPIO_LEVELS1); | ||
1638 | for (i=0; i<KEYLARGO_GPIO_EXTINT_CNT; i++) | ||
1639 | save_gpio_extint[i] = MACIO_IN8(KEYLARGO_GPIO_EXTINT_0+i); | ||
1640 | for (i=0; i<KEYLARGO_GPIO_CNT; i++) | ||
1641 | save_gpio_normal[i] = MACIO_IN8(KEYLARGO_GPIO_0+i); | ||
1642 | |||
1643 | /* Save the FCRs */ | ||
1644 | if (macio->type == macio_keylargo) | ||
1645 | save_mbcr = MACIO_IN32(KEYLARGO_MBCR); | ||
1646 | save_fcr[0] = MACIO_IN32(KEYLARGO_FCR0); | ||
1647 | save_fcr[1] = MACIO_IN32(KEYLARGO_FCR1); | ||
1648 | save_fcr[2] = MACIO_IN32(KEYLARGO_FCR2); | ||
1649 | save_fcr[3] = MACIO_IN32(KEYLARGO_FCR3); | ||
1650 | save_fcr[4] = MACIO_IN32(KEYLARGO_FCR4); | ||
1651 | if (macio->type == macio_pangea || macio->type == macio_intrepid) | ||
1652 | save_fcr[5] = MACIO_IN32(KEYLARGO_FCR5); | ||
1653 | |||
1654 | /* Save state & config of DBDMA channels */ | ||
1655 | dbdma_save(macio, save_dbdma); | ||
1656 | |||
1657 | /* | ||
1658 | * Turn off as much as we can | ||
1659 | */ | ||
1660 | if (macio->type == macio_pangea) | ||
1661 | pangea_shutdown(macio, 1); | ||
1662 | else if (macio->type == macio_intrepid) | ||
1663 | intrepid_shutdown(macio, 1); | ||
1664 | else if (macio->type == macio_keylargo) | ||
1665 | keylargo_shutdown(macio, 1); | ||
1666 | |||
1667 | /* | ||
1668 | * Put the host bridge to sleep | ||
1669 | */ | ||
1670 | |||
1671 | save_unin_clock_ctl = UN_IN(UNI_N_CLOCK_CNTL); | ||
1672 | /* Note: do not switch GMAC off, driver does it when necessary, WOL must keep it | ||
1673 | * enabled ! | ||
1674 | */ | ||
1675 | UN_OUT(UNI_N_CLOCK_CNTL, save_unin_clock_ctl & | ||
1676 | ~(/*UNI_N_CLOCK_CNTL_GMAC|*/UNI_N_CLOCK_CNTL_FW/*|UNI_N_CLOCK_CNTL_PCI*/)); | ||
1677 | udelay(100); | ||
1678 | UN_OUT(UNI_N_HWINIT_STATE, UNI_N_HWINIT_STATE_SLEEPING); | ||
1679 | UN_OUT(UNI_N_POWER_MGT, UNI_N_POWER_MGT_SLEEP); | ||
1680 | mdelay(10); | ||
1681 | |||
1682 | /* | ||
1683 | * FIXME: A bit of black magic with OpenPIC (don't ask me why) | ||
1684 | */ | ||
1685 | if (pmac_mb.model_id == PMAC_TYPE_SAWTOOTH) { | ||
1686 | MACIO_BIS(0x506e0, 0x00400000); | ||
1687 | MACIO_BIS(0x506e0, 0x80000000); | ||
1688 | } | ||
1689 | return 0; | ||
1690 | } | ||
1691 | |||
1692 | static int __pmac | ||
1693 | core99_wake_up(void) | ||
1694 | { | ||
1695 | struct macio_chip* macio; | ||
1696 | int i; | ||
1697 | |||
1698 | macio = &macio_chips[0]; | ||
1699 | if (macio->type != macio_keylargo && macio->type != macio_pangea && | ||
1700 | macio->type != macio_intrepid) | ||
1701 | return -ENODEV; | ||
1702 | |||
1703 | /* | ||
1704 | * Wakeup the host bridge | ||
1705 | */ | ||
1706 | UN_OUT(UNI_N_POWER_MGT, UNI_N_POWER_MGT_NORMAL); | ||
1707 | udelay(10); | ||
1708 | UN_OUT(UNI_N_HWINIT_STATE, UNI_N_HWINIT_STATE_RUNNING); | ||
1709 | udelay(10); | ||
1710 | |||
1711 | /* | ||
1712 | * Restore KeyLargo | ||
1713 | */ | ||
1714 | |||
1715 | if (macio->type == macio_keylargo) { | ||
1716 | MACIO_OUT32(KEYLARGO_MBCR, save_mbcr); | ||
1717 | (void)MACIO_IN32(KEYLARGO_MBCR); udelay(10); | ||
1718 | } | ||
1719 | MACIO_OUT32(KEYLARGO_FCR0, save_fcr[0]); | ||
1720 | (void)MACIO_IN32(KEYLARGO_FCR0); udelay(10); | ||
1721 | MACIO_OUT32(KEYLARGO_FCR1, save_fcr[1]); | ||
1722 | (void)MACIO_IN32(KEYLARGO_FCR1); udelay(10); | ||
1723 | MACIO_OUT32(KEYLARGO_FCR2, save_fcr[2]); | ||
1724 | (void)MACIO_IN32(KEYLARGO_FCR2); udelay(10); | ||
1725 | MACIO_OUT32(KEYLARGO_FCR3, save_fcr[3]); | ||
1726 | (void)MACIO_IN32(KEYLARGO_FCR3); udelay(10); | ||
1727 | MACIO_OUT32(KEYLARGO_FCR4, save_fcr[4]); | ||
1728 | (void)MACIO_IN32(KEYLARGO_FCR4); udelay(10); | ||
1729 | if (macio->type == macio_pangea || macio->type == macio_intrepid) { | ||
1730 | MACIO_OUT32(KEYLARGO_FCR5, save_fcr[5]); | ||
1731 | (void)MACIO_IN32(KEYLARGO_FCR5); udelay(10); | ||
1732 | } | ||
1733 | |||
1734 | dbdma_restore(macio, save_dbdma); | ||
1735 | |||
1736 | MACIO_OUT32(KEYLARGO_GPIO_LEVELS0, save_gpio_levels[0]); | ||
1737 | MACIO_OUT32(KEYLARGO_GPIO_LEVELS1, save_gpio_levels[1]); | ||
1738 | for (i=0; i<KEYLARGO_GPIO_EXTINT_CNT; i++) | ||
1739 | MACIO_OUT8(KEYLARGO_GPIO_EXTINT_0+i, save_gpio_extint[i]); | ||
1740 | for (i=0; i<KEYLARGO_GPIO_CNT; i++) | ||
1741 | MACIO_OUT8(KEYLARGO_GPIO_0+i, save_gpio_normal[i]); | ||
1742 | |||
1743 | /* FIXME more black magic with OpenPIC ... */ | ||
1744 | if (pmac_mb.model_id == PMAC_TYPE_SAWTOOTH) { | ||
1745 | MACIO_BIC(0x506e0, 0x00400000); | ||
1746 | MACIO_BIC(0x506e0, 0x80000000); | ||
1747 | } | ||
1748 | |||
1749 | UN_OUT(UNI_N_CLOCK_CNTL, save_unin_clock_ctl); | ||
1750 | udelay(100); | ||
1751 | |||
1752 | /* Restore clock spreading */ | ||
1753 | if (macio->type == macio_intrepid) { | ||
1754 | UN_OUT(UNI_N_CLOCK_SPREADING, 2); | ||
1755 | mdelay(40); | ||
1756 | } | ||
1757 | |||
1758 | return 0; | ||
1759 | } | ||
1760 | |||
1761 | static long __pmac | ||
1762 | core99_sleep_state(struct device_node* node, long param, long value) | ||
1763 | { | ||
1764 | /* Param == 1 means to enter the "fake sleep" mode that is | ||
1765 | * used for CPU speed switch | ||
1766 | */ | ||
1767 | if (param == 1) { | ||
1768 | if (value == 1) { | ||
1769 | UN_OUT(UNI_N_HWINIT_STATE, UNI_N_HWINIT_STATE_SLEEPING); | ||
1770 | UN_OUT(UNI_N_POWER_MGT, UNI_N_POWER_MGT_IDLE2); | ||
1771 | } else { | ||
1772 | UN_OUT(UNI_N_POWER_MGT, UNI_N_POWER_MGT_NORMAL); | ||
1773 | udelay(10); | ||
1774 | UN_OUT(UNI_N_HWINIT_STATE, UNI_N_HWINIT_STATE_RUNNING); | ||
1775 | udelay(10); | ||
1776 | } | ||
1777 | return 0; | ||
1778 | } | ||
1779 | if ((pmac_mb.board_flags & PMAC_MB_CAN_SLEEP) == 0) | ||
1780 | return -EPERM; | ||
1781 | |||
1782 | #ifdef CONFIG_CPU_FREQ_PMAC | ||
1783 | /* XXX should be elsewhere */ | ||
1784 | if (machine_is_compatible("PowerBook6,5") || | ||
1785 | machine_is_compatible("PowerBook6,4") || | ||
1786 | machine_is_compatible("PowerBook5,5") || | ||
1787 | machine_is_compatible("PowerBook5,4")) { | ||
1788 | struct device_node *volt_gpio_np; | ||
1789 | u32 *reg = NULL; | ||
1790 | |||
1791 | volt_gpio_np = of_find_node_by_name(NULL, "cpu-vcore-select"); | ||
1792 | if (volt_gpio_np != NULL) | ||
1793 | reg = (u32 *)get_property(volt_gpio_np, "reg", NULL); | ||
1794 | if (reg != NULL) { | ||
1795 | /* Set the CPU voltage high if sleeping */ | ||
1796 | if (value == 1) { | ||
1797 | pmac_call_feature(PMAC_FTR_WRITE_GPIO, NULL, | ||
1798 | *reg, 0x05); | ||
1799 | } else if (value == 0 && (mfspr(SPRN_HID1) & HID1_DFS)) { | ||
1800 | pmac_call_feature(PMAC_FTR_WRITE_GPIO, NULL, | ||
1801 | *reg, 0x04); | ||
1802 | } | ||
1803 | mdelay(2); | ||
1804 | } | ||
1805 | } | ||
1806 | #endif /* CONFIG_CPU_FREQ_PMAC */ | ||
1807 | |||
1808 | if (value == 1) | ||
1809 | return core99_sleep(); | ||
1810 | else if (value == 0) | ||
1811 | return core99_wake_up(); | ||
1812 | return 0; | ||
1813 | } | ||
1814 | |||
1815 | #endif /* CONFIG_POWER4 */ | ||
1816 | |||
1817 | static long __pmac | ||
1818 | generic_dev_can_wake(struct device_node* node, long param, long value) | ||
1819 | { | ||
1820 | /* Todo: eventually check we are really dealing with on-board | ||
1821 | * video device ... | ||
1822 | */ | ||
1823 | |||
1824 | if (pmac_mb.board_flags & PMAC_MB_MAY_SLEEP) | ||
1825 | pmac_mb.board_flags |= PMAC_MB_CAN_SLEEP; | ||
1826 | return 0; | ||
1827 | } | ||
1828 | |||
1829 | static long __pmac | ||
1830 | generic_get_mb_info(struct device_node* node, long param, long value) | ||
1831 | { | ||
1832 | switch(param) { | ||
1833 | case PMAC_MB_INFO_MODEL: | ||
1834 | return pmac_mb.model_id; | ||
1835 | case PMAC_MB_INFO_FLAGS: | ||
1836 | return pmac_mb.board_flags; | ||
1837 | case PMAC_MB_INFO_NAME: | ||
1838 | /* hack hack hack... but should work */ | ||
1839 | *((const char **)value) = pmac_mb.model_name; | ||
1840 | return 0; | ||
1841 | } | ||
1842 | return -EINVAL; | ||
1843 | } | ||
1844 | |||
1845 | |||
1846 | /* | ||
1847 | * Table definitions | ||
1848 | */ | ||
1849 | |||
1850 | /* Used on any machine | ||
1851 | */ | ||
1852 | static struct feature_table_entry any_features[] __pmacdata = { | ||
1853 | { PMAC_FTR_GET_MB_INFO, generic_get_mb_info }, | ||
1854 | { PMAC_FTR_DEVICE_CAN_WAKE, generic_dev_can_wake }, | ||
1855 | { 0, NULL } | ||
1856 | }; | ||
1857 | |||
1858 | #ifndef CONFIG_POWER4 | ||
1859 | |||
1860 | /* OHare based motherboards. Currently, we only use these on the | ||
1861 | * 2400,3400 and 3500 series powerbooks. Some older desktops seem | ||
1862 | * to have issues with turning on/off those asic cells | ||
1863 | */ | ||
1864 | static struct feature_table_entry ohare_features[] __pmacdata = { | ||
1865 | { PMAC_FTR_SCC_ENABLE, ohare_htw_scc_enable }, | ||
1866 | { PMAC_FTR_SWIM3_ENABLE, ohare_floppy_enable }, | ||
1867 | { PMAC_FTR_MESH_ENABLE, ohare_mesh_enable }, | ||
1868 | { PMAC_FTR_IDE_ENABLE, ohare_ide_enable}, | ||
1869 | { PMAC_FTR_IDE_RESET, ohare_ide_reset}, | ||
1870 | { PMAC_FTR_SLEEP_STATE, ohare_sleep_state }, | ||
1871 | { 0, NULL } | ||
1872 | }; | ||
1873 | |||
1874 | /* Heathrow desktop machines (Beige G3). | ||
1875 | * Separated as some features couldn't be properly tested | ||
1876 | * and the serial port control bits appear to confuse it. | ||
1877 | */ | ||
1878 | static struct feature_table_entry heathrow_desktop_features[] __pmacdata = { | ||
1879 | { PMAC_FTR_SWIM3_ENABLE, heathrow_floppy_enable }, | ||
1880 | { PMAC_FTR_MESH_ENABLE, heathrow_mesh_enable }, | ||
1881 | { PMAC_FTR_IDE_ENABLE, heathrow_ide_enable }, | ||
1882 | { PMAC_FTR_IDE_RESET, heathrow_ide_reset }, | ||
1883 | { PMAC_FTR_BMAC_ENABLE, heathrow_bmac_enable }, | ||
1884 | { 0, NULL } | ||
1885 | }; | ||
1886 | |||
1887 | /* Heathrow based laptop, that is the Wallstreet and mainstreet | ||
1888 | * powerbooks. | ||
1889 | */ | ||
1890 | static struct feature_table_entry heathrow_laptop_features[] __pmacdata = { | ||
1891 | { PMAC_FTR_SCC_ENABLE, ohare_htw_scc_enable }, | ||
1892 | { PMAC_FTR_MODEM_ENABLE, heathrow_modem_enable }, | ||
1893 | { PMAC_FTR_SWIM3_ENABLE, heathrow_floppy_enable }, | ||
1894 | { PMAC_FTR_MESH_ENABLE, heathrow_mesh_enable }, | ||
1895 | { PMAC_FTR_IDE_ENABLE, heathrow_ide_enable }, | ||
1896 | { PMAC_FTR_IDE_RESET, heathrow_ide_reset }, | ||
1897 | { PMAC_FTR_BMAC_ENABLE, heathrow_bmac_enable }, | ||
1898 | { PMAC_FTR_SOUND_CHIP_ENABLE, heathrow_sound_enable }, | ||
1899 | { PMAC_FTR_SLEEP_STATE, heathrow_sleep_state }, | ||
1900 | { 0, NULL } | ||
1901 | }; | ||
1902 | |||
1903 | /* Paddington based machines | ||
1904 | * The lombard (101) powerbook, first iMac models, B&W G3 and Yikes G4. | ||
1905 | */ | ||
1906 | static struct feature_table_entry paddington_features[] __pmacdata = { | ||
1907 | { PMAC_FTR_SCC_ENABLE, ohare_htw_scc_enable }, | ||
1908 | { PMAC_FTR_MODEM_ENABLE, heathrow_modem_enable }, | ||
1909 | { PMAC_FTR_SWIM3_ENABLE, heathrow_floppy_enable }, | ||
1910 | { PMAC_FTR_MESH_ENABLE, heathrow_mesh_enable }, | ||
1911 | { PMAC_FTR_IDE_ENABLE, heathrow_ide_enable }, | ||
1912 | { PMAC_FTR_IDE_RESET, heathrow_ide_reset }, | ||
1913 | { PMAC_FTR_BMAC_ENABLE, heathrow_bmac_enable }, | ||
1914 | { PMAC_FTR_SOUND_CHIP_ENABLE, heathrow_sound_enable }, | ||
1915 | { PMAC_FTR_SLEEP_STATE, heathrow_sleep_state }, | ||
1916 | { 0, NULL } | ||
1917 | }; | ||
1918 | |||
1919 | /* Core99 & MacRISC 2 machines (all machines released since the | ||
1920 | * iBook (included), that is all AGP machines, except pangea | ||
1921 | * chipset. The pangea chipset is the "combo" UniNorth/KeyLargo | ||
1922 | * used on iBook2 & iMac "flow power". | ||
1923 | */ | ||
1924 | static struct feature_table_entry core99_features[] __pmacdata = { | ||
1925 | { PMAC_FTR_SCC_ENABLE, core99_scc_enable }, | ||
1926 | { PMAC_FTR_MODEM_ENABLE, core99_modem_enable }, | ||
1927 | { PMAC_FTR_IDE_ENABLE, core99_ide_enable }, | ||
1928 | { PMAC_FTR_IDE_RESET, core99_ide_reset }, | ||
1929 | { PMAC_FTR_GMAC_ENABLE, core99_gmac_enable }, | ||
1930 | { PMAC_FTR_GMAC_PHY_RESET, core99_gmac_phy_reset }, | ||
1931 | { PMAC_FTR_SOUND_CHIP_ENABLE, core99_sound_chip_enable }, | ||
1932 | { PMAC_FTR_AIRPORT_ENABLE, core99_airport_enable }, | ||
1933 | { PMAC_FTR_USB_ENABLE, core99_usb_enable }, | ||
1934 | { PMAC_FTR_1394_ENABLE, core99_firewire_enable }, | ||
1935 | { PMAC_FTR_1394_CABLE_POWER, core99_firewire_cable_power }, | ||
1936 | { PMAC_FTR_SLEEP_STATE, core99_sleep_state }, | ||
1937 | #ifdef CONFIG_SMP | ||
1938 | { PMAC_FTR_RESET_CPU, core99_reset_cpu }, | ||
1939 | #endif /* CONFIG_SMP */ | ||
1940 | { PMAC_FTR_READ_GPIO, core99_read_gpio }, | ||
1941 | { PMAC_FTR_WRITE_GPIO, core99_write_gpio }, | ||
1942 | { 0, NULL } | ||
1943 | }; | ||
1944 | |||
1945 | /* RackMac | ||
1946 | */ | ||
1947 | static struct feature_table_entry rackmac_features[] __pmacdata = { | ||
1948 | { PMAC_FTR_SCC_ENABLE, core99_scc_enable }, | ||
1949 | { PMAC_FTR_IDE_ENABLE, core99_ide_enable }, | ||
1950 | { PMAC_FTR_IDE_RESET, core99_ide_reset }, | ||
1951 | { PMAC_FTR_GMAC_ENABLE, core99_gmac_enable }, | ||
1952 | { PMAC_FTR_GMAC_PHY_RESET, core99_gmac_phy_reset }, | ||
1953 | { PMAC_FTR_USB_ENABLE, core99_usb_enable }, | ||
1954 | { PMAC_FTR_1394_ENABLE, core99_firewire_enable }, | ||
1955 | { PMAC_FTR_1394_CABLE_POWER, core99_firewire_cable_power }, | ||
1956 | { PMAC_FTR_SLEEP_STATE, core99_sleep_state }, | ||
1957 | #ifdef CONFIG_SMP | ||
1958 | { PMAC_FTR_RESET_CPU, core99_reset_cpu }, | ||
1959 | #endif /* CONFIG_SMP */ | ||
1960 | { PMAC_FTR_READ_GPIO, core99_read_gpio }, | ||
1961 | { PMAC_FTR_WRITE_GPIO, core99_write_gpio }, | ||
1962 | { 0, NULL } | ||
1963 | }; | ||
1964 | |||
1965 | /* Pangea features | ||
1966 | */ | ||
1967 | static struct feature_table_entry pangea_features[] __pmacdata = { | ||
1968 | { PMAC_FTR_SCC_ENABLE, core99_scc_enable }, | ||
1969 | { PMAC_FTR_MODEM_ENABLE, pangea_modem_enable }, | ||
1970 | { PMAC_FTR_IDE_ENABLE, core99_ide_enable }, | ||
1971 | { PMAC_FTR_IDE_RESET, core99_ide_reset }, | ||
1972 | { PMAC_FTR_GMAC_ENABLE, core99_gmac_enable }, | ||
1973 | { PMAC_FTR_GMAC_PHY_RESET, core99_gmac_phy_reset }, | ||
1974 | { PMAC_FTR_SOUND_CHIP_ENABLE, core99_sound_chip_enable }, | ||
1975 | { PMAC_FTR_AIRPORT_ENABLE, core99_airport_enable }, | ||
1976 | { PMAC_FTR_USB_ENABLE, core99_usb_enable }, | ||
1977 | { PMAC_FTR_1394_ENABLE, core99_firewire_enable }, | ||
1978 | { PMAC_FTR_1394_CABLE_POWER, core99_firewire_cable_power }, | ||
1979 | { PMAC_FTR_SLEEP_STATE, core99_sleep_state }, | ||
1980 | { PMAC_FTR_READ_GPIO, core99_read_gpio }, | ||
1981 | { PMAC_FTR_WRITE_GPIO, core99_write_gpio }, | ||
1982 | { 0, NULL } | ||
1983 | }; | ||
1984 | |||
1985 | /* Intrepid features | ||
1986 | */ | ||
1987 | static struct feature_table_entry intrepid_features[] __pmacdata = { | ||
1988 | { PMAC_FTR_SCC_ENABLE, core99_scc_enable }, | ||
1989 | { PMAC_FTR_MODEM_ENABLE, pangea_modem_enable }, | ||
1990 | { PMAC_FTR_IDE_ENABLE, core99_ide_enable }, | ||
1991 | { PMAC_FTR_IDE_RESET, core99_ide_reset }, | ||
1992 | { PMAC_FTR_GMAC_ENABLE, core99_gmac_enable }, | ||
1993 | { PMAC_FTR_GMAC_PHY_RESET, core99_gmac_phy_reset }, | ||
1994 | { PMAC_FTR_SOUND_CHIP_ENABLE, core99_sound_chip_enable }, | ||
1995 | { PMAC_FTR_AIRPORT_ENABLE, core99_airport_enable }, | ||
1996 | { PMAC_FTR_USB_ENABLE, core99_usb_enable }, | ||
1997 | { PMAC_FTR_1394_ENABLE, core99_firewire_enable }, | ||
1998 | { PMAC_FTR_1394_CABLE_POWER, core99_firewire_cable_power }, | ||
1999 | { PMAC_FTR_SLEEP_STATE, core99_sleep_state }, | ||
2000 | { PMAC_FTR_READ_GPIO, core99_read_gpio }, | ||
2001 | { PMAC_FTR_WRITE_GPIO, core99_write_gpio }, | ||
2002 | { PMAC_FTR_AACK_DELAY_ENABLE, intrepid_aack_delay_enable }, | ||
2003 | { 0, NULL } | ||
2004 | }; | ||
2005 | |||
2006 | #else /* CONFIG_POWER4 */ | ||
2007 | |||
2008 | /* G5 features | ||
2009 | */ | ||
2010 | static struct feature_table_entry g5_features[] __pmacdata = { | ||
2011 | { PMAC_FTR_GMAC_ENABLE, g5_gmac_enable }, | ||
2012 | { PMAC_FTR_1394_ENABLE, g5_fw_enable }, | ||
2013 | { PMAC_FTR_ENABLE_MPIC, g5_mpic_enable }, | ||
2014 | #ifdef CONFIG_SMP | ||
2015 | { PMAC_FTR_RESET_CPU, g5_reset_cpu }, | ||
2016 | #endif /* CONFIG_SMP */ | ||
2017 | { PMAC_FTR_READ_GPIO, core99_read_gpio }, | ||
2018 | { PMAC_FTR_WRITE_GPIO, core99_write_gpio }, | ||
2019 | { 0, NULL } | ||
2020 | }; | ||
2021 | |||
2022 | #endif /* CONFIG_POWER4 */ | ||
2023 | |||
2024 | static struct pmac_mb_def pmac_mb_defs[] __pmacdata = { | ||
2025 | #ifndef CONFIG_POWER4 | ||
2026 | /* | ||
2027 | * Desktops | ||
2028 | */ | ||
2029 | |||
2030 | { "AAPL,8500", "PowerMac 8500/8600", | ||
2031 | PMAC_TYPE_PSURGE, NULL, | ||
2032 | 0 | ||
2033 | }, | ||
2034 | { "AAPL,9500", "PowerMac 9500/9600", | ||
2035 | PMAC_TYPE_PSURGE, NULL, | ||
2036 | 0 | ||
2037 | }, | ||
2038 | { "AAPL,7200", "PowerMac 7200", | ||
2039 | PMAC_TYPE_PSURGE, NULL, | ||
2040 | 0 | ||
2041 | }, | ||
2042 | { "AAPL,7300", "PowerMac 7200/7300", | ||
2043 | PMAC_TYPE_PSURGE, NULL, | ||
2044 | 0 | ||
2045 | }, | ||
2046 | { "AAPL,7500", "PowerMac 7500", | ||
2047 | PMAC_TYPE_PSURGE, NULL, | ||
2048 | 0 | ||
2049 | }, | ||
2050 | { "AAPL,ShinerESB", "Apple Network Server", | ||
2051 | PMAC_TYPE_ANS, NULL, | ||
2052 | 0 | ||
2053 | }, | ||
2054 | { "AAPL,e407", "Alchemy", | ||
2055 | PMAC_TYPE_ALCHEMY, NULL, | ||
2056 | 0 | ||
2057 | }, | ||
2058 | { "AAPL,e411", "Gazelle", | ||
2059 | PMAC_TYPE_GAZELLE, NULL, | ||
2060 | 0 | ||
2061 | }, | ||
2062 | { "AAPL,Gossamer", "PowerMac G3 (Gossamer)", | ||
2063 | PMAC_TYPE_GOSSAMER, heathrow_desktop_features, | ||
2064 | 0 | ||
2065 | }, | ||
2066 | { "AAPL,PowerMac G3", "PowerMac G3 (Silk)", | ||
2067 | PMAC_TYPE_SILK, heathrow_desktop_features, | ||
2068 | 0 | ||
2069 | }, | ||
2070 | { "PowerMac1,1", "Blue&White G3", | ||
2071 | PMAC_TYPE_YOSEMITE, paddington_features, | ||
2072 | 0 | ||
2073 | }, | ||
2074 | { "PowerMac1,2", "PowerMac G4 PCI Graphics", | ||
2075 | PMAC_TYPE_YIKES, paddington_features, | ||
2076 | 0 | ||
2077 | }, | ||
2078 | { "PowerMac2,1", "iMac FireWire", | ||
2079 | PMAC_TYPE_FW_IMAC, core99_features, | ||
2080 | PMAC_MB_MAY_SLEEP | PMAC_MB_OLD_CORE99 | ||
2081 | }, | ||
2082 | { "PowerMac2,2", "iMac FireWire", | ||
2083 | PMAC_TYPE_FW_IMAC, core99_features, | ||
2084 | PMAC_MB_MAY_SLEEP | PMAC_MB_OLD_CORE99 | ||
2085 | }, | ||
2086 | { "PowerMac3,1", "PowerMac G4 AGP Graphics", | ||
2087 | PMAC_TYPE_SAWTOOTH, core99_features, | ||
2088 | PMAC_MB_OLD_CORE99 | ||
2089 | }, | ||
2090 | { "PowerMac3,2", "PowerMac G4 AGP Graphics", | ||
2091 | PMAC_TYPE_SAWTOOTH, core99_features, | ||
2092 | PMAC_MB_MAY_SLEEP | PMAC_MB_OLD_CORE99 | ||
2093 | }, | ||
2094 | { "PowerMac3,3", "PowerMac G4 AGP Graphics", | ||
2095 | PMAC_TYPE_SAWTOOTH, core99_features, | ||
2096 | PMAC_MB_MAY_SLEEP | PMAC_MB_OLD_CORE99 | ||
2097 | }, | ||
2098 | { "PowerMac3,4", "PowerMac G4 Silver", | ||
2099 | PMAC_TYPE_QUICKSILVER, core99_features, | ||
2100 | PMAC_MB_MAY_SLEEP | ||
2101 | }, | ||
2102 | { "PowerMac3,5", "PowerMac G4 Silver", | ||
2103 | PMAC_TYPE_QUICKSILVER, core99_features, | ||
2104 | PMAC_MB_MAY_SLEEP | ||
2105 | }, | ||
2106 | { "PowerMac3,6", "PowerMac G4 Windtunnel", | ||
2107 | PMAC_TYPE_WINDTUNNEL, core99_features, | ||
2108 | PMAC_MB_MAY_SLEEP, | ||
2109 | }, | ||
2110 | { "PowerMac4,1", "iMac \"Flower Power\"", | ||
2111 | PMAC_TYPE_PANGEA_IMAC, pangea_features, | ||
2112 | PMAC_MB_MAY_SLEEP | ||
2113 | }, | ||
2114 | { "PowerMac4,2", "Flat panel iMac", | ||
2115 | PMAC_TYPE_FLAT_PANEL_IMAC, pangea_features, | ||
2116 | PMAC_MB_CAN_SLEEP | ||
2117 | }, | ||
2118 | { "PowerMac4,4", "eMac", | ||
2119 | PMAC_TYPE_EMAC, core99_features, | ||
2120 | PMAC_MB_MAY_SLEEP | ||
2121 | }, | ||
2122 | { "PowerMac5,1", "PowerMac G4 Cube", | ||
2123 | PMAC_TYPE_CUBE, core99_features, | ||
2124 | PMAC_MB_MAY_SLEEP | PMAC_MB_OLD_CORE99 | ||
2125 | }, | ||
2126 | { "PowerMac6,1", "Flat panel iMac", | ||
2127 | PMAC_TYPE_UNKNOWN_INTREPID, intrepid_features, | ||
2128 | PMAC_MB_MAY_SLEEP, | ||
2129 | }, | ||
2130 | { "PowerMac6,3", "Flat panel iMac", | ||
2131 | PMAC_TYPE_UNKNOWN_INTREPID, intrepid_features, | ||
2132 | PMAC_MB_MAY_SLEEP, | ||
2133 | }, | ||
2134 | { "PowerMac6,4", "eMac", | ||
2135 | PMAC_TYPE_UNKNOWN_INTREPID, intrepid_features, | ||
2136 | PMAC_MB_MAY_SLEEP, | ||
2137 | }, | ||
2138 | { "PowerMac10,1", "Mac mini", | ||
2139 | PMAC_TYPE_UNKNOWN_INTREPID, intrepid_features, | ||
2140 | PMAC_MB_MAY_SLEEP | PMAC_MB_HAS_FW_POWER, | ||
2141 | }, | ||
2142 | { "iMac,1", "iMac (first generation)", | ||
2143 | PMAC_TYPE_ORIG_IMAC, paddington_features, | ||
2144 | 0 | ||
2145 | }, | ||
2146 | |||
2147 | /* | ||
2148 | * Xserve's | ||
2149 | */ | ||
2150 | |||
2151 | { "RackMac1,1", "XServe", | ||
2152 | PMAC_TYPE_RACKMAC, rackmac_features, | ||
2153 | 0, | ||
2154 | }, | ||
2155 | { "RackMac1,2", "XServe rev. 2", | ||
2156 | PMAC_TYPE_RACKMAC, rackmac_features, | ||
2157 | 0, | ||
2158 | }, | ||
2159 | |||
2160 | /* | ||
2161 | * Laptops | ||
2162 | */ | ||
2163 | |||
2164 | { "AAPL,3400/2400", "PowerBook 3400", | ||
2165 | PMAC_TYPE_HOOPER, ohare_features, | ||
2166 | PMAC_MB_CAN_SLEEP | PMAC_MB_MOBILE | ||
2167 | }, | ||
2168 | { "AAPL,3500", "PowerBook 3500", | ||
2169 | PMAC_TYPE_KANGA, ohare_features, | ||
2170 | PMAC_MB_CAN_SLEEP | PMAC_MB_MOBILE | ||
2171 | }, | ||
2172 | { "AAPL,PowerBook1998", "PowerBook Wallstreet", | ||
2173 | PMAC_TYPE_WALLSTREET, heathrow_laptop_features, | ||
2174 | PMAC_MB_CAN_SLEEP | PMAC_MB_MOBILE | ||
2175 | }, | ||
2176 | { "PowerBook1,1", "PowerBook 101 (Lombard)", | ||
2177 | PMAC_TYPE_101_PBOOK, paddington_features, | ||
2178 | PMAC_MB_MAY_SLEEP | PMAC_MB_MOBILE | ||
2179 | }, | ||
2180 | { "PowerBook2,1", "iBook (first generation)", | ||
2181 | PMAC_TYPE_ORIG_IBOOK, core99_features, | ||
2182 | PMAC_MB_CAN_SLEEP | PMAC_MB_OLD_CORE99 | PMAC_MB_MOBILE | ||
2183 | }, | ||
2184 | { "PowerBook2,2", "iBook FireWire", | ||
2185 | PMAC_TYPE_FW_IBOOK, core99_features, | ||
2186 | PMAC_MB_MAY_SLEEP | PMAC_MB_HAS_FW_POWER | | ||
2187 | PMAC_MB_OLD_CORE99 | PMAC_MB_MOBILE | ||
2188 | }, | ||
2189 | { "PowerBook3,1", "PowerBook Pismo", | ||
2190 | PMAC_TYPE_PISMO, core99_features, | ||
2191 | PMAC_MB_MAY_SLEEP | PMAC_MB_HAS_FW_POWER | | ||
2192 | PMAC_MB_OLD_CORE99 | PMAC_MB_MOBILE | ||
2193 | }, | ||
2194 | { "PowerBook3,2", "PowerBook Titanium", | ||
2195 | PMAC_TYPE_TITANIUM, core99_features, | ||
2196 | PMAC_MB_MAY_SLEEP | PMAC_MB_HAS_FW_POWER | PMAC_MB_MOBILE | ||
2197 | }, | ||
2198 | { "PowerBook3,3", "PowerBook Titanium II", | ||
2199 | PMAC_TYPE_TITANIUM2, core99_features, | ||
2200 | PMAC_MB_MAY_SLEEP | PMAC_MB_HAS_FW_POWER | PMAC_MB_MOBILE | ||
2201 | }, | ||
2202 | { "PowerBook3,4", "PowerBook Titanium III", | ||
2203 | PMAC_TYPE_TITANIUM3, core99_features, | ||
2204 | PMAC_MB_MAY_SLEEP | PMAC_MB_HAS_FW_POWER | PMAC_MB_MOBILE | ||
2205 | }, | ||
2206 | { "PowerBook3,5", "PowerBook Titanium IV", | ||
2207 | PMAC_TYPE_TITANIUM4, core99_features, | ||
2208 | PMAC_MB_MAY_SLEEP | PMAC_MB_HAS_FW_POWER | PMAC_MB_MOBILE | ||
2209 | }, | ||
2210 | { "PowerBook4,1", "iBook 2", | ||
2211 | PMAC_TYPE_IBOOK2, pangea_features, | ||
2212 | PMAC_MB_MAY_SLEEP | PMAC_MB_HAS_FW_POWER | PMAC_MB_MOBILE | ||
2213 | }, | ||
2214 | { "PowerBook4,2", "iBook 2", | ||
2215 | PMAC_TYPE_IBOOK2, pangea_features, | ||
2216 | PMAC_MB_MAY_SLEEP | PMAC_MB_HAS_FW_POWER | PMAC_MB_MOBILE | ||
2217 | }, | ||
2218 | { "PowerBook4,3", "iBook 2 rev. 2", | ||
2219 | PMAC_TYPE_IBOOK2, pangea_features, | ||
2220 | PMAC_MB_MAY_SLEEP | PMAC_MB_HAS_FW_POWER | PMAC_MB_MOBILE | ||
2221 | }, | ||
2222 | { "PowerBook5,1", "PowerBook G4 17\"", | ||
2223 | PMAC_TYPE_UNKNOWN_INTREPID, intrepid_features, | ||
2224 | PMAC_MB_HAS_FW_POWER | PMAC_MB_MOBILE, | ||
2225 | }, | ||
2226 | { "PowerBook5,2", "PowerBook G4 15\"", | ||
2227 | PMAC_TYPE_UNKNOWN_INTREPID, intrepid_features, | ||
2228 | PMAC_MB_MAY_SLEEP | PMAC_MB_HAS_FW_POWER | PMAC_MB_MOBILE, | ||
2229 | }, | ||
2230 | { "PowerBook5,3", "PowerBook G4 17\"", | ||
2231 | PMAC_TYPE_UNKNOWN_INTREPID, intrepid_features, | ||
2232 | PMAC_MB_MAY_SLEEP | PMAC_MB_HAS_FW_POWER | PMAC_MB_MOBILE, | ||
2233 | }, | ||
2234 | { "PowerBook5,4", "PowerBook G4 15\"", | ||
2235 | PMAC_TYPE_UNKNOWN_INTREPID, intrepid_features, | ||
2236 | PMAC_MB_MAY_SLEEP | PMAC_MB_HAS_FW_POWER | PMAC_MB_MOBILE, | ||
2237 | }, | ||
2238 | { "PowerBook5,5", "PowerBook G4 17\"", | ||
2239 | PMAC_TYPE_UNKNOWN_INTREPID, intrepid_features, | ||
2240 | PMAC_MB_MAY_SLEEP | PMAC_MB_HAS_FW_POWER | PMAC_MB_MOBILE, | ||
2241 | }, | ||
2242 | { "PowerBook5,6", "PowerBook G4 15\"", | ||
2243 | PMAC_TYPE_UNKNOWN_INTREPID, intrepid_features, | ||
2244 | PMAC_MB_MAY_SLEEP | PMAC_MB_HAS_FW_POWER | PMAC_MB_MOBILE, | ||
2245 | }, | ||
2246 | { "PowerBook5,7", "PowerBook G4 17\"", | ||
2247 | PMAC_TYPE_UNKNOWN_INTREPID, intrepid_features, | ||
2248 | PMAC_MB_MAY_SLEEP | PMAC_MB_HAS_FW_POWER | PMAC_MB_MOBILE, | ||
2249 | }, | ||
2250 | { "PowerBook6,1", "PowerBook G4 12\"", | ||
2251 | PMAC_TYPE_UNKNOWN_INTREPID, intrepid_features, | ||
2252 | PMAC_MB_MAY_SLEEP | PMAC_MB_HAS_FW_POWER | PMAC_MB_MOBILE, | ||
2253 | }, | ||
2254 | { "PowerBook6,2", "PowerBook G4", | ||
2255 | PMAC_TYPE_UNKNOWN_INTREPID, intrepid_features, | ||
2256 | PMAC_MB_MAY_SLEEP | PMAC_MB_HAS_FW_POWER | PMAC_MB_MOBILE, | ||
2257 | }, | ||
2258 | { "PowerBook6,3", "iBook G4", | ||
2259 | PMAC_TYPE_UNKNOWN_INTREPID, intrepid_features, | ||
2260 | PMAC_MB_MAY_SLEEP | PMAC_MB_HAS_FW_POWER | PMAC_MB_MOBILE, | ||
2261 | }, | ||
2262 | { "PowerBook6,4", "PowerBook G4 12\"", | ||
2263 | PMAC_TYPE_UNKNOWN_INTREPID, intrepid_features, | ||
2264 | PMAC_MB_MAY_SLEEP | PMAC_MB_HAS_FW_POWER | PMAC_MB_MOBILE, | ||
2265 | }, | ||
2266 | { "PowerBook6,5", "iBook G4", | ||
2267 | PMAC_TYPE_UNKNOWN_INTREPID, intrepid_features, | ||
2268 | PMAC_MB_MAY_SLEEP | PMAC_MB_HAS_FW_POWER | PMAC_MB_MOBILE, | ||
2269 | }, | ||
2270 | { "PowerBook6,8", "PowerBook G4 12\"", | ||
2271 | PMAC_TYPE_UNKNOWN_INTREPID, intrepid_features, | ||
2272 | PMAC_MB_MAY_SLEEP | PMAC_MB_HAS_FW_POWER | PMAC_MB_MOBILE, | ||
2273 | }, | ||
2274 | #else /* CONFIG_POWER4 */ | ||
2275 | { "PowerMac7,2", "PowerMac G5", | ||
2276 | PMAC_TYPE_POWERMAC_G5, g5_features, | ||
2277 | 0, | ||
2278 | }, | ||
2279 | #endif /* CONFIG_POWER4 */ | ||
2280 | }; | ||
2281 | |||
2282 | /* | ||
2283 | * The toplevel feature_call callback | ||
2284 | */ | ||
2285 | long __pmac | ||
2286 | pmac_do_feature_call(unsigned int selector, ...) | ||
2287 | { | ||
2288 | struct device_node* node; | ||
2289 | long param, value; | ||
2290 | int i; | ||
2291 | feature_call func = NULL; | ||
2292 | va_list args; | ||
2293 | |||
2294 | if (pmac_mb.features) | ||
2295 | for (i=0; pmac_mb.features[i].function; i++) | ||
2296 | if (pmac_mb.features[i].selector == selector) { | ||
2297 | func = pmac_mb.features[i].function; | ||
2298 | break; | ||
2299 | } | ||
2300 | if (!func) | ||
2301 | for (i=0; any_features[i].function; i++) | ||
2302 | if (any_features[i].selector == selector) { | ||
2303 | func = any_features[i].function; | ||
2304 | break; | ||
2305 | } | ||
2306 | if (!func) | ||
2307 | return -ENODEV; | ||
2308 | |||
2309 | va_start(args, selector); | ||
2310 | node = (struct device_node*)va_arg(args, void*); | ||
2311 | param = va_arg(args, long); | ||
2312 | value = va_arg(args, long); | ||
2313 | va_end(args); | ||
2314 | |||
2315 | return func(node, param, value); | ||
2316 | } | ||
2317 | |||
2318 | static int __init | ||
2319 | probe_motherboard(void) | ||
2320 | { | ||
2321 | int i; | ||
2322 | struct macio_chip* macio = &macio_chips[0]; | ||
2323 | const char* model = NULL; | ||
2324 | struct device_node *dt; | ||
2325 | |||
2326 | /* Lookup known motherboard type in device-tree. First try an | ||
2327 | * exact match on the "model" property, then try a "compatible" | ||
2328 | * match is none is found. | ||
2329 | */ | ||
2330 | dt = find_devices("device-tree"); | ||
2331 | if (dt != NULL) | ||
2332 | model = (const char *) get_property(dt, "model", NULL); | ||
2333 | for(i=0; model && i<(sizeof(pmac_mb_defs)/sizeof(struct pmac_mb_def)); i++) { | ||
2334 | if (strcmp(model, pmac_mb_defs[i].model_string) == 0) { | ||
2335 | pmac_mb = pmac_mb_defs[i]; | ||
2336 | goto found; | ||
2337 | } | ||
2338 | } | ||
2339 | for(i=0; i<(sizeof(pmac_mb_defs)/sizeof(struct pmac_mb_def)); i++) { | ||
2340 | if (machine_is_compatible(pmac_mb_defs[i].model_string)) { | ||
2341 | pmac_mb = pmac_mb_defs[i]; | ||
2342 | goto found; | ||
2343 | } | ||
2344 | } | ||
2345 | |||
2346 | /* Fallback to selection depending on mac-io chip type */ | ||
2347 | switch(macio->type) { | ||
2348 | #ifndef CONFIG_POWER4 | ||
2349 | case macio_grand_central: | ||
2350 | pmac_mb.model_id = PMAC_TYPE_PSURGE; | ||
2351 | pmac_mb.model_name = "Unknown PowerSurge"; | ||
2352 | break; | ||
2353 | case macio_ohare: | ||
2354 | pmac_mb.model_id = PMAC_TYPE_UNKNOWN_OHARE; | ||
2355 | pmac_mb.model_name = "Unknown OHare-based"; | ||
2356 | break; | ||
2357 | case macio_heathrow: | ||
2358 | pmac_mb.model_id = PMAC_TYPE_UNKNOWN_HEATHROW; | ||
2359 | pmac_mb.model_name = "Unknown Heathrow-based"; | ||
2360 | pmac_mb.features = heathrow_desktop_features; | ||
2361 | break; | ||
2362 | case macio_paddington: | ||
2363 | pmac_mb.model_id = PMAC_TYPE_UNKNOWN_PADDINGTON; | ||
2364 | pmac_mb.model_name = "Unknown Paddington-based"; | ||
2365 | pmac_mb.features = paddington_features; | ||
2366 | break; | ||
2367 | case macio_keylargo: | ||
2368 | pmac_mb.model_id = PMAC_TYPE_UNKNOWN_CORE99; | ||
2369 | pmac_mb.model_name = "Unknown Keylargo-based"; | ||
2370 | pmac_mb.features = core99_features; | ||
2371 | break; | ||
2372 | case macio_pangea: | ||
2373 | pmac_mb.model_id = PMAC_TYPE_UNKNOWN_PANGEA; | ||
2374 | pmac_mb.model_name = "Unknown Pangea-based"; | ||
2375 | pmac_mb.features = pangea_features; | ||
2376 | break; | ||
2377 | case macio_intrepid: | ||
2378 | pmac_mb.model_id = PMAC_TYPE_UNKNOWN_INTREPID; | ||
2379 | pmac_mb.model_name = "Unknown Intrepid-based"; | ||
2380 | pmac_mb.features = intrepid_features; | ||
2381 | break; | ||
2382 | #else /* CONFIG_POWER4 */ | ||
2383 | case macio_keylargo2: | ||
2384 | pmac_mb.model_id = PMAC_TYPE_UNKNOWN_K2; | ||
2385 | pmac_mb.model_name = "Unknown G5"; | ||
2386 | pmac_mb.features = g5_features; | ||
2387 | break; | ||
2388 | #endif /* CONFIG_POWER4 */ | ||
2389 | default: | ||
2390 | return -ENODEV; | ||
2391 | } | ||
2392 | found: | ||
2393 | #ifndef CONFIG_POWER4 | ||
2394 | /* Fixup Hooper vs. Comet */ | ||
2395 | if (pmac_mb.model_id == PMAC_TYPE_HOOPER) { | ||
2396 | u32 __iomem * mach_id_ptr = ioremap(0xf3000034, 4); | ||
2397 | if (!mach_id_ptr) | ||
2398 | return -ENODEV; | ||
2399 | /* Here, I used to disable the media-bay on comet. It | ||
2400 | * appears this is wrong, the floppy connector is actually | ||
2401 | * a kind of media-bay and works with the current driver. | ||
2402 | */ | ||
2403 | if (__raw_readl(mach_id_ptr) & 0x20000000UL) | ||
2404 | pmac_mb.model_id = PMAC_TYPE_COMET; | ||
2405 | iounmap(mach_id_ptr); | ||
2406 | } | ||
2407 | #endif /* CONFIG_POWER4 */ | ||
2408 | |||
2409 | #ifdef CONFIG_6xx | ||
2410 | /* Set default value of powersave_nap on machines that support it. | ||
2411 | * It appears that uninorth rev 3 has a problem with it, we don't | ||
2412 | * enable it on those. In theory, the flush-on-lock property is | ||
2413 | * supposed to be set when not supported, but I'm not very confident | ||
2414 | * that all Apple OF revs did it properly, I do it the paranoid way. | ||
2415 | */ | ||
2416 | while (uninorth_base && uninorth_rev > 3) { | ||
2417 | struct device_node* np = find_path_device("/cpus"); | ||
2418 | if (!np || !np->child) { | ||
2419 | printk(KERN_WARNING "Can't find CPU(s) in device tree !\n"); | ||
2420 | break; | ||
2421 | } | ||
2422 | np = np->child; | ||
2423 | /* Nap mode not supported on SMP */ | ||
2424 | if (np->sibling) | ||
2425 | break; | ||
2426 | /* Nap mode not supported if flush-on-lock property is present */ | ||
2427 | if (get_property(np, "flush-on-lock", NULL)) | ||
2428 | break; | ||
2429 | powersave_nap = 1; | ||
2430 | printk(KERN_INFO "Processor NAP mode on idle enabled.\n"); | ||
2431 | break; | ||
2432 | } | ||
2433 | |||
2434 | /* On CPUs that support it (750FX), lowspeed by default during | ||
2435 | * NAP mode | ||
2436 | */ | ||
2437 | powersave_lowspeed = 1; | ||
2438 | #endif /* CONFIG_6xx */ | ||
2439 | #ifdef CONFIG_POWER4 | ||
2440 | powersave_nap = 1; | ||
2441 | #endif | ||
2442 | /* Check for "mobile" machine */ | ||
2443 | if (model && (strncmp(model, "PowerBook", 9) == 0 | ||
2444 | || strncmp(model, "iBook", 5) == 0)) | ||
2445 | pmac_mb.board_flags |= PMAC_MB_MOBILE; | ||
2446 | |||
2447 | |||
2448 | printk(KERN_INFO "PowerMac motherboard: %s\n", pmac_mb.model_name); | ||
2449 | return 0; | ||
2450 | } | ||
2451 | |||
2452 | /* Initialize the Core99 UniNorth host bridge and memory controller | ||
2453 | */ | ||
2454 | static void __init | ||
2455 | probe_uninorth(void) | ||
2456 | { | ||
2457 | unsigned long actrl; | ||
2458 | |||
2459 | /* Locate core99 Uni-N */ | ||
2460 | uninorth_node = of_find_node_by_name(NULL, "uni-n"); | ||
2461 | /* Locate G5 u3 */ | ||
2462 | if (uninorth_node == NULL) { | ||
2463 | uninorth_node = of_find_node_by_name(NULL, "u3"); | ||
2464 | uninorth_u3 = 1; | ||
2465 | } | ||
2466 | if (uninorth_node && uninorth_node->n_addrs > 0) { | ||
2467 | unsigned long address = uninorth_node->addrs[0].address; | ||
2468 | uninorth_base = ioremap(address, 0x40000); | ||
2469 | uninorth_rev = in_be32(UN_REG(UNI_N_VERSION)); | ||
2470 | if (uninorth_u3) | ||
2471 | u3_ht = ioremap(address + U3_HT_CONFIG_BASE, 0x1000); | ||
2472 | } else | ||
2473 | uninorth_node = NULL; | ||
2474 | |||
2475 | if (!uninorth_node) | ||
2476 | return; | ||
2477 | |||
2478 | printk(KERN_INFO "Found %s memory controller & host bridge, revision: %d\n", | ||
2479 | uninorth_u3 ? "U3" : "UniNorth", uninorth_rev); | ||
2480 | printk(KERN_INFO "Mapped at 0x%08lx\n", (unsigned long)uninorth_base); | ||
2481 | |||
2482 | /* Set the arbitrer QAck delay according to what Apple does | ||
2483 | */ | ||
2484 | if (uninorth_rev < 0x11) { | ||
2485 | actrl = UN_IN(UNI_N_ARB_CTRL) & ~UNI_N_ARB_CTRL_QACK_DELAY_MASK; | ||
2486 | actrl |= ((uninorth_rev < 3) ? UNI_N_ARB_CTRL_QACK_DELAY105 : | ||
2487 | UNI_N_ARB_CTRL_QACK_DELAY) << UNI_N_ARB_CTRL_QACK_DELAY_SHIFT; | ||
2488 | UN_OUT(UNI_N_ARB_CTRL, actrl); | ||
2489 | } | ||
2490 | |||
2491 | /* Some more magic as done by them in recent MacOS X on UniNorth | ||
2492 | * revs 1.5 to 2.O and Pangea. Seem to toggle the UniN Maxbus/PCI | ||
2493 | * memory timeout | ||
2494 | */ | ||
2495 | if ((uninorth_rev >= 0x11 && uninorth_rev <= 0x24) || uninorth_rev == 0xc0) | ||
2496 | UN_OUT(0x2160, UN_IN(0x2160) & 0x00ffffff); | ||
2497 | } | ||
2498 | |||
2499 | static void __init | ||
2500 | probe_one_macio(const char* name, const char* compat, int type) | ||
2501 | { | ||
2502 | struct device_node* node; | ||
2503 | int i; | ||
2504 | volatile u32 __iomem * base; | ||
2505 | u32* revp; | ||
2506 | |||
2507 | node = find_devices(name); | ||
2508 | if (!node || !node->n_addrs) | ||
2509 | return; | ||
2510 | if (compat) | ||
2511 | do { | ||
2512 | if (device_is_compatible(node, compat)) | ||
2513 | break; | ||
2514 | node = node->next; | ||
2515 | } while (node); | ||
2516 | if (!node) | ||
2517 | return; | ||
2518 | for(i=0; i<MAX_MACIO_CHIPS; i++) { | ||
2519 | if (!macio_chips[i].of_node) | ||
2520 | break; | ||
2521 | if (macio_chips[i].of_node == node) | ||
2522 | return; | ||
2523 | } | ||
2524 | if (i >= MAX_MACIO_CHIPS) { | ||
2525 | printk(KERN_ERR "pmac_feature: Please increase MAX_MACIO_CHIPS !\n"); | ||
2526 | printk(KERN_ERR "pmac_feature: %s skipped\n", node->full_name); | ||
2527 | return; | ||
2528 | } | ||
2529 | base = ioremap(node->addrs[0].address, node->addrs[0].size); | ||
2530 | if (!base) { | ||
2531 | printk(KERN_ERR "pmac_feature: Can't map mac-io chip !\n"); | ||
2532 | return; | ||
2533 | } | ||
2534 | if (type == macio_keylargo) { | ||
2535 | u32* did = (u32 *)get_property(node, "device-id", NULL); | ||
2536 | if (*did == 0x00000025) | ||
2537 | type = macio_pangea; | ||
2538 | if (*did == 0x0000003e) | ||
2539 | type = macio_intrepid; | ||
2540 | } | ||
2541 | macio_chips[i].of_node = node; | ||
2542 | macio_chips[i].type = type; | ||
2543 | macio_chips[i].base = base; | ||
2544 | macio_chips[i].flags = MACIO_FLAG_SCCB_ON | MACIO_FLAG_SCCB_ON; | ||
2545 | macio_chips[i].name = macio_names[type]; | ||
2546 | revp = (u32 *)get_property(node, "revision-id", NULL); | ||
2547 | if (revp) | ||
2548 | macio_chips[i].rev = *revp; | ||
2549 | printk(KERN_INFO "Found a %s mac-io controller, rev: %d, mapped at 0x%p\n", | ||
2550 | macio_names[type], macio_chips[i].rev, macio_chips[i].base); | ||
2551 | } | ||
2552 | |||
2553 | static int __init | ||
2554 | probe_macios(void) | ||
2555 | { | ||
2556 | /* Warning, ordering is important */ | ||
2557 | probe_one_macio("gc", NULL, macio_grand_central); | ||
2558 | probe_one_macio("ohare", NULL, macio_ohare); | ||
2559 | probe_one_macio("pci106b,7", NULL, macio_ohareII); | ||
2560 | probe_one_macio("mac-io", "keylargo", macio_keylargo); | ||
2561 | probe_one_macio("mac-io", "paddington", macio_paddington); | ||
2562 | probe_one_macio("mac-io", "gatwick", macio_gatwick); | ||
2563 | probe_one_macio("mac-io", "heathrow", macio_heathrow); | ||
2564 | probe_one_macio("mac-io", "K2-Keylargo", macio_keylargo2); | ||
2565 | |||
2566 | /* Make sure the "main" macio chip appear first */ | ||
2567 | if (macio_chips[0].type == macio_gatwick | ||
2568 | && macio_chips[1].type == macio_heathrow) { | ||
2569 | struct macio_chip temp = macio_chips[0]; | ||
2570 | macio_chips[0] = macio_chips[1]; | ||
2571 | macio_chips[1] = temp; | ||
2572 | } | ||
2573 | if (macio_chips[0].type == macio_ohareII | ||
2574 | && macio_chips[1].type == macio_ohare) { | ||
2575 | struct macio_chip temp = macio_chips[0]; | ||
2576 | macio_chips[0] = macio_chips[1]; | ||
2577 | macio_chips[1] = temp; | ||
2578 | } | ||
2579 | macio_chips[0].lbus.index = 0; | ||
2580 | macio_chips[1].lbus.index = 1; | ||
2581 | |||
2582 | return (macio_chips[0].of_node == NULL) ? -ENODEV : 0; | ||
2583 | } | ||
2584 | |||
2585 | static void __init | ||
2586 | initial_serial_shutdown(struct device_node* np) | ||
2587 | { | ||
2588 | int len; | ||
2589 | struct slot_names_prop { | ||
2590 | int count; | ||
2591 | char name[1]; | ||
2592 | } *slots; | ||
2593 | char *conn; | ||
2594 | int port_type = PMAC_SCC_ASYNC; | ||
2595 | int modem = 0; | ||
2596 | |||
2597 | slots = (struct slot_names_prop *)get_property(np, "slot-names", &len); | ||
2598 | conn = get_property(np, "AAPL,connector", &len); | ||
2599 | if (conn && (strcmp(conn, "infrared") == 0)) | ||
2600 | port_type = PMAC_SCC_IRDA; | ||
2601 | else if (device_is_compatible(np, "cobalt")) | ||
2602 | modem = 1; | ||
2603 | else if (slots && slots->count > 0) { | ||
2604 | if (strcmp(slots->name, "IrDA") == 0) | ||
2605 | port_type = PMAC_SCC_IRDA; | ||
2606 | else if (strcmp(slots->name, "Modem") == 0) | ||
2607 | modem = 1; | ||
2608 | } | ||
2609 | if (modem) | ||
2610 | pmac_call_feature(PMAC_FTR_MODEM_ENABLE, np, 0, 0); | ||
2611 | pmac_call_feature(PMAC_FTR_SCC_ENABLE, np, port_type, 0); | ||
2612 | } | ||
2613 | |||
2614 | static void __init | ||
2615 | set_initial_features(void) | ||
2616 | { | ||
2617 | struct device_node* np; | ||
2618 | |||
2619 | /* That hack appears to be necessary for some StarMax motherboards | ||
2620 | * but I'm not too sure it was audited for side-effects on other | ||
2621 | * ohare based machines... | ||
2622 | * Since I still have difficulties figuring the right way to | ||
2623 | * differenciate them all and since that hack was there for a long | ||
2624 | * time, I'll keep it around | ||
2625 | */ | ||
2626 | if (macio_chips[0].type == macio_ohare && !find_devices("via-pmu")) { | ||
2627 | struct macio_chip* macio = &macio_chips[0]; | ||
2628 | MACIO_OUT32(OHARE_FCR, STARMAX_FEATURES); | ||
2629 | } else if (macio_chips[0].type == macio_ohare) { | ||
2630 | struct macio_chip* macio = &macio_chips[0]; | ||
2631 | MACIO_BIS(OHARE_FCR, OH_IOBUS_ENABLE); | ||
2632 | } else if (macio_chips[1].type == macio_ohare) { | ||
2633 | struct macio_chip* macio = &macio_chips[1]; | ||
2634 | MACIO_BIS(OHARE_FCR, OH_IOBUS_ENABLE); | ||
2635 | } | ||
2636 | |||
2637 | #ifdef CONFIG_POWER4 | ||
2638 | if (macio_chips[0].type == macio_keylargo2) { | ||
2639 | #ifndef CONFIG_SMP | ||
2640 | /* On SMP machines running UP, we have the second CPU eating | ||
2641 | * bus cycles. We need to take it off the bus. This is done | ||
2642 | * from pmac_smp for SMP kernels running on one CPU | ||
2643 | */ | ||
2644 | np = of_find_node_by_type(NULL, "cpu"); | ||
2645 | if (np != NULL) | ||
2646 | np = of_find_node_by_type(np, "cpu"); | ||
2647 | if (np != NULL) { | ||
2648 | g5_phy_disable_cpu1(); | ||
2649 | of_node_put(np); | ||
2650 | } | ||
2651 | #endif /* CONFIG_SMP */ | ||
2652 | /* Enable GMAC for now for PCI probing. It will be disabled | ||
2653 | * later on after PCI probe | ||
2654 | */ | ||
2655 | np = of_find_node_by_name(NULL, "ethernet"); | ||
2656 | while(np) { | ||
2657 | if (device_is_compatible(np, "K2-GMAC")) | ||
2658 | g5_gmac_enable(np, 0, 1); | ||
2659 | np = of_find_node_by_name(np, "ethernet"); | ||
2660 | } | ||
2661 | |||
2662 | /* Enable FW before PCI probe. Will be disabled later on | ||
2663 | * Note: We should have a batter way to check that we are | ||
2664 | * dealing with uninorth internal cell and not a PCI cell | ||
2665 | * on the external PCI. The code below works though. | ||
2666 | */ | ||
2667 | np = of_find_node_by_name(NULL, "firewire"); | ||
2668 | while(np) { | ||
2669 | if (device_is_compatible(np, "pci106b,5811")) { | ||
2670 | macio_chips[0].flags |= MACIO_FLAG_FW_SUPPORTED; | ||
2671 | g5_fw_enable(np, 0, 1); | ||
2672 | } | ||
2673 | np = of_find_node_by_name(np, "firewire"); | ||
2674 | } | ||
2675 | } | ||
2676 | #else /* CONFIG_POWER4 */ | ||
2677 | |||
2678 | if (macio_chips[0].type == macio_keylargo || | ||
2679 | macio_chips[0].type == macio_pangea || | ||
2680 | macio_chips[0].type == macio_intrepid) { | ||
2681 | /* Enable GMAC for now for PCI probing. It will be disabled | ||
2682 | * later on after PCI probe | ||
2683 | */ | ||
2684 | np = of_find_node_by_name(NULL, "ethernet"); | ||
2685 | while(np) { | ||
2686 | if (np->parent | ||
2687 | && device_is_compatible(np->parent, "uni-north") | ||
2688 | && device_is_compatible(np, "gmac")) | ||
2689 | core99_gmac_enable(np, 0, 1); | ||
2690 | np = of_find_node_by_name(np, "ethernet"); | ||
2691 | } | ||
2692 | |||
2693 | /* Enable FW before PCI probe. Will be disabled later on | ||
2694 | * Note: We should have a batter way to check that we are | ||
2695 | * dealing with uninorth internal cell and not a PCI cell | ||
2696 | * on the external PCI. The code below works though. | ||
2697 | */ | ||
2698 | np = of_find_node_by_name(NULL, "firewire"); | ||
2699 | while(np) { | ||
2700 | if (np->parent | ||
2701 | && device_is_compatible(np->parent, "uni-north") | ||
2702 | && (device_is_compatible(np, "pci106b,18") || | ||
2703 | device_is_compatible(np, "pci106b,30") || | ||
2704 | device_is_compatible(np, "pci11c1,5811"))) { | ||
2705 | macio_chips[0].flags |= MACIO_FLAG_FW_SUPPORTED; | ||
2706 | core99_firewire_enable(np, 0, 1); | ||
2707 | } | ||
2708 | np = of_find_node_by_name(np, "firewire"); | ||
2709 | } | ||
2710 | |||
2711 | /* Enable ATA-100 before PCI probe. */ | ||
2712 | np = of_find_node_by_name(NULL, "ata-6"); | ||
2713 | while(np) { | ||
2714 | if (np->parent | ||
2715 | && device_is_compatible(np->parent, "uni-north") | ||
2716 | && device_is_compatible(np, "kauai-ata")) { | ||
2717 | core99_ata100_enable(np, 1); | ||
2718 | } | ||
2719 | np = of_find_node_by_name(np, "ata-6"); | ||
2720 | } | ||
2721 | |||
2722 | /* Switch airport off */ | ||
2723 | np = find_devices("radio"); | ||
2724 | while(np) { | ||
2725 | if (np && np->parent == macio_chips[0].of_node) { | ||
2726 | macio_chips[0].flags |= MACIO_FLAG_AIRPORT_ON; | ||
2727 | core99_airport_enable(np, 0, 0); | ||
2728 | } | ||
2729 | np = np->next; | ||
2730 | } | ||
2731 | } | ||
2732 | |||
2733 | /* On all machines that support sound PM, switch sound off */ | ||
2734 | if (macio_chips[0].of_node) | ||
2735 | pmac_do_feature_call(PMAC_FTR_SOUND_CHIP_ENABLE, | ||
2736 | macio_chips[0].of_node, 0, 0); | ||
2737 | |||
2738 | /* While on some desktop G3s, we turn it back on */ | ||
2739 | if (macio_chips[0].of_node && macio_chips[0].type == macio_heathrow | ||
2740 | && (pmac_mb.model_id == PMAC_TYPE_GOSSAMER || | ||
2741 | pmac_mb.model_id == PMAC_TYPE_SILK)) { | ||
2742 | struct macio_chip* macio = &macio_chips[0]; | ||
2743 | MACIO_BIS(HEATHROW_FCR, HRW_SOUND_CLK_ENABLE); | ||
2744 | MACIO_BIC(HEATHROW_FCR, HRW_SOUND_POWER_N); | ||
2745 | } | ||
2746 | |||
2747 | /* Hack for bumping clock speed on the new PowerBooks and the | ||
2748 | * iBook G4. This implements the "platform-do-clockspreading" OF | ||
2749 | * property. For safety, we also check the product ID in the | ||
2750 | * device-tree to make reasonably sure we won't set wrong values | ||
2751 | * in the clock chip. | ||
2752 | * | ||
2753 | * Of course, ultimately, we have to implement a real parser for | ||
2754 | * the platform-do-* stuff... | ||
2755 | */ | ||
2756 | while (machine_is_compatible("PowerBook5,2") || | ||
2757 | machine_is_compatible("PowerBook5,3") || | ||
2758 | machine_is_compatible("PowerBook6,2") || | ||
2759 | machine_is_compatible("PowerBook6,3")) { | ||
2760 | struct device_node *ui2c = of_find_node_by_type(NULL, "i2c"); | ||
2761 | struct device_node *dt = of_find_node_by_name(NULL, "device-tree"); | ||
2762 | u8 buffer[9]; | ||
2763 | u32 *productID; | ||
2764 | int i, rc, changed = 0; | ||
2765 | |||
2766 | if (dt == NULL) | ||
2767 | break; | ||
2768 | productID = (u32 *)get_property(dt, "pid#", NULL); | ||
2769 | if (productID == NULL) | ||
2770 | break; | ||
2771 | while(ui2c) { | ||
2772 | struct device_node *p = of_get_parent(ui2c); | ||
2773 | if (p && !strcmp(p->name, "uni-n")) | ||
2774 | break; | ||
2775 | ui2c = of_find_node_by_type(ui2c, "i2c"); | ||
2776 | } | ||
2777 | if (ui2c == NULL) | ||
2778 | break; | ||
2779 | DBG("Trying to bump clock speed for PID: %08x...\n", *productID); | ||
2780 | rc = pmac_low_i2c_open(ui2c, 1); | ||
2781 | if (rc != 0) | ||
2782 | break; | ||
2783 | pmac_low_i2c_setmode(ui2c, pmac_low_i2c_mode_combined); | ||
2784 | rc = pmac_low_i2c_xfer(ui2c, 0xd2 | pmac_low_i2c_read, 0x80, buffer, 9); | ||
2785 | DBG("read result: %d,", rc); | ||
2786 | if (rc != 0) { | ||
2787 | pmac_low_i2c_close(ui2c); | ||
2788 | break; | ||
2789 | } | ||
2790 | for (i=0; i<9; i++) | ||
2791 | DBG(" %02x", buffer[i]); | ||
2792 | DBG("\n"); | ||
2793 | |||
2794 | switch(*productID) { | ||
2795 | case 0x1182: /* AlBook 12" rev 2 */ | ||
2796 | case 0x1183: /* iBook G4 12" */ | ||
2797 | buffer[0] = (buffer[0] & 0x8f) | 0x70; | ||
2798 | buffer[2] = (buffer[2] & 0x7f) | 0x00; | ||
2799 | buffer[5] = (buffer[5] & 0x80) | 0x31; | ||
2800 | buffer[6] = (buffer[6] & 0x40) | 0xb0; | ||
2801 | buffer[7] = (buffer[7] & 0x00) | 0xc0; | ||
2802 | buffer[8] = (buffer[8] & 0x00) | 0x30; | ||
2803 | changed = 1; | ||
2804 | break; | ||
2805 | case 0x3142: /* AlBook 15" (ATI M10) */ | ||
2806 | case 0x3143: /* AlBook 17" (ATI M10) */ | ||
2807 | buffer[0] = (buffer[0] & 0xaf) | 0x50; | ||
2808 | buffer[2] = (buffer[2] & 0x7f) | 0x00; | ||
2809 | buffer[5] = (buffer[5] & 0x80) | 0x31; | ||
2810 | buffer[6] = (buffer[6] & 0x40) | 0xb0; | ||
2811 | buffer[7] = (buffer[7] & 0x00) | 0xd0; | ||
2812 | buffer[8] = (buffer[8] & 0x00) | 0x30; | ||
2813 | changed = 1; | ||
2814 | break; | ||
2815 | default: | ||
2816 | DBG("i2c-hwclock: Machine model not handled\n"); | ||
2817 | break; | ||
2818 | } | ||
2819 | if (!changed) { | ||
2820 | pmac_low_i2c_close(ui2c); | ||
2821 | break; | ||
2822 | } | ||
2823 | pmac_low_i2c_setmode(ui2c, pmac_low_i2c_mode_stdsub); | ||
2824 | rc = pmac_low_i2c_xfer(ui2c, 0xd2 | pmac_low_i2c_write, 0x80, buffer, 9); | ||
2825 | DBG("write result: %d,", rc); | ||
2826 | pmac_low_i2c_setmode(ui2c, pmac_low_i2c_mode_combined); | ||
2827 | rc = pmac_low_i2c_xfer(ui2c, 0xd2 | pmac_low_i2c_read, 0x80, buffer, 9); | ||
2828 | DBG("read result: %d,", rc); | ||
2829 | if (rc != 0) { | ||
2830 | pmac_low_i2c_close(ui2c); | ||
2831 | break; | ||
2832 | } | ||
2833 | for (i=0; i<9; i++) | ||
2834 | DBG(" %02x", buffer[i]); | ||
2835 | pmac_low_i2c_close(ui2c); | ||
2836 | break; | ||
2837 | } | ||
2838 | |||
2839 | #endif /* CONFIG_POWER4 */ | ||
2840 | |||
2841 | /* On all machines, switch modem & serial ports off */ | ||
2842 | np = find_devices("ch-a"); | ||
2843 | while(np) { | ||
2844 | initial_serial_shutdown(np); | ||
2845 | np = np->next; | ||
2846 | } | ||
2847 | np = find_devices("ch-b"); | ||
2848 | while(np) { | ||
2849 | initial_serial_shutdown(np); | ||
2850 | np = np->next; | ||
2851 | } | ||
2852 | } | ||
2853 | |||
2854 | void __init | ||
2855 | pmac_feature_init(void) | ||
2856 | { | ||
2857 | /* Detect the UniNorth memory controller */ | ||
2858 | probe_uninorth(); | ||
2859 | |||
2860 | /* Probe mac-io controllers */ | ||
2861 | if (probe_macios()) { | ||
2862 | printk(KERN_WARNING "No mac-io chip found\n"); | ||
2863 | return; | ||
2864 | } | ||
2865 | |||
2866 | /* Setup low-level i2c stuffs */ | ||
2867 | pmac_init_low_i2c(); | ||
2868 | |||
2869 | /* Probe machine type */ | ||
2870 | if (probe_motherboard()) | ||
2871 | printk(KERN_WARNING "Unknown PowerMac !\n"); | ||
2872 | |||
2873 | /* Set some initial features (turn off some chips that will | ||
2874 | * be later turned on) | ||
2875 | */ | ||
2876 | set_initial_features(); | ||
2877 | } | ||
2878 | |||
2879 | int __init | ||
2880 | pmac_feature_late_init(void) | ||
2881 | { | ||
2882 | struct device_node* np; | ||
2883 | |||
2884 | /* Request some resources late */ | ||
2885 | if (uninorth_node) | ||
2886 | request_OF_resource(uninorth_node, 0, NULL); | ||
2887 | np = find_devices("hammerhead"); | ||
2888 | if (np) | ||
2889 | request_OF_resource(np, 0, NULL); | ||
2890 | np = find_devices("interrupt-controller"); | ||
2891 | if (np) | ||
2892 | request_OF_resource(np, 0, NULL); | ||
2893 | return 0; | ||
2894 | } | ||
2895 | |||
2896 | device_initcall(pmac_feature_late_init); | ||
2897 | |||
2898 | #ifdef CONFIG_POWER4 | ||
2899 | |||
2900 | static void dump_HT_speeds(char *name, u32 cfg, u32 frq) | ||
2901 | { | ||
2902 | int freqs[16] = { 200,300,400,500,600,800,1000,0,0,0,0,0,0,0,0,0 }; | ||
2903 | int bits[8] = { 8,16,0,32,2,4,0,0 }; | ||
2904 | int freq = (frq >> 8) & 0xf; | ||
2905 | |||
2906 | if (freqs[freq] == 0) | ||
2907 | printk("%s: Unknown HT link frequency %x\n", name, freq); | ||
2908 | else | ||
2909 | printk("%s: %d MHz on main link, (%d in / %d out) bits width\n", | ||
2910 | name, freqs[freq], | ||
2911 | bits[(cfg >> 28) & 0x7], bits[(cfg >> 24) & 0x7]); | ||
2912 | } | ||
2913 | |||
2914 | void __init pmac_check_ht_link(void) | ||
2915 | { | ||
2916 | u32 ufreq, freq, ucfg, cfg; | ||
2917 | struct device_node *pcix_node; | ||
2918 | u8 px_bus, px_devfn; | ||
2919 | struct pci_controller *px_hose; | ||
2920 | |||
2921 | (void)in_be32(u3_ht + U3_HT_LINK_COMMAND); | ||
2922 | ucfg = cfg = in_be32(u3_ht + U3_HT_LINK_CONFIG); | ||
2923 | ufreq = freq = in_be32(u3_ht + U3_HT_LINK_FREQ); | ||
2924 | dump_HT_speeds("U3 HyperTransport", cfg, freq); | ||
2925 | |||
2926 | pcix_node = of_find_compatible_node(NULL, "pci", "pci-x"); | ||
2927 | if (pcix_node == NULL) { | ||
2928 | printk("No PCI-X bridge found\n"); | ||
2929 | return; | ||
2930 | } | ||
2931 | if (pci_device_from_OF_node(pcix_node, &px_bus, &px_devfn) != 0) { | ||
2932 | printk("PCI-X bridge found but not matched to pci\n"); | ||
2933 | return; | ||
2934 | } | ||
2935 | px_hose = pci_find_hose_for_OF_device(pcix_node); | ||
2936 | if (px_hose == NULL) { | ||
2937 | printk("PCI-X bridge found but not matched to host\n"); | ||
2938 | return; | ||
2939 | } | ||
2940 | early_read_config_dword(px_hose, px_bus, px_devfn, 0xc4, &cfg); | ||
2941 | early_read_config_dword(px_hose, px_bus, px_devfn, 0xcc, &freq); | ||
2942 | dump_HT_speeds("PCI-X HT Uplink", cfg, freq); | ||
2943 | early_read_config_dword(px_hose, px_bus, px_devfn, 0xc8, &cfg); | ||
2944 | early_read_config_dword(px_hose, px_bus, px_devfn, 0xd0, &freq); | ||
2945 | dump_HT_speeds("PCI-X HT Downlink", cfg, freq); | ||
2946 | } | ||
2947 | |||
2948 | #endif /* CONFIG_POWER4 */ | ||
2949 | |||
2950 | /* | ||
2951 | * Early video resume hook | ||
2952 | */ | ||
2953 | |||
2954 | static void (*pmac_early_vresume_proc)(void *data) __pmacdata; | ||
2955 | static void *pmac_early_vresume_data __pmacdata; | ||
2956 | |||
2957 | void pmac_set_early_video_resume(void (*proc)(void *data), void *data) | ||
2958 | { | ||
2959 | if (_machine != _MACH_Pmac) | ||
2960 | return; | ||
2961 | preempt_disable(); | ||
2962 | pmac_early_vresume_proc = proc; | ||
2963 | pmac_early_vresume_data = data; | ||
2964 | preempt_enable(); | ||
2965 | } | ||
2966 | EXPORT_SYMBOL(pmac_set_early_video_resume); | ||
2967 | |||
2968 | void __pmac pmac_call_early_video_resume(void) | ||
2969 | { | ||
2970 | if (pmac_early_vresume_proc) | ||
2971 | pmac_early_vresume_proc(pmac_early_vresume_data); | ||
2972 | } | ||
diff --git a/arch/ppc/platforms/pmac_low_i2c.c b/arch/ppc/platforms/pmac_low_i2c.c new file mode 100644 index 000000000000..d07579f2b8b9 --- /dev/null +++ b/arch/ppc/platforms/pmac_low_i2c.c | |||
@@ -0,0 +1,513 @@ | |||
1 | /* | ||
2 | * arch/ppc/platforms/pmac_low_i2c.c | ||
3 | * | ||
4 | * Copyright (C) 2003 Ben. Herrenschmidt (benh@kernel.crashing.org) | ||
5 | * | ||
6 | * This program is free software; you can redistribute it and/or | ||
7 | * modify it under the terms of the GNU General Public License | ||
8 | * as published by the Free Software Foundation; either version | ||
9 | * 2 of the License, or (at your option) any later version. | ||
10 | * | ||
11 | * This file contains some low-level i2c access routines that | ||
12 | * need to be used by various bits of the PowerMac platform code | ||
13 | * at times where the real asynchronous & interrupt driven driver | ||
14 | * cannot be used. The API borrows some semantics from the darwin | ||
15 | * driver in order to ease the implementation of the platform | ||
16 | * properties parser | ||
17 | */ | ||
18 | |||
19 | #include <linux/config.h> | ||
20 | #include <linux/types.h> | ||
21 | #include <linux/delay.h> | ||
22 | #include <linux/sched.h> | ||
23 | #include <linux/init.h> | ||
24 | #include <linux/module.h> | ||
25 | #include <linux/adb.h> | ||
26 | #include <linux/pmu.h> | ||
27 | #include <asm/keylargo.h> | ||
28 | #include <asm/uninorth.h> | ||
29 | #include <asm/io.h> | ||
30 | #include <asm/prom.h> | ||
31 | #include <asm/machdep.h> | ||
32 | #include <asm/pmac_low_i2c.h> | ||
33 | |||
34 | #define MAX_LOW_I2C_HOST 4 | ||
35 | |||
36 | #if 1 | ||
37 | #define DBG(x...) do {\ | ||
38 | printk(KERN_DEBUG "KW:" x); \ | ||
39 | } while(0) | ||
40 | #else | ||
41 | #define DBGG(x...) | ||
42 | #endif | ||
43 | |||
44 | struct low_i2c_host; | ||
45 | |||
46 | typedef int (*low_i2c_func_t)(struct low_i2c_host *host, u8 addr, u8 sub, u8 *data, int len); | ||
47 | |||
48 | struct low_i2c_host | ||
49 | { | ||
50 | struct device_node *np; /* OF device node */ | ||
51 | struct semaphore mutex; /* Access mutex for use by i2c-keywest */ | ||
52 | low_i2c_func_t func; /* Access function */ | ||
53 | int is_open : 1; /* Poor man's access control */ | ||
54 | int mode; /* Current mode */ | ||
55 | int channel; /* Current channel */ | ||
56 | int num_channels; /* Number of channels */ | ||
57 | unsigned long base; /* For keywest-i2c, base address */ | ||
58 | int bsteps; /* And register stepping */ | ||
59 | int speed; /* And speed */ | ||
60 | }; | ||
61 | |||
62 | static struct low_i2c_host low_i2c_hosts[MAX_LOW_I2C_HOST]; | ||
63 | |||
64 | /* No locking is necessary on allocation, we are running way before | ||
65 | * anything can race with us | ||
66 | */ | ||
67 | static struct low_i2c_host *find_low_i2c_host(struct device_node *np) | ||
68 | { | ||
69 | int i; | ||
70 | |||
71 | for (i = 0; i < MAX_LOW_I2C_HOST; i++) | ||
72 | if (low_i2c_hosts[i].np == np) | ||
73 | return &low_i2c_hosts[i]; | ||
74 | return NULL; | ||
75 | } | ||
76 | |||
77 | /* | ||
78 | * | ||
79 | * i2c-keywest implementation (UniNorth, U2, U3, Keylargo's) | ||
80 | * | ||
81 | */ | ||
82 | |||
83 | /* | ||
84 | * Keywest i2c definitions borrowed from drivers/i2c/i2c-keywest.h, | ||
85 | * should be moved somewhere in include/asm-ppc/ | ||
86 | */ | ||
87 | /* Register indices */ | ||
88 | typedef enum { | ||
89 | reg_mode = 0, | ||
90 | reg_control, | ||
91 | reg_status, | ||
92 | reg_isr, | ||
93 | reg_ier, | ||
94 | reg_addr, | ||
95 | reg_subaddr, | ||
96 | reg_data | ||
97 | } reg_t; | ||
98 | |||
99 | |||
100 | /* Mode register */ | ||
101 | #define KW_I2C_MODE_100KHZ 0x00 | ||
102 | #define KW_I2C_MODE_50KHZ 0x01 | ||
103 | #define KW_I2C_MODE_25KHZ 0x02 | ||
104 | #define KW_I2C_MODE_DUMB 0x00 | ||
105 | #define KW_I2C_MODE_STANDARD 0x04 | ||
106 | #define KW_I2C_MODE_STANDARDSUB 0x08 | ||
107 | #define KW_I2C_MODE_COMBINED 0x0C | ||
108 | #define KW_I2C_MODE_MODE_MASK 0x0C | ||
109 | #define KW_I2C_MODE_CHAN_MASK 0xF0 | ||
110 | |||
111 | /* Control register */ | ||
112 | #define KW_I2C_CTL_AAK 0x01 | ||
113 | #define KW_I2C_CTL_XADDR 0x02 | ||
114 | #define KW_I2C_CTL_STOP 0x04 | ||
115 | #define KW_I2C_CTL_START 0x08 | ||
116 | |||
117 | /* Status register */ | ||
118 | #define KW_I2C_STAT_BUSY 0x01 | ||
119 | #define KW_I2C_STAT_LAST_AAK 0x02 | ||
120 | #define KW_I2C_STAT_LAST_RW 0x04 | ||
121 | #define KW_I2C_STAT_SDA 0x08 | ||
122 | #define KW_I2C_STAT_SCL 0x10 | ||
123 | |||
124 | /* IER & ISR registers */ | ||
125 | #define KW_I2C_IRQ_DATA 0x01 | ||
126 | #define KW_I2C_IRQ_ADDR 0x02 | ||
127 | #define KW_I2C_IRQ_STOP 0x04 | ||
128 | #define KW_I2C_IRQ_START 0x08 | ||
129 | #define KW_I2C_IRQ_MASK 0x0F | ||
130 | |||
131 | /* State machine states */ | ||
132 | enum { | ||
133 | state_idle, | ||
134 | state_addr, | ||
135 | state_read, | ||
136 | state_write, | ||
137 | state_stop, | ||
138 | state_dead | ||
139 | }; | ||
140 | |||
141 | #define WRONG_STATE(name) do {\ | ||
142 | printk(KERN_DEBUG "KW: wrong state. Got %s, state: %s (isr: %02x)\n", \ | ||
143 | name, __kw_state_names[state], isr); \ | ||
144 | } while(0) | ||
145 | |||
146 | static const char *__kw_state_names[] = { | ||
147 | "state_idle", | ||
148 | "state_addr", | ||
149 | "state_read", | ||
150 | "state_write", | ||
151 | "state_stop", | ||
152 | "state_dead" | ||
153 | }; | ||
154 | |||
155 | static inline u8 __kw_read_reg(struct low_i2c_host *host, reg_t reg) | ||
156 | { | ||
157 | return in_8(((volatile u8 *)host->base) | ||
158 | + (((unsigned)reg) << host->bsteps)); | ||
159 | } | ||
160 | |||
161 | static inline void __kw_write_reg(struct low_i2c_host *host, reg_t reg, u8 val) | ||
162 | { | ||
163 | out_8(((volatile u8 *)host->base) | ||
164 | + (((unsigned)reg) << host->bsteps), val); | ||
165 | (void)__kw_read_reg(host, reg_subaddr); | ||
166 | } | ||
167 | |||
168 | #define kw_write_reg(reg, val) __kw_write_reg(host, reg, val) | ||
169 | #define kw_read_reg(reg) __kw_read_reg(host, reg) | ||
170 | |||
171 | |||
172 | /* Don't schedule, the g5 fan controller is too | ||
173 | * timing sensitive | ||
174 | */ | ||
175 | static u8 kw_wait_interrupt(struct low_i2c_host* host) | ||
176 | { | ||
177 | int i; | ||
178 | u8 isr; | ||
179 | |||
180 | for (i = 0; i < 200000; i++) { | ||
181 | isr = kw_read_reg(reg_isr) & KW_I2C_IRQ_MASK; | ||
182 | if (isr != 0) | ||
183 | return isr; | ||
184 | udelay(1); | ||
185 | } | ||
186 | return isr; | ||
187 | } | ||
188 | |||
189 | static int kw_handle_interrupt(struct low_i2c_host *host, int state, int rw, int *rc, u8 **data, int *len, u8 isr) | ||
190 | { | ||
191 | u8 ack; | ||
192 | |||
193 | if (isr == 0) { | ||
194 | if (state != state_stop) { | ||
195 | DBG("KW: Timeout !\n"); | ||
196 | *rc = -EIO; | ||
197 | goto stop; | ||
198 | } | ||
199 | if (state == state_stop) { | ||
200 | ack = kw_read_reg(reg_status); | ||
201 | if (!(ack & KW_I2C_STAT_BUSY)) { | ||
202 | state = state_idle; | ||
203 | kw_write_reg(reg_ier, 0x00); | ||
204 | } | ||
205 | } | ||
206 | return state; | ||
207 | } | ||
208 | |||
209 | if (isr & KW_I2C_IRQ_ADDR) { | ||
210 | ack = kw_read_reg(reg_status); | ||
211 | if (state != state_addr) { | ||
212 | kw_write_reg(reg_isr, KW_I2C_IRQ_ADDR); | ||
213 | WRONG_STATE("KW_I2C_IRQ_ADDR"); | ||
214 | *rc = -EIO; | ||
215 | goto stop; | ||
216 | } | ||
217 | if ((ack & KW_I2C_STAT_LAST_AAK) == 0) { | ||
218 | *rc = -ENODEV; | ||
219 | DBG("KW: NAK on address\n"); | ||
220 | return state_stop; | ||
221 | } else { | ||
222 | if (rw) { | ||
223 | state = state_read; | ||
224 | if (*len > 1) | ||
225 | kw_write_reg(reg_control, KW_I2C_CTL_AAK); | ||
226 | } else { | ||
227 | state = state_write; | ||
228 | kw_write_reg(reg_data, **data); | ||
229 | (*data)++; (*len)--; | ||
230 | } | ||
231 | } | ||
232 | kw_write_reg(reg_isr, KW_I2C_IRQ_ADDR); | ||
233 | } | ||
234 | |||
235 | if (isr & KW_I2C_IRQ_DATA) { | ||
236 | if (state == state_read) { | ||
237 | **data = kw_read_reg(reg_data); | ||
238 | (*data)++; (*len)--; | ||
239 | kw_write_reg(reg_isr, KW_I2C_IRQ_DATA); | ||
240 | if ((*len) == 0) | ||
241 | state = state_stop; | ||
242 | else if ((*len) == 1) | ||
243 | kw_write_reg(reg_control, 0); | ||
244 | } else if (state == state_write) { | ||
245 | ack = kw_read_reg(reg_status); | ||
246 | if ((ack & KW_I2C_STAT_LAST_AAK) == 0) { | ||
247 | DBG("KW: nack on data write\n"); | ||
248 | *rc = -EIO; | ||
249 | goto stop; | ||
250 | } else if (*len) { | ||
251 | kw_write_reg(reg_data, **data); | ||
252 | (*data)++; (*len)--; | ||
253 | } else { | ||
254 | kw_write_reg(reg_control, KW_I2C_CTL_STOP); | ||
255 | state = state_stop; | ||
256 | *rc = 0; | ||
257 | } | ||
258 | kw_write_reg(reg_isr, KW_I2C_IRQ_DATA); | ||
259 | } else { | ||
260 | kw_write_reg(reg_isr, KW_I2C_IRQ_DATA); | ||
261 | WRONG_STATE("KW_I2C_IRQ_DATA"); | ||
262 | if (state != state_stop) { | ||
263 | *rc = -EIO; | ||
264 | goto stop; | ||
265 | } | ||
266 | } | ||
267 | } | ||
268 | |||
269 | if (isr & KW_I2C_IRQ_STOP) { | ||
270 | kw_write_reg(reg_isr, KW_I2C_IRQ_STOP); | ||
271 | if (state != state_stop) { | ||
272 | WRONG_STATE("KW_I2C_IRQ_STOP"); | ||
273 | *rc = -EIO; | ||
274 | } | ||
275 | return state_idle; | ||
276 | } | ||
277 | |||
278 | if (isr & KW_I2C_IRQ_START) | ||
279 | kw_write_reg(reg_isr, KW_I2C_IRQ_START); | ||
280 | |||
281 | return state; | ||
282 | |||
283 | stop: | ||
284 | kw_write_reg(reg_control, KW_I2C_CTL_STOP); | ||
285 | return state_stop; | ||
286 | } | ||
287 | |||
288 | static int keywest_low_i2c_func(struct low_i2c_host *host, u8 addr, u8 subaddr, u8 *data, int len) | ||
289 | { | ||
290 | u8 mode_reg = host->speed; | ||
291 | int state = state_addr; | ||
292 | int rc = 0; | ||
293 | |||
294 | /* Setup mode & subaddress if any */ | ||
295 | switch(host->mode) { | ||
296 | case pmac_low_i2c_mode_dumb: | ||
297 | printk(KERN_ERR "low_i2c: Dumb mode not supported !\n"); | ||
298 | return -EINVAL; | ||
299 | case pmac_low_i2c_mode_std: | ||
300 | mode_reg |= KW_I2C_MODE_STANDARD; | ||
301 | break; | ||
302 | case pmac_low_i2c_mode_stdsub: | ||
303 | mode_reg |= KW_I2C_MODE_STANDARDSUB; | ||
304 | kw_write_reg(reg_subaddr, subaddr); | ||
305 | break; | ||
306 | case pmac_low_i2c_mode_combined: | ||
307 | mode_reg |= KW_I2C_MODE_COMBINED; | ||
308 | kw_write_reg(reg_subaddr, subaddr); | ||
309 | break; | ||
310 | } | ||
311 | |||
312 | /* Setup channel & clear pending irqs */ | ||
313 | kw_write_reg(reg_isr, kw_read_reg(reg_isr)); | ||
314 | kw_write_reg(reg_mode, mode_reg | (host->channel << 4)); | ||
315 | kw_write_reg(reg_status, 0); | ||
316 | |||
317 | /* Set up address and r/w bit */ | ||
318 | kw_write_reg(reg_addr, addr); | ||
319 | |||
320 | /* Start sending address & disable interrupt*/ | ||
321 | kw_write_reg(reg_ier, 0 /*KW_I2C_IRQ_MASK*/); | ||
322 | kw_write_reg(reg_control, KW_I2C_CTL_XADDR); | ||
323 | |||
324 | /* State machine, to turn into an interrupt handler */ | ||
325 | while(state != state_idle) { | ||
326 | u8 isr = kw_wait_interrupt(host); | ||
327 | state = kw_handle_interrupt(host, state, addr & 1, &rc, &data, &len, isr); | ||
328 | } | ||
329 | |||
330 | return rc; | ||
331 | } | ||
332 | |||
333 | static void keywest_low_i2c_add(struct device_node *np) | ||
334 | { | ||
335 | struct low_i2c_host *host = find_low_i2c_host(NULL); | ||
336 | unsigned long *psteps, *prate, steps, aoffset = 0; | ||
337 | struct device_node *parent; | ||
338 | |||
339 | if (host == NULL) { | ||
340 | printk(KERN_ERR "low_i2c: Can't allocate host for %s\n", | ||
341 | np->full_name); | ||
342 | return; | ||
343 | } | ||
344 | memset(host, 0, sizeof(*host)); | ||
345 | |||
346 | init_MUTEX(&host->mutex); | ||
347 | host->np = of_node_get(np); | ||
348 | psteps = (unsigned long *)get_property(np, "AAPL,address-step", NULL); | ||
349 | steps = psteps ? (*psteps) : 0x10; | ||
350 | for (host->bsteps = 0; (steps & 0x01) == 0; host->bsteps++) | ||
351 | steps >>= 1; | ||
352 | parent = of_get_parent(np); | ||
353 | host->num_channels = 1; | ||
354 | if (parent && parent->name[0] == 'u') { | ||
355 | host->num_channels = 2; | ||
356 | aoffset = 3; | ||
357 | } | ||
358 | /* Select interface rate */ | ||
359 | host->speed = KW_I2C_MODE_100KHZ; | ||
360 | prate = (unsigned long *)get_property(np, "AAPL,i2c-rate", NULL); | ||
361 | if (prate) switch(*prate) { | ||
362 | case 100: | ||
363 | host->speed = KW_I2C_MODE_100KHZ; | ||
364 | break; | ||
365 | case 50: | ||
366 | host->speed = KW_I2C_MODE_50KHZ; | ||
367 | break; | ||
368 | case 25: | ||
369 | host->speed = KW_I2C_MODE_25KHZ; | ||
370 | break; | ||
371 | } | ||
372 | host->mode = pmac_low_i2c_mode_std; | ||
373 | host->base = (unsigned long)ioremap(np->addrs[0].address + aoffset, | ||
374 | np->addrs[0].size); | ||
375 | host->func = keywest_low_i2c_func; | ||
376 | } | ||
377 | |||
378 | /* | ||
379 | * | ||
380 | * PMU implementation | ||
381 | * | ||
382 | */ | ||
383 | |||
384 | |||
385 | #ifdef CONFIG_ADB_PMU | ||
386 | |||
387 | static int pmu_low_i2c_func(struct low_i2c_host *host, u8 addr, u8 sub, u8 *data, int len) | ||
388 | { | ||
389 | // TODO | ||
390 | return -ENODEV; | ||
391 | } | ||
392 | |||
393 | static void pmu_low_i2c_add(struct device_node *np) | ||
394 | { | ||
395 | struct low_i2c_host *host = find_low_i2c_host(NULL); | ||
396 | |||
397 | if (host == NULL) { | ||
398 | printk(KERN_ERR "low_i2c: Can't allocate host for %s\n", | ||
399 | np->full_name); | ||
400 | return; | ||
401 | } | ||
402 | memset(host, 0, sizeof(*host)); | ||
403 | |||
404 | init_MUTEX(&host->mutex); | ||
405 | host->np = of_node_get(np); | ||
406 | host->num_channels = 3; | ||
407 | host->mode = pmac_low_i2c_mode_std; | ||
408 | host->func = pmu_low_i2c_func; | ||
409 | } | ||
410 | |||
411 | #endif /* CONFIG_ADB_PMU */ | ||
412 | |||
413 | void __init pmac_init_low_i2c(void) | ||
414 | { | ||
415 | struct device_node *np; | ||
416 | |||
417 | /* Probe keywest-i2c busses */ | ||
418 | np = of_find_compatible_node(NULL, "i2c", "keywest-i2c"); | ||
419 | while(np) { | ||
420 | keywest_low_i2c_add(np); | ||
421 | np = of_find_compatible_node(np, "i2c", "keywest-i2c"); | ||
422 | } | ||
423 | |||
424 | #ifdef CONFIG_ADB_PMU | ||
425 | /* Probe PMU busses */ | ||
426 | np = of_find_node_by_name(NULL, "via-pmu"); | ||
427 | if (np) | ||
428 | pmu_low_i2c_add(np); | ||
429 | #endif /* CONFIG_ADB_PMU */ | ||
430 | |||
431 | /* TODO: Add CUDA support as well */ | ||
432 | } | ||
433 | |||
434 | int pmac_low_i2c_lock(struct device_node *np) | ||
435 | { | ||
436 | struct low_i2c_host *host = find_low_i2c_host(np); | ||
437 | |||
438 | if (!host) | ||
439 | return -ENODEV; | ||
440 | down(&host->mutex); | ||
441 | return 0; | ||
442 | } | ||
443 | EXPORT_SYMBOL(pmac_low_i2c_lock); | ||
444 | |||
445 | int pmac_low_i2c_unlock(struct device_node *np) | ||
446 | { | ||
447 | struct low_i2c_host *host = find_low_i2c_host(np); | ||
448 | |||
449 | if (!host) | ||
450 | return -ENODEV; | ||
451 | up(&host->mutex); | ||
452 | return 0; | ||
453 | } | ||
454 | EXPORT_SYMBOL(pmac_low_i2c_unlock); | ||
455 | |||
456 | |||
457 | int pmac_low_i2c_open(struct device_node *np, int channel) | ||
458 | { | ||
459 | struct low_i2c_host *host = find_low_i2c_host(np); | ||
460 | |||
461 | if (!host) | ||
462 | return -ENODEV; | ||
463 | |||
464 | if (channel >= host->num_channels) | ||
465 | return -EINVAL; | ||
466 | |||
467 | down(&host->mutex); | ||
468 | host->is_open = 1; | ||
469 | host->channel = channel; | ||
470 | |||
471 | return 0; | ||
472 | } | ||
473 | EXPORT_SYMBOL(pmac_low_i2c_open); | ||
474 | |||
475 | int pmac_low_i2c_close(struct device_node *np) | ||
476 | { | ||
477 | struct low_i2c_host *host = find_low_i2c_host(np); | ||
478 | |||
479 | if (!host) | ||
480 | return -ENODEV; | ||
481 | |||
482 | host->is_open = 0; | ||
483 | up(&host->mutex); | ||
484 | |||
485 | return 0; | ||
486 | } | ||
487 | EXPORT_SYMBOL(pmac_low_i2c_close); | ||
488 | |||
489 | int pmac_low_i2c_setmode(struct device_node *np, int mode) | ||
490 | { | ||
491 | struct low_i2c_host *host = find_low_i2c_host(np); | ||
492 | |||
493 | if (!host) | ||
494 | return -ENODEV; | ||
495 | WARN_ON(!host->is_open); | ||
496 | host->mode = mode; | ||
497 | |||
498 | return 0; | ||
499 | } | ||
500 | EXPORT_SYMBOL(pmac_low_i2c_setmode); | ||
501 | |||
502 | int pmac_low_i2c_xfer(struct device_node *np, u8 addrdir, u8 subaddr, u8 *data, int len) | ||
503 | { | ||
504 | struct low_i2c_host *host = find_low_i2c_host(np); | ||
505 | |||
506 | if (!host) | ||
507 | return -ENODEV; | ||
508 | WARN_ON(!host->is_open); | ||
509 | |||
510 | return host->func(host, addrdir, subaddr, data, len); | ||
511 | } | ||
512 | EXPORT_SYMBOL(pmac_low_i2c_xfer); | ||
513 | |||
diff --git a/arch/ppc/platforms/pmac_nvram.c b/arch/ppc/platforms/pmac_nvram.c new file mode 100644 index 000000000000..c9de64205996 --- /dev/null +++ b/arch/ppc/platforms/pmac_nvram.c | |||
@@ -0,0 +1,584 @@ | |||
1 | /* | ||
2 | * arch/ppc/platforms/pmac_nvram.c | ||
3 | * | ||
4 | * Copyright (C) 2002 Benjamin Herrenschmidt (benh@kernel.crashing.org) | ||
5 | * | ||
6 | * This program is free software; you can redistribute it and/or | ||
7 | * modify it under the terms of the GNU General Public License | ||
8 | * as published by the Free Software Foundation; either version | ||
9 | * 2 of the License, or (at your option) any later version. | ||
10 | * | ||
11 | * Todo: - add support for the OF persistent properties | ||
12 | */ | ||
13 | #include <linux/config.h> | ||
14 | #include <linux/module.h> | ||
15 | #include <linux/kernel.h> | ||
16 | #include <linux/stddef.h> | ||
17 | #include <linux/string.h> | ||
18 | #include <linux/nvram.h> | ||
19 | #include <linux/init.h> | ||
20 | #include <linux/slab.h> | ||
21 | #include <linux/delay.h> | ||
22 | #include <linux/errno.h> | ||
23 | #include <linux/adb.h> | ||
24 | #include <linux/pmu.h> | ||
25 | #include <linux/bootmem.h> | ||
26 | #include <linux/completion.h> | ||
27 | #include <linux/spinlock.h> | ||
28 | #include <asm/sections.h> | ||
29 | #include <asm/io.h> | ||
30 | #include <asm/system.h> | ||
31 | #include <asm/prom.h> | ||
32 | #include <asm/machdep.h> | ||
33 | #include <asm/nvram.h> | ||
34 | |||
35 | #define DEBUG | ||
36 | |||
37 | #ifdef DEBUG | ||
38 | #define DBG(x...) printk(x) | ||
39 | #else | ||
40 | #define DBG(x...) | ||
41 | #endif | ||
42 | |||
43 | #define NVRAM_SIZE 0x2000 /* 8kB of non-volatile RAM */ | ||
44 | |||
45 | #define CORE99_SIGNATURE 0x5a | ||
46 | #define CORE99_ADLER_START 0x14 | ||
47 | |||
48 | /* On Core99, nvram is either a sharp, a micron or an AMD flash */ | ||
49 | #define SM_FLASH_STATUS_DONE 0x80 | ||
50 | #define SM_FLASH_STATUS_ERR 0x38 | ||
51 | #define SM_FLASH_CMD_ERASE_CONFIRM 0xd0 | ||
52 | #define SM_FLASH_CMD_ERASE_SETUP 0x20 | ||
53 | #define SM_FLASH_CMD_RESET 0xff | ||
54 | #define SM_FLASH_CMD_WRITE_SETUP 0x40 | ||
55 | #define SM_FLASH_CMD_CLEAR_STATUS 0x50 | ||
56 | #define SM_FLASH_CMD_READ_STATUS 0x70 | ||
57 | |||
58 | /* CHRP NVRAM header */ | ||
59 | struct chrp_header { | ||
60 | u8 signature; | ||
61 | u8 cksum; | ||
62 | u16 len; | ||
63 | char name[12]; | ||
64 | u8 data[0]; | ||
65 | }; | ||
66 | |||
67 | struct core99_header { | ||
68 | struct chrp_header hdr; | ||
69 | u32 adler; | ||
70 | u32 generation; | ||
71 | u32 reserved[2]; | ||
72 | }; | ||
73 | |||
74 | /* | ||
75 | * Read and write the non-volatile RAM on PowerMacs and CHRP machines. | ||
76 | */ | ||
77 | static int nvram_naddrs; | ||
78 | static volatile unsigned char *nvram_addr; | ||
79 | static volatile unsigned char *nvram_data; | ||
80 | static int nvram_mult, is_core_99; | ||
81 | static int core99_bank = 0; | ||
82 | static int nvram_partitions[3]; | ||
83 | static DEFINE_SPINLOCK(nv_lock); | ||
84 | |||
85 | extern int pmac_newworld; | ||
86 | extern int system_running; | ||
87 | |||
88 | static int (*core99_write_bank)(int bank, u8* datas); | ||
89 | static int (*core99_erase_bank)(int bank); | ||
90 | |||
91 | static char *nvram_image __pmacdata; | ||
92 | |||
93 | |||
94 | static unsigned char __pmac core99_nvram_read_byte(int addr) | ||
95 | { | ||
96 | if (nvram_image == NULL) | ||
97 | return 0xff; | ||
98 | return nvram_image[addr]; | ||
99 | } | ||
100 | |||
101 | static void __pmac core99_nvram_write_byte(int addr, unsigned char val) | ||
102 | { | ||
103 | if (nvram_image == NULL) | ||
104 | return; | ||
105 | nvram_image[addr] = val; | ||
106 | } | ||
107 | |||
108 | |||
109 | static unsigned char __openfirmware direct_nvram_read_byte(int addr) | ||
110 | { | ||
111 | return in_8(&nvram_data[(addr & (NVRAM_SIZE - 1)) * nvram_mult]); | ||
112 | } | ||
113 | |||
114 | static void __openfirmware direct_nvram_write_byte(int addr, unsigned char val) | ||
115 | { | ||
116 | out_8(&nvram_data[(addr & (NVRAM_SIZE - 1)) * nvram_mult], val); | ||
117 | } | ||
118 | |||
119 | |||
120 | static unsigned char __pmac indirect_nvram_read_byte(int addr) | ||
121 | { | ||
122 | unsigned char val; | ||
123 | unsigned long flags; | ||
124 | |||
125 | spin_lock_irqsave(&nv_lock, flags); | ||
126 | out_8(nvram_addr, addr >> 5); | ||
127 | val = in_8(&nvram_data[(addr & 0x1f) << 4]); | ||
128 | spin_unlock_irqrestore(&nv_lock, flags); | ||
129 | |||
130 | return val; | ||
131 | } | ||
132 | |||
133 | static void __pmac indirect_nvram_write_byte(int addr, unsigned char val) | ||
134 | { | ||
135 | unsigned long flags; | ||
136 | |||
137 | spin_lock_irqsave(&nv_lock, flags); | ||
138 | out_8(nvram_addr, addr >> 5); | ||
139 | out_8(&nvram_data[(addr & 0x1f) << 4], val); | ||
140 | spin_unlock_irqrestore(&nv_lock, flags); | ||
141 | } | ||
142 | |||
143 | |||
144 | #ifdef CONFIG_ADB_PMU | ||
145 | |||
146 | static void __pmac pmu_nvram_complete(struct adb_request *req) | ||
147 | { | ||
148 | if (req->arg) | ||
149 | complete((struct completion *)req->arg); | ||
150 | } | ||
151 | |||
152 | static unsigned char __pmac pmu_nvram_read_byte(int addr) | ||
153 | { | ||
154 | struct adb_request req; | ||
155 | DECLARE_COMPLETION(req_complete); | ||
156 | |||
157 | req.arg = system_state == SYSTEM_RUNNING ? &req_complete : NULL; | ||
158 | if (pmu_request(&req, pmu_nvram_complete, 3, PMU_READ_NVRAM, | ||
159 | (addr >> 8) & 0xff, addr & 0xff)) | ||
160 | return 0xff; | ||
161 | if (system_state == SYSTEM_RUNNING) | ||
162 | wait_for_completion(&req_complete); | ||
163 | while (!req.complete) | ||
164 | pmu_poll(); | ||
165 | return req.reply[0]; | ||
166 | } | ||
167 | |||
168 | static void __pmac pmu_nvram_write_byte(int addr, unsigned char val) | ||
169 | { | ||
170 | struct adb_request req; | ||
171 | DECLARE_COMPLETION(req_complete); | ||
172 | |||
173 | req.arg = system_state == SYSTEM_RUNNING ? &req_complete : NULL; | ||
174 | if (pmu_request(&req, pmu_nvram_complete, 4, PMU_WRITE_NVRAM, | ||
175 | (addr >> 8) & 0xff, addr & 0xff, val)) | ||
176 | return; | ||
177 | if (system_state == SYSTEM_RUNNING) | ||
178 | wait_for_completion(&req_complete); | ||
179 | while (!req.complete) | ||
180 | pmu_poll(); | ||
181 | } | ||
182 | |||
183 | #endif /* CONFIG_ADB_PMU */ | ||
184 | |||
185 | |||
186 | static u8 __pmac chrp_checksum(struct chrp_header* hdr) | ||
187 | { | ||
188 | u8 *ptr; | ||
189 | u16 sum = hdr->signature; | ||
190 | for (ptr = (u8 *)&hdr->len; ptr < hdr->data; ptr++) | ||
191 | sum += *ptr; | ||
192 | while (sum > 0xFF) | ||
193 | sum = (sum & 0xFF) + (sum>>8); | ||
194 | return sum; | ||
195 | } | ||
196 | |||
197 | static u32 __pmac core99_calc_adler(u8 *buffer) | ||
198 | { | ||
199 | int cnt; | ||
200 | u32 low, high; | ||
201 | |||
202 | buffer += CORE99_ADLER_START; | ||
203 | low = 1; | ||
204 | high = 0; | ||
205 | for (cnt=0; cnt<(NVRAM_SIZE-CORE99_ADLER_START); cnt++) { | ||
206 | if ((cnt % 5000) == 0) { | ||
207 | high %= 65521UL; | ||
208 | high %= 65521UL; | ||
209 | } | ||
210 | low += buffer[cnt]; | ||
211 | high += low; | ||
212 | } | ||
213 | low %= 65521UL; | ||
214 | high %= 65521UL; | ||
215 | |||
216 | return (high << 16) | low; | ||
217 | } | ||
218 | |||
219 | static u32 __pmac core99_check(u8* datas) | ||
220 | { | ||
221 | struct core99_header* hdr99 = (struct core99_header*)datas; | ||
222 | |||
223 | if (hdr99->hdr.signature != CORE99_SIGNATURE) { | ||
224 | DBG("Invalid signature\n"); | ||
225 | return 0; | ||
226 | } | ||
227 | if (hdr99->hdr.cksum != chrp_checksum(&hdr99->hdr)) { | ||
228 | DBG("Invalid checksum\n"); | ||
229 | return 0; | ||
230 | } | ||
231 | if (hdr99->adler != core99_calc_adler(datas)) { | ||
232 | DBG("Invalid adler\n"); | ||
233 | return 0; | ||
234 | } | ||
235 | return hdr99->generation; | ||
236 | } | ||
237 | |||
238 | static int __pmac sm_erase_bank(int bank) | ||
239 | { | ||
240 | int stat, i; | ||
241 | unsigned long timeout; | ||
242 | |||
243 | u8* base = (u8 *)nvram_data + core99_bank*NVRAM_SIZE; | ||
244 | |||
245 | DBG("nvram: Sharp/Micron Erasing bank %d...\n", bank); | ||
246 | |||
247 | out_8(base, SM_FLASH_CMD_ERASE_SETUP); | ||
248 | out_8(base, SM_FLASH_CMD_ERASE_CONFIRM); | ||
249 | timeout = 0; | ||
250 | do { | ||
251 | if (++timeout > 1000000) { | ||
252 | printk(KERN_ERR "nvram: Sharp/Miron flash erase timeout !\n"); | ||
253 | break; | ||
254 | } | ||
255 | out_8(base, SM_FLASH_CMD_READ_STATUS); | ||
256 | stat = in_8(base); | ||
257 | } while (!(stat & SM_FLASH_STATUS_DONE)); | ||
258 | |||
259 | out_8(base, SM_FLASH_CMD_CLEAR_STATUS); | ||
260 | out_8(base, SM_FLASH_CMD_RESET); | ||
261 | |||
262 | for (i=0; i<NVRAM_SIZE; i++) | ||
263 | if (base[i] != 0xff) { | ||
264 | printk(KERN_ERR "nvram: Sharp/Micron flash erase failed !\n"); | ||
265 | return -ENXIO; | ||
266 | } | ||
267 | return 0; | ||
268 | } | ||
269 | |||
270 | static int __pmac sm_write_bank(int bank, u8* datas) | ||
271 | { | ||
272 | int i, stat = 0; | ||
273 | unsigned long timeout; | ||
274 | |||
275 | u8* base = (u8 *)nvram_data + core99_bank*NVRAM_SIZE; | ||
276 | |||
277 | DBG("nvram: Sharp/Micron Writing bank %d...\n", bank); | ||
278 | |||
279 | for (i=0; i<NVRAM_SIZE; i++) { | ||
280 | out_8(base+i, SM_FLASH_CMD_WRITE_SETUP); | ||
281 | udelay(1); | ||
282 | out_8(base+i, datas[i]); | ||
283 | timeout = 0; | ||
284 | do { | ||
285 | if (++timeout > 1000000) { | ||
286 | printk(KERN_ERR "nvram: Sharp/Micron flash write timeout !\n"); | ||
287 | break; | ||
288 | } | ||
289 | out_8(base, SM_FLASH_CMD_READ_STATUS); | ||
290 | stat = in_8(base); | ||
291 | } while (!(stat & SM_FLASH_STATUS_DONE)); | ||
292 | if (!(stat & SM_FLASH_STATUS_DONE)) | ||
293 | break; | ||
294 | } | ||
295 | out_8(base, SM_FLASH_CMD_CLEAR_STATUS); | ||
296 | out_8(base, SM_FLASH_CMD_RESET); | ||
297 | for (i=0; i<NVRAM_SIZE; i++) | ||
298 | if (base[i] != datas[i]) { | ||
299 | printk(KERN_ERR "nvram: Sharp/Micron flash write failed !\n"); | ||
300 | return -ENXIO; | ||
301 | } | ||
302 | return 0; | ||
303 | } | ||
304 | |||
305 | static int __pmac amd_erase_bank(int bank) | ||
306 | { | ||
307 | int i, stat = 0; | ||
308 | unsigned long timeout; | ||
309 | |||
310 | u8* base = (u8 *)nvram_data + core99_bank*NVRAM_SIZE; | ||
311 | |||
312 | DBG("nvram: AMD Erasing bank %d...\n", bank); | ||
313 | |||
314 | /* Unlock 1 */ | ||
315 | out_8(base+0x555, 0xaa); | ||
316 | udelay(1); | ||
317 | /* Unlock 2 */ | ||
318 | out_8(base+0x2aa, 0x55); | ||
319 | udelay(1); | ||
320 | |||
321 | /* Sector-Erase */ | ||
322 | out_8(base+0x555, 0x80); | ||
323 | udelay(1); | ||
324 | out_8(base+0x555, 0xaa); | ||
325 | udelay(1); | ||
326 | out_8(base+0x2aa, 0x55); | ||
327 | udelay(1); | ||
328 | out_8(base, 0x30); | ||
329 | udelay(1); | ||
330 | |||
331 | timeout = 0; | ||
332 | do { | ||
333 | if (++timeout > 1000000) { | ||
334 | printk(KERN_ERR "nvram: AMD flash erase timeout !\n"); | ||
335 | break; | ||
336 | } | ||
337 | stat = in_8(base) ^ in_8(base); | ||
338 | } while (stat != 0); | ||
339 | |||
340 | /* Reset */ | ||
341 | out_8(base, 0xf0); | ||
342 | udelay(1); | ||
343 | |||
344 | for (i=0; i<NVRAM_SIZE; i++) | ||
345 | if (base[i] != 0xff) { | ||
346 | printk(KERN_ERR "nvram: AMD flash erase failed !\n"); | ||
347 | return -ENXIO; | ||
348 | } | ||
349 | return 0; | ||
350 | } | ||
351 | |||
352 | static int __pmac amd_write_bank(int bank, u8* datas) | ||
353 | { | ||
354 | int i, stat = 0; | ||
355 | unsigned long timeout; | ||
356 | |||
357 | u8* base = (u8 *)nvram_data + core99_bank*NVRAM_SIZE; | ||
358 | |||
359 | DBG("nvram: AMD Writing bank %d...\n", bank); | ||
360 | |||
361 | for (i=0; i<NVRAM_SIZE; i++) { | ||
362 | /* Unlock 1 */ | ||
363 | out_8(base+0x555, 0xaa); | ||
364 | udelay(1); | ||
365 | /* Unlock 2 */ | ||
366 | out_8(base+0x2aa, 0x55); | ||
367 | udelay(1); | ||
368 | |||
369 | /* Write single word */ | ||
370 | out_8(base+0x555, 0xa0); | ||
371 | udelay(1); | ||
372 | out_8(base+i, datas[i]); | ||
373 | |||
374 | timeout = 0; | ||
375 | do { | ||
376 | if (++timeout > 1000000) { | ||
377 | printk(KERN_ERR "nvram: AMD flash write timeout !\n"); | ||
378 | break; | ||
379 | } | ||
380 | stat = in_8(base) ^ in_8(base); | ||
381 | } while (stat != 0); | ||
382 | if (stat != 0) | ||
383 | break; | ||
384 | } | ||
385 | |||
386 | /* Reset */ | ||
387 | out_8(base, 0xf0); | ||
388 | udelay(1); | ||
389 | |||
390 | for (i=0; i<NVRAM_SIZE; i++) | ||
391 | if (base[i] != datas[i]) { | ||
392 | printk(KERN_ERR "nvram: AMD flash write failed !\n"); | ||
393 | return -ENXIO; | ||
394 | } | ||
395 | return 0; | ||
396 | } | ||
397 | |||
398 | static void __init lookup_partitions(void) | ||
399 | { | ||
400 | u8 buffer[17]; | ||
401 | int i, offset; | ||
402 | struct chrp_header* hdr; | ||
403 | |||
404 | if (pmac_newworld) { | ||
405 | nvram_partitions[pmac_nvram_OF] = -1; | ||
406 | nvram_partitions[pmac_nvram_XPRAM] = -1; | ||
407 | nvram_partitions[pmac_nvram_NR] = -1; | ||
408 | hdr = (struct chrp_header *)buffer; | ||
409 | |||
410 | offset = 0; | ||
411 | buffer[16] = 0; | ||
412 | do { | ||
413 | for (i=0;i<16;i++) | ||
414 | buffer[i] = nvram_read_byte(offset+i); | ||
415 | if (!strcmp(hdr->name, "common")) | ||
416 | nvram_partitions[pmac_nvram_OF] = offset + 0x10; | ||
417 | if (!strcmp(hdr->name, "APL,MacOS75")) { | ||
418 | nvram_partitions[pmac_nvram_XPRAM] = offset + 0x10; | ||
419 | nvram_partitions[pmac_nvram_NR] = offset + 0x110; | ||
420 | } | ||
421 | offset += (hdr->len * 0x10); | ||
422 | } while(offset < NVRAM_SIZE); | ||
423 | } else { | ||
424 | nvram_partitions[pmac_nvram_OF] = 0x1800; | ||
425 | nvram_partitions[pmac_nvram_XPRAM] = 0x1300; | ||
426 | nvram_partitions[pmac_nvram_NR] = 0x1400; | ||
427 | } | ||
428 | DBG("nvram: OF partition at 0x%x\n", nvram_partitions[pmac_nvram_OF]); | ||
429 | DBG("nvram: XP partition at 0x%x\n", nvram_partitions[pmac_nvram_XPRAM]); | ||
430 | DBG("nvram: NR partition at 0x%x\n", nvram_partitions[pmac_nvram_NR]); | ||
431 | } | ||
432 | |||
433 | static void __pmac core99_nvram_sync(void) | ||
434 | { | ||
435 | struct core99_header* hdr99; | ||
436 | unsigned long flags; | ||
437 | |||
438 | if (!is_core_99 || !nvram_data || !nvram_image) | ||
439 | return; | ||
440 | |||
441 | spin_lock_irqsave(&nv_lock, flags); | ||
442 | if (!memcmp(nvram_image, (u8*)nvram_data + core99_bank*NVRAM_SIZE, | ||
443 | NVRAM_SIZE)) | ||
444 | goto bail; | ||
445 | |||
446 | DBG("Updating nvram...\n"); | ||
447 | |||
448 | hdr99 = (struct core99_header*)nvram_image; | ||
449 | hdr99->generation++; | ||
450 | hdr99->hdr.signature = CORE99_SIGNATURE; | ||
451 | hdr99->hdr.cksum = chrp_checksum(&hdr99->hdr); | ||
452 | hdr99->adler = core99_calc_adler(nvram_image); | ||
453 | core99_bank = core99_bank ? 0 : 1; | ||
454 | if (core99_erase_bank) | ||
455 | if (core99_erase_bank(core99_bank)) { | ||
456 | printk("nvram: Error erasing bank %d\n", core99_bank); | ||
457 | goto bail; | ||
458 | } | ||
459 | if (core99_write_bank) | ||
460 | if (core99_write_bank(core99_bank, nvram_image)) | ||
461 | printk("nvram: Error writing bank %d\n", core99_bank); | ||
462 | bail: | ||
463 | spin_unlock_irqrestore(&nv_lock, flags); | ||
464 | |||
465 | #ifdef DEBUG | ||
466 | mdelay(2000); | ||
467 | #endif | ||
468 | } | ||
469 | |||
470 | void __init pmac_nvram_init(void) | ||
471 | { | ||
472 | struct device_node *dp; | ||
473 | |||
474 | nvram_naddrs = 0; | ||
475 | |||
476 | dp = find_devices("nvram"); | ||
477 | if (dp == NULL) { | ||
478 | printk(KERN_ERR "Can't find NVRAM device\n"); | ||
479 | return; | ||
480 | } | ||
481 | nvram_naddrs = dp->n_addrs; | ||
482 | is_core_99 = device_is_compatible(dp, "nvram,flash"); | ||
483 | if (is_core_99) { | ||
484 | int i; | ||
485 | u32 gen_bank0, gen_bank1; | ||
486 | |||
487 | if (nvram_naddrs < 1) { | ||
488 | printk(KERN_ERR "nvram: no address\n"); | ||
489 | return; | ||
490 | } | ||
491 | nvram_image = alloc_bootmem(NVRAM_SIZE); | ||
492 | if (nvram_image == NULL) { | ||
493 | printk(KERN_ERR "nvram: can't allocate ram image\n"); | ||
494 | return; | ||
495 | } | ||
496 | nvram_data = ioremap(dp->addrs[0].address, NVRAM_SIZE*2); | ||
497 | nvram_naddrs = 1; /* Make sure we get the correct case */ | ||
498 | |||
499 | DBG("nvram: Checking bank 0...\n"); | ||
500 | |||
501 | gen_bank0 = core99_check((u8 *)nvram_data); | ||
502 | gen_bank1 = core99_check((u8 *)nvram_data + NVRAM_SIZE); | ||
503 | core99_bank = (gen_bank0 < gen_bank1) ? 1 : 0; | ||
504 | |||
505 | DBG("nvram: gen0=%d, gen1=%d\n", gen_bank0, gen_bank1); | ||
506 | DBG("nvram: Active bank is: %d\n", core99_bank); | ||
507 | |||
508 | for (i=0; i<NVRAM_SIZE; i++) | ||
509 | nvram_image[i] = nvram_data[i + core99_bank*NVRAM_SIZE]; | ||
510 | |||
511 | ppc_md.nvram_read_val = core99_nvram_read_byte; | ||
512 | ppc_md.nvram_write_val = core99_nvram_write_byte; | ||
513 | ppc_md.nvram_sync = core99_nvram_sync; | ||
514 | /* | ||
515 | * Maybe we could be smarter here though making an exclusive list | ||
516 | * of known flash chips is a bit nasty as older OF didn't provide us | ||
517 | * with a useful "compatible" entry. A solution would be to really | ||
518 | * identify the chip using flash id commands and base ourselves on | ||
519 | * a list of known chips IDs | ||
520 | */ | ||
521 | if (device_is_compatible(dp, "amd-0137")) { | ||
522 | core99_erase_bank = amd_erase_bank; | ||
523 | core99_write_bank = amd_write_bank; | ||
524 | } else { | ||
525 | core99_erase_bank = sm_erase_bank; | ||
526 | core99_write_bank = sm_write_bank; | ||
527 | } | ||
528 | } else if (_machine == _MACH_chrp && nvram_naddrs == 1) { | ||
529 | nvram_data = ioremap(dp->addrs[0].address + isa_mem_base, | ||
530 | dp->addrs[0].size); | ||
531 | nvram_mult = 1; | ||
532 | ppc_md.nvram_read_val = direct_nvram_read_byte; | ||
533 | ppc_md.nvram_write_val = direct_nvram_write_byte; | ||
534 | } else if (nvram_naddrs == 1) { | ||
535 | nvram_data = ioremap(dp->addrs[0].address, dp->addrs[0].size); | ||
536 | nvram_mult = (dp->addrs[0].size + NVRAM_SIZE - 1) / NVRAM_SIZE; | ||
537 | ppc_md.nvram_read_val = direct_nvram_read_byte; | ||
538 | ppc_md.nvram_write_val = direct_nvram_write_byte; | ||
539 | } else if (nvram_naddrs == 2) { | ||
540 | nvram_addr = ioremap(dp->addrs[0].address, dp->addrs[0].size); | ||
541 | nvram_data = ioremap(dp->addrs[1].address, dp->addrs[1].size); | ||
542 | ppc_md.nvram_read_val = indirect_nvram_read_byte; | ||
543 | ppc_md.nvram_write_val = indirect_nvram_write_byte; | ||
544 | } else if (nvram_naddrs == 0 && sys_ctrler == SYS_CTRLER_PMU) { | ||
545 | #ifdef CONFIG_ADB_PMU | ||
546 | nvram_naddrs = -1; | ||
547 | ppc_md.nvram_read_val = pmu_nvram_read_byte; | ||
548 | ppc_md.nvram_write_val = pmu_nvram_write_byte; | ||
549 | #endif /* CONFIG_ADB_PMU */ | ||
550 | } else { | ||
551 | printk(KERN_ERR "Don't know how to access NVRAM with %d addresses\n", | ||
552 | nvram_naddrs); | ||
553 | } | ||
554 | lookup_partitions(); | ||
555 | } | ||
556 | |||
557 | int __pmac pmac_get_partition(int partition) | ||
558 | { | ||
559 | return nvram_partitions[partition]; | ||
560 | } | ||
561 | |||
562 | u8 __pmac pmac_xpram_read(int xpaddr) | ||
563 | { | ||
564 | int offset = nvram_partitions[pmac_nvram_XPRAM]; | ||
565 | |||
566 | if (offset < 0) | ||
567 | return 0xff; | ||
568 | |||
569 | return ppc_md.nvram_read_val(xpaddr + offset); | ||
570 | } | ||
571 | |||
572 | void __pmac pmac_xpram_write(int xpaddr, u8 data) | ||
573 | { | ||
574 | int offset = nvram_partitions[pmac_nvram_XPRAM]; | ||
575 | |||
576 | if (offset < 0) | ||
577 | return; | ||
578 | |||
579 | ppc_md.nvram_write_val(xpaddr + offset, data); | ||
580 | } | ||
581 | |||
582 | EXPORT_SYMBOL(pmac_get_partition); | ||
583 | EXPORT_SYMBOL(pmac_xpram_read); | ||
584 | EXPORT_SYMBOL(pmac_xpram_write); | ||
diff --git a/arch/ppc/platforms/pmac_pci.c b/arch/ppc/platforms/pmac_pci.c new file mode 100644 index 000000000000..f6ff51924061 --- /dev/null +++ b/arch/ppc/platforms/pmac_pci.c | |||
@@ -0,0 +1,1125 @@ | |||
1 | /* | ||
2 | * Support for PCI bridges found on Power Macintoshes. | ||
3 | * At present the "bandit" and "chaos" bridges are supported. | ||
4 | * Fortunately you access configuration space in the same | ||
5 | * way with either bridge. | ||
6 | * | ||
7 | * Copyright (C) 1997 Paul Mackerras (paulus@cs.anu.edu.au) | ||
8 | * | ||
9 | * This program is free software; you can redistribute it and/or | ||
10 | * modify it under the terms of the GNU General Public License | ||
11 | * as published by the Free Software Foundation; either version | ||
12 | * 2 of the License, or (at your option) any later version. | ||
13 | */ | ||
14 | |||
15 | #include <linux/kernel.h> | ||
16 | #include <linux/pci.h> | ||
17 | #include <linux/delay.h> | ||
18 | #include <linux/string.h> | ||
19 | #include <linux/init.h> | ||
20 | #include <linux/bootmem.h> | ||
21 | |||
22 | #include <asm/sections.h> | ||
23 | #include <asm/io.h> | ||
24 | #include <asm/prom.h> | ||
25 | #include <asm/pci-bridge.h> | ||
26 | #include <asm/machdep.h> | ||
27 | #include <asm/pmac_feature.h> | ||
28 | |||
29 | #undef DEBUG | ||
30 | |||
31 | #ifdef DEBUG | ||
32 | #ifdef CONFIG_XMON | ||
33 | extern void xmon_printf(const char *fmt, ...); | ||
34 | #define DBG(x...) xmon_printf(x) | ||
35 | #else | ||
36 | #define DBG(x...) printk(x) | ||
37 | #endif | ||
38 | #else | ||
39 | #define DBG(x...) | ||
40 | #endif | ||
41 | |||
42 | static int add_bridge(struct device_node *dev); | ||
43 | extern void pmac_check_ht_link(void); | ||
44 | |||
45 | /* XXX Could be per-controller, but I don't think we risk anything by | ||
46 | * assuming we won't have both UniNorth and Bandit */ | ||
47 | static int has_uninorth; | ||
48 | #ifdef CONFIG_POWER4 | ||
49 | static struct pci_controller *u3_agp; | ||
50 | #endif /* CONFIG_POWER4 */ | ||
51 | |||
52 | extern u8 pci_cache_line_size; | ||
53 | extern int pcibios_assign_bus_offset; | ||
54 | |||
55 | struct device_node *k2_skiplist[2]; | ||
56 | |||
57 | /* | ||
58 | * Magic constants for enabling cache coherency in the bandit/PSX bridge. | ||
59 | */ | ||
60 | #define BANDIT_DEVID_2 8 | ||
61 | #define BANDIT_REVID 3 | ||
62 | |||
63 | #define BANDIT_DEVNUM 11 | ||
64 | #define BANDIT_MAGIC 0x50 | ||
65 | #define BANDIT_COHERENT 0x40 | ||
66 | |||
67 | static int __init | ||
68 | fixup_one_level_bus_range(struct device_node *node, int higher) | ||
69 | { | ||
70 | for (; node != 0;node = node->sibling) { | ||
71 | int * bus_range; | ||
72 | unsigned int *class_code; | ||
73 | int len; | ||
74 | |||
75 | /* For PCI<->PCI bridges or CardBus bridges, we go down */ | ||
76 | class_code = (unsigned int *) get_property(node, "class-code", NULL); | ||
77 | if (!class_code || ((*class_code >> 8) != PCI_CLASS_BRIDGE_PCI && | ||
78 | (*class_code >> 8) != PCI_CLASS_BRIDGE_CARDBUS)) | ||
79 | continue; | ||
80 | bus_range = (int *) get_property(node, "bus-range", &len); | ||
81 | if (bus_range != NULL && len > 2 * sizeof(int)) { | ||
82 | if (bus_range[1] > higher) | ||
83 | higher = bus_range[1]; | ||
84 | } | ||
85 | higher = fixup_one_level_bus_range(node->child, higher); | ||
86 | } | ||
87 | return higher; | ||
88 | } | ||
89 | |||
90 | /* This routine fixes the "bus-range" property of all bridges in the | ||
91 | * system since they tend to have their "last" member wrong on macs | ||
92 | * | ||
93 | * Note that the bus numbers manipulated here are OF bus numbers, they | ||
94 | * are not Linux bus numbers. | ||
95 | */ | ||
96 | static void __init | ||
97 | fixup_bus_range(struct device_node *bridge) | ||
98 | { | ||
99 | int * bus_range; | ||
100 | int len; | ||
101 | |||
102 | /* Lookup the "bus-range" property for the hose */ | ||
103 | bus_range = (int *) get_property(bridge, "bus-range", &len); | ||
104 | if (bus_range == NULL || len < 2 * sizeof(int)) { | ||
105 | printk(KERN_WARNING "Can't get bus-range for %s\n", | ||
106 | bridge->full_name); | ||
107 | return; | ||
108 | } | ||
109 | bus_range[1] = fixup_one_level_bus_range(bridge->child, bus_range[1]); | ||
110 | } | ||
111 | |||
112 | /* | ||
113 | * Apple MacRISC (U3, UniNorth, Bandit, Chaos) PCI controllers. | ||
114 | * | ||
115 | * The "Bandit" version is present in all early PCI PowerMacs, | ||
116 | * and up to the first ones using Grackle. Some machines may | ||
117 | * have 2 bandit controllers (2 PCI busses). | ||
118 | * | ||
119 | * "Chaos" is used in some "Bandit"-type machines as a bridge | ||
120 | * for the separate display bus. It is accessed the same | ||
121 | * way as bandit, but cannot be probed for devices. It therefore | ||
122 | * has its own config access functions. | ||
123 | * | ||
124 | * The "UniNorth" version is present in all Core99 machines | ||
125 | * (iBook, G4, new IMacs, and all the recent Apple machines). | ||
126 | * It contains 3 controllers in one ASIC. | ||
127 | * | ||
128 | * The U3 is the bridge used on G5 machines. It contains an | ||
129 | * AGP bus which is dealt with the old UniNorth access routines | ||
130 | * and a HyperTransport bus which uses its own set of access | ||
131 | * functions. | ||
132 | */ | ||
133 | |||
134 | #define MACRISC_CFA0(devfn, off) \ | ||
135 | ((1 << (unsigned long)PCI_SLOT(dev_fn)) \ | ||
136 | | (((unsigned long)PCI_FUNC(dev_fn)) << 8) \ | ||
137 | | (((unsigned long)(off)) & 0xFCUL)) | ||
138 | |||
139 | #define MACRISC_CFA1(bus, devfn, off) \ | ||
140 | ((((unsigned long)(bus)) << 16) \ | ||
141 | |(((unsigned long)(devfn)) << 8) \ | ||
142 | |(((unsigned long)(off)) & 0xFCUL) \ | ||
143 | |1UL) | ||
144 | |||
145 | static void volatile __iomem * __pmac | ||
146 | macrisc_cfg_access(struct pci_controller* hose, u8 bus, u8 dev_fn, u8 offset) | ||
147 | { | ||
148 | unsigned int caddr; | ||
149 | |||
150 | if (bus == hose->first_busno) { | ||
151 | if (dev_fn < (11 << 3)) | ||
152 | return NULL; | ||
153 | caddr = MACRISC_CFA0(dev_fn, offset); | ||
154 | } else | ||
155 | caddr = MACRISC_CFA1(bus, dev_fn, offset); | ||
156 | |||
157 | /* Uninorth will return garbage if we don't read back the value ! */ | ||
158 | do { | ||
159 | out_le32(hose->cfg_addr, caddr); | ||
160 | } while (in_le32(hose->cfg_addr) != caddr); | ||
161 | |||
162 | offset &= has_uninorth ? 0x07 : 0x03; | ||
163 | return hose->cfg_data + offset; | ||
164 | } | ||
165 | |||
166 | static int __pmac | ||
167 | macrisc_read_config(struct pci_bus *bus, unsigned int devfn, int offset, | ||
168 | int len, u32 *val) | ||
169 | { | ||
170 | struct pci_controller *hose = bus->sysdata; | ||
171 | void volatile __iomem *addr; | ||
172 | |||
173 | addr = macrisc_cfg_access(hose, bus->number, devfn, offset); | ||
174 | if (!addr) | ||
175 | return PCIBIOS_DEVICE_NOT_FOUND; | ||
176 | /* | ||
177 | * Note: the caller has already checked that offset is | ||
178 | * suitably aligned and that len is 1, 2 or 4. | ||
179 | */ | ||
180 | switch (len) { | ||
181 | case 1: | ||
182 | *val = in_8(addr); | ||
183 | break; | ||
184 | case 2: | ||
185 | *val = in_le16(addr); | ||
186 | break; | ||
187 | default: | ||
188 | *val = in_le32(addr); | ||
189 | break; | ||
190 | } | ||
191 | return PCIBIOS_SUCCESSFUL; | ||
192 | } | ||
193 | |||
194 | static int __pmac | ||
195 | macrisc_write_config(struct pci_bus *bus, unsigned int devfn, int offset, | ||
196 | int len, u32 val) | ||
197 | { | ||
198 | struct pci_controller *hose = bus->sysdata; | ||
199 | void volatile __iomem *addr; | ||
200 | |||
201 | addr = macrisc_cfg_access(hose, bus->number, devfn, offset); | ||
202 | if (!addr) | ||
203 | return PCIBIOS_DEVICE_NOT_FOUND; | ||
204 | /* | ||
205 | * Note: the caller has already checked that offset is | ||
206 | * suitably aligned and that len is 1, 2 or 4. | ||
207 | */ | ||
208 | switch (len) { | ||
209 | case 1: | ||
210 | out_8(addr, val); | ||
211 | (void) in_8(addr); | ||
212 | break; | ||
213 | case 2: | ||
214 | out_le16(addr, val); | ||
215 | (void) in_le16(addr); | ||
216 | break; | ||
217 | default: | ||
218 | out_le32(addr, val); | ||
219 | (void) in_le32(addr); | ||
220 | break; | ||
221 | } | ||
222 | return PCIBIOS_SUCCESSFUL; | ||
223 | } | ||
224 | |||
225 | static struct pci_ops macrisc_pci_ops = | ||
226 | { | ||
227 | macrisc_read_config, | ||
228 | macrisc_write_config | ||
229 | }; | ||
230 | |||
231 | /* | ||
232 | * Verifiy that a specific (bus, dev_fn) exists on chaos | ||
233 | */ | ||
234 | static int __pmac | ||
235 | chaos_validate_dev(struct pci_bus *bus, int devfn, int offset) | ||
236 | { | ||
237 | struct device_node *np; | ||
238 | u32 *vendor, *device; | ||
239 | |||
240 | np = pci_busdev_to_OF_node(bus, devfn); | ||
241 | if (np == NULL) | ||
242 | return PCIBIOS_DEVICE_NOT_FOUND; | ||
243 | |||
244 | vendor = (u32 *)get_property(np, "vendor-id", NULL); | ||
245 | device = (u32 *)get_property(np, "device-id", NULL); | ||
246 | if (vendor == NULL || device == NULL) | ||
247 | return PCIBIOS_DEVICE_NOT_FOUND; | ||
248 | |||
249 | if ((*vendor == 0x106b) && (*device == 3) && (offset >= 0x10) | ||
250 | && (offset != 0x14) && (offset != 0x18) && (offset <= 0x24)) | ||
251 | return PCIBIOS_BAD_REGISTER_NUMBER; | ||
252 | |||
253 | return PCIBIOS_SUCCESSFUL; | ||
254 | } | ||
255 | |||
256 | static int __pmac | ||
257 | chaos_read_config(struct pci_bus *bus, unsigned int devfn, int offset, | ||
258 | int len, u32 *val) | ||
259 | { | ||
260 | int result = chaos_validate_dev(bus, devfn, offset); | ||
261 | if (result == PCIBIOS_BAD_REGISTER_NUMBER) | ||
262 | *val = ~0U; | ||
263 | if (result != PCIBIOS_SUCCESSFUL) | ||
264 | return result; | ||
265 | return macrisc_read_config(bus, devfn, offset, len, val); | ||
266 | } | ||
267 | |||
268 | static int __pmac | ||
269 | chaos_write_config(struct pci_bus *bus, unsigned int devfn, int offset, | ||
270 | int len, u32 val) | ||
271 | { | ||
272 | int result = chaos_validate_dev(bus, devfn, offset); | ||
273 | if (result != PCIBIOS_SUCCESSFUL) | ||
274 | return result; | ||
275 | return macrisc_write_config(bus, devfn, offset, len, val); | ||
276 | } | ||
277 | |||
278 | static struct pci_ops chaos_pci_ops = | ||
279 | { | ||
280 | chaos_read_config, | ||
281 | chaos_write_config | ||
282 | }; | ||
283 | |||
284 | #ifdef CONFIG_POWER4 | ||
285 | |||
286 | /* | ||
287 | * These versions of U3 HyperTransport config space access ops do not | ||
288 | * implement self-view of the HT host yet | ||
289 | */ | ||
290 | |||
291 | #define U3_HT_CFA0(devfn, off) \ | ||
292 | ((((unsigned long)devfn) << 8) | offset) | ||
293 | #define U3_HT_CFA1(bus, devfn, off) \ | ||
294 | (U3_HT_CFA0(devfn, off) \ | ||
295 | + (((unsigned long)bus) << 16) \ | ||
296 | + 0x01000000UL) | ||
297 | |||
298 | static void volatile __iomem * __pmac | ||
299 | u3_ht_cfg_access(struct pci_controller* hose, u8 bus, u8 devfn, u8 offset) | ||
300 | { | ||
301 | if (bus == hose->first_busno) { | ||
302 | /* For now, we don't self probe U3 HT bridge */ | ||
303 | if (PCI_FUNC(devfn) != 0 || PCI_SLOT(devfn) > 7 || | ||
304 | PCI_SLOT(devfn) < 1) | ||
305 | return 0; | ||
306 | return hose->cfg_data + U3_HT_CFA0(devfn, offset); | ||
307 | } else | ||
308 | return hose->cfg_data + U3_HT_CFA1(bus, devfn, offset); | ||
309 | } | ||
310 | |||
311 | static int __pmac | ||
312 | u3_ht_read_config(struct pci_bus *bus, unsigned int devfn, int offset, | ||
313 | int len, u32 *val) | ||
314 | { | ||
315 | struct pci_controller *hose = bus->sysdata; | ||
316 | void volatile __iomem *addr; | ||
317 | int i; | ||
318 | |||
319 | struct device_node *np = pci_busdev_to_OF_node(bus, devfn); | ||
320 | if (np == NULL) | ||
321 | return PCIBIOS_DEVICE_NOT_FOUND; | ||
322 | |||
323 | /* | ||
324 | * When a device in K2 is powered down, we die on config | ||
325 | * cycle accesses. Fix that here. | ||
326 | */ | ||
327 | for (i=0; i<2; i++) | ||
328 | if (k2_skiplist[i] == np) { | ||
329 | switch (len) { | ||
330 | case 1: | ||
331 | *val = 0xff; break; | ||
332 | case 2: | ||
333 | *val = 0xffff; break; | ||
334 | default: | ||
335 | *val = 0xfffffffful; break; | ||
336 | } | ||
337 | return PCIBIOS_SUCCESSFUL; | ||
338 | } | ||
339 | |||
340 | addr = u3_ht_cfg_access(hose, bus->number, devfn, offset); | ||
341 | if (!addr) | ||
342 | return PCIBIOS_DEVICE_NOT_FOUND; | ||
343 | /* | ||
344 | * Note: the caller has already checked that offset is | ||
345 | * suitably aligned and that len is 1, 2 or 4. | ||
346 | */ | ||
347 | switch (len) { | ||
348 | case 1: | ||
349 | *val = in_8(addr); | ||
350 | break; | ||
351 | case 2: | ||
352 | *val = in_le16(addr); | ||
353 | break; | ||
354 | default: | ||
355 | *val = in_le32(addr); | ||
356 | break; | ||
357 | } | ||
358 | return PCIBIOS_SUCCESSFUL; | ||
359 | } | ||
360 | |||
361 | static int __pmac | ||
362 | u3_ht_write_config(struct pci_bus *bus, unsigned int devfn, int offset, | ||
363 | int len, u32 val) | ||
364 | { | ||
365 | struct pci_controller *hose = bus->sysdata; | ||
366 | void volatile __iomem *addr; | ||
367 | int i; | ||
368 | |||
369 | struct device_node *np = pci_busdev_to_OF_node(bus, devfn); | ||
370 | if (np == NULL) | ||
371 | return PCIBIOS_DEVICE_NOT_FOUND; | ||
372 | /* | ||
373 | * When a device in K2 is powered down, we die on config | ||
374 | * cycle accesses. Fix that here. | ||
375 | */ | ||
376 | for (i=0; i<2; i++) | ||
377 | if (k2_skiplist[i] == np) | ||
378 | return PCIBIOS_SUCCESSFUL; | ||
379 | |||
380 | addr = u3_ht_cfg_access(hose, bus->number, devfn, offset); | ||
381 | if (!addr) | ||
382 | return PCIBIOS_DEVICE_NOT_FOUND; | ||
383 | /* | ||
384 | * Note: the caller has already checked that offset is | ||
385 | * suitably aligned and that len is 1, 2 or 4. | ||
386 | */ | ||
387 | switch (len) { | ||
388 | case 1: | ||
389 | out_8(addr, val); | ||
390 | (void) in_8(addr); | ||
391 | break; | ||
392 | case 2: | ||
393 | out_le16(addr, val); | ||
394 | (void) in_le16(addr); | ||
395 | break; | ||
396 | default: | ||
397 | out_le32(addr, val); | ||
398 | (void) in_le32(addr); | ||
399 | break; | ||
400 | } | ||
401 | return PCIBIOS_SUCCESSFUL; | ||
402 | } | ||
403 | |||
404 | static struct pci_ops u3_ht_pci_ops = | ||
405 | { | ||
406 | u3_ht_read_config, | ||
407 | u3_ht_write_config | ||
408 | }; | ||
409 | |||
410 | #endif /* CONFIG_POWER4 */ | ||
411 | |||
412 | /* | ||
413 | * For a bandit bridge, turn on cache coherency if necessary. | ||
414 | * N.B. we could clean this up using the hose ops directly. | ||
415 | */ | ||
416 | static void __init | ||
417 | init_bandit(struct pci_controller *bp) | ||
418 | { | ||
419 | unsigned int vendev, magic; | ||
420 | int rev; | ||
421 | |||
422 | /* read the word at offset 0 in config space for device 11 */ | ||
423 | out_le32(bp->cfg_addr, (1UL << BANDIT_DEVNUM) + PCI_VENDOR_ID); | ||
424 | udelay(2); | ||
425 | vendev = in_le32(bp->cfg_data); | ||
426 | if (vendev == (PCI_DEVICE_ID_APPLE_BANDIT << 16) + | ||
427 | PCI_VENDOR_ID_APPLE) { | ||
428 | /* read the revision id */ | ||
429 | out_le32(bp->cfg_addr, | ||
430 | (1UL << BANDIT_DEVNUM) + PCI_REVISION_ID); | ||
431 | udelay(2); | ||
432 | rev = in_8(bp->cfg_data); | ||
433 | if (rev != BANDIT_REVID) | ||
434 | printk(KERN_WARNING | ||
435 | "Unknown revision %d for bandit\n", rev); | ||
436 | } else if (vendev != (BANDIT_DEVID_2 << 16) + PCI_VENDOR_ID_APPLE) { | ||
437 | printk(KERN_WARNING "bandit isn't? (%x)\n", vendev); | ||
438 | return; | ||
439 | } | ||
440 | |||
441 | /* read the word at offset 0x50 */ | ||
442 | out_le32(bp->cfg_addr, (1UL << BANDIT_DEVNUM) + BANDIT_MAGIC); | ||
443 | udelay(2); | ||
444 | magic = in_le32(bp->cfg_data); | ||
445 | if ((magic & BANDIT_COHERENT) != 0) | ||
446 | return; | ||
447 | magic |= BANDIT_COHERENT; | ||
448 | udelay(2); | ||
449 | out_le32(bp->cfg_data, magic); | ||
450 | printk(KERN_INFO "Cache coherency enabled for bandit/PSX\n"); | ||
451 | } | ||
452 | |||
453 | |||
454 | /* | ||
455 | * Tweak the PCI-PCI bridge chip on the blue & white G3s. | ||
456 | */ | ||
457 | static void __init | ||
458 | init_p2pbridge(void) | ||
459 | { | ||
460 | struct device_node *p2pbridge; | ||
461 | struct pci_controller* hose; | ||
462 | u8 bus, devfn; | ||
463 | u16 val; | ||
464 | |||
465 | /* XXX it would be better here to identify the specific | ||
466 | PCI-PCI bridge chip we have. */ | ||
467 | if ((p2pbridge = find_devices("pci-bridge")) == 0 | ||
468 | || p2pbridge->parent == NULL | ||
469 | || strcmp(p2pbridge->parent->name, "pci") != 0) | ||
470 | return; | ||
471 | if (pci_device_from_OF_node(p2pbridge, &bus, &devfn) < 0) { | ||
472 | DBG("Can't find PCI infos for PCI<->PCI bridge\n"); | ||
473 | return; | ||
474 | } | ||
475 | /* Warning: At this point, we have not yet renumbered all busses. | ||
476 | * So we must use OF walking to find out hose | ||
477 | */ | ||
478 | hose = pci_find_hose_for_OF_device(p2pbridge); | ||
479 | if (!hose) { | ||
480 | DBG("Can't find hose for PCI<->PCI bridge\n"); | ||
481 | return; | ||
482 | } | ||
483 | if (early_read_config_word(hose, bus, devfn, | ||
484 | PCI_BRIDGE_CONTROL, &val) < 0) { | ||
485 | printk(KERN_ERR "init_p2pbridge: couldn't read bridge control\n"); | ||
486 | return; | ||
487 | } | ||
488 | val &= ~PCI_BRIDGE_CTL_MASTER_ABORT; | ||
489 | early_write_config_word(hose, bus, devfn, PCI_BRIDGE_CONTROL, val); | ||
490 | } | ||
491 | |||
492 | /* | ||
493 | * Some Apple desktop machines have a NEC PD720100A USB2 controller | ||
494 | * on the motherboard. Open Firmware, on these, will disable the | ||
495 | * EHCI part of it so it behaves like a pair of OHCI's. This fixup | ||
496 | * code re-enables it ;) | ||
497 | */ | ||
498 | static void __init | ||
499 | fixup_nec_usb2(void) | ||
500 | { | ||
501 | struct device_node *nec; | ||
502 | |||
503 | for (nec = NULL; (nec = of_find_node_by_name(nec, "usb")) != NULL;) { | ||
504 | struct pci_controller *hose; | ||
505 | u32 data, *prop; | ||
506 | u8 bus, devfn; | ||
507 | |||
508 | prop = (u32 *)get_property(nec, "vendor-id", NULL); | ||
509 | if (prop == NULL) | ||
510 | continue; | ||
511 | if (0x1033 != *prop) | ||
512 | continue; | ||
513 | prop = (u32 *)get_property(nec, "device-id", NULL); | ||
514 | if (prop == NULL) | ||
515 | continue; | ||
516 | if (0x0035 != *prop) | ||
517 | continue; | ||
518 | prop = (u32 *)get_property(nec, "reg", NULL); | ||
519 | if (prop == NULL) | ||
520 | continue; | ||
521 | devfn = (prop[0] >> 8) & 0xff; | ||
522 | bus = (prop[0] >> 16) & 0xff; | ||
523 | if (PCI_FUNC(devfn) != 0) | ||
524 | continue; | ||
525 | hose = pci_find_hose_for_OF_device(nec); | ||
526 | if (!hose) | ||
527 | continue; | ||
528 | early_read_config_dword(hose, bus, devfn, 0xe4, &data); | ||
529 | if (data & 1UL) { | ||
530 | printk("Found NEC PD720100A USB2 chip with disabled EHCI, fixing up...\n"); | ||
531 | data &= ~1UL; | ||
532 | early_write_config_dword(hose, bus, devfn, 0xe4, data); | ||
533 | early_write_config_byte(hose, bus, devfn | 2, PCI_INTERRUPT_LINE, | ||
534 | nec->intrs[0].line); | ||
535 | } | ||
536 | } | ||
537 | } | ||
538 | |||
539 | void __init | ||
540 | pmac_find_bridges(void) | ||
541 | { | ||
542 | struct device_node *np, *root; | ||
543 | struct device_node *ht = NULL; | ||
544 | |||
545 | root = of_find_node_by_path("/"); | ||
546 | if (root == NULL) { | ||
547 | printk(KERN_CRIT "pmac_find_bridges: can't find root of device tree\n"); | ||
548 | return; | ||
549 | } | ||
550 | for (np = NULL; (np = of_get_next_child(root, np)) != NULL;) { | ||
551 | if (np->name == NULL) | ||
552 | continue; | ||
553 | if (strcmp(np->name, "bandit") == 0 | ||
554 | || strcmp(np->name, "chaos") == 0 | ||
555 | || strcmp(np->name, "pci") == 0) { | ||
556 | if (add_bridge(np) == 0) | ||
557 | of_node_get(np); | ||
558 | } | ||
559 | if (strcmp(np->name, "ht") == 0) { | ||
560 | of_node_get(np); | ||
561 | ht = np; | ||
562 | } | ||
563 | } | ||
564 | of_node_put(root); | ||
565 | |||
566 | /* Probe HT last as it relies on the agp resources to be already | ||
567 | * setup | ||
568 | */ | ||
569 | if (ht && add_bridge(ht) != 0) | ||
570 | of_node_put(ht); | ||
571 | |||
572 | init_p2pbridge(); | ||
573 | fixup_nec_usb2(); | ||
574 | |||
575 | /* We are still having some issues with the Xserve G4, enabling | ||
576 | * some offset between bus number and domains for now when we | ||
577 | * assign all busses should help for now | ||
578 | */ | ||
579 | if (pci_assign_all_busses) | ||
580 | pcibios_assign_bus_offset = 0x10; | ||
581 | |||
582 | #ifdef CONFIG_POWER4 | ||
583 | /* There is something wrong with DMA on U3/HT. I haven't figured out | ||
584 | * the details yet, but if I set the cache line size to 128 bytes like | ||
585 | * it should, I'm getting memory corruption caused by devices like | ||
586 | * sungem (even without the MWI bit set, but maybe sungem doesn't | ||
587 | * care). Right now, it appears that setting up a 64 bytes line size | ||
588 | * works properly, 64 bytes beeing the max transfer size of HT, I | ||
589 | * suppose this is related the way HT/PCI are hooked together. I still | ||
590 | * need to dive into more specs though to be really sure of what's | ||
591 | * going on. --BenH. | ||
592 | * | ||
593 | * Ok, apparently, it's just that HT can't do more than 64 bytes | ||
594 | * transactions. MWI seem to be meaningless there as well, it may | ||
595 | * be worth nop'ing out pci_set_mwi too though I haven't done that | ||
596 | * yet. | ||
597 | * | ||
598 | * Note that it's a bit different for whatever is in the AGP slot. | ||
599 | * For now, I don't care, but this can become a real issue, we | ||
600 | * should probably hook pci_set_mwi anyway to make sure it sets | ||
601 | * the real cache line size in there. | ||
602 | */ | ||
603 | if (machine_is_compatible("MacRISC4")) | ||
604 | pci_cache_line_size = 16; /* 64 bytes */ | ||
605 | |||
606 | pmac_check_ht_link(); | ||
607 | #endif /* CONFIG_POWER4 */ | ||
608 | } | ||
609 | |||
610 | #define GRACKLE_CFA(b, d, o) (0x80 | ((b) << 8) | ((d) << 16) \ | ||
611 | | (((o) & ~3) << 24)) | ||
612 | |||
613 | #define GRACKLE_PICR1_STG 0x00000040 | ||
614 | #define GRACKLE_PICR1_LOOPSNOOP 0x00000010 | ||
615 | |||
616 | /* N.B. this is called before bridges is initialized, so we can't | ||
617 | use grackle_pcibios_{read,write}_config_dword. */ | ||
618 | static inline void grackle_set_stg(struct pci_controller* bp, int enable) | ||
619 | { | ||
620 | unsigned int val; | ||
621 | |||
622 | out_be32(bp->cfg_addr, GRACKLE_CFA(0, 0, 0xa8)); | ||
623 | val = in_le32(bp->cfg_data); | ||
624 | val = enable? (val | GRACKLE_PICR1_STG) : | ||
625 | (val & ~GRACKLE_PICR1_STG); | ||
626 | out_be32(bp->cfg_addr, GRACKLE_CFA(0, 0, 0xa8)); | ||
627 | out_le32(bp->cfg_data, val); | ||
628 | (void)in_le32(bp->cfg_data); | ||
629 | } | ||
630 | |||
631 | static inline void grackle_set_loop_snoop(struct pci_controller *bp, int enable) | ||
632 | { | ||
633 | unsigned int val; | ||
634 | |||
635 | out_be32(bp->cfg_addr, GRACKLE_CFA(0, 0, 0xa8)); | ||
636 | val = in_le32(bp->cfg_data); | ||
637 | val = enable? (val | GRACKLE_PICR1_LOOPSNOOP) : | ||
638 | (val & ~GRACKLE_PICR1_LOOPSNOOP); | ||
639 | out_be32(bp->cfg_addr, GRACKLE_CFA(0, 0, 0xa8)); | ||
640 | out_le32(bp->cfg_data, val); | ||
641 | (void)in_le32(bp->cfg_data); | ||
642 | } | ||
643 | |||
644 | static int __init | ||
645 | setup_uninorth(struct pci_controller* hose, struct reg_property* addr) | ||
646 | { | ||
647 | pci_assign_all_busses = 1; | ||
648 | has_uninorth = 1; | ||
649 | hose->ops = ¯isc_pci_ops; | ||
650 | hose->cfg_addr = ioremap(addr->address + 0x800000, 0x1000); | ||
651 | hose->cfg_data = ioremap(addr->address + 0xc00000, 0x1000); | ||
652 | /* We "know" that the bridge at f2000000 has the PCI slots. */ | ||
653 | return addr->address == 0xf2000000; | ||
654 | } | ||
655 | |||
656 | static void __init | ||
657 | setup_bandit(struct pci_controller* hose, struct reg_property* addr) | ||
658 | { | ||
659 | hose->ops = ¯isc_pci_ops; | ||
660 | hose->cfg_addr = ioremap(addr->address + 0x800000, 0x1000); | ||
661 | hose->cfg_data = ioremap(addr->address + 0xc00000, 0x1000); | ||
662 | init_bandit(hose); | ||
663 | } | ||
664 | |||
665 | static void __init | ||
666 | setup_chaos(struct pci_controller* hose, struct reg_property* addr) | ||
667 | { | ||
668 | /* assume a `chaos' bridge */ | ||
669 | hose->ops = &chaos_pci_ops; | ||
670 | hose->cfg_addr = ioremap(addr->address + 0x800000, 0x1000); | ||
671 | hose->cfg_data = ioremap(addr->address + 0xc00000, 0x1000); | ||
672 | } | ||
673 | |||
674 | #ifdef CONFIG_POWER4 | ||
675 | |||
676 | static void __init | ||
677 | setup_u3_agp(struct pci_controller* hose, struct reg_property* addr) | ||
678 | { | ||
679 | /* On G5, we move AGP up to high bus number so we don't need | ||
680 | * to reassign bus numbers for HT. If we ever have P2P bridges | ||
681 | * on AGP, we'll have to move pci_assign_all_busses to the | ||
682 | * pci_controller structure so we enable it for AGP and not for | ||
683 | * HT childs. | ||
684 | * We hard code the address because of the different size of | ||
685 | * the reg address cell, we shall fix that by killing struct | ||
686 | * reg_property and using some accessor functions instead | ||
687 | */ | ||
688 | hose->first_busno = 0xf0; | ||
689 | hose->last_busno = 0xff; | ||
690 | has_uninorth = 1; | ||
691 | hose->ops = ¯isc_pci_ops; | ||
692 | hose->cfg_addr = ioremap(0xf0000000 + 0x800000, 0x1000); | ||
693 | hose->cfg_data = ioremap(0xf0000000 + 0xc00000, 0x1000); | ||
694 | |||
695 | u3_agp = hose; | ||
696 | } | ||
697 | |||
698 | static void __init | ||
699 | setup_u3_ht(struct pci_controller* hose, struct reg_property *addr) | ||
700 | { | ||
701 | struct device_node *np = (struct device_node *)hose->arch_data; | ||
702 | int i, cur; | ||
703 | |||
704 | hose->ops = &u3_ht_pci_ops; | ||
705 | |||
706 | /* We hard code the address because of the different size of | ||
707 | * the reg address cell, we shall fix that by killing struct | ||
708 | * reg_property and using some accessor functions instead | ||
709 | */ | ||
710 | hose->cfg_data = ioremap(0xf2000000, 0x02000000); | ||
711 | |||
712 | /* | ||
713 | * /ht node doesn't expose a "ranges" property, so we "remove" regions that | ||
714 | * have been allocated to AGP. So far, this version of the code doesn't assign | ||
715 | * any of the 0xfxxxxxxx "fine" memory regions to /ht. | ||
716 | * We need to fix that sooner or later by either parsing all child "ranges" | ||
717 | * properties or figuring out the U3 address space decoding logic and | ||
718 | * then read its configuration register (if any). | ||
719 | */ | ||
720 | hose->io_base_phys = 0xf4000000; | ||
721 | hose->io_base_virt = ioremap(hose->io_base_phys, 0x00400000); | ||
722 | isa_io_base = (unsigned long) hose->io_base_virt; | ||
723 | hose->io_resource.name = np->full_name; | ||
724 | hose->io_resource.start = 0; | ||
725 | hose->io_resource.end = 0x003fffff; | ||
726 | hose->io_resource.flags = IORESOURCE_IO; | ||
727 | hose->pci_mem_offset = 0; | ||
728 | hose->first_busno = 0; | ||
729 | hose->last_busno = 0xef; | ||
730 | hose->mem_resources[0].name = np->full_name; | ||
731 | hose->mem_resources[0].start = 0x80000000; | ||
732 | hose->mem_resources[0].end = 0xefffffff; | ||
733 | hose->mem_resources[0].flags = IORESOURCE_MEM; | ||
734 | |||
735 | if (u3_agp == NULL) { | ||
736 | DBG("U3 has no AGP, using full resource range\n"); | ||
737 | return; | ||
738 | } | ||
739 | |||
740 | /* We "remove" the AGP resources from the resources allocated to HT, that | ||
741 | * is we create "holes". However, that code does assumptions that so far | ||
742 | * happen to be true (cross fingers...), typically that resources in the | ||
743 | * AGP node are properly ordered | ||
744 | */ | ||
745 | cur = 0; | ||
746 | for (i=0; i<3; i++) { | ||
747 | struct resource *res = &u3_agp->mem_resources[i]; | ||
748 | if (res->flags != IORESOURCE_MEM) | ||
749 | continue; | ||
750 | /* We don't care about "fine" resources */ | ||
751 | if (res->start >= 0xf0000000) | ||
752 | continue; | ||
753 | /* Check if it's just a matter of "shrinking" us in one direction */ | ||
754 | if (hose->mem_resources[cur].start == res->start) { | ||
755 | DBG("U3/HT: shrink start of %d, %08lx -> %08lx\n", | ||
756 | cur, hose->mem_resources[cur].start, res->end + 1); | ||
757 | hose->mem_resources[cur].start = res->end + 1; | ||
758 | continue; | ||
759 | } | ||
760 | if (hose->mem_resources[cur].end == res->end) { | ||
761 | DBG("U3/HT: shrink end of %d, %08lx -> %08lx\n", | ||
762 | cur, hose->mem_resources[cur].end, res->start - 1); | ||
763 | hose->mem_resources[cur].end = res->start - 1; | ||
764 | continue; | ||
765 | } | ||
766 | /* No, it's not the case, we need a hole */ | ||
767 | if (cur == 2) { | ||
768 | /* not enough resources to make a hole, we drop part of the range */ | ||
769 | printk(KERN_WARNING "Running out of resources for /ht host !\n"); | ||
770 | hose->mem_resources[cur].end = res->start - 1; | ||
771 | continue; | ||
772 | } | ||
773 | cur++; | ||
774 | DBG("U3/HT: hole, %d end at %08lx, %d start at %08lx\n", | ||
775 | cur-1, res->start - 1, cur, res->end + 1); | ||
776 | hose->mem_resources[cur].name = np->full_name; | ||
777 | hose->mem_resources[cur].flags = IORESOURCE_MEM; | ||
778 | hose->mem_resources[cur].start = res->end + 1; | ||
779 | hose->mem_resources[cur].end = hose->mem_resources[cur-1].end; | ||
780 | hose->mem_resources[cur-1].end = res->start - 1; | ||
781 | } | ||
782 | } | ||
783 | |||
784 | #endif /* CONFIG_POWER4 */ | ||
785 | |||
786 | void __init | ||
787 | setup_grackle(struct pci_controller *hose) | ||
788 | { | ||
789 | setup_indirect_pci(hose, 0xfec00000, 0xfee00000); | ||
790 | if (machine_is_compatible("AAPL,PowerBook1998")) | ||
791 | grackle_set_loop_snoop(hose, 1); | ||
792 | #if 0 /* Disabled for now, HW problems ??? */ | ||
793 | grackle_set_stg(hose, 1); | ||
794 | #endif | ||
795 | } | ||
796 | |||
797 | /* | ||
798 | * We assume that if we have a G3 powermac, we have one bridge called | ||
799 | * "pci" (a MPC106) and no bandit or chaos bridges, and contrariwise, | ||
800 | * if we have one or more bandit or chaos bridges, we don't have a MPC106. | ||
801 | */ | ||
802 | static int __init | ||
803 | add_bridge(struct device_node *dev) | ||
804 | { | ||
805 | int len; | ||
806 | struct pci_controller *hose; | ||
807 | struct reg_property *addr; | ||
808 | char* disp_name; | ||
809 | int *bus_range; | ||
810 | int primary = 1; | ||
811 | |||
812 | DBG("Adding PCI host bridge %s\n", dev->full_name); | ||
813 | |||
814 | addr = (struct reg_property *) get_property(dev, "reg", &len); | ||
815 | if (addr == NULL || len < sizeof(*addr)) { | ||
816 | printk(KERN_WARNING "Can't use %s: no address\n", | ||
817 | dev->full_name); | ||
818 | return -ENODEV; | ||
819 | } | ||
820 | bus_range = (int *) get_property(dev, "bus-range", &len); | ||
821 | if (bus_range == NULL || len < 2 * sizeof(int)) { | ||
822 | printk(KERN_WARNING "Can't get bus-range for %s, assume bus 0\n", | ||
823 | dev->full_name); | ||
824 | } | ||
825 | |||
826 | hose = pcibios_alloc_controller(); | ||
827 | if (!hose) | ||
828 | return -ENOMEM; | ||
829 | hose->arch_data = dev; | ||
830 | hose->first_busno = bus_range ? bus_range[0] : 0; | ||
831 | hose->last_busno = bus_range ? bus_range[1] : 0xff; | ||
832 | |||
833 | disp_name = NULL; | ||
834 | #ifdef CONFIG_POWER4 | ||
835 | if (device_is_compatible(dev, "u3-agp")) { | ||
836 | setup_u3_agp(hose, addr); | ||
837 | disp_name = "U3-AGP"; | ||
838 | primary = 0; | ||
839 | } else if (device_is_compatible(dev, "u3-ht")) { | ||
840 | setup_u3_ht(hose, addr); | ||
841 | disp_name = "U3-HT"; | ||
842 | primary = 1; | ||
843 | } else | ||
844 | #endif /* CONFIG_POWER4 */ | ||
845 | if (device_is_compatible(dev, "uni-north")) { | ||
846 | primary = setup_uninorth(hose, addr); | ||
847 | disp_name = "UniNorth"; | ||
848 | } else if (strcmp(dev->name, "pci") == 0) { | ||
849 | /* XXX assume this is a mpc106 (grackle) */ | ||
850 | setup_grackle(hose); | ||
851 | disp_name = "Grackle (MPC106)"; | ||
852 | } else if (strcmp(dev->name, "bandit") == 0) { | ||
853 | setup_bandit(hose, addr); | ||
854 | disp_name = "Bandit"; | ||
855 | } else if (strcmp(dev->name, "chaos") == 0) { | ||
856 | setup_chaos(hose, addr); | ||
857 | disp_name = "Chaos"; | ||
858 | primary = 0; | ||
859 | } | ||
860 | printk(KERN_INFO "Found %s PCI host bridge at 0x%08x. Firmware bus number: %d->%d\n", | ||
861 | disp_name, addr->address, hose->first_busno, hose->last_busno); | ||
862 | DBG(" ->Hose at 0x%p, cfg_addr=0x%p,cfg_data=0x%p\n", | ||
863 | hose, hose->cfg_addr, hose->cfg_data); | ||
864 | |||
865 | /* Interpret the "ranges" property */ | ||
866 | /* This also maps the I/O region and sets isa_io/mem_base */ | ||
867 | pci_process_bridge_OF_ranges(hose, dev, primary); | ||
868 | |||
869 | /* Fixup "bus-range" OF property */ | ||
870 | fixup_bus_range(dev); | ||
871 | |||
872 | return 0; | ||
873 | } | ||
874 | |||
875 | static void __init | ||
876 | pcibios_fixup_OF_interrupts(void) | ||
877 | { | ||
878 | struct pci_dev* dev = NULL; | ||
879 | |||
880 | /* | ||
881 | * Open Firmware often doesn't initialize the | ||
882 | * PCI_INTERRUPT_LINE config register properly, so we | ||
883 | * should find the device node and apply the interrupt | ||
884 | * obtained from the OF device-tree | ||
885 | */ | ||
886 | for_each_pci_dev(dev) { | ||
887 | struct device_node *node; | ||
888 | node = pci_device_to_OF_node(dev); | ||
889 | /* this is the node, see if it has interrupts */ | ||
890 | if (node && node->n_intrs > 0) | ||
891 | dev->irq = node->intrs[0].line; | ||
892 | pci_write_config_byte(dev, PCI_INTERRUPT_LINE, dev->irq); | ||
893 | } | ||
894 | } | ||
895 | |||
896 | void __init | ||
897 | pmac_pcibios_fixup(void) | ||
898 | { | ||
899 | /* Fixup interrupts according to OF tree */ | ||
900 | pcibios_fixup_OF_interrupts(); | ||
901 | } | ||
902 | |||
903 | int __pmac | ||
904 | pmac_pci_enable_device_hook(struct pci_dev *dev, int initial) | ||
905 | { | ||
906 | struct device_node* node; | ||
907 | int updatecfg = 0; | ||
908 | int uninorth_child; | ||
909 | |||
910 | node = pci_device_to_OF_node(dev); | ||
911 | |||
912 | /* We don't want to enable USB controllers absent from the OF tree | ||
913 | * (iBook second controller) | ||
914 | */ | ||
915 | if (dev->vendor == PCI_VENDOR_ID_APPLE | ||
916 | && (dev->class == ((PCI_CLASS_SERIAL_USB << 8) | 0x10)) | ||
917 | && !node) { | ||
918 | printk(KERN_INFO "Apple USB OHCI %s disabled by firmware\n", | ||
919 | pci_name(dev)); | ||
920 | return -EINVAL; | ||
921 | } | ||
922 | |||
923 | if (!node) | ||
924 | return 0; | ||
925 | |||
926 | uninorth_child = node->parent && | ||
927 | device_is_compatible(node->parent, "uni-north"); | ||
928 | |||
929 | /* Firewire & GMAC were disabled after PCI probe, the driver is | ||
930 | * claiming them, we must re-enable them now. | ||
931 | */ | ||
932 | if (uninorth_child && !strcmp(node->name, "firewire") && | ||
933 | (device_is_compatible(node, "pci106b,18") || | ||
934 | device_is_compatible(node, "pci106b,30") || | ||
935 | device_is_compatible(node, "pci11c1,5811"))) { | ||
936 | pmac_call_feature(PMAC_FTR_1394_CABLE_POWER, node, 0, 1); | ||
937 | pmac_call_feature(PMAC_FTR_1394_ENABLE, node, 0, 1); | ||
938 | updatecfg = 1; | ||
939 | } | ||
940 | if (uninorth_child && !strcmp(node->name, "ethernet") && | ||
941 | device_is_compatible(node, "gmac")) { | ||
942 | pmac_call_feature(PMAC_FTR_GMAC_ENABLE, node, 0, 1); | ||
943 | updatecfg = 1; | ||
944 | } | ||
945 | |||
946 | if (updatecfg) { | ||
947 | u16 cmd; | ||
948 | |||
949 | /* | ||
950 | * Make sure PCI is correctly configured | ||
951 | * | ||
952 | * We use old pci_bios versions of the function since, by | ||
953 | * default, gmac is not powered up, and so will be absent | ||
954 | * from the kernel initial PCI lookup. | ||
955 | * | ||
956 | * Should be replaced by 2.4 new PCI mechanisms and really | ||
957 | * register the device. | ||
958 | */ | ||
959 | pci_read_config_word(dev, PCI_COMMAND, &cmd); | ||
960 | cmd |= PCI_COMMAND_MEMORY | PCI_COMMAND_MASTER | PCI_COMMAND_INVALIDATE; | ||
961 | pci_write_config_word(dev, PCI_COMMAND, cmd); | ||
962 | pci_write_config_byte(dev, PCI_LATENCY_TIMER, 16); | ||
963 | pci_write_config_byte(dev, PCI_CACHE_LINE_SIZE, pci_cache_line_size); | ||
964 | } | ||
965 | |||
966 | return 0; | ||
967 | } | ||
968 | |||
969 | /* We power down some devices after they have been probed. They'll | ||
970 | * be powered back on later on | ||
971 | */ | ||
972 | void __init | ||
973 | pmac_pcibios_after_init(void) | ||
974 | { | ||
975 | struct device_node* nd; | ||
976 | |||
977 | #ifdef CONFIG_BLK_DEV_IDE | ||
978 | struct pci_dev *dev = NULL; | ||
979 | |||
980 | /* OF fails to initialize IDE controllers on macs | ||
981 | * (and maybe other machines) | ||
982 | * | ||
983 | * Ideally, this should be moved to the IDE layer, but we need | ||
984 | * to check specifically with Andre Hedrick how to do it cleanly | ||
985 | * since the common IDE code seem to care about the fact that the | ||
986 | * BIOS may have disabled a controller. | ||
987 | * | ||
988 | * -- BenH | ||
989 | */ | ||
990 | for_each_pci_dev(dev) { | ||
991 | if ((dev->class >> 16) == PCI_BASE_CLASS_STORAGE) | ||
992 | pci_enable_device(dev); | ||
993 | } | ||
994 | #endif /* CONFIG_BLK_DEV_IDE */ | ||
995 | |||
996 | nd = find_devices("firewire"); | ||
997 | while (nd) { | ||
998 | if (nd->parent && (device_is_compatible(nd, "pci106b,18") || | ||
999 | device_is_compatible(nd, "pci106b,30") || | ||
1000 | device_is_compatible(nd, "pci11c1,5811")) | ||
1001 | && device_is_compatible(nd->parent, "uni-north")) { | ||
1002 | pmac_call_feature(PMAC_FTR_1394_ENABLE, nd, 0, 0); | ||
1003 | pmac_call_feature(PMAC_FTR_1394_CABLE_POWER, nd, 0, 0); | ||
1004 | } | ||
1005 | nd = nd->next; | ||
1006 | } | ||
1007 | nd = find_devices("ethernet"); | ||
1008 | while (nd) { | ||
1009 | if (nd->parent && device_is_compatible(nd, "gmac") | ||
1010 | && device_is_compatible(nd->parent, "uni-north")) | ||
1011 | pmac_call_feature(PMAC_FTR_GMAC_ENABLE, nd, 0, 0); | ||
1012 | nd = nd->next; | ||
1013 | } | ||
1014 | } | ||
1015 | |||
1016 | void pmac_pci_fixup_cardbus(struct pci_dev* dev) | ||
1017 | { | ||
1018 | if (_machine != _MACH_Pmac) | ||
1019 | return; | ||
1020 | /* | ||
1021 | * Fix the interrupt routing on the various cardbus bridges | ||
1022 | * used on powerbooks | ||
1023 | */ | ||
1024 | if (dev->vendor != PCI_VENDOR_ID_TI) | ||
1025 | return; | ||
1026 | if (dev->device == PCI_DEVICE_ID_TI_1130 || | ||
1027 | dev->device == PCI_DEVICE_ID_TI_1131) { | ||
1028 | u8 val; | ||
1029 | /* Enable PCI interrupt */ | ||
1030 | if (pci_read_config_byte(dev, 0x91, &val) == 0) | ||
1031 | pci_write_config_byte(dev, 0x91, val | 0x30); | ||
1032 | /* Disable ISA interrupt mode */ | ||
1033 | if (pci_read_config_byte(dev, 0x92, &val) == 0) | ||
1034 | pci_write_config_byte(dev, 0x92, val & ~0x06); | ||
1035 | } | ||
1036 | if (dev->device == PCI_DEVICE_ID_TI_1210 || | ||
1037 | dev->device == PCI_DEVICE_ID_TI_1211 || | ||
1038 | dev->device == PCI_DEVICE_ID_TI_1410 || | ||
1039 | dev->device == PCI_DEVICE_ID_TI_1510) { | ||
1040 | u8 val; | ||
1041 | /* 0x8c == TI122X_IRQMUX, 2 says to route the INTA | ||
1042 | signal out the MFUNC0 pin */ | ||
1043 | if (pci_read_config_byte(dev, 0x8c, &val) == 0) | ||
1044 | pci_write_config_byte(dev, 0x8c, (val & ~0x0f) | 2); | ||
1045 | /* Disable ISA interrupt mode */ | ||
1046 | if (pci_read_config_byte(dev, 0x92, &val) == 0) | ||
1047 | pci_write_config_byte(dev, 0x92, val & ~0x06); | ||
1048 | } | ||
1049 | } | ||
1050 | |||
1051 | DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_TI, PCI_ANY_ID, pmac_pci_fixup_cardbus); | ||
1052 | |||
1053 | void pmac_pci_fixup_pciata(struct pci_dev* dev) | ||
1054 | { | ||
1055 | u8 progif = 0; | ||
1056 | |||
1057 | /* | ||
1058 | * On PowerMacs, we try to switch any PCI ATA controller to | ||
1059 | * fully native mode | ||
1060 | */ | ||
1061 | if (_machine != _MACH_Pmac) | ||
1062 | return; | ||
1063 | /* Some controllers don't have the class IDE */ | ||
1064 | if (dev->vendor == PCI_VENDOR_ID_PROMISE) | ||
1065 | switch(dev->device) { | ||
1066 | case PCI_DEVICE_ID_PROMISE_20246: | ||
1067 | case PCI_DEVICE_ID_PROMISE_20262: | ||
1068 | case PCI_DEVICE_ID_PROMISE_20263: | ||
1069 | case PCI_DEVICE_ID_PROMISE_20265: | ||
1070 | case PCI_DEVICE_ID_PROMISE_20267: | ||
1071 | case PCI_DEVICE_ID_PROMISE_20268: | ||
1072 | case PCI_DEVICE_ID_PROMISE_20269: | ||
1073 | case PCI_DEVICE_ID_PROMISE_20270: | ||
1074 | case PCI_DEVICE_ID_PROMISE_20271: | ||
1075 | case PCI_DEVICE_ID_PROMISE_20275: | ||
1076 | case PCI_DEVICE_ID_PROMISE_20276: | ||
1077 | case PCI_DEVICE_ID_PROMISE_20277: | ||
1078 | goto good; | ||
1079 | } | ||
1080 | /* Others, check PCI class */ | ||
1081 | if ((dev->class >> 8) != PCI_CLASS_STORAGE_IDE) | ||
1082 | return; | ||
1083 | good: | ||
1084 | pci_read_config_byte(dev, PCI_CLASS_PROG, &progif); | ||
1085 | if ((progif & 5) != 5) { | ||
1086 | printk(KERN_INFO "Forcing PCI IDE into native mode: %s\n", pci_name(dev)); | ||
1087 | (void) pci_write_config_byte(dev, PCI_CLASS_PROG, progif|5); | ||
1088 | if (pci_read_config_byte(dev, PCI_CLASS_PROG, &progif) || | ||
1089 | (progif & 5) != 5) | ||
1090 | printk(KERN_ERR "Rewrite of PROGIF failed !\n"); | ||
1091 | } | ||
1092 | } | ||
1093 | DECLARE_PCI_FIXUP_FINAL(PCI_ANY_ID, PCI_ANY_ID, pmac_pci_fixup_pciata); | ||
1094 | |||
1095 | |||
1096 | /* | ||
1097 | * Disable second function on K2-SATA, it's broken | ||
1098 | * and disable IO BARs on first one | ||
1099 | */ | ||
1100 | void __pmac pmac_pci_fixup_k2_sata(struct pci_dev* dev) | ||
1101 | { | ||
1102 | int i; | ||
1103 | u16 cmd; | ||
1104 | |||
1105 | if (PCI_FUNC(dev->devfn) > 0) { | ||
1106 | pci_read_config_word(dev, PCI_COMMAND, &cmd); | ||
1107 | cmd &= ~(PCI_COMMAND_IO | PCI_COMMAND_MEMORY); | ||
1108 | pci_write_config_word(dev, PCI_COMMAND, cmd); | ||
1109 | for (i = 0; i < 6; i++) { | ||
1110 | dev->resource[i].start = dev->resource[i].end = 0; | ||
1111 | dev->resource[i].flags = 0; | ||
1112 | pci_write_config_dword(dev, PCI_BASE_ADDRESS_0 + 4 * i, 0); | ||
1113 | } | ||
1114 | } else { | ||
1115 | pci_read_config_word(dev, PCI_COMMAND, &cmd); | ||
1116 | cmd &= ~PCI_COMMAND_IO; | ||
1117 | pci_write_config_word(dev, PCI_COMMAND, cmd); | ||
1118 | for (i = 0; i < 5; i++) { | ||
1119 | dev->resource[i].start = dev->resource[i].end = 0; | ||
1120 | dev->resource[i].flags = 0; | ||
1121 | pci_write_config_dword(dev, PCI_BASE_ADDRESS_0 + 4 * i, 0); | ||
1122 | } | ||
1123 | } | ||
1124 | } | ||
1125 | DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_SERVERWORKS, 0x0240, pmac_pci_fixup_k2_sata); | ||
diff --git a/arch/ppc/platforms/pmac_pic.c b/arch/ppc/platforms/pmac_pic.c new file mode 100644 index 000000000000..9f92e1bb7f34 --- /dev/null +++ b/arch/ppc/platforms/pmac_pic.c | |||
@@ -0,0 +1,689 @@ | |||
1 | /* | ||
2 | * Support for the interrupt controllers found on Power Macintosh, | ||
3 | * currently Apple's "Grand Central" interrupt controller in all | ||
4 | * it's incarnations. OpenPIC support used on newer machines is | ||
5 | * in a separate file | ||
6 | * | ||
7 | * Copyright (C) 1997 Paul Mackerras (paulus@cs.anu.edu.au) | ||
8 | * | ||
9 | * Maintained by Benjamin Herrenschmidt (benh@kernel.crashing.org) | ||
10 | * | ||
11 | * This program is free software; you can redistribute it and/or | ||
12 | * modify it under the terms of the GNU General Public License | ||
13 | * as published by the Free Software Foundation; either version | ||
14 | * 2 of the License, or (at your option) any later version. | ||
15 | * | ||
16 | */ | ||
17 | |||
18 | #include <linux/config.h> | ||
19 | #include <linux/stddef.h> | ||
20 | #include <linux/init.h> | ||
21 | #include <linux/sched.h> | ||
22 | #include <linux/signal.h> | ||
23 | #include <linux/pci.h> | ||
24 | #include <linux/interrupt.h> | ||
25 | #include <linux/sysdev.h> | ||
26 | #include <linux/adb.h> | ||
27 | #include <linux/pmu.h> | ||
28 | |||
29 | #include <asm/sections.h> | ||
30 | #include <asm/io.h> | ||
31 | #include <asm/smp.h> | ||
32 | #include <asm/prom.h> | ||
33 | #include <asm/pci-bridge.h> | ||
34 | #include <asm/time.h> | ||
35 | #include <asm/open_pic.h> | ||
36 | #include <asm/xmon.h> | ||
37 | #include <asm/pmac_feature.h> | ||
38 | |||
39 | #include "pmac_pic.h" | ||
40 | |||
41 | /* | ||
42 | * XXX this should be in xmon.h, but putting it there means xmon.h | ||
43 | * has to include <linux/interrupt.h> (to get irqreturn_t), which | ||
44 | * causes all sorts of problems. -- paulus | ||
45 | */ | ||
46 | extern irqreturn_t xmon_irq(int, void *, struct pt_regs *); | ||
47 | |||
48 | struct pmac_irq_hw { | ||
49 | unsigned int event; | ||
50 | unsigned int enable; | ||
51 | unsigned int ack; | ||
52 | unsigned int level; | ||
53 | }; | ||
54 | |||
55 | /* Default addresses */ | ||
56 | static volatile struct pmac_irq_hw *pmac_irq_hw[4] __pmacdata = { | ||
57 | (struct pmac_irq_hw *) 0xf3000020, | ||
58 | (struct pmac_irq_hw *) 0xf3000010, | ||
59 | (struct pmac_irq_hw *) 0xf4000020, | ||
60 | (struct pmac_irq_hw *) 0xf4000010, | ||
61 | }; | ||
62 | |||
63 | #define GC_LEVEL_MASK 0x3ff00000 | ||
64 | #define OHARE_LEVEL_MASK 0x1ff00000 | ||
65 | #define HEATHROW_LEVEL_MASK 0x1ff00000 | ||
66 | |||
67 | static int max_irqs __pmacdata; | ||
68 | static int max_real_irqs __pmacdata; | ||
69 | static u32 level_mask[4] __pmacdata; | ||
70 | |||
71 | static DEFINE_SPINLOCK(pmac_pic_lock __pmacdata); | ||
72 | |||
73 | |||
74 | #define GATWICK_IRQ_POOL_SIZE 10 | ||
75 | static struct interrupt_info gatwick_int_pool[GATWICK_IRQ_POOL_SIZE] __pmacdata; | ||
76 | |||
77 | /* | ||
78 | * Mark an irq as "lost". This is only used on the pmac | ||
79 | * since it can lose interrupts (see pmac_set_irq_mask). | ||
80 | * -- Cort | ||
81 | */ | ||
82 | void __pmac | ||
83 | __set_lost(unsigned long irq_nr, int nokick) | ||
84 | { | ||
85 | if (!test_and_set_bit(irq_nr, ppc_lost_interrupts)) { | ||
86 | atomic_inc(&ppc_n_lost_interrupts); | ||
87 | if (!nokick) | ||
88 | set_dec(1); | ||
89 | } | ||
90 | } | ||
91 | |||
92 | static void __pmac | ||
93 | pmac_mask_and_ack_irq(unsigned int irq_nr) | ||
94 | { | ||
95 | unsigned long bit = 1UL << (irq_nr & 0x1f); | ||
96 | int i = irq_nr >> 5; | ||
97 | unsigned long flags; | ||
98 | |||
99 | if ((unsigned)irq_nr >= max_irqs) | ||
100 | return; | ||
101 | |||
102 | clear_bit(irq_nr, ppc_cached_irq_mask); | ||
103 | if (test_and_clear_bit(irq_nr, ppc_lost_interrupts)) | ||
104 | atomic_dec(&ppc_n_lost_interrupts); | ||
105 | spin_lock_irqsave(&pmac_pic_lock, flags); | ||
106 | out_le32(&pmac_irq_hw[i]->enable, ppc_cached_irq_mask[i]); | ||
107 | out_le32(&pmac_irq_hw[i]->ack, bit); | ||
108 | do { | ||
109 | /* make sure ack gets to controller before we enable | ||
110 | interrupts */ | ||
111 | mb(); | ||
112 | } while((in_le32(&pmac_irq_hw[i]->enable) & bit) | ||
113 | != (ppc_cached_irq_mask[i] & bit)); | ||
114 | spin_unlock_irqrestore(&pmac_pic_lock, flags); | ||
115 | } | ||
116 | |||
117 | static void __pmac pmac_set_irq_mask(unsigned int irq_nr, int nokicklost) | ||
118 | { | ||
119 | unsigned long bit = 1UL << (irq_nr & 0x1f); | ||
120 | int i = irq_nr >> 5; | ||
121 | unsigned long flags; | ||
122 | |||
123 | if ((unsigned)irq_nr >= max_irqs) | ||
124 | return; | ||
125 | |||
126 | spin_lock_irqsave(&pmac_pic_lock, flags); | ||
127 | /* enable unmasked interrupts */ | ||
128 | out_le32(&pmac_irq_hw[i]->enable, ppc_cached_irq_mask[i]); | ||
129 | |||
130 | do { | ||
131 | /* make sure mask gets to controller before we | ||
132 | return to user */ | ||
133 | mb(); | ||
134 | } while((in_le32(&pmac_irq_hw[i]->enable) & bit) | ||
135 | != (ppc_cached_irq_mask[i] & bit)); | ||
136 | |||
137 | /* | ||
138 | * Unfortunately, setting the bit in the enable register | ||
139 | * when the device interrupt is already on *doesn't* set | ||
140 | * the bit in the flag register or request another interrupt. | ||
141 | */ | ||
142 | if (bit & ppc_cached_irq_mask[i] & in_le32(&pmac_irq_hw[i]->level)) | ||
143 | __set_lost((ulong)irq_nr, nokicklost); | ||
144 | spin_unlock_irqrestore(&pmac_pic_lock, flags); | ||
145 | } | ||
146 | |||
147 | /* When an irq gets requested for the first client, if it's an | ||
148 | * edge interrupt, we clear any previous one on the controller | ||
149 | */ | ||
150 | static unsigned int __pmac pmac_startup_irq(unsigned int irq_nr) | ||
151 | { | ||
152 | unsigned long bit = 1UL << (irq_nr & 0x1f); | ||
153 | int i = irq_nr >> 5; | ||
154 | |||
155 | if ((irq_desc[irq_nr].status & IRQ_LEVEL) == 0) | ||
156 | out_le32(&pmac_irq_hw[i]->ack, bit); | ||
157 | set_bit(irq_nr, ppc_cached_irq_mask); | ||
158 | pmac_set_irq_mask(irq_nr, 0); | ||
159 | |||
160 | return 0; | ||
161 | } | ||
162 | |||
163 | static void __pmac pmac_mask_irq(unsigned int irq_nr) | ||
164 | { | ||
165 | clear_bit(irq_nr, ppc_cached_irq_mask); | ||
166 | pmac_set_irq_mask(irq_nr, 0); | ||
167 | mb(); | ||
168 | } | ||
169 | |||
170 | static void __pmac pmac_unmask_irq(unsigned int irq_nr) | ||
171 | { | ||
172 | set_bit(irq_nr, ppc_cached_irq_mask); | ||
173 | pmac_set_irq_mask(irq_nr, 0); | ||
174 | } | ||
175 | |||
176 | static void __pmac pmac_end_irq(unsigned int irq_nr) | ||
177 | { | ||
178 | if (!(irq_desc[irq_nr].status & (IRQ_DISABLED|IRQ_INPROGRESS)) | ||
179 | && irq_desc[irq_nr].action) { | ||
180 | set_bit(irq_nr, ppc_cached_irq_mask); | ||
181 | pmac_set_irq_mask(irq_nr, 1); | ||
182 | } | ||
183 | } | ||
184 | |||
185 | |||
186 | struct hw_interrupt_type pmac_pic = { | ||
187 | .typename = " PMAC-PIC ", | ||
188 | .startup = pmac_startup_irq, | ||
189 | .enable = pmac_unmask_irq, | ||
190 | .disable = pmac_mask_irq, | ||
191 | .ack = pmac_mask_and_ack_irq, | ||
192 | .end = pmac_end_irq, | ||
193 | }; | ||
194 | |||
195 | struct hw_interrupt_type gatwick_pic = { | ||
196 | .typename = " GATWICK ", | ||
197 | .startup = pmac_startup_irq, | ||
198 | .enable = pmac_unmask_irq, | ||
199 | .disable = pmac_mask_irq, | ||
200 | .ack = pmac_mask_and_ack_irq, | ||
201 | .end = pmac_end_irq, | ||
202 | }; | ||
203 | |||
204 | static irqreturn_t gatwick_action(int cpl, void *dev_id, struct pt_regs *regs) | ||
205 | { | ||
206 | int irq, bits; | ||
207 | |||
208 | for (irq = max_irqs; (irq -= 32) >= max_real_irqs; ) { | ||
209 | int i = irq >> 5; | ||
210 | bits = in_le32(&pmac_irq_hw[i]->event) | ppc_lost_interrupts[i]; | ||
211 | /* We must read level interrupts from the level register */ | ||
212 | bits |= (in_le32(&pmac_irq_hw[i]->level) & level_mask[i]); | ||
213 | bits &= ppc_cached_irq_mask[i]; | ||
214 | if (bits == 0) | ||
215 | continue; | ||
216 | irq += __ilog2(bits); | ||
217 | __do_IRQ(irq, regs); | ||
218 | return IRQ_HANDLED; | ||
219 | } | ||
220 | printk("gatwick irq not from gatwick pic\n"); | ||
221 | return IRQ_NONE; | ||
222 | } | ||
223 | |||
224 | int | ||
225 | pmac_get_irq(struct pt_regs *regs) | ||
226 | { | ||
227 | int irq; | ||
228 | unsigned long bits = 0; | ||
229 | |||
230 | #ifdef CONFIG_SMP | ||
231 | void psurge_smp_message_recv(struct pt_regs *); | ||
232 | |||
233 | /* IPI's are a hack on the powersurge -- Cort */ | ||
234 | if ( smp_processor_id() != 0 ) { | ||
235 | psurge_smp_message_recv(regs); | ||
236 | return -2; /* ignore, already handled */ | ||
237 | } | ||
238 | #endif /* CONFIG_SMP */ | ||
239 | for (irq = max_real_irqs; (irq -= 32) >= 0; ) { | ||
240 | int i = irq >> 5; | ||
241 | bits = in_le32(&pmac_irq_hw[i]->event) | ppc_lost_interrupts[i]; | ||
242 | /* We must read level interrupts from the level register */ | ||
243 | bits |= (in_le32(&pmac_irq_hw[i]->level) & level_mask[i]); | ||
244 | bits &= ppc_cached_irq_mask[i]; | ||
245 | if (bits == 0) | ||
246 | continue; | ||
247 | irq += __ilog2(bits); | ||
248 | break; | ||
249 | } | ||
250 | |||
251 | return irq; | ||
252 | } | ||
253 | |||
254 | /* This routine will fix some missing interrupt values in the device tree | ||
255 | * on the gatwick mac-io controller used by some PowerBooks | ||
256 | */ | ||
257 | static void __init | ||
258 | pmac_fix_gatwick_interrupts(struct device_node *gw, int irq_base) | ||
259 | { | ||
260 | struct device_node *node; | ||
261 | int count; | ||
262 | |||
263 | memset(gatwick_int_pool, 0, sizeof(gatwick_int_pool)); | ||
264 | node = gw->child; | ||
265 | count = 0; | ||
266 | while(node) | ||
267 | { | ||
268 | /* Fix SCC */ | ||
269 | if (strcasecmp(node->name, "escc") == 0) | ||
270 | if (node->child) { | ||
271 | if (node->child->n_intrs < 3) { | ||
272 | node->child->intrs = &gatwick_int_pool[count]; | ||
273 | count += 3; | ||
274 | } | ||
275 | node->child->n_intrs = 3; | ||
276 | node->child->intrs[0].line = 15+irq_base; | ||
277 | node->child->intrs[1].line = 4+irq_base; | ||
278 | node->child->intrs[2].line = 5+irq_base; | ||
279 | printk(KERN_INFO "irq: fixed SCC on second controller (%d,%d,%d)\n", | ||
280 | node->child->intrs[0].line, | ||
281 | node->child->intrs[1].line, | ||
282 | node->child->intrs[2].line); | ||
283 | } | ||
284 | /* Fix media-bay & left SWIM */ | ||
285 | if (strcasecmp(node->name, "media-bay") == 0) { | ||
286 | struct device_node* ya_node; | ||
287 | |||
288 | if (node->n_intrs == 0) | ||
289 | node->intrs = &gatwick_int_pool[count++]; | ||
290 | node->n_intrs = 1; | ||
291 | node->intrs[0].line = 29+irq_base; | ||
292 | printk(KERN_INFO "irq: fixed media-bay on second controller (%d)\n", | ||
293 | node->intrs[0].line); | ||
294 | |||
295 | ya_node = node->child; | ||
296 | while(ya_node) | ||
297 | { | ||
298 | if (strcasecmp(ya_node->name, "floppy") == 0) { | ||
299 | if (ya_node->n_intrs < 2) { | ||
300 | ya_node->intrs = &gatwick_int_pool[count]; | ||
301 | count += 2; | ||
302 | } | ||
303 | ya_node->n_intrs = 2; | ||
304 | ya_node->intrs[0].line = 19+irq_base; | ||
305 | ya_node->intrs[1].line = 1+irq_base; | ||
306 | printk(KERN_INFO "irq: fixed floppy on second controller (%d,%d)\n", | ||
307 | ya_node->intrs[0].line, ya_node->intrs[1].line); | ||
308 | } | ||
309 | if (strcasecmp(ya_node->name, "ata4") == 0) { | ||
310 | if (ya_node->n_intrs < 2) { | ||
311 | ya_node->intrs = &gatwick_int_pool[count]; | ||
312 | count += 2; | ||
313 | } | ||
314 | ya_node->n_intrs = 2; | ||
315 | ya_node->intrs[0].line = 14+irq_base; | ||
316 | ya_node->intrs[1].line = 3+irq_base; | ||
317 | printk(KERN_INFO "irq: fixed ide on second controller (%d,%d)\n", | ||
318 | ya_node->intrs[0].line, ya_node->intrs[1].line); | ||
319 | } | ||
320 | ya_node = ya_node->sibling; | ||
321 | } | ||
322 | } | ||
323 | node = node->sibling; | ||
324 | } | ||
325 | if (count > 10) { | ||
326 | printk("WARNING !! Gatwick interrupt pool overflow\n"); | ||
327 | printk(" GATWICK_IRQ_POOL_SIZE = %d\n", GATWICK_IRQ_POOL_SIZE); | ||
328 | printk(" requested = %d\n", count); | ||
329 | } | ||
330 | } | ||
331 | |||
332 | /* | ||
333 | * The PowerBook 3400/2400/3500 can have a combo ethernet/modem | ||
334 | * card which includes an ohare chip that acts as a second interrupt | ||
335 | * controller. If we find this second ohare, set it up and fix the | ||
336 | * interrupt value in the device tree for the ethernet chip. | ||
337 | */ | ||
338 | static int __init enable_second_ohare(void) | ||
339 | { | ||
340 | unsigned char bus, devfn; | ||
341 | unsigned short cmd; | ||
342 | unsigned long addr; | ||
343 | struct device_node *irqctrler = find_devices("pci106b,7"); | ||
344 | struct device_node *ether; | ||
345 | |||
346 | if (irqctrler == NULL || irqctrler->n_addrs <= 0) | ||
347 | return -1; | ||
348 | addr = (unsigned long) ioremap(irqctrler->addrs[0].address, 0x40); | ||
349 | pmac_irq_hw[1] = (volatile struct pmac_irq_hw *)(addr + 0x20); | ||
350 | max_irqs = 64; | ||
351 | if (pci_device_from_OF_node(irqctrler, &bus, &devfn) == 0) { | ||
352 | struct pci_controller* hose = pci_find_hose_for_OF_device(irqctrler); | ||
353 | if (!hose) | ||
354 | printk(KERN_ERR "Can't find PCI hose for OHare2 !\n"); | ||
355 | else { | ||
356 | early_read_config_word(hose, bus, devfn, PCI_COMMAND, &cmd); | ||
357 | cmd |= PCI_COMMAND_MEMORY | PCI_COMMAND_MASTER; | ||
358 | cmd &= ~PCI_COMMAND_IO; | ||
359 | early_write_config_word(hose, bus, devfn, PCI_COMMAND, cmd); | ||
360 | } | ||
361 | } | ||
362 | |||
363 | /* Fix interrupt for the modem/ethernet combo controller. The number | ||
364 | in the device tree (27) is bogus (correct for the ethernet-only | ||
365 | board but not the combo ethernet/modem board). | ||
366 | The real interrupt is 28 on the second controller -> 28+32 = 60. | ||
367 | */ | ||
368 | ether = find_devices("pci1011,14"); | ||
369 | if (ether && ether->n_intrs > 0) { | ||
370 | ether->intrs[0].line = 60; | ||
371 | printk(KERN_INFO "irq: Fixed ethernet IRQ to %d\n", | ||
372 | ether->intrs[0].line); | ||
373 | } | ||
374 | |||
375 | /* Return the interrupt number of the cascade */ | ||
376 | return irqctrler->intrs[0].line; | ||
377 | } | ||
378 | |||
379 | #ifdef CONFIG_POWER4 | ||
380 | static irqreturn_t k2u3_action(int cpl, void *dev_id, struct pt_regs *regs) | ||
381 | { | ||
382 | int irq; | ||
383 | |||
384 | irq = openpic2_get_irq(regs); | ||
385 | if (irq != -1) | ||
386 | __do_IRQ(irq, regs); | ||
387 | return IRQ_HANDLED; | ||
388 | } | ||
389 | |||
390 | static struct irqaction k2u3_cascade_action = { | ||
391 | .handler = k2u3_action, | ||
392 | .flags = 0, | ||
393 | .mask = CPU_MASK_NONE, | ||
394 | .name = "U3->K2 Cascade", | ||
395 | }; | ||
396 | #endif /* CONFIG_POWER4 */ | ||
397 | |||
398 | #ifdef CONFIG_XMON | ||
399 | static struct irqaction xmon_action = { | ||
400 | .handler = xmon_irq, | ||
401 | .flags = 0, | ||
402 | .mask = CPU_MASK_NONE, | ||
403 | .name = "NMI - XMON" | ||
404 | }; | ||
405 | #endif | ||
406 | |||
407 | static struct irqaction gatwick_cascade_action = { | ||
408 | .handler = gatwick_action, | ||
409 | .flags = SA_INTERRUPT, | ||
410 | .mask = CPU_MASK_NONE, | ||
411 | .name = "cascade", | ||
412 | }; | ||
413 | |||
414 | void __init pmac_pic_init(void) | ||
415 | { | ||
416 | int i; | ||
417 | struct device_node *irqctrler = NULL; | ||
418 | struct device_node *irqctrler2 = NULL; | ||
419 | struct device_node *np; | ||
420 | unsigned long addr; | ||
421 | int irq_cascade = -1; | ||
422 | |||
423 | /* We first try to detect Apple's new Core99 chipset, since mac-io | ||
424 | * is quite different on those machines and contains an IBM MPIC2. | ||
425 | */ | ||
426 | np = find_type_devices("open-pic"); | ||
427 | while(np) { | ||
428 | if (np->parent && !strcmp(np->parent->name, "u3")) | ||
429 | irqctrler2 = np; | ||
430 | else | ||
431 | irqctrler = np; | ||
432 | np = np->next; | ||
433 | } | ||
434 | if (irqctrler != NULL) | ||
435 | { | ||
436 | if (irqctrler->n_addrs > 0) | ||
437 | { | ||
438 | unsigned char senses[128]; | ||
439 | |||
440 | printk(KERN_INFO "PowerMac using OpenPIC irq controller at 0x%08x\n", | ||
441 | irqctrler->addrs[0].address); | ||
442 | |||
443 | prom_get_irq_senses(senses, 0, 128); | ||
444 | OpenPIC_InitSenses = senses; | ||
445 | OpenPIC_NumInitSenses = 128; | ||
446 | ppc_md.get_irq = openpic_get_irq; | ||
447 | pmac_call_feature(PMAC_FTR_ENABLE_MPIC, irqctrler, 0, 0); | ||
448 | OpenPIC_Addr = ioremap(irqctrler->addrs[0].address, | ||
449 | irqctrler->addrs[0].size); | ||
450 | openpic_init(0); | ||
451 | |||
452 | #ifdef CONFIG_POWER4 | ||
453 | if (irqctrler2 != NULL && irqctrler2->n_intrs > 0 && | ||
454 | irqctrler2->n_addrs > 0) { | ||
455 | printk(KERN_INFO "Slave OpenPIC at 0x%08x hooked on IRQ %d\n", | ||
456 | irqctrler2->addrs[0].address, | ||
457 | irqctrler2->intrs[0].line); | ||
458 | pmac_call_feature(PMAC_FTR_ENABLE_MPIC, irqctrler2, 0, 0); | ||
459 | OpenPIC2_Addr = ioremap(irqctrler2->addrs[0].address, | ||
460 | irqctrler2->addrs[0].size); | ||
461 | prom_get_irq_senses(senses, PMAC_OPENPIC2_OFFSET, | ||
462 | PMAC_OPENPIC2_OFFSET+128); | ||
463 | OpenPIC_InitSenses = senses; | ||
464 | OpenPIC_NumInitSenses = 128; | ||
465 | openpic2_init(PMAC_OPENPIC2_OFFSET); | ||
466 | |||
467 | if (setup_irq(irqctrler2->intrs[0].line, | ||
468 | &k2u3_cascade_action)) | ||
469 | printk("Unable to get OpenPIC IRQ for cascade\n"); | ||
470 | } | ||
471 | #endif /* CONFIG_POWER4 */ | ||
472 | |||
473 | #ifdef CONFIG_XMON | ||
474 | { | ||
475 | struct device_node* pswitch; | ||
476 | int nmi_irq; | ||
477 | |||
478 | pswitch = find_devices("programmer-switch"); | ||
479 | if (pswitch && pswitch->n_intrs) { | ||
480 | nmi_irq = pswitch->intrs[0].line; | ||
481 | openpic_init_nmi_irq(nmi_irq); | ||
482 | setup_irq(nmi_irq, &xmon_action); | ||
483 | } | ||
484 | } | ||
485 | #endif /* CONFIG_XMON */ | ||
486 | return; | ||
487 | } | ||
488 | irqctrler = NULL; | ||
489 | } | ||
490 | |||
491 | /* Get the level/edge settings, assume if it's not | ||
492 | * a Grand Central nor an OHare, then it's an Heathrow | ||
493 | * (or Paddington). | ||
494 | */ | ||
495 | if (find_devices("gc")) | ||
496 | level_mask[0] = GC_LEVEL_MASK; | ||
497 | else if (find_devices("ohare")) { | ||
498 | level_mask[0] = OHARE_LEVEL_MASK; | ||
499 | /* We might have a second cascaded ohare */ | ||
500 | level_mask[1] = OHARE_LEVEL_MASK; | ||
501 | } else { | ||
502 | level_mask[0] = HEATHROW_LEVEL_MASK; | ||
503 | level_mask[1] = 0; | ||
504 | /* We might have a second cascaded heathrow */ | ||
505 | level_mask[2] = HEATHROW_LEVEL_MASK; | ||
506 | level_mask[3] = 0; | ||
507 | } | ||
508 | |||
509 | /* | ||
510 | * G3 powermacs and 1999 G3 PowerBooks have 64 interrupts, | ||
511 | * 1998 G3 Series PowerBooks have 128, | ||
512 | * other powermacs have 32. | ||
513 | * The combo ethernet/modem card for the Powerstar powerbooks | ||
514 | * (2400/3400/3500, ohare based) has a second ohare chip | ||
515 | * effectively making a total of 64. | ||
516 | */ | ||
517 | max_irqs = max_real_irqs = 32; | ||
518 | irqctrler = find_devices("mac-io"); | ||
519 | if (irqctrler) | ||
520 | { | ||
521 | max_real_irqs = 64; | ||
522 | if (irqctrler->next) | ||
523 | max_irqs = 128; | ||
524 | else | ||
525 | max_irqs = 64; | ||
526 | } | ||
527 | for ( i = 0; i < max_real_irqs ; i++ ) | ||
528 | irq_desc[i].handler = &pmac_pic; | ||
529 | |||
530 | /* get addresses of first controller */ | ||
531 | if (irqctrler) { | ||
532 | if (irqctrler->n_addrs > 0) { | ||
533 | addr = (unsigned long) | ||
534 | ioremap(irqctrler->addrs[0].address, 0x40); | ||
535 | for (i = 0; i < 2; ++i) | ||
536 | pmac_irq_hw[i] = (volatile struct pmac_irq_hw*) | ||
537 | (addr + (2 - i) * 0x10); | ||
538 | } | ||
539 | |||
540 | /* get addresses of second controller */ | ||
541 | irqctrler = irqctrler->next; | ||
542 | if (irqctrler && irqctrler->n_addrs > 0) { | ||
543 | addr = (unsigned long) | ||
544 | ioremap(irqctrler->addrs[0].address, 0x40); | ||
545 | for (i = 2; i < 4; ++i) | ||
546 | pmac_irq_hw[i] = (volatile struct pmac_irq_hw*) | ||
547 | (addr + (4 - i) * 0x10); | ||
548 | irq_cascade = irqctrler->intrs[0].line; | ||
549 | if (device_is_compatible(irqctrler, "gatwick")) | ||
550 | pmac_fix_gatwick_interrupts(irqctrler, max_real_irqs); | ||
551 | } | ||
552 | } else { | ||
553 | /* older powermacs have a GC (grand central) or ohare at | ||
554 | f3000000, with interrupt control registers at f3000020. */ | ||
555 | addr = (unsigned long) ioremap(0xf3000000, 0x40); | ||
556 | pmac_irq_hw[0] = (volatile struct pmac_irq_hw *) (addr + 0x20); | ||
557 | } | ||
558 | |||
559 | /* PowerBooks 3400 and 3500 can have a second controller in a second | ||
560 | ohare chip, on the combo ethernet/modem card */ | ||
561 | if (machine_is_compatible("AAPL,3400/2400") | ||
562 | || machine_is_compatible("AAPL,3500")) | ||
563 | irq_cascade = enable_second_ohare(); | ||
564 | |||
565 | /* disable all interrupts in all controllers */ | ||
566 | for (i = 0; i * 32 < max_irqs; ++i) | ||
567 | out_le32(&pmac_irq_hw[i]->enable, 0); | ||
568 | /* mark level interrupts */ | ||
569 | for (i = 0; i < max_irqs; i++) | ||
570 | if (level_mask[i >> 5] & (1UL << (i & 0x1f))) | ||
571 | irq_desc[i].status = IRQ_LEVEL; | ||
572 | |||
573 | /* get interrupt line of secondary interrupt controller */ | ||
574 | if (irq_cascade >= 0) { | ||
575 | printk(KERN_INFO "irq: secondary controller on irq %d\n", | ||
576 | (int)irq_cascade); | ||
577 | for ( i = max_real_irqs ; i < max_irqs ; i++ ) | ||
578 | irq_desc[i].handler = &gatwick_pic; | ||
579 | setup_irq(irq_cascade, &gatwick_cascade_action); | ||
580 | } | ||
581 | printk("System has %d possible interrupts\n", max_irqs); | ||
582 | if (max_irqs != max_real_irqs) | ||
583 | printk(KERN_DEBUG "%d interrupts on main controller\n", | ||
584 | max_real_irqs); | ||
585 | |||
586 | #ifdef CONFIG_XMON | ||
587 | setup_irq(20, &xmon_action); | ||
588 | #endif /* CONFIG_XMON */ | ||
589 | } | ||
590 | |||
591 | #ifdef CONFIG_PM | ||
592 | /* | ||
593 | * These procedures are used in implementing sleep on the powerbooks. | ||
594 | * sleep_save_intrs() saves the states of all interrupt enables | ||
595 | * and disables all interrupts except for the nominated one. | ||
596 | * sleep_restore_intrs() restores the states of all interrupt enables. | ||
597 | */ | ||
598 | unsigned long sleep_save_mask[2]; | ||
599 | |||
600 | /* This used to be passed by the PMU driver but that link got | ||
601 | * broken with the new driver model. We use this tweak for now... | ||
602 | */ | ||
603 | static int pmacpic_find_viaint(void) | ||
604 | { | ||
605 | int viaint = -1; | ||
606 | |||
607 | #ifdef CONFIG_ADB_PMU | ||
608 | struct device_node *np; | ||
609 | |||
610 | if (pmu_get_model() != PMU_OHARE_BASED) | ||
611 | goto not_found; | ||
612 | np = of_find_node_by_name(NULL, "via-pmu"); | ||
613 | if (np == NULL) | ||
614 | goto not_found; | ||
615 | viaint = np->intrs[0].line; | ||
616 | #endif /* CONFIG_ADB_PMU */ | ||
617 | |||
618 | not_found: | ||
619 | return viaint; | ||
620 | } | ||
621 | |||
622 | static int pmacpic_suspend(struct sys_device *sysdev, u32 state) | ||
623 | { | ||
624 | int viaint = pmacpic_find_viaint(); | ||
625 | |||
626 | sleep_save_mask[0] = ppc_cached_irq_mask[0]; | ||
627 | sleep_save_mask[1] = ppc_cached_irq_mask[1]; | ||
628 | ppc_cached_irq_mask[0] = 0; | ||
629 | ppc_cached_irq_mask[1] = 0; | ||
630 | if (viaint > 0) | ||
631 | set_bit(viaint, ppc_cached_irq_mask); | ||
632 | out_le32(&pmac_irq_hw[0]->enable, ppc_cached_irq_mask[0]); | ||
633 | if (max_real_irqs > 32) | ||
634 | out_le32(&pmac_irq_hw[1]->enable, ppc_cached_irq_mask[1]); | ||
635 | (void)in_le32(&pmac_irq_hw[0]->event); | ||
636 | /* make sure mask gets to controller before we return to caller */ | ||
637 | mb(); | ||
638 | (void)in_le32(&pmac_irq_hw[0]->enable); | ||
639 | |||
640 | return 0; | ||
641 | } | ||
642 | |||
643 | static int pmacpic_resume(struct sys_device *sysdev) | ||
644 | { | ||
645 | int i; | ||
646 | |||
647 | out_le32(&pmac_irq_hw[0]->enable, 0); | ||
648 | if (max_real_irqs > 32) | ||
649 | out_le32(&pmac_irq_hw[1]->enable, 0); | ||
650 | mb(); | ||
651 | for (i = 0; i < max_real_irqs; ++i) | ||
652 | if (test_bit(i, sleep_save_mask)) | ||
653 | pmac_unmask_irq(i); | ||
654 | |||
655 | return 0; | ||
656 | } | ||
657 | |||
658 | #endif /* CONFIG_PM */ | ||
659 | |||
660 | static struct sysdev_class pmacpic_sysclass = { | ||
661 | set_kset_name("pmac_pic"), | ||
662 | }; | ||
663 | |||
664 | static struct sys_device device_pmacpic = { | ||
665 | .id = 0, | ||
666 | .cls = &pmacpic_sysclass, | ||
667 | }; | ||
668 | |||
669 | static struct sysdev_driver driver_pmacpic = { | ||
670 | #ifdef CONFIG_PM | ||
671 | .suspend = &pmacpic_suspend, | ||
672 | .resume = &pmacpic_resume, | ||
673 | #endif /* CONFIG_PM */ | ||
674 | }; | ||
675 | |||
676 | static int __init init_pmacpic_sysfs(void) | ||
677 | { | ||
678 | if (max_irqs == 0) | ||
679 | return -ENODEV; | ||
680 | |||
681 | printk(KERN_DEBUG "Registering pmac pic with sysfs...\n"); | ||
682 | sysdev_class_register(&pmacpic_sysclass); | ||
683 | sysdev_register(&device_pmacpic); | ||
684 | sysdev_driver_register(&pmacpic_sysclass, &driver_pmacpic); | ||
685 | return 0; | ||
686 | } | ||
687 | |||
688 | subsys_initcall(init_pmacpic_sysfs); | ||
689 | |||
diff --git a/arch/ppc/platforms/pmac_pic.h b/arch/ppc/platforms/pmac_pic.h new file mode 100644 index 000000000000..664103dfeef9 --- /dev/null +++ b/arch/ppc/platforms/pmac_pic.h | |||
@@ -0,0 +1,11 @@ | |||
1 | #ifndef __PPC_PLATFORMS_PMAC_PIC_H | ||
2 | #define __PPC_PLATFORMS_PMAC_PIC_H | ||
3 | |||
4 | #include <linux/irq.h> | ||
5 | |||
6 | extern struct hw_interrupt_type pmac_pic; | ||
7 | |||
8 | void pmac_pic_init(void); | ||
9 | int pmac_get_irq(struct pt_regs *regs); | ||
10 | |||
11 | #endif /* __PPC_PLATFORMS_PMAC_PIC_H */ | ||
diff --git a/arch/ppc/platforms/pmac_setup.c b/arch/ppc/platforms/pmac_setup.c new file mode 100644 index 000000000000..4d324b630f4f --- /dev/null +++ b/arch/ppc/platforms/pmac_setup.c | |||
@@ -0,0 +1,745 @@ | |||
1 | /* | ||
2 | * arch/ppc/platforms/setup.c | ||
3 | * | ||
4 | * PowerPC version | ||
5 | * Copyright (C) 1995-1996 Gary Thomas (gdt@linuxppc.org) | ||
6 | * | ||
7 | * Adapted for Power Macintosh by Paul Mackerras | ||
8 | * Copyright (C) 1996 Paul Mackerras (paulus@cs.anu.edu.au) | ||
9 | * | ||
10 | * Derived from "arch/alpha/kernel/setup.c" | ||
11 | * Copyright (C) 1995 Linus Torvalds | ||
12 | * | ||
13 | * Maintained by Benjamin Herrenschmidt (benh@kernel.crashing.org) | ||
14 | * | ||
15 | * This program is free software; you can redistribute it and/or | ||
16 | * modify it under the terms of the GNU General Public License | ||
17 | * as published by the Free Software Foundation; either version | ||
18 | * 2 of the License, or (at your option) any later version. | ||
19 | * | ||
20 | */ | ||
21 | |||
22 | /* | ||
23 | * bootup setup stuff.. | ||
24 | */ | ||
25 | |||
26 | #include <linux/config.h> | ||
27 | #include <linux/init.h> | ||
28 | #include <linux/errno.h> | ||
29 | #include <linux/sched.h> | ||
30 | #include <linux/kernel.h> | ||
31 | #include <linux/mm.h> | ||
32 | #include <linux/stddef.h> | ||
33 | #include <linux/unistd.h> | ||
34 | #include <linux/ptrace.h> | ||
35 | #include <linux/slab.h> | ||
36 | #include <linux/user.h> | ||
37 | #include <linux/a.out.h> | ||
38 | #include <linux/tty.h> | ||
39 | #include <linux/string.h> | ||
40 | #include <linux/delay.h> | ||
41 | #include <linux/ioport.h> | ||
42 | #include <linux/major.h> | ||
43 | #include <linux/initrd.h> | ||
44 | #include <linux/vt_kern.h> | ||
45 | #include <linux/console.h> | ||
46 | #include <linux/ide.h> | ||
47 | #include <linux/pci.h> | ||
48 | #include <linux/adb.h> | ||
49 | #include <linux/cuda.h> | ||
50 | #include <linux/pmu.h> | ||
51 | #include <linux/irq.h> | ||
52 | #include <linux/seq_file.h> | ||
53 | #include <linux/root_dev.h> | ||
54 | #include <linux/bitops.h> | ||
55 | #include <linux/suspend.h> | ||
56 | |||
57 | #include <asm/reg.h> | ||
58 | #include <asm/sections.h> | ||
59 | #include <asm/prom.h> | ||
60 | #include <asm/system.h> | ||
61 | #include <asm/pgtable.h> | ||
62 | #include <asm/io.h> | ||
63 | #include <asm/pci-bridge.h> | ||
64 | #include <asm/ohare.h> | ||
65 | #include <asm/mediabay.h> | ||
66 | #include <asm/machdep.h> | ||
67 | #include <asm/dma.h> | ||
68 | #include <asm/bootx.h> | ||
69 | #include <asm/cputable.h> | ||
70 | #include <asm/btext.h> | ||
71 | #include <asm/pmac_feature.h> | ||
72 | #include <asm/time.h> | ||
73 | #include <asm/of_device.h> | ||
74 | #include <asm/mmu_context.h> | ||
75 | |||
76 | #include "pmac_pic.h" | ||
77 | #include "mem_pieces.h" | ||
78 | |||
79 | #undef SHOW_GATWICK_IRQS | ||
80 | |||
81 | extern long pmac_time_init(void); | ||
82 | extern unsigned long pmac_get_rtc_time(void); | ||
83 | extern int pmac_set_rtc_time(unsigned long nowtime); | ||
84 | extern void pmac_read_rtc_time(void); | ||
85 | extern void pmac_calibrate_decr(void); | ||
86 | extern void pmac_pcibios_fixup(void); | ||
87 | extern void pmac_find_bridges(void); | ||
88 | extern unsigned long pmac_ide_get_base(int index); | ||
89 | extern void pmac_ide_init_hwif_ports(hw_regs_t *hw, | ||
90 | unsigned long data_port, unsigned long ctrl_port, int *irq); | ||
91 | |||
92 | extern void pmac_nvram_update(void); | ||
93 | extern unsigned char pmac_nvram_read_byte(int addr); | ||
94 | extern void pmac_nvram_write_byte(int addr, unsigned char val); | ||
95 | extern int pmac_pci_enable_device_hook(struct pci_dev *dev, int initial); | ||
96 | extern void pmac_pcibios_after_init(void); | ||
97 | extern int of_show_percpuinfo(struct seq_file *m, int i); | ||
98 | |||
99 | struct device_node *memory_node; | ||
100 | |||
101 | unsigned char drive_info; | ||
102 | |||
103 | int ppc_override_l2cr = 0; | ||
104 | int ppc_override_l2cr_value; | ||
105 | int has_l2cache = 0; | ||
106 | |||
107 | static int current_root_goodness = -1; | ||
108 | |||
109 | extern int pmac_newworld; | ||
110 | |||
111 | #define DEFAULT_ROOT_DEVICE Root_SDA1 /* sda1 - slightly silly choice */ | ||
112 | |||
113 | extern void zs_kgdb_hook(int tty_num); | ||
114 | static void ohare_init(void); | ||
115 | #ifdef CONFIG_BOOTX_TEXT | ||
116 | void pmac_progress(char *s, unsigned short hex); | ||
117 | #endif | ||
118 | |||
119 | sys_ctrler_t sys_ctrler = SYS_CTRLER_UNKNOWN; | ||
120 | |||
121 | #ifdef CONFIG_SMP | ||
122 | extern struct smp_ops_t psurge_smp_ops; | ||
123 | extern struct smp_ops_t core99_smp_ops; | ||
124 | #endif /* CONFIG_SMP */ | ||
125 | |||
126 | int __pmac | ||
127 | pmac_show_cpuinfo(struct seq_file *m) | ||
128 | { | ||
129 | struct device_node *np; | ||
130 | char *pp; | ||
131 | int plen; | ||
132 | int mbmodel = pmac_call_feature(PMAC_FTR_GET_MB_INFO, | ||
133 | NULL, PMAC_MB_INFO_MODEL, 0); | ||
134 | unsigned int mbflags = (unsigned int)pmac_call_feature(PMAC_FTR_GET_MB_INFO, | ||
135 | NULL, PMAC_MB_INFO_FLAGS, 0); | ||
136 | char* mbname; | ||
137 | |||
138 | if (pmac_call_feature(PMAC_FTR_GET_MB_INFO, NULL, PMAC_MB_INFO_NAME, (int)&mbname) != 0) | ||
139 | mbname = "Unknown"; | ||
140 | |||
141 | /* find motherboard type */ | ||
142 | seq_printf(m, "machine\t\t: "); | ||
143 | np = find_devices("device-tree"); | ||
144 | if (np != NULL) { | ||
145 | pp = (char *) get_property(np, "model", NULL); | ||
146 | if (pp != NULL) | ||
147 | seq_printf(m, "%s\n", pp); | ||
148 | else | ||
149 | seq_printf(m, "PowerMac\n"); | ||
150 | pp = (char *) get_property(np, "compatible", &plen); | ||
151 | if (pp != NULL) { | ||
152 | seq_printf(m, "motherboard\t:"); | ||
153 | while (plen > 0) { | ||
154 | int l = strlen(pp) + 1; | ||
155 | seq_printf(m, " %s", pp); | ||
156 | plen -= l; | ||
157 | pp += l; | ||
158 | } | ||
159 | seq_printf(m, "\n"); | ||
160 | } | ||
161 | } else | ||
162 | seq_printf(m, "PowerMac\n"); | ||
163 | |||
164 | /* print parsed model */ | ||
165 | seq_printf(m, "detected as\t: %d (%s)\n", mbmodel, mbname); | ||
166 | seq_printf(m, "pmac flags\t: %08x\n", mbflags); | ||
167 | |||
168 | /* find l2 cache info */ | ||
169 | np = find_devices("l2-cache"); | ||
170 | if (np == 0) | ||
171 | np = find_type_devices("cache"); | ||
172 | if (np != 0) { | ||
173 | unsigned int *ic = (unsigned int *) | ||
174 | get_property(np, "i-cache-size", NULL); | ||
175 | unsigned int *dc = (unsigned int *) | ||
176 | get_property(np, "d-cache-size", NULL); | ||
177 | seq_printf(m, "L2 cache\t:"); | ||
178 | has_l2cache = 1; | ||
179 | if (get_property(np, "cache-unified", NULL) != 0 && dc) { | ||
180 | seq_printf(m, " %dK unified", *dc / 1024); | ||
181 | } else { | ||
182 | if (ic) | ||
183 | seq_printf(m, " %dK instruction", *ic / 1024); | ||
184 | if (dc) | ||
185 | seq_printf(m, "%s %dK data", | ||
186 | (ic? " +": ""), *dc / 1024); | ||
187 | } | ||
188 | pp = get_property(np, "ram-type", NULL); | ||
189 | if (pp) | ||
190 | seq_printf(m, " %s", pp); | ||
191 | seq_printf(m, "\n"); | ||
192 | } | ||
193 | |||
194 | /* find ram info */ | ||
195 | np = find_devices("memory"); | ||
196 | if (np != 0) { | ||
197 | int n; | ||
198 | struct reg_property *reg = (struct reg_property *) | ||
199 | get_property(np, "reg", &n); | ||
200 | |||
201 | if (reg != 0) { | ||
202 | unsigned long total = 0; | ||
203 | |||
204 | for (n /= sizeof(struct reg_property); n > 0; --n) | ||
205 | total += (reg++)->size; | ||
206 | seq_printf(m, "memory\t\t: %luMB\n", total >> 20); | ||
207 | } | ||
208 | } | ||
209 | |||
210 | /* Checks "l2cr-value" property in the registry */ | ||
211 | np = find_devices("cpus"); | ||
212 | if (np == 0) | ||
213 | np = find_type_devices("cpu"); | ||
214 | if (np != 0) { | ||
215 | unsigned int *l2cr = (unsigned int *) | ||
216 | get_property(np, "l2cr-value", NULL); | ||
217 | if (l2cr != 0) { | ||
218 | seq_printf(m, "l2cr override\t: 0x%x\n", *l2cr); | ||
219 | } | ||
220 | } | ||
221 | |||
222 | /* Indicate newworld/oldworld */ | ||
223 | seq_printf(m, "pmac-generation\t: %s\n", | ||
224 | pmac_newworld ? "NewWorld" : "OldWorld"); | ||
225 | |||
226 | |||
227 | return 0; | ||
228 | } | ||
229 | |||
230 | int __openfirmware | ||
231 | pmac_show_percpuinfo(struct seq_file *m, int i) | ||
232 | { | ||
233 | #ifdef CONFIG_CPU_FREQ_PMAC | ||
234 | extern unsigned int pmac_get_one_cpufreq(int i); | ||
235 | unsigned int freq = pmac_get_one_cpufreq(i); | ||
236 | if (freq != 0) { | ||
237 | seq_printf(m, "clock\t\t: %dMHz\n", freq/1000); | ||
238 | return 0; | ||
239 | } | ||
240 | #endif /* CONFIG_CPU_FREQ_PMAC */ | ||
241 | return of_show_percpuinfo(m, i); | ||
242 | } | ||
243 | |||
244 | static volatile u32 *sysctrl_regs; | ||
245 | |||
246 | void __init | ||
247 | pmac_setup_arch(void) | ||
248 | { | ||
249 | struct device_node *cpu; | ||
250 | int *fp; | ||
251 | unsigned long pvr; | ||
252 | |||
253 | pvr = PVR_VER(mfspr(SPRN_PVR)); | ||
254 | |||
255 | /* Set loops_per_jiffy to a half-way reasonable value, | ||
256 | for use until calibrate_delay gets called. */ | ||
257 | cpu = find_type_devices("cpu"); | ||
258 | if (cpu != 0) { | ||
259 | fp = (int *) get_property(cpu, "clock-frequency", NULL); | ||
260 | if (fp != 0) { | ||
261 | if (pvr == 4 || pvr >= 8) | ||
262 | /* 604, G3, G4 etc. */ | ||
263 | loops_per_jiffy = *fp / HZ; | ||
264 | else | ||
265 | /* 601, 603, etc. */ | ||
266 | loops_per_jiffy = *fp / (2*HZ); | ||
267 | } else | ||
268 | loops_per_jiffy = 50000000 / HZ; | ||
269 | } | ||
270 | |||
271 | /* this area has the CPU identification register | ||
272 | and some registers used by smp boards */ | ||
273 | sysctrl_regs = (volatile u32 *) ioremap(0xf8000000, 0x1000); | ||
274 | ohare_init(); | ||
275 | |||
276 | /* Lookup PCI hosts */ | ||
277 | pmac_find_bridges(); | ||
278 | |||
279 | /* Checks "l2cr-value" property in the registry */ | ||
280 | if (cpu_has_feature(CPU_FTR_L2CR)) { | ||
281 | struct device_node *np = find_devices("cpus"); | ||
282 | if (np == 0) | ||
283 | np = find_type_devices("cpu"); | ||
284 | if (np != 0) { | ||
285 | unsigned int *l2cr = (unsigned int *) | ||
286 | get_property(np, "l2cr-value", NULL); | ||
287 | if (l2cr != 0) { | ||
288 | ppc_override_l2cr = 1; | ||
289 | ppc_override_l2cr_value = *l2cr; | ||
290 | _set_L2CR(0); | ||
291 | _set_L2CR(ppc_override_l2cr_value); | ||
292 | } | ||
293 | } | ||
294 | } | ||
295 | |||
296 | if (ppc_override_l2cr) | ||
297 | printk(KERN_INFO "L2CR overriden (0x%x), backside cache is %s\n", | ||
298 | ppc_override_l2cr_value, (ppc_override_l2cr_value & 0x80000000) | ||
299 | ? "enabled" : "disabled"); | ||
300 | |||
301 | #ifdef CONFIG_KGDB | ||
302 | zs_kgdb_hook(0); | ||
303 | #endif | ||
304 | |||
305 | #ifdef CONFIG_ADB_CUDA | ||
306 | find_via_cuda(); | ||
307 | #else | ||
308 | if (find_devices("via-cuda")) { | ||
309 | printk("WARNING ! Your machine is Cuda based but your kernel\n"); | ||
310 | printk(" wasn't compiled with CONFIG_ADB_CUDA option !\n"); | ||
311 | } | ||
312 | #endif | ||
313 | #ifdef CONFIG_ADB_PMU | ||
314 | find_via_pmu(); | ||
315 | #else | ||
316 | if (find_devices("via-pmu")) { | ||
317 | printk("WARNING ! Your machine is PMU based but your kernel\n"); | ||
318 | printk(" wasn't compiled with CONFIG_ADB_PMU option !\n"); | ||
319 | } | ||
320 | #endif | ||
321 | #ifdef CONFIG_NVRAM | ||
322 | pmac_nvram_init(); | ||
323 | #endif | ||
324 | #ifdef CONFIG_BLK_DEV_INITRD | ||
325 | if (initrd_start) | ||
326 | ROOT_DEV = Root_RAM0; | ||
327 | else | ||
328 | #endif | ||
329 | ROOT_DEV = DEFAULT_ROOT_DEVICE; | ||
330 | |||
331 | #ifdef CONFIG_SMP | ||
332 | /* Check for Core99 */ | ||
333 | if (find_devices("uni-n") || find_devices("u3")) | ||
334 | ppc_md.smp_ops = &core99_smp_ops; | ||
335 | else | ||
336 | ppc_md.smp_ops = &psurge_smp_ops; | ||
337 | #endif /* CONFIG_SMP */ | ||
338 | |||
339 | pci_create_OF_bus_map(); | ||
340 | } | ||
341 | |||
342 | static void __init ohare_init(void) | ||
343 | { | ||
344 | /* | ||
345 | * Turn on the L2 cache. | ||
346 | * We assume that we have a PSX memory controller iff | ||
347 | * we have an ohare I/O controller. | ||
348 | */ | ||
349 | if (find_devices("ohare") != NULL) { | ||
350 | if (((sysctrl_regs[2] >> 24) & 0xf) >= 3) { | ||
351 | if (sysctrl_regs[4] & 0x10) | ||
352 | sysctrl_regs[4] |= 0x04000020; | ||
353 | else | ||
354 | sysctrl_regs[4] |= 0x04000000; | ||
355 | if(has_l2cache) | ||
356 | printk(KERN_INFO "Level 2 cache enabled\n"); | ||
357 | } | ||
358 | } | ||
359 | } | ||
360 | |||
361 | extern char *bootpath; | ||
362 | extern char *bootdevice; | ||
363 | void *boot_host; | ||
364 | int boot_target; | ||
365 | int boot_part; | ||
366 | extern dev_t boot_dev; | ||
367 | |||
368 | #ifdef CONFIG_SCSI | ||
369 | void __init | ||
370 | note_scsi_host(struct device_node *node, void *host) | ||
371 | { | ||
372 | int l; | ||
373 | char *p; | ||
374 | |||
375 | l = strlen(node->full_name); | ||
376 | if (bootpath != NULL && bootdevice != NULL | ||
377 | && strncmp(node->full_name, bootdevice, l) == 0 | ||
378 | && (bootdevice[l] == '/' || bootdevice[l] == 0)) { | ||
379 | boot_host = host; | ||
380 | /* | ||
381 | * There's a bug in OF 1.0.5. (Why am I not surprised.) | ||
382 | * If you pass a path like scsi/sd@1:0 to canon, it returns | ||
383 | * something like /bandit@F2000000/gc@10/53c94@10000/sd@0,0 | ||
384 | * That is, the scsi target number doesn't get preserved. | ||
385 | * So we pick the target number out of bootpath and use that. | ||
386 | */ | ||
387 | p = strstr(bootpath, "/sd@"); | ||
388 | if (p != NULL) { | ||
389 | p += 4; | ||
390 | boot_target = simple_strtoul(p, NULL, 10); | ||
391 | p = strchr(p, ':'); | ||
392 | if (p != NULL) | ||
393 | boot_part = simple_strtoul(p + 1, NULL, 10); | ||
394 | } | ||
395 | } | ||
396 | } | ||
397 | #endif | ||
398 | |||
399 | #if defined(CONFIG_BLK_DEV_IDE) && defined(CONFIG_BLK_DEV_IDE_PMAC) | ||
400 | static dev_t __init | ||
401 | find_ide_boot(void) | ||
402 | { | ||
403 | char *p; | ||
404 | int n; | ||
405 | dev_t __init pmac_find_ide_boot(char *bootdevice, int n); | ||
406 | |||
407 | if (bootdevice == NULL) | ||
408 | return 0; | ||
409 | p = strrchr(bootdevice, '/'); | ||
410 | if (p == NULL) | ||
411 | return 0; | ||
412 | n = p - bootdevice; | ||
413 | |||
414 | return pmac_find_ide_boot(bootdevice, n); | ||
415 | } | ||
416 | #endif /* CONFIG_BLK_DEV_IDE && CONFIG_BLK_DEV_IDE_PMAC */ | ||
417 | |||
418 | void __init | ||
419 | find_boot_device(void) | ||
420 | { | ||
421 | #if defined(CONFIG_BLK_DEV_IDE) && defined(CONFIG_BLK_DEV_IDE_PMAC) | ||
422 | boot_dev = find_ide_boot(); | ||
423 | #endif | ||
424 | } | ||
425 | |||
426 | static int initializing = 1; | ||
427 | /* TODO: Merge the suspend-to-ram with the common code !!! | ||
428 | * currently, this is a stub implementation for suspend-to-disk | ||
429 | * only | ||
430 | */ | ||
431 | |||
432 | #ifdef CONFIG_SOFTWARE_SUSPEND | ||
433 | |||
434 | static int pmac_pm_prepare(suspend_state_t state) | ||
435 | { | ||
436 | printk(KERN_DEBUG "%s(%d)\n", __FUNCTION__, state); | ||
437 | |||
438 | return 0; | ||
439 | } | ||
440 | |||
441 | static int pmac_pm_enter(suspend_state_t state) | ||
442 | { | ||
443 | printk(KERN_DEBUG "%s(%d)\n", __FUNCTION__, state); | ||
444 | |||
445 | /* Giveup the lazy FPU & vec so we don't have to back them | ||
446 | * up from the low level code | ||
447 | */ | ||
448 | enable_kernel_fp(); | ||
449 | |||
450 | #ifdef CONFIG_ALTIVEC | ||
451 | if (cur_cpu_spec[0]->cpu_features & CPU_FTR_ALTIVEC) | ||
452 | enable_kernel_altivec(); | ||
453 | #endif /* CONFIG_ALTIVEC */ | ||
454 | |||
455 | return 0; | ||
456 | } | ||
457 | |||
458 | static int pmac_pm_finish(suspend_state_t state) | ||
459 | { | ||
460 | printk(KERN_DEBUG "%s(%d)\n", __FUNCTION__, state); | ||
461 | |||
462 | /* Restore userland MMU context */ | ||
463 | set_context(current->active_mm->context, current->active_mm->pgd); | ||
464 | |||
465 | return 0; | ||
466 | } | ||
467 | |||
468 | static struct pm_ops pmac_pm_ops = { | ||
469 | .pm_disk_mode = PM_DISK_SHUTDOWN, | ||
470 | .prepare = pmac_pm_prepare, | ||
471 | .enter = pmac_pm_enter, | ||
472 | .finish = pmac_pm_finish, | ||
473 | }; | ||
474 | |||
475 | #endif /* CONFIG_SOFTWARE_SUSPEND */ | ||
476 | |||
477 | static int pmac_late_init(void) | ||
478 | { | ||
479 | initializing = 0; | ||
480 | #ifdef CONFIG_SOFTWARE_SUSPEND | ||
481 | pm_set_ops(&pmac_pm_ops); | ||
482 | #endif /* CONFIG_SOFTWARE_SUSPEND */ | ||
483 | return 0; | ||
484 | } | ||
485 | |||
486 | late_initcall(pmac_late_init); | ||
487 | |||
488 | /* can't be __init - can be called whenever a disk is first accessed */ | ||
489 | void __pmac | ||
490 | note_bootable_part(dev_t dev, int part, int goodness) | ||
491 | { | ||
492 | static int found_boot = 0; | ||
493 | char *p; | ||
494 | |||
495 | if (!initializing) | ||
496 | return; | ||
497 | if ((goodness <= current_root_goodness) && | ||
498 | ROOT_DEV != DEFAULT_ROOT_DEVICE) | ||
499 | return; | ||
500 | p = strstr(saved_command_line, "root="); | ||
501 | if (p != NULL && (p == saved_command_line || p[-1] == ' ')) | ||
502 | return; | ||
503 | |||
504 | if (!found_boot) { | ||
505 | find_boot_device(); | ||
506 | found_boot = 1; | ||
507 | } | ||
508 | if (!boot_dev || dev == boot_dev) { | ||
509 | ROOT_DEV = dev + part; | ||
510 | boot_dev = 0; | ||
511 | current_root_goodness = goodness; | ||
512 | } | ||
513 | } | ||
514 | |||
515 | void __pmac | ||
516 | pmac_restart(char *cmd) | ||
517 | { | ||
518 | #ifdef CONFIG_ADB_CUDA | ||
519 | struct adb_request req; | ||
520 | #endif /* CONFIG_ADB_CUDA */ | ||
521 | |||
522 | switch (sys_ctrler) { | ||
523 | #ifdef CONFIG_ADB_CUDA | ||
524 | case SYS_CTRLER_CUDA: | ||
525 | cuda_request(&req, NULL, 2, CUDA_PACKET, | ||
526 | CUDA_RESET_SYSTEM); | ||
527 | for (;;) | ||
528 | cuda_poll(); | ||
529 | break; | ||
530 | #endif /* CONFIG_ADB_CUDA */ | ||
531 | #ifdef CONFIG_ADB_PMU | ||
532 | case SYS_CTRLER_PMU: | ||
533 | pmu_restart(); | ||
534 | break; | ||
535 | #endif /* CONFIG_ADB_PMU */ | ||
536 | default: ; | ||
537 | } | ||
538 | } | ||
539 | |||
540 | void __pmac | ||
541 | pmac_power_off(void) | ||
542 | { | ||
543 | #ifdef CONFIG_ADB_CUDA | ||
544 | struct adb_request req; | ||
545 | #endif /* CONFIG_ADB_CUDA */ | ||
546 | |||
547 | switch (sys_ctrler) { | ||
548 | #ifdef CONFIG_ADB_CUDA | ||
549 | case SYS_CTRLER_CUDA: | ||
550 | cuda_request(&req, NULL, 2, CUDA_PACKET, | ||
551 | CUDA_POWERDOWN); | ||
552 | for (;;) | ||
553 | cuda_poll(); | ||
554 | break; | ||
555 | #endif /* CONFIG_ADB_CUDA */ | ||
556 | #ifdef CONFIG_ADB_PMU | ||
557 | case SYS_CTRLER_PMU: | ||
558 | pmu_shutdown(); | ||
559 | break; | ||
560 | #endif /* CONFIG_ADB_PMU */ | ||
561 | default: ; | ||
562 | } | ||
563 | } | ||
564 | |||
565 | void __pmac | ||
566 | pmac_halt(void) | ||
567 | { | ||
568 | pmac_power_off(); | ||
569 | } | ||
570 | |||
571 | /* | ||
572 | * Read in a property describing some pieces of memory. | ||
573 | */ | ||
574 | |||
575 | static int __init | ||
576 | get_mem_prop(char *name, struct mem_pieces *mp) | ||
577 | { | ||
578 | struct reg_property *rp; | ||
579 | int i, s; | ||
580 | unsigned int *ip; | ||
581 | int nac = prom_n_addr_cells(memory_node); | ||
582 | int nsc = prom_n_size_cells(memory_node); | ||
583 | |||
584 | ip = (unsigned int *) get_property(memory_node, name, &s); | ||
585 | if (ip == NULL) { | ||
586 | printk(KERN_ERR "error: couldn't get %s property on /memory\n", | ||
587 | name); | ||
588 | return 0; | ||
589 | } | ||
590 | s /= (nsc + nac) * 4; | ||
591 | rp = mp->regions; | ||
592 | for (i = 0; i < s; ++i, ip += nac+nsc) { | ||
593 | if (nac >= 2 && ip[nac-2] != 0) | ||
594 | continue; | ||
595 | rp->address = ip[nac-1]; | ||
596 | if (nsc >= 2 && ip[nac+nsc-2] != 0) | ||
597 | rp->size = ~0U; | ||
598 | else | ||
599 | rp->size = ip[nac+nsc-1]; | ||
600 | ++rp; | ||
601 | } | ||
602 | mp->n_regions = rp - mp->regions; | ||
603 | |||
604 | /* Make sure the pieces are sorted. */ | ||
605 | mem_pieces_sort(mp); | ||
606 | mem_pieces_coalesce(mp); | ||
607 | return 1; | ||
608 | } | ||
609 | |||
610 | /* | ||
611 | * On systems with Open Firmware, collect information about | ||
612 | * physical RAM and which pieces are already in use. | ||
613 | * At this point, we have (at least) the first 8MB mapped with a BAT. | ||
614 | * Our text, data, bss use something over 1MB, starting at 0. | ||
615 | * Open Firmware may be using 1MB at the 4MB point. | ||
616 | */ | ||
617 | unsigned long __init | ||
618 | pmac_find_end_of_memory(void) | ||
619 | { | ||
620 | unsigned long a, total; | ||
621 | struct mem_pieces phys_mem; | ||
622 | |||
623 | /* | ||
624 | * Find out where physical memory is, and check that it | ||
625 | * starts at 0 and is contiguous. It seems that RAM is | ||
626 | * always physically contiguous on Power Macintoshes. | ||
627 | * | ||
628 | * Supporting discontiguous physical memory isn't hard, | ||
629 | * it just makes the virtual <-> physical mapping functions | ||
630 | * more complicated (or else you end up wasting space | ||
631 | * in mem_map). | ||
632 | */ | ||
633 | memory_node = find_devices("memory"); | ||
634 | if (memory_node == NULL || !get_mem_prop("reg", &phys_mem) | ||
635 | || phys_mem.n_regions == 0) | ||
636 | panic("No RAM??"); | ||
637 | a = phys_mem.regions[0].address; | ||
638 | if (a != 0) | ||
639 | panic("RAM doesn't start at physical address 0"); | ||
640 | total = phys_mem.regions[0].size; | ||
641 | |||
642 | if (phys_mem.n_regions > 1) { | ||
643 | printk("RAM starting at 0x%x is not contiguous\n", | ||
644 | phys_mem.regions[1].address); | ||
645 | printk("Using RAM from 0 to 0x%lx\n", total-1); | ||
646 | } | ||
647 | |||
648 | return total; | ||
649 | } | ||
650 | |||
651 | void __init | ||
652 | pmac_init(unsigned long r3, unsigned long r4, unsigned long r5, | ||
653 | unsigned long r6, unsigned long r7) | ||
654 | { | ||
655 | /* isa_io_base gets set in pmac_find_bridges */ | ||
656 | isa_mem_base = PMAC_ISA_MEM_BASE; | ||
657 | pci_dram_offset = PMAC_PCI_DRAM_OFFSET; | ||
658 | ISA_DMA_THRESHOLD = ~0L; | ||
659 | DMA_MODE_READ = 1; | ||
660 | DMA_MODE_WRITE = 2; | ||
661 | |||
662 | ppc_md.setup_arch = pmac_setup_arch; | ||
663 | ppc_md.show_cpuinfo = pmac_show_cpuinfo; | ||
664 | ppc_md.show_percpuinfo = pmac_show_percpuinfo; | ||
665 | ppc_md.irq_canonicalize = NULL; | ||
666 | ppc_md.init_IRQ = pmac_pic_init; | ||
667 | ppc_md.get_irq = pmac_get_irq; /* Changed later on ... */ | ||
668 | |||
669 | ppc_md.pcibios_fixup = pmac_pcibios_fixup; | ||
670 | ppc_md.pcibios_enable_device_hook = pmac_pci_enable_device_hook; | ||
671 | ppc_md.pcibios_after_init = pmac_pcibios_after_init; | ||
672 | ppc_md.phys_mem_access_prot = pci_phys_mem_access_prot; | ||
673 | |||
674 | ppc_md.restart = pmac_restart; | ||
675 | ppc_md.power_off = pmac_power_off; | ||
676 | ppc_md.halt = pmac_halt; | ||
677 | |||
678 | ppc_md.time_init = pmac_time_init; | ||
679 | ppc_md.set_rtc_time = pmac_set_rtc_time; | ||
680 | ppc_md.get_rtc_time = pmac_get_rtc_time; | ||
681 | ppc_md.calibrate_decr = pmac_calibrate_decr; | ||
682 | |||
683 | ppc_md.find_end_of_memory = pmac_find_end_of_memory; | ||
684 | |||
685 | ppc_md.feature_call = pmac_do_feature_call; | ||
686 | |||
687 | #if defined(CONFIG_BLK_DEV_IDE) || defined(CONFIG_BLK_DEV_IDE_MODULE) | ||
688 | #ifdef CONFIG_BLK_DEV_IDE_PMAC | ||
689 | ppc_ide_md.ide_init_hwif = pmac_ide_init_hwif_ports; | ||
690 | ppc_ide_md.default_io_base = pmac_ide_get_base; | ||
691 | #endif /* CONFIG_BLK_DEV_IDE_PMAC */ | ||
692 | #endif /* defined(CONFIG_BLK_DEV_IDE) || defined(CONFIG_BLK_DEV_IDE_MODULE) */ | ||
693 | |||
694 | #ifdef CONFIG_BOOTX_TEXT | ||
695 | ppc_md.progress = pmac_progress; | ||
696 | #endif /* CONFIG_BOOTX_TEXT */ | ||
697 | |||
698 | if (ppc_md.progress) ppc_md.progress("pmac_init(): exit", 0); | ||
699 | |||
700 | } | ||
701 | |||
702 | #ifdef CONFIG_BOOTX_TEXT | ||
703 | void __init | ||
704 | pmac_progress(char *s, unsigned short hex) | ||
705 | { | ||
706 | if (boot_text_mapped) { | ||
707 | btext_drawstring(s); | ||
708 | btext_drawchar('\n'); | ||
709 | } | ||
710 | } | ||
711 | #endif /* CONFIG_BOOTX_TEXT */ | ||
712 | |||
713 | static int __init | ||
714 | pmac_declare_of_platform_devices(void) | ||
715 | { | ||
716 | struct device_node *np; | ||
717 | |||
718 | np = find_devices("uni-n"); | ||
719 | if (np) { | ||
720 | for (np = np->child; np != NULL; np = np->sibling) | ||
721 | if (strncmp(np->name, "i2c", 3) == 0) { | ||
722 | of_platform_device_create(np, "uni-n-i2c"); | ||
723 | break; | ||
724 | } | ||
725 | } | ||
726 | np = find_devices("u3"); | ||
727 | if (np) { | ||
728 | for (np = np->child; np != NULL; np = np->sibling) | ||
729 | if (strncmp(np->name, "i2c", 3) == 0) { | ||
730 | of_platform_device_create(np, "u3-i2c"); | ||
731 | break; | ||
732 | } | ||
733 | } | ||
734 | |||
735 | np = find_devices("valkyrie"); | ||
736 | if (np) | ||
737 | of_platform_device_create(np, "valkyrie"); | ||
738 | np = find_devices("platinum"); | ||
739 | if (np) | ||
740 | of_platform_device_create(np, "platinum"); | ||
741 | |||
742 | return 0; | ||
743 | } | ||
744 | |||
745 | device_initcall(pmac_declare_of_platform_devices); | ||
diff --git a/arch/ppc/platforms/pmac_sleep.S b/arch/ppc/platforms/pmac_sleep.S new file mode 100644 index 000000000000..3139b6766ad3 --- /dev/null +++ b/arch/ppc/platforms/pmac_sleep.S | |||
@@ -0,0 +1,390 @@ | |||
1 | /* | ||
2 | * This file contains sleep low-level functions for PowerBook G3. | ||
3 | * Copyright (C) 1999 Benjamin Herrenschmidt (benh@kernel.crashing.org) | ||
4 | * and Paul Mackerras (paulus@samba.org). | ||
5 | * | ||
6 | * This program is free software; you can redistribute it and/or | ||
7 | * modify it under the terms of the GNU General Public License | ||
8 | * as published by the Free Software Foundation; either version | ||
9 | * 2 of the License, or (at your option) any later version. | ||
10 | * | ||
11 | */ | ||
12 | |||
13 | #include <linux/config.h> | ||
14 | #include <asm/processor.h> | ||
15 | #include <asm/page.h> | ||
16 | #include <asm/ppc_asm.h> | ||
17 | #include <asm/cputable.h> | ||
18 | #include <asm/cache.h> | ||
19 | #include <asm/thread_info.h> | ||
20 | #include <asm/offsets.h> | ||
21 | |||
22 | #define MAGIC 0x4c617273 /* 'Lars' */ | ||
23 | |||
24 | /* | ||
25 | * Structure for storing CPU registers on the stack. | ||
26 | */ | ||
27 | #define SL_SP 0 | ||
28 | #define SL_PC 4 | ||
29 | #define SL_MSR 8 | ||
30 | #define SL_SDR1 0xc | ||
31 | #define SL_SPRG0 0x10 /* 4 sprg's */ | ||
32 | #define SL_DBAT0 0x20 | ||
33 | #define SL_IBAT0 0x28 | ||
34 | #define SL_DBAT1 0x30 | ||
35 | #define SL_IBAT1 0x38 | ||
36 | #define SL_DBAT2 0x40 | ||
37 | #define SL_IBAT2 0x48 | ||
38 | #define SL_DBAT3 0x50 | ||
39 | #define SL_IBAT3 0x58 | ||
40 | #define SL_TB 0x60 | ||
41 | #define SL_R2 0x68 | ||
42 | #define SL_CR 0x6c | ||
43 | #define SL_R12 0x70 /* r12 to r31 */ | ||
44 | #define SL_SIZE (SL_R12 + 80) | ||
45 | |||
46 | .section .text | ||
47 | .align 5 | ||
48 | |||
49 | #if defined(CONFIG_PMAC_PBOOK) || defined(CONFIG_CPU_FREQ_PMAC) | ||
50 | |||
51 | /* This gets called by via-pmu.c late during the sleep process. | ||
52 | * The PMU was already send the sleep command and will shut us down | ||
53 | * soon. We need to save all that is needed and setup the wakeup | ||
54 | * vector that will be called by the ROM on wakeup | ||
55 | */ | ||
56 | _GLOBAL(low_sleep_handler) | ||
57 | #ifndef CONFIG_6xx | ||
58 | blr | ||
59 | #else | ||
60 | mflr r0 | ||
61 | stw r0,4(r1) | ||
62 | stwu r1,-SL_SIZE(r1) | ||
63 | mfcr r0 | ||
64 | stw r0,SL_CR(r1) | ||
65 | stw r2,SL_R2(r1) | ||
66 | stmw r12,SL_R12(r1) | ||
67 | |||
68 | /* Save MSR & SDR1 */ | ||
69 | mfmsr r4 | ||
70 | stw r4,SL_MSR(r1) | ||
71 | mfsdr1 r4 | ||
72 | stw r4,SL_SDR1(r1) | ||
73 | |||
74 | /* Get a stable timebase and save it */ | ||
75 | 1: mftbu r4 | ||
76 | stw r4,SL_TB(r1) | ||
77 | mftb r5 | ||
78 | stw r5,SL_TB+4(r1) | ||
79 | mftbu r3 | ||
80 | cmpw r3,r4 | ||
81 | bne 1b | ||
82 | |||
83 | /* Save SPRGs */ | ||
84 | mfsprg r4,0 | ||
85 | stw r4,SL_SPRG0(r1) | ||
86 | mfsprg r4,1 | ||
87 | stw r4,SL_SPRG0+4(r1) | ||
88 | mfsprg r4,2 | ||
89 | stw r4,SL_SPRG0+8(r1) | ||
90 | mfsprg r4,3 | ||
91 | stw r4,SL_SPRG0+12(r1) | ||
92 | |||
93 | /* Save BATs */ | ||
94 | mfdbatu r4,0 | ||
95 | stw r4,SL_DBAT0(r1) | ||
96 | mfdbatl r4,0 | ||
97 | stw r4,SL_DBAT0+4(r1) | ||
98 | mfdbatu r4,1 | ||
99 | stw r4,SL_DBAT1(r1) | ||
100 | mfdbatl r4,1 | ||
101 | stw r4,SL_DBAT1+4(r1) | ||
102 | mfdbatu r4,2 | ||
103 | stw r4,SL_DBAT2(r1) | ||
104 | mfdbatl r4,2 | ||
105 | stw r4,SL_DBAT2+4(r1) | ||
106 | mfdbatu r4,3 | ||
107 | stw r4,SL_DBAT3(r1) | ||
108 | mfdbatl r4,3 | ||
109 | stw r4,SL_DBAT3+4(r1) | ||
110 | mfibatu r4,0 | ||
111 | stw r4,SL_IBAT0(r1) | ||
112 | mfibatl r4,0 | ||
113 | stw r4,SL_IBAT0+4(r1) | ||
114 | mfibatu r4,1 | ||
115 | stw r4,SL_IBAT1(r1) | ||
116 | mfibatl r4,1 | ||
117 | stw r4,SL_IBAT1+4(r1) | ||
118 | mfibatu r4,2 | ||
119 | stw r4,SL_IBAT2(r1) | ||
120 | mfibatl r4,2 | ||
121 | stw r4,SL_IBAT2+4(r1) | ||
122 | mfibatu r4,3 | ||
123 | stw r4,SL_IBAT3(r1) | ||
124 | mfibatl r4,3 | ||
125 | stw r4,SL_IBAT3+4(r1) | ||
126 | |||
127 | /* Backup various CPU config stuffs */ | ||
128 | bl __save_cpu_setup | ||
129 | |||
130 | /* The ROM can wake us up via 2 different vectors: | ||
131 | * - On wallstreet & lombard, we must write a magic | ||
132 | * value 'Lars' at address 4 and a pointer to a | ||
133 | * memory location containing the PC to resume from | ||
134 | * at address 0. | ||
135 | * - On Core99, we must store the wakeup vector at | ||
136 | * address 0x80 and eventually it's parameters | ||
137 | * at address 0x84. I've have some trouble with those | ||
138 | * parameters however and I no longer use them. | ||
139 | */ | ||
140 | lis r5,grackle_wake_up@ha | ||
141 | addi r5,r5,grackle_wake_up@l | ||
142 | tophys(r5,r5) | ||
143 | stw r5,SL_PC(r1) | ||
144 | lis r4,KERNELBASE@h | ||
145 | tophys(r5,r1) | ||
146 | addi r5,r5,SL_PC | ||
147 | lis r6,MAGIC@ha | ||
148 | addi r6,r6,MAGIC@l | ||
149 | stw r5,0(r4) | ||
150 | stw r6,4(r4) | ||
151 | /* Setup stuffs at 0x80-0x84 for Core99 */ | ||
152 | lis r3,core99_wake_up@ha | ||
153 | addi r3,r3,core99_wake_up@l | ||
154 | tophys(r3,r3) | ||
155 | stw r3,0x80(r4) | ||
156 | stw r5,0x84(r4) | ||
157 | /* Store a pointer to our backup storage into | ||
158 | * a kernel global | ||
159 | */ | ||
160 | lis r3,sleep_storage@ha | ||
161 | addi r3,r3,sleep_storage@l | ||
162 | stw r5,0(r3) | ||
163 | |||
164 | /* Flush & disable all caches */ | ||
165 | bl flush_disable_caches | ||
166 | |||
167 | /* Turn off data relocation. */ | ||
168 | mfmsr r3 /* Save MSR in r7 */ | ||
169 | rlwinm r3,r3,0,28,26 /* Turn off DR bit */ | ||
170 | sync | ||
171 | mtmsr r3 | ||
172 | isync | ||
173 | |||
174 | BEGIN_FTR_SECTION | ||
175 | /* Flush any pending L2 data prefetches to work around HW bug */ | ||
176 | sync | ||
177 | lis r3,0xfff0 | ||
178 | lwz r0,0(r3) /* perform cache-inhibited load to ROM */ | ||
179 | sync /* (caches are disabled at this point) */ | ||
180 | END_FTR_SECTION_IFSET(CPU_FTR_SPEC7450) | ||
181 | |||
182 | /* | ||
183 | * Set the HID0 and MSR for sleep. | ||
184 | */ | ||
185 | mfspr r2,SPRN_HID0 | ||
186 | rlwinm r2,r2,0,10,7 /* clear doze, nap */ | ||
187 | oris r2,r2,HID0_SLEEP@h | ||
188 | sync | ||
189 | isync | ||
190 | mtspr SPRN_HID0,r2 | ||
191 | sync | ||
192 | |||
193 | /* This loop puts us back to sleep in case we have a spurrious | ||
194 | * wakeup so that the host bridge properly stays asleep. The | ||
195 | * CPU will be turned off, either after a known time (about 1 | ||
196 | * second) on wallstreet & lombard, or as soon as the CPU enters | ||
197 | * SLEEP mode on core99 | ||
198 | */ | ||
199 | mfmsr r2 | ||
200 | oris r2,r2,MSR_POW@h | ||
201 | 1: sync | ||
202 | mtmsr r2 | ||
203 | isync | ||
204 | b 1b | ||
205 | |||
206 | /* | ||
207 | * Here is the resume code. | ||
208 | */ | ||
209 | |||
210 | |||
211 | /* | ||
212 | * Core99 machines resume here | ||
213 | * r4 has the physical address of SL_PC(sp) (unused) | ||
214 | */ | ||
215 | _GLOBAL(core99_wake_up) | ||
216 | /* Make sure HID0 no longer contains any sleep bit and that data cache | ||
217 | * is disabled | ||
218 | */ | ||
219 | mfspr r3,SPRN_HID0 | ||
220 | rlwinm r3,r3,0,11,7 /* clear SLEEP, NAP, DOZE bits */ | ||
221 | rlwinm 3,r3,0,18,15 /* clear DCE, ICE */ | ||
222 | mtspr SPRN_HID0,r3 | ||
223 | sync | ||
224 | isync | ||
225 | |||
226 | /* sanitize MSR */ | ||
227 | mfmsr r3 | ||
228 | ori r3,r3,MSR_EE|MSR_IP | ||
229 | xori r3,r3,MSR_EE|MSR_IP | ||
230 | sync | ||
231 | isync | ||
232 | mtmsr r3 | ||
233 | sync | ||
234 | isync | ||
235 | |||
236 | /* Recover sleep storage */ | ||
237 | lis r3,sleep_storage@ha | ||
238 | addi r3,r3,sleep_storage@l | ||
239 | tophys(r3,r3) | ||
240 | lwz r1,0(r3) | ||
241 | |||
242 | /* Pass thru to older resume code ... */ | ||
243 | /* | ||
244 | * Here is the resume code for older machines. | ||
245 | * r1 has the physical address of SL_PC(sp). | ||
246 | */ | ||
247 | |||
248 | grackle_wake_up: | ||
249 | |||
250 | /* Restore the kernel's segment registers before | ||
251 | * we do any r1 memory access as we are not sure they | ||
252 | * are in a sane state above the first 256Mb region | ||
253 | */ | ||
254 | li r0,16 /* load up segment register values */ | ||
255 | mtctr r0 /* for context 0 */ | ||
256 | lis r3,0x2000 /* Ku = 1, VSID = 0 */ | ||
257 | li r4,0 | ||
258 | 3: mtsrin r3,r4 | ||
259 | addi r3,r3,0x111 /* increment VSID */ | ||
260 | addis r4,r4,0x1000 /* address of next segment */ | ||
261 | bdnz 3b | ||
262 | sync | ||
263 | isync | ||
264 | |||
265 | subi r1,r1,SL_PC | ||
266 | |||
267 | /* Restore various CPU config stuffs */ | ||
268 | bl __restore_cpu_setup | ||
269 | |||
270 | /* Invalidate & enable L1 cache, we don't care about | ||
271 | * whatever the ROM may have tried to write to memory | ||
272 | */ | ||
273 | bl __inval_enable_L1 | ||
274 | |||
275 | /* Restore the BATs, and SDR1. Then we can turn on the MMU. */ | ||
276 | lwz r4,SL_SDR1(r1) | ||
277 | mtsdr1 r4 | ||
278 | lwz r4,SL_SPRG0(r1) | ||
279 | mtsprg 0,r4 | ||
280 | lwz r4,SL_SPRG0+4(r1) | ||
281 | mtsprg 1,r4 | ||
282 | lwz r4,SL_SPRG0+8(r1) | ||
283 | mtsprg 2,r4 | ||
284 | lwz r4,SL_SPRG0+12(r1) | ||
285 | mtsprg 3,r4 | ||
286 | |||
287 | lwz r4,SL_DBAT0(r1) | ||
288 | mtdbatu 0,r4 | ||
289 | lwz r4,SL_DBAT0+4(r1) | ||
290 | mtdbatl 0,r4 | ||
291 | lwz r4,SL_DBAT1(r1) | ||
292 | mtdbatu 1,r4 | ||
293 | lwz r4,SL_DBAT1+4(r1) | ||
294 | mtdbatl 1,r4 | ||
295 | lwz r4,SL_DBAT2(r1) | ||
296 | mtdbatu 2,r4 | ||
297 | lwz r4,SL_DBAT2+4(r1) | ||
298 | mtdbatl 2,r4 | ||
299 | lwz r4,SL_DBAT3(r1) | ||
300 | mtdbatu 3,r4 | ||
301 | lwz r4,SL_DBAT3+4(r1) | ||
302 | mtdbatl 3,r4 | ||
303 | lwz r4,SL_IBAT0(r1) | ||
304 | mtibatu 0,r4 | ||
305 | lwz r4,SL_IBAT0+4(r1) | ||
306 | mtibatl 0,r4 | ||
307 | lwz r4,SL_IBAT1(r1) | ||
308 | mtibatu 1,r4 | ||
309 | lwz r4,SL_IBAT1+4(r1) | ||
310 | mtibatl 1,r4 | ||
311 | lwz r4,SL_IBAT2(r1) | ||
312 | mtibatu 2,r4 | ||
313 | lwz r4,SL_IBAT2+4(r1) | ||
314 | mtibatl 2,r4 | ||
315 | lwz r4,SL_IBAT3(r1) | ||
316 | mtibatu 3,r4 | ||
317 | lwz r4,SL_IBAT3+4(r1) | ||
318 | mtibatl 3,r4 | ||
319 | |||
320 | BEGIN_FTR_SECTION | ||
321 | li r4,0 | ||
322 | mtspr SPRN_DBAT4U,r4 | ||
323 | mtspr SPRN_DBAT4L,r4 | ||
324 | mtspr SPRN_DBAT5U,r4 | ||
325 | mtspr SPRN_DBAT5L,r4 | ||
326 | mtspr SPRN_DBAT6U,r4 | ||
327 | mtspr SPRN_DBAT6L,r4 | ||
328 | mtspr SPRN_DBAT7U,r4 | ||
329 | mtspr SPRN_DBAT7L,r4 | ||
330 | mtspr SPRN_IBAT4U,r4 | ||
331 | mtspr SPRN_IBAT4L,r4 | ||
332 | mtspr SPRN_IBAT5U,r4 | ||
333 | mtspr SPRN_IBAT5L,r4 | ||
334 | mtspr SPRN_IBAT6U,r4 | ||
335 | mtspr SPRN_IBAT6L,r4 | ||
336 | mtspr SPRN_IBAT7U,r4 | ||
337 | mtspr SPRN_IBAT7L,r4 | ||
338 | END_FTR_SECTION_IFSET(CPU_FTR_HAS_HIGH_BATS) | ||
339 | |||
340 | /* Flush all TLBs */ | ||
341 | lis r4,0x1000 | ||
342 | 1: addic. r4,r4,-0x1000 | ||
343 | tlbie r4 | ||
344 | blt 1b | ||
345 | sync | ||
346 | |||
347 | /* restore the MSR and turn on the MMU */ | ||
348 | lwz r3,SL_MSR(r1) | ||
349 | bl turn_on_mmu | ||
350 | |||
351 | /* get back the stack pointer */ | ||
352 | tovirt(r1,r1) | ||
353 | |||
354 | /* Restore TB */ | ||
355 | li r3,0 | ||
356 | mttbl r3 | ||
357 | lwz r3,SL_TB(r1) | ||
358 | lwz r4,SL_TB+4(r1) | ||
359 | mttbu r3 | ||
360 | mttbl r4 | ||
361 | |||
362 | /* Restore the callee-saved registers and return */ | ||
363 | lwz r0,SL_CR(r1) | ||
364 | mtcr r0 | ||
365 | lwz r2,SL_R2(r1) | ||
366 | lmw r12,SL_R12(r1) | ||
367 | addi r1,r1,SL_SIZE | ||
368 | lwz r0,4(r1) | ||
369 | mtlr r0 | ||
370 | blr | ||
371 | |||
372 | turn_on_mmu: | ||
373 | mflr r4 | ||
374 | tovirt(r4,r4) | ||
375 | mtsrr0 r4 | ||
376 | mtsrr1 r3 | ||
377 | sync | ||
378 | isync | ||
379 | rfi | ||
380 | |||
381 | #endif /* defined(CONFIG_PMAC_PBOOK) || defined(CONFIG_CPU_FREQ) */ | ||
382 | |||
383 | .section .data | ||
384 | .balign L1_CACHE_LINE_SIZE | ||
385 | sleep_storage: | ||
386 | .long 0 | ||
387 | .balign L1_CACHE_LINE_SIZE, 0 | ||
388 | |||
389 | #endif /* CONFIG_6xx */ | ||
390 | .section .text | ||
diff --git a/arch/ppc/platforms/pmac_smp.c b/arch/ppc/platforms/pmac_smp.c new file mode 100644 index 000000000000..2b88745576a0 --- /dev/null +++ b/arch/ppc/platforms/pmac_smp.c | |||
@@ -0,0 +1,640 @@ | |||
1 | /* | ||
2 | * SMP support for power macintosh. | ||
3 | * | ||
4 | * We support both the old "powersurge" SMP architecture | ||
5 | * and the current Core99 (G4 PowerMac) machines. | ||
6 | * | ||
7 | * Note that we don't support the very first rev. of | ||
8 | * Apple/DayStar 2 CPUs board, the one with the funky | ||
9 | * watchdog. Hopefully, none of these should be there except | ||
10 | * maybe internally to Apple. I should probably still add some | ||
11 | * code to detect this card though and disable SMP. --BenH. | ||
12 | * | ||
13 | * Support Macintosh G4 SMP by Troy Benjegerdes (hozer@drgw.net) | ||
14 | * and Ben Herrenschmidt <benh@kernel.crashing.org>. | ||
15 | * | ||
16 | * Support for DayStar quad CPU cards | ||
17 | * Copyright (C) XLR8, Inc. 1994-2000 | ||
18 | * | ||
19 | * This program is free software; you can redistribute it and/or | ||
20 | * modify it under the terms of the GNU General Public License | ||
21 | * as published by the Free Software Foundation; either version | ||
22 | * 2 of the License, or (at your option) any later version. | ||
23 | */ | ||
24 | #include <linux/config.h> | ||
25 | #include <linux/kernel.h> | ||
26 | #include <linux/sched.h> | ||
27 | #include <linux/smp.h> | ||
28 | #include <linux/smp_lock.h> | ||
29 | #include <linux/interrupt.h> | ||
30 | #include <linux/kernel_stat.h> | ||
31 | #include <linux/delay.h> | ||
32 | #include <linux/init.h> | ||
33 | #include <linux/spinlock.h> | ||
34 | #include <linux/errno.h> | ||
35 | #include <linux/hardirq.h> | ||
36 | |||
37 | #include <asm/ptrace.h> | ||
38 | #include <asm/atomic.h> | ||
39 | #include <asm/irq.h> | ||
40 | #include <asm/page.h> | ||
41 | #include <asm/pgtable.h> | ||
42 | #include <asm/sections.h> | ||
43 | #include <asm/io.h> | ||
44 | #include <asm/prom.h> | ||
45 | #include <asm/smp.h> | ||
46 | #include <asm/residual.h> | ||
47 | #include <asm/machdep.h> | ||
48 | #include <asm/pmac_feature.h> | ||
49 | #include <asm/time.h> | ||
50 | #include <asm/open_pic.h> | ||
51 | #include <asm/cacheflush.h> | ||
52 | #include <asm/keylargo.h> | ||
53 | |||
54 | /* | ||
55 | * Powersurge (old powermac SMP) support. | ||
56 | */ | ||
57 | |||
58 | extern void __secondary_start_psurge(void); | ||
59 | extern void __secondary_start_psurge2(void); /* Temporary horrible hack */ | ||
60 | extern void __secondary_start_psurge3(void); /* Temporary horrible hack */ | ||
61 | |||
62 | /* Addresses for powersurge registers */ | ||
63 | #define HAMMERHEAD_BASE 0xf8000000 | ||
64 | #define HHEAD_CONFIG 0x90 | ||
65 | #define HHEAD_SEC_INTR 0xc0 | ||
66 | |||
67 | /* register for interrupting the primary processor on the powersurge */ | ||
68 | /* N.B. this is actually the ethernet ROM! */ | ||
69 | #define PSURGE_PRI_INTR 0xf3019000 | ||
70 | |||
71 | /* register for storing the start address for the secondary processor */ | ||
72 | /* N.B. this is the PCI config space address register for the 1st bridge */ | ||
73 | #define PSURGE_START 0xf2800000 | ||
74 | |||
75 | /* Daystar/XLR8 4-CPU card */ | ||
76 | #define PSURGE_QUAD_REG_ADDR 0xf8800000 | ||
77 | |||
78 | #define PSURGE_QUAD_IRQ_SET 0 | ||
79 | #define PSURGE_QUAD_IRQ_CLR 1 | ||
80 | #define PSURGE_QUAD_IRQ_PRIMARY 2 | ||
81 | #define PSURGE_QUAD_CKSTOP_CTL 3 | ||
82 | #define PSURGE_QUAD_PRIMARY_ARB 4 | ||
83 | #define PSURGE_QUAD_BOARD_ID 6 | ||
84 | #define PSURGE_QUAD_WHICH_CPU 7 | ||
85 | #define PSURGE_QUAD_CKSTOP_RDBK 8 | ||
86 | #define PSURGE_QUAD_RESET_CTL 11 | ||
87 | |||
88 | #define PSURGE_QUAD_OUT(r, v) (out_8(quad_base + ((r) << 4) + 4, (v))) | ||
89 | #define PSURGE_QUAD_IN(r) (in_8(quad_base + ((r) << 4) + 4) & 0x0f) | ||
90 | #define PSURGE_QUAD_BIS(r, v) (PSURGE_QUAD_OUT((r), PSURGE_QUAD_IN(r) | (v))) | ||
91 | #define PSURGE_QUAD_BIC(r, v) (PSURGE_QUAD_OUT((r), PSURGE_QUAD_IN(r) & ~(v))) | ||
92 | |||
93 | /* virtual addresses for the above */ | ||
94 | static volatile u8 *hhead_base; | ||
95 | static volatile u8 *quad_base; | ||
96 | static volatile u32 *psurge_pri_intr; | ||
97 | static volatile u8 *psurge_sec_intr; | ||
98 | static volatile u32 *psurge_start; | ||
99 | |||
100 | /* values for psurge_type */ | ||
101 | #define PSURGE_NONE -1 | ||
102 | #define PSURGE_DUAL 0 | ||
103 | #define PSURGE_QUAD_OKEE 1 | ||
104 | #define PSURGE_QUAD_COTTON 2 | ||
105 | #define PSURGE_QUAD_ICEGRASS 3 | ||
106 | |||
107 | /* what sort of powersurge board we have */ | ||
108 | static int psurge_type = PSURGE_NONE; | ||
109 | |||
110 | /* L2 and L3 cache settings to pass from CPU0 to CPU1 */ | ||
111 | volatile static long int core99_l2_cache; | ||
112 | volatile static long int core99_l3_cache; | ||
113 | |||
114 | /* Timebase freeze GPIO */ | ||
115 | static unsigned int core99_tb_gpio; | ||
116 | |||
117 | /* Sync flag for HW tb sync */ | ||
118 | static volatile int sec_tb_reset = 0; | ||
119 | |||
120 | static void __init core99_init_caches(int cpu) | ||
121 | { | ||
122 | if (!cpu_has_feature(CPU_FTR_L2CR)) | ||
123 | return; | ||
124 | |||
125 | if (cpu == 0) { | ||
126 | core99_l2_cache = _get_L2CR(); | ||
127 | printk("CPU0: L2CR is %lx\n", core99_l2_cache); | ||
128 | } else { | ||
129 | printk("CPU%d: L2CR was %lx\n", cpu, _get_L2CR()); | ||
130 | _set_L2CR(0); | ||
131 | _set_L2CR(core99_l2_cache); | ||
132 | printk("CPU%d: L2CR set to %lx\n", cpu, core99_l2_cache); | ||
133 | } | ||
134 | |||
135 | if (!cpu_has_feature(CPU_FTR_L3CR)) | ||
136 | return; | ||
137 | |||
138 | if (cpu == 0){ | ||
139 | core99_l3_cache = _get_L3CR(); | ||
140 | printk("CPU0: L3CR is %lx\n", core99_l3_cache); | ||
141 | } else { | ||
142 | printk("CPU%d: L3CR was %lx\n", cpu, _get_L3CR()); | ||
143 | _set_L3CR(0); | ||
144 | _set_L3CR(core99_l3_cache); | ||
145 | printk("CPU%d: L3CR set to %lx\n", cpu, core99_l3_cache); | ||
146 | } | ||
147 | } | ||
148 | |||
149 | /* | ||
150 | * Set and clear IPIs for powersurge. | ||
151 | */ | ||
152 | static inline void psurge_set_ipi(int cpu) | ||
153 | { | ||
154 | if (psurge_type == PSURGE_NONE) | ||
155 | return; | ||
156 | if (cpu == 0) | ||
157 | in_be32(psurge_pri_intr); | ||
158 | else if (psurge_type == PSURGE_DUAL) | ||
159 | out_8(psurge_sec_intr, 0); | ||
160 | else | ||
161 | PSURGE_QUAD_OUT(PSURGE_QUAD_IRQ_SET, 1 << cpu); | ||
162 | } | ||
163 | |||
164 | static inline void psurge_clr_ipi(int cpu) | ||
165 | { | ||
166 | if (cpu > 0) { | ||
167 | switch(psurge_type) { | ||
168 | case PSURGE_DUAL: | ||
169 | out_8(psurge_sec_intr, ~0); | ||
170 | case PSURGE_NONE: | ||
171 | break; | ||
172 | default: | ||
173 | PSURGE_QUAD_OUT(PSURGE_QUAD_IRQ_CLR, 1 << cpu); | ||
174 | } | ||
175 | } | ||
176 | } | ||
177 | |||
178 | /* | ||
179 | * On powersurge (old SMP powermac architecture) we don't have | ||
180 | * separate IPIs for separate messages like openpic does. Instead | ||
181 | * we have a bitmap for each processor, where a 1 bit means that | ||
182 | * the corresponding message is pending for that processor. | ||
183 | * Ideally each cpu's entry would be in a different cache line. | ||
184 | * -- paulus. | ||
185 | */ | ||
186 | static unsigned long psurge_smp_message[NR_CPUS]; | ||
187 | |||
188 | void __pmac psurge_smp_message_recv(struct pt_regs *regs) | ||
189 | { | ||
190 | int cpu = smp_processor_id(); | ||
191 | int msg; | ||
192 | |||
193 | /* clear interrupt */ | ||
194 | psurge_clr_ipi(cpu); | ||
195 | |||
196 | if (num_online_cpus() < 2) | ||
197 | return; | ||
198 | |||
199 | /* make sure there is a message there */ | ||
200 | for (msg = 0; msg < 4; msg++) | ||
201 | if (test_and_clear_bit(msg, &psurge_smp_message[cpu])) | ||
202 | smp_message_recv(msg, regs); | ||
203 | } | ||
204 | |||
205 | irqreturn_t __pmac psurge_primary_intr(int irq, void *d, struct pt_regs *regs) | ||
206 | { | ||
207 | psurge_smp_message_recv(regs); | ||
208 | return IRQ_HANDLED; | ||
209 | } | ||
210 | |||
211 | static void __pmac smp_psurge_message_pass(int target, int msg, unsigned long data, | ||
212 | int wait) | ||
213 | { | ||
214 | int i; | ||
215 | |||
216 | if (num_online_cpus() < 2) | ||
217 | return; | ||
218 | |||
219 | for (i = 0; i < NR_CPUS; i++) { | ||
220 | if (!cpu_online(i)) | ||
221 | continue; | ||
222 | if (target == MSG_ALL | ||
223 | || (target == MSG_ALL_BUT_SELF && i != smp_processor_id()) | ||
224 | || target == i) { | ||
225 | set_bit(msg, &psurge_smp_message[i]); | ||
226 | psurge_set_ipi(i); | ||
227 | } | ||
228 | } | ||
229 | } | ||
230 | |||
231 | /* | ||
232 | * Determine a quad card presence. We read the board ID register, we | ||
233 | * force the data bus to change to something else, and we read it again. | ||
234 | * It it's stable, then the register probably exist (ugh !) | ||
235 | */ | ||
236 | static int __init psurge_quad_probe(void) | ||
237 | { | ||
238 | int type; | ||
239 | unsigned int i; | ||
240 | |||
241 | type = PSURGE_QUAD_IN(PSURGE_QUAD_BOARD_ID); | ||
242 | if (type < PSURGE_QUAD_OKEE || type > PSURGE_QUAD_ICEGRASS | ||
243 | || type != PSURGE_QUAD_IN(PSURGE_QUAD_BOARD_ID)) | ||
244 | return PSURGE_DUAL; | ||
245 | |||
246 | /* looks OK, try a slightly more rigorous test */ | ||
247 | /* bogus is not necessarily cacheline-aligned, | ||
248 | though I don't suppose that really matters. -- paulus */ | ||
249 | for (i = 0; i < 100; i++) { | ||
250 | volatile u32 bogus[8]; | ||
251 | bogus[(0+i)%8] = 0x00000000; | ||
252 | bogus[(1+i)%8] = 0x55555555; | ||
253 | bogus[(2+i)%8] = 0xFFFFFFFF; | ||
254 | bogus[(3+i)%8] = 0xAAAAAAAA; | ||
255 | bogus[(4+i)%8] = 0x33333333; | ||
256 | bogus[(5+i)%8] = 0xCCCCCCCC; | ||
257 | bogus[(6+i)%8] = 0xCCCCCCCC; | ||
258 | bogus[(7+i)%8] = 0x33333333; | ||
259 | wmb(); | ||
260 | asm volatile("dcbf 0,%0" : : "r" (bogus) : "memory"); | ||
261 | mb(); | ||
262 | if (type != PSURGE_QUAD_IN(PSURGE_QUAD_BOARD_ID)) | ||
263 | return PSURGE_DUAL; | ||
264 | } | ||
265 | return type; | ||
266 | } | ||
267 | |||
268 | static void __init psurge_quad_init(void) | ||
269 | { | ||
270 | int procbits; | ||
271 | |||
272 | if (ppc_md.progress) ppc_md.progress("psurge_quad_init", 0x351); | ||
273 | procbits = ~PSURGE_QUAD_IN(PSURGE_QUAD_WHICH_CPU); | ||
274 | if (psurge_type == PSURGE_QUAD_ICEGRASS) | ||
275 | PSURGE_QUAD_BIS(PSURGE_QUAD_RESET_CTL, procbits); | ||
276 | else | ||
277 | PSURGE_QUAD_BIC(PSURGE_QUAD_CKSTOP_CTL, procbits); | ||
278 | mdelay(33); | ||
279 | out_8(psurge_sec_intr, ~0); | ||
280 | PSURGE_QUAD_OUT(PSURGE_QUAD_IRQ_CLR, procbits); | ||
281 | PSURGE_QUAD_BIS(PSURGE_QUAD_RESET_CTL, procbits); | ||
282 | if (psurge_type != PSURGE_QUAD_ICEGRASS) | ||
283 | PSURGE_QUAD_BIS(PSURGE_QUAD_CKSTOP_CTL, procbits); | ||
284 | PSURGE_QUAD_BIC(PSURGE_QUAD_PRIMARY_ARB, procbits); | ||
285 | mdelay(33); | ||
286 | PSURGE_QUAD_BIC(PSURGE_QUAD_RESET_CTL, procbits); | ||
287 | mdelay(33); | ||
288 | PSURGE_QUAD_BIS(PSURGE_QUAD_PRIMARY_ARB, procbits); | ||
289 | mdelay(33); | ||
290 | } | ||
291 | |||
292 | static int __init smp_psurge_probe(void) | ||
293 | { | ||
294 | int i, ncpus; | ||
295 | |||
296 | /* We don't do SMP on the PPC601 -- paulus */ | ||
297 | if (PVR_VER(mfspr(SPRN_PVR)) == 1) | ||
298 | return 1; | ||
299 | |||
300 | /* | ||
301 | * The powersurge cpu board can be used in the generation | ||
302 | * of powermacs that have a socket for an upgradeable cpu card, | ||
303 | * including the 7500, 8500, 9500, 9600. | ||
304 | * The device tree doesn't tell you if you have 2 cpus because | ||
305 | * OF doesn't know anything about the 2nd processor. | ||
306 | * Instead we look for magic bits in magic registers, | ||
307 | * in the hammerhead memory controller in the case of the | ||
308 | * dual-cpu powersurge board. -- paulus. | ||
309 | */ | ||
310 | if (find_devices("hammerhead") == NULL) | ||
311 | return 1; | ||
312 | |||
313 | hhead_base = ioremap(HAMMERHEAD_BASE, 0x800); | ||
314 | quad_base = ioremap(PSURGE_QUAD_REG_ADDR, 1024); | ||
315 | psurge_sec_intr = hhead_base + HHEAD_SEC_INTR; | ||
316 | |||
317 | psurge_type = psurge_quad_probe(); | ||
318 | if (psurge_type != PSURGE_DUAL) { | ||
319 | psurge_quad_init(); | ||
320 | /* All released cards using this HW design have 4 CPUs */ | ||
321 | ncpus = 4; | ||
322 | } else { | ||
323 | iounmap((void *) quad_base); | ||
324 | if ((in_8(hhead_base + HHEAD_CONFIG) & 0x02) == 0) { | ||
325 | /* not a dual-cpu card */ | ||
326 | iounmap((void *) hhead_base); | ||
327 | psurge_type = PSURGE_NONE; | ||
328 | return 1; | ||
329 | } | ||
330 | ncpus = 2; | ||
331 | } | ||
332 | |||
333 | psurge_start = ioremap(PSURGE_START, 4); | ||
334 | psurge_pri_intr = ioremap(PSURGE_PRI_INTR, 4); | ||
335 | |||
336 | /* this is not actually strictly necessary -- paulus. */ | ||
337 | for (i = 1; i < ncpus; ++i) | ||
338 | smp_hw_index[i] = i; | ||
339 | |||
340 | if (ppc_md.progress) ppc_md.progress("smp_psurge_probe - done", 0x352); | ||
341 | |||
342 | return ncpus; | ||
343 | } | ||
344 | |||
345 | static void __init smp_psurge_kick_cpu(int nr) | ||
346 | { | ||
347 | void (*start)(void) = __secondary_start_psurge; | ||
348 | unsigned long a; | ||
349 | |||
350 | /* may need to flush here if secondary bats aren't setup */ | ||
351 | for (a = KERNELBASE; a < KERNELBASE + 0x800000; a += 32) | ||
352 | asm volatile("dcbf 0,%0" : : "r" (a) : "memory"); | ||
353 | asm volatile("sync"); | ||
354 | |||
355 | if (ppc_md.progress) ppc_md.progress("smp_psurge_kick_cpu", 0x353); | ||
356 | |||
357 | /* setup entry point of secondary processor */ | ||
358 | switch (nr) { | ||
359 | case 2: | ||
360 | start = __secondary_start_psurge2; | ||
361 | break; | ||
362 | case 3: | ||
363 | start = __secondary_start_psurge3; | ||
364 | break; | ||
365 | } | ||
366 | |||
367 | out_be32(psurge_start, __pa(start)); | ||
368 | mb(); | ||
369 | |||
370 | psurge_set_ipi(nr); | ||
371 | udelay(10); | ||
372 | psurge_clr_ipi(nr); | ||
373 | |||
374 | if (ppc_md.progress) ppc_md.progress("smp_psurge_kick_cpu - done", 0x354); | ||
375 | } | ||
376 | |||
377 | /* | ||
378 | * With the dual-cpu powersurge board, the decrementers and timebases | ||
379 | * of both cpus are frozen after the secondary cpu is started up, | ||
380 | * until we give the secondary cpu another interrupt. This routine | ||
381 | * uses this to get the timebases synchronized. | ||
382 | * -- paulus. | ||
383 | */ | ||
384 | static void __init psurge_dual_sync_tb(int cpu_nr) | ||
385 | { | ||
386 | int t; | ||
387 | |||
388 | set_dec(tb_ticks_per_jiffy); | ||
389 | set_tb(0, 0); | ||
390 | last_jiffy_stamp(cpu_nr) = 0; | ||
391 | |||
392 | if (cpu_nr > 0) { | ||
393 | mb(); | ||
394 | sec_tb_reset = 1; | ||
395 | return; | ||
396 | } | ||
397 | |||
398 | /* wait for the secondary to have reset its TB before proceeding */ | ||
399 | for (t = 10000000; t > 0 && !sec_tb_reset; --t) | ||
400 | ; | ||
401 | |||
402 | /* now interrupt the secondary, starting both TBs */ | ||
403 | psurge_set_ipi(1); | ||
404 | |||
405 | smp_tb_synchronized = 1; | ||
406 | } | ||
407 | |||
408 | static struct irqaction psurge_irqaction = { | ||
409 | .handler = psurge_primary_intr, | ||
410 | .flags = SA_INTERRUPT, | ||
411 | .mask = CPU_MASK_NONE, | ||
412 | .name = "primary IPI", | ||
413 | }; | ||
414 | |||
415 | static void __init smp_psurge_setup_cpu(int cpu_nr) | ||
416 | { | ||
417 | |||
418 | if (cpu_nr == 0) { | ||
419 | /* If we failed to start the second CPU, we should still | ||
420 | * send it an IPI to start the timebase & DEC or we might | ||
421 | * have them stuck. | ||
422 | */ | ||
423 | if (num_online_cpus() < 2) { | ||
424 | if (psurge_type == PSURGE_DUAL) | ||
425 | psurge_set_ipi(1); | ||
426 | return; | ||
427 | } | ||
428 | /* reset the entry point so if we get another intr we won't | ||
429 | * try to startup again */ | ||
430 | out_be32(psurge_start, 0x100); | ||
431 | if (setup_irq(30, &psurge_irqaction)) | ||
432 | printk(KERN_ERR "Couldn't get primary IPI interrupt"); | ||
433 | } | ||
434 | |||
435 | if (psurge_type == PSURGE_DUAL) | ||
436 | psurge_dual_sync_tb(cpu_nr); | ||
437 | } | ||
438 | |||
439 | void __init smp_psurge_take_timebase(void) | ||
440 | { | ||
441 | /* Dummy implementation */ | ||
442 | } | ||
443 | |||
444 | void __init smp_psurge_give_timebase(void) | ||
445 | { | ||
446 | /* Dummy implementation */ | ||
447 | } | ||
448 | |||
449 | static int __init smp_core99_probe(void) | ||
450 | { | ||
451 | #ifdef CONFIG_6xx | ||
452 | extern int powersave_nap; | ||
453 | #endif | ||
454 | struct device_node *cpus, *firstcpu; | ||
455 | int i, ncpus = 0, boot_cpu = -1; | ||
456 | u32 *tbprop; | ||
457 | |||
458 | if (ppc_md.progress) ppc_md.progress("smp_core99_probe", 0x345); | ||
459 | cpus = firstcpu = find_type_devices("cpu"); | ||
460 | while(cpus != NULL) { | ||
461 | u32 *regprop = (u32 *)get_property(cpus, "reg", NULL); | ||
462 | char *stateprop = (char *)get_property(cpus, "state", NULL); | ||
463 | if (regprop != NULL && stateprop != NULL && | ||
464 | !strncmp(stateprop, "running", 7)) | ||
465 | boot_cpu = *regprop; | ||
466 | ++ncpus; | ||
467 | cpus = cpus->next; | ||
468 | } | ||
469 | if (boot_cpu == -1) | ||
470 | printk(KERN_WARNING "Couldn't detect boot CPU !\n"); | ||
471 | if (boot_cpu != 0) | ||
472 | printk(KERN_WARNING "Boot CPU is %d, unsupported setup !\n", boot_cpu); | ||
473 | |||
474 | if (machine_is_compatible("MacRISC4")) { | ||
475 | extern struct smp_ops_t core99_smp_ops; | ||
476 | |||
477 | core99_smp_ops.take_timebase = smp_generic_take_timebase; | ||
478 | core99_smp_ops.give_timebase = smp_generic_give_timebase; | ||
479 | } else { | ||
480 | if (firstcpu != NULL) | ||
481 | tbprop = (u32 *)get_property(firstcpu, "timebase-enable", NULL); | ||
482 | if (tbprop) | ||
483 | core99_tb_gpio = *tbprop; | ||
484 | else | ||
485 | core99_tb_gpio = KL_GPIO_TB_ENABLE; | ||
486 | } | ||
487 | |||
488 | if (ncpus > 1) { | ||
489 | openpic_request_IPIs(); | ||
490 | for (i = 1; i < ncpus; ++i) | ||
491 | smp_hw_index[i] = i; | ||
492 | #ifdef CONFIG_6xx | ||
493 | powersave_nap = 0; | ||
494 | #endif | ||
495 | core99_init_caches(0); | ||
496 | } | ||
497 | |||
498 | return ncpus; | ||
499 | } | ||
500 | |||
501 | static void __init smp_core99_kick_cpu(int nr) | ||
502 | { | ||
503 | unsigned long save_vector, new_vector; | ||
504 | unsigned long flags; | ||
505 | |||
506 | volatile unsigned long *vector | ||
507 | = ((volatile unsigned long *)(KERNELBASE+0x100)); | ||
508 | if (nr < 1 || nr > 3) | ||
509 | return; | ||
510 | if (ppc_md.progress) ppc_md.progress("smp_core99_kick_cpu", 0x346); | ||
511 | |||
512 | local_irq_save(flags); | ||
513 | local_irq_disable(); | ||
514 | |||
515 | /* Save reset vector */ | ||
516 | save_vector = *vector; | ||
517 | |||
518 | /* Setup fake reset vector that does | ||
519 | * b __secondary_start_psurge - KERNELBASE | ||
520 | */ | ||
521 | switch(nr) { | ||
522 | case 1: | ||
523 | new_vector = (unsigned long)__secondary_start_psurge; | ||
524 | break; | ||
525 | case 2: | ||
526 | new_vector = (unsigned long)__secondary_start_psurge2; | ||
527 | break; | ||
528 | case 3: | ||
529 | new_vector = (unsigned long)__secondary_start_psurge3; | ||
530 | break; | ||
531 | } | ||
532 | *vector = 0x48000002 + new_vector - KERNELBASE; | ||
533 | |||
534 | /* flush data cache and inval instruction cache */ | ||
535 | flush_icache_range((unsigned long) vector, (unsigned long) vector + 4); | ||
536 | |||
537 | /* Put some life in our friend */ | ||
538 | pmac_call_feature(PMAC_FTR_RESET_CPU, NULL, nr, 0); | ||
539 | |||
540 | /* FIXME: We wait a bit for the CPU to take the exception, I should | ||
541 | * instead wait for the entry code to set something for me. Well, | ||
542 | * ideally, all that crap will be done in prom.c and the CPU left | ||
543 | * in a RAM-based wait loop like CHRP. | ||
544 | */ | ||
545 | mdelay(1); | ||
546 | |||
547 | /* Restore our exception vector */ | ||
548 | *vector = save_vector; | ||
549 | flush_icache_range((unsigned long) vector, (unsigned long) vector + 4); | ||
550 | |||
551 | local_irq_restore(flags); | ||
552 | if (ppc_md.progress) ppc_md.progress("smp_core99_kick_cpu done", 0x347); | ||
553 | } | ||
554 | |||
555 | static void __init smp_core99_setup_cpu(int cpu_nr) | ||
556 | { | ||
557 | /* Setup L2/L3 */ | ||
558 | if (cpu_nr != 0) | ||
559 | core99_init_caches(cpu_nr); | ||
560 | |||
561 | /* Setup openpic */ | ||
562 | do_openpic_setup_cpu(); | ||
563 | |||
564 | if (cpu_nr == 0) { | ||
565 | #ifdef CONFIG_POWER4 | ||
566 | extern void g5_phy_disable_cpu1(void); | ||
567 | |||
568 | /* If we didn't start the second CPU, we must take | ||
569 | * it off the bus | ||
570 | */ | ||
571 | if (machine_is_compatible("MacRISC4") && | ||
572 | num_online_cpus() < 2) | ||
573 | g5_phy_disable_cpu1(); | ||
574 | #endif /* CONFIG_POWER4 */ | ||
575 | if (ppc_md.progress) ppc_md.progress("core99_setup_cpu 0 done", 0x349); | ||
576 | } | ||
577 | } | ||
578 | |||
579 | void __init smp_core99_take_timebase(void) | ||
580 | { | ||
581 | /* Secondary processor "takes" the timebase by freezing | ||
582 | * it, resetting its local TB and telling CPU 0 to go on | ||
583 | */ | ||
584 | pmac_call_feature(PMAC_FTR_WRITE_GPIO, NULL, core99_tb_gpio, 4); | ||
585 | pmac_call_feature(PMAC_FTR_READ_GPIO, NULL, core99_tb_gpio, 0); | ||
586 | mb(); | ||
587 | |||
588 | set_dec(tb_ticks_per_jiffy); | ||
589 | set_tb(0, 0); | ||
590 | last_jiffy_stamp(smp_processor_id()) = 0; | ||
591 | |||
592 | mb(); | ||
593 | sec_tb_reset = 1; | ||
594 | } | ||
595 | |||
596 | void __init smp_core99_give_timebase(void) | ||
597 | { | ||
598 | unsigned int t; | ||
599 | |||
600 | /* Primary processor waits for secondary to have frozen | ||
601 | * the timebase, resets local TB, and kick timebase again | ||
602 | */ | ||
603 | /* wait for the secondary to have reset its TB before proceeding */ | ||
604 | for (t = 1000; t > 0 && !sec_tb_reset; --t) | ||
605 | udelay(1000); | ||
606 | if (t == 0) | ||
607 | printk(KERN_WARNING "Timeout waiting sync on second CPU\n"); | ||
608 | |||
609 | set_dec(tb_ticks_per_jiffy); | ||
610 | set_tb(0, 0); | ||
611 | last_jiffy_stamp(smp_processor_id()) = 0; | ||
612 | mb(); | ||
613 | |||
614 | /* Now, restart the timebase by leaving the GPIO to an open collector */ | ||
615 | pmac_call_feature(PMAC_FTR_WRITE_GPIO, NULL, core99_tb_gpio, 0); | ||
616 | pmac_call_feature(PMAC_FTR_READ_GPIO, NULL, core99_tb_gpio, 0); | ||
617 | |||
618 | smp_tb_synchronized = 1; | ||
619 | } | ||
620 | |||
621 | |||
622 | /* PowerSurge-style Macs */ | ||
623 | struct smp_ops_t psurge_smp_ops __pmacdata = { | ||
624 | .message_pass = smp_psurge_message_pass, | ||
625 | .probe = smp_psurge_probe, | ||
626 | .kick_cpu = smp_psurge_kick_cpu, | ||
627 | .setup_cpu = smp_psurge_setup_cpu, | ||
628 | .give_timebase = smp_psurge_give_timebase, | ||
629 | .take_timebase = smp_psurge_take_timebase, | ||
630 | }; | ||
631 | |||
632 | /* Core99 Macs (dual G4s) */ | ||
633 | struct smp_ops_t core99_smp_ops __pmacdata = { | ||
634 | .message_pass = smp_openpic_message_pass, | ||
635 | .probe = smp_core99_probe, | ||
636 | .kick_cpu = smp_core99_kick_cpu, | ||
637 | .setup_cpu = smp_core99_setup_cpu, | ||
638 | .give_timebase = smp_core99_give_timebase, | ||
639 | .take_timebase = smp_core99_take_timebase, | ||
640 | }; | ||
diff --git a/arch/ppc/platforms/pmac_time.c b/arch/ppc/platforms/pmac_time.c new file mode 100644 index 000000000000..09636546f44e --- /dev/null +++ b/arch/ppc/platforms/pmac_time.c | |||
@@ -0,0 +1,292 @@ | |||
1 | /* | ||
2 | * Support for periodic interrupts (100 per second) and for getting | ||
3 | * the current time from the RTC on Power Macintoshes. | ||
4 | * | ||
5 | * We use the decrementer register for our periodic interrupts. | ||
6 | * | ||
7 | * Paul Mackerras August 1996. | ||
8 | * Copyright (C) 1996 Paul Mackerras. | ||
9 | */ | ||
10 | #include <linux/config.h> | ||
11 | #include <linux/errno.h> | ||
12 | #include <linux/sched.h> | ||
13 | #include <linux/kernel.h> | ||
14 | #include <linux/param.h> | ||
15 | #include <linux/string.h> | ||
16 | #include <linux/mm.h> | ||
17 | #include <linux/init.h> | ||
18 | #include <linux/time.h> | ||
19 | #include <linux/adb.h> | ||
20 | #include <linux/cuda.h> | ||
21 | #include <linux/pmu.h> | ||
22 | #include <linux/hardirq.h> | ||
23 | |||
24 | #include <asm/sections.h> | ||
25 | #include <asm/prom.h> | ||
26 | #include <asm/system.h> | ||
27 | #include <asm/io.h> | ||
28 | #include <asm/pgtable.h> | ||
29 | #include <asm/machdep.h> | ||
30 | #include <asm/time.h> | ||
31 | #include <asm/nvram.h> | ||
32 | |||
33 | /* Apparently the RTC stores seconds since 1 Jan 1904 */ | ||
34 | #define RTC_OFFSET 2082844800 | ||
35 | |||
36 | /* | ||
37 | * Calibrate the decrementer frequency with the VIA timer 1. | ||
38 | */ | ||
39 | #define VIA_TIMER_FREQ_6 4700000 /* time 1 frequency * 6 */ | ||
40 | |||
41 | /* VIA registers */ | ||
42 | #define RS 0x200 /* skip between registers */ | ||
43 | #define T1CL (4*RS) /* Timer 1 ctr/latch (low 8 bits) */ | ||
44 | #define T1CH (5*RS) /* Timer 1 counter (high 8 bits) */ | ||
45 | #define T1LL (6*RS) /* Timer 1 latch (low 8 bits) */ | ||
46 | #define T1LH (7*RS) /* Timer 1 latch (high 8 bits) */ | ||
47 | #define ACR (11*RS) /* Auxiliary control register */ | ||
48 | #define IFR (13*RS) /* Interrupt flag register */ | ||
49 | |||
50 | /* Bits in ACR */ | ||
51 | #define T1MODE 0xc0 /* Timer 1 mode */ | ||
52 | #define T1MODE_CONT 0x40 /* continuous interrupts */ | ||
53 | |||
54 | /* Bits in IFR and IER */ | ||
55 | #define T1_INT 0x40 /* Timer 1 interrupt */ | ||
56 | |||
57 | extern struct timezone sys_tz; | ||
58 | |||
59 | long __init | ||
60 | pmac_time_init(void) | ||
61 | { | ||
62 | #ifdef CONFIG_NVRAM | ||
63 | s32 delta = 0; | ||
64 | int dst; | ||
65 | |||
66 | delta = ((s32)pmac_xpram_read(PMAC_XPRAM_MACHINE_LOC + 0x9)) << 16; | ||
67 | delta |= ((s32)pmac_xpram_read(PMAC_XPRAM_MACHINE_LOC + 0xa)) << 8; | ||
68 | delta |= pmac_xpram_read(PMAC_XPRAM_MACHINE_LOC + 0xb); | ||
69 | if (delta & 0x00800000UL) | ||
70 | delta |= 0xFF000000UL; | ||
71 | dst = ((pmac_xpram_read(PMAC_XPRAM_MACHINE_LOC + 0x8) & 0x80) != 0); | ||
72 | printk("GMT Delta read from XPRAM: %d minutes, DST: %s\n", delta/60, | ||
73 | dst ? "on" : "off"); | ||
74 | return delta; | ||
75 | #else | ||
76 | return 0; | ||
77 | #endif | ||
78 | } | ||
79 | |||
80 | unsigned long __pmac | ||
81 | pmac_get_rtc_time(void) | ||
82 | { | ||
83 | #if defined(CONFIG_ADB_CUDA) || defined(CONFIG_ADB_PMU) | ||
84 | struct adb_request req; | ||
85 | unsigned long now; | ||
86 | #endif | ||
87 | |||
88 | /* Get the time from the RTC */ | ||
89 | switch (sys_ctrler) { | ||
90 | #ifdef CONFIG_ADB_CUDA | ||
91 | case SYS_CTRLER_CUDA: | ||
92 | if (cuda_request(&req, NULL, 2, CUDA_PACKET, CUDA_GET_TIME) < 0) | ||
93 | return 0; | ||
94 | while (!req.complete) | ||
95 | cuda_poll(); | ||
96 | if (req.reply_len != 7) | ||
97 | printk(KERN_ERR "pmac_get_rtc_time: got %d byte reply\n", | ||
98 | req.reply_len); | ||
99 | now = (req.reply[3] << 24) + (req.reply[4] << 16) | ||
100 | + (req.reply[5] << 8) + req.reply[6]; | ||
101 | return now - RTC_OFFSET; | ||
102 | #endif /* CONFIG_ADB_CUDA */ | ||
103 | #ifdef CONFIG_ADB_PMU | ||
104 | case SYS_CTRLER_PMU: | ||
105 | if (pmu_request(&req, NULL, 1, PMU_READ_RTC) < 0) | ||
106 | return 0; | ||
107 | while (!req.complete) | ||
108 | pmu_poll(); | ||
109 | if (req.reply_len != 4) | ||
110 | printk(KERN_ERR "pmac_get_rtc_time: got %d byte reply\n", | ||
111 | req.reply_len); | ||
112 | now = (req.reply[0] << 24) + (req.reply[1] << 16) | ||
113 | + (req.reply[2] << 8) + req.reply[3]; | ||
114 | return now - RTC_OFFSET; | ||
115 | #endif /* CONFIG_ADB_PMU */ | ||
116 | default: ; | ||
117 | } | ||
118 | return 0; | ||
119 | } | ||
120 | |||
121 | int __pmac | ||
122 | pmac_set_rtc_time(unsigned long nowtime) | ||
123 | { | ||
124 | #if defined(CONFIG_ADB_CUDA) || defined(CONFIG_ADB_PMU) | ||
125 | struct adb_request req; | ||
126 | #endif | ||
127 | |||
128 | nowtime += RTC_OFFSET; | ||
129 | |||
130 | switch (sys_ctrler) { | ||
131 | #ifdef CONFIG_ADB_CUDA | ||
132 | case SYS_CTRLER_CUDA: | ||
133 | if (cuda_request(&req, NULL, 6, CUDA_PACKET, CUDA_SET_TIME, | ||
134 | nowtime >> 24, nowtime >> 16, nowtime >> 8, nowtime) < 0) | ||
135 | return 0; | ||
136 | while (!req.complete) | ||
137 | cuda_poll(); | ||
138 | if ((req.reply_len != 3) && (req.reply_len != 7)) | ||
139 | printk(KERN_ERR "pmac_set_rtc_time: got %d byte reply\n", | ||
140 | req.reply_len); | ||
141 | return 1; | ||
142 | #endif /* CONFIG_ADB_CUDA */ | ||
143 | #ifdef CONFIG_ADB_PMU | ||
144 | case SYS_CTRLER_PMU: | ||
145 | if (pmu_request(&req, NULL, 5, PMU_SET_RTC, | ||
146 | nowtime >> 24, nowtime >> 16, nowtime >> 8, nowtime) < 0) | ||
147 | return 0; | ||
148 | while (!req.complete) | ||
149 | pmu_poll(); | ||
150 | if (req.reply_len != 0) | ||
151 | printk(KERN_ERR "pmac_set_rtc_time: got %d byte reply\n", | ||
152 | req.reply_len); | ||
153 | return 1; | ||
154 | #endif /* CONFIG_ADB_PMU */ | ||
155 | default: | ||
156 | return 0; | ||
157 | } | ||
158 | } | ||
159 | |||
160 | /* | ||
161 | * Calibrate the decrementer register using VIA timer 1. | ||
162 | * This is used both on powermacs and CHRP machines. | ||
163 | */ | ||
164 | int __init | ||
165 | via_calibrate_decr(void) | ||
166 | { | ||
167 | struct device_node *vias; | ||
168 | volatile unsigned char *via; | ||
169 | int count = VIA_TIMER_FREQ_6 / 100; | ||
170 | unsigned int dstart, dend; | ||
171 | |||
172 | vias = find_devices("via-cuda"); | ||
173 | if (vias == 0) | ||
174 | vias = find_devices("via-pmu"); | ||
175 | if (vias == 0) | ||
176 | vias = find_devices("via"); | ||
177 | if (vias == 0 || vias->n_addrs == 0) | ||
178 | return 0; | ||
179 | via = (volatile unsigned char *) | ||
180 | ioremap(vias->addrs[0].address, vias->addrs[0].size); | ||
181 | |||
182 | /* set timer 1 for continuous interrupts */ | ||
183 | out_8(&via[ACR], (via[ACR] & ~T1MODE) | T1MODE_CONT); | ||
184 | /* set the counter to a small value */ | ||
185 | out_8(&via[T1CH], 2); | ||
186 | /* set the latch to `count' */ | ||
187 | out_8(&via[T1LL], count); | ||
188 | out_8(&via[T1LH], count >> 8); | ||
189 | /* wait until it hits 0 */ | ||
190 | while ((in_8(&via[IFR]) & T1_INT) == 0) | ||
191 | ; | ||
192 | dstart = get_dec(); | ||
193 | /* clear the interrupt & wait until it hits 0 again */ | ||
194 | in_8(&via[T1CL]); | ||
195 | while ((in_8(&via[IFR]) & T1_INT) == 0) | ||
196 | ; | ||
197 | dend = get_dec(); | ||
198 | |||
199 | tb_ticks_per_jiffy = (dstart - dend) / (6 * (HZ/100)); | ||
200 | tb_to_us = mulhwu_scale_factor(dstart - dend, 60000); | ||
201 | |||
202 | printk(KERN_INFO "via_calibrate_decr: ticks per jiffy = %u (%u ticks)\n", | ||
203 | tb_ticks_per_jiffy, dstart - dend); | ||
204 | |||
205 | iounmap((void*)via); | ||
206 | |||
207 | return 1; | ||
208 | } | ||
209 | |||
210 | #ifdef CONFIG_PMAC_PBOOK | ||
211 | /* | ||
212 | * Reset the time after a sleep. | ||
213 | */ | ||
214 | static int __pmac | ||
215 | time_sleep_notify(struct pmu_sleep_notifier *self, int when) | ||
216 | { | ||
217 | static unsigned long time_diff; | ||
218 | unsigned long flags; | ||
219 | unsigned long seq; | ||
220 | |||
221 | switch (when) { | ||
222 | case PBOOK_SLEEP_NOW: | ||
223 | do { | ||
224 | seq = read_seqbegin_irqsave(&xtime_lock, flags); | ||
225 | time_diff = xtime.tv_sec - pmac_get_rtc_time(); | ||
226 | } while (read_seqretry_irqrestore(&xtime_lock, seq, flags)); | ||
227 | break; | ||
228 | case PBOOK_WAKE: | ||
229 | write_seqlock_irqsave(&xtime_lock, flags); | ||
230 | xtime.tv_sec = pmac_get_rtc_time() + time_diff; | ||
231 | xtime.tv_nsec = 0; | ||
232 | last_rtc_update = xtime.tv_sec; | ||
233 | write_sequnlock_irqrestore(&xtime_lock, flags); | ||
234 | break; | ||
235 | } | ||
236 | return PBOOK_SLEEP_OK; | ||
237 | } | ||
238 | |||
239 | static struct pmu_sleep_notifier time_sleep_notifier __pmacdata = { | ||
240 | time_sleep_notify, SLEEP_LEVEL_MISC, | ||
241 | }; | ||
242 | #endif /* CONFIG_PMAC_PBOOK */ | ||
243 | |||
244 | /* | ||
245 | * Query the OF and get the decr frequency. | ||
246 | * This was taken from the pmac time_init() when merging the prep/pmac | ||
247 | * time functions. | ||
248 | */ | ||
249 | void __init | ||
250 | pmac_calibrate_decr(void) | ||
251 | { | ||
252 | struct device_node *cpu; | ||
253 | unsigned int freq, *fp; | ||
254 | |||
255 | #ifdef CONFIG_PMAC_PBOOK | ||
256 | pmu_register_sleep_notifier(&time_sleep_notifier); | ||
257 | #endif /* CONFIG_PMAC_PBOOK */ | ||
258 | |||
259 | /* We assume MacRISC2 machines have correct device-tree | ||
260 | * calibration. That's better since the VIA itself seems | ||
261 | * to be slightly off. --BenH | ||
262 | */ | ||
263 | if (!machine_is_compatible("MacRISC2") && | ||
264 | !machine_is_compatible("MacRISC3") && | ||
265 | !machine_is_compatible("MacRISC4")) | ||
266 | if (via_calibrate_decr()) | ||
267 | return; | ||
268 | |||
269 | /* Special case: QuickSilver G4s seem to have a badly calibrated | ||
270 | * timebase-frequency in OF, VIA is much better on these. We should | ||
271 | * probably implement calibration based on the KL timer on these | ||
272 | * machines anyway... -BenH | ||
273 | */ | ||
274 | if (machine_is_compatible("PowerMac3,5")) | ||
275 | if (via_calibrate_decr()) | ||
276 | return; | ||
277 | /* | ||
278 | * The cpu node should have a timebase-frequency property | ||
279 | * to tell us the rate at which the decrementer counts. | ||
280 | */ | ||
281 | cpu = find_type_devices("cpu"); | ||
282 | if (cpu == 0) | ||
283 | panic("can't find cpu node in time_init"); | ||
284 | fp = (unsigned int *) get_property(cpu, "timebase-frequency", NULL); | ||
285 | if (fp == 0) | ||
286 | panic("can't get cpu timebase frequency"); | ||
287 | freq = *fp; | ||
288 | printk("time_init: decrementer frequency = %u.%.6u MHz\n", | ||
289 | freq/1000000, freq%1000000); | ||
290 | tb_ticks_per_jiffy = freq / HZ; | ||
291 | tb_to_us = mulhwu_scale_factor(freq, 1000000); | ||
292 | } | ||
diff --git a/arch/ppc/platforms/powerpmc250.c b/arch/ppc/platforms/powerpmc250.c new file mode 100644 index 000000000000..0abe15159e6c --- /dev/null +++ b/arch/ppc/platforms/powerpmc250.c | |||
@@ -0,0 +1,383 @@ | |||
1 | /* | ||
2 | * arch/ppc/platforms/powerpmc250.c | ||
3 | * | ||
4 | * Board setup routines for Force PowerPMC-250 Processor PMC | ||
5 | * | ||
6 | * Author: Troy Benjegerdes <tbenjegerdes@mvista.com> | ||
7 | * Borrowed heavily from prpmc750_*.c by | ||
8 | * Matt Porter <mporter@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 | #include <linux/config.h> | ||
17 | #include <linux/stddef.h> | ||
18 | #include <linux/kernel.h> | ||
19 | #include <linux/init.h> | ||
20 | #include <linux/errno.h> | ||
21 | #include <linux/reboot.h> | ||
22 | #include <linux/pci.h> | ||
23 | #include <linux/kdev_t.h> | ||
24 | #include <linux/types.h> | ||
25 | #include <linux/major.h> | ||
26 | #include <linux/initrd.h> | ||
27 | #include <linux/console.h> | ||
28 | #include <linux/delay.h> | ||
29 | #include <linux/irq.h> | ||
30 | #include <linux/slab.h> | ||
31 | #include <linux/seq_file.h> | ||
32 | #include <linux/ide.h> | ||
33 | #include <linux/root_dev.h> | ||
34 | |||
35 | #include <asm/byteorder.h> | ||
36 | #include <asm/system.h> | ||
37 | #include <asm/pgtable.h> | ||
38 | #include <asm/page.h> | ||
39 | #include <asm/dma.h> | ||
40 | #include <asm/io.h> | ||
41 | #include <asm/irq.h> | ||
42 | #include <asm/machdep.h> | ||
43 | #include <asm/time.h> | ||
44 | #include <platforms/powerpmc250.h> | ||
45 | #include <asm/open_pic.h> | ||
46 | #include <asm/pci-bridge.h> | ||
47 | #include <asm/mpc10x.h> | ||
48 | #include <asm/uaccess.h> | ||
49 | #include <asm/bootinfo.h> | ||
50 | |||
51 | extern void powerpmc250_find_bridges(void); | ||
52 | extern unsigned long loops_per_jiffy; | ||
53 | |||
54 | static u_char powerpmc250_openpic_initsenses[] __initdata = | ||
55 | { | ||
56 | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, | ||
57 | 1, /* PMC INTA (also MPC107 output interrupt INTA) */ | ||
58 | 1, /* PMC INTB (also I82559 Ethernet controller) */ | ||
59 | 1, /* PMC INTC */ | ||
60 | 1, /* PMC INTD */ | ||
61 | 0, /* DUART interrupt (active high) */ | ||
62 | }; | ||
63 | |||
64 | static int | ||
65 | powerpmc250_show_cpuinfo(struct seq_file *m) | ||
66 | { | ||
67 | seq_printf(m,"machine\t\t: Force PowerPMC250\n"); | ||
68 | |||
69 | return 0; | ||
70 | } | ||
71 | |||
72 | static void __init | ||
73 | powerpmc250_setup_arch(void) | ||
74 | { | ||
75 | /* init to some ~sane value until calibrate_delay() runs */ | ||
76 | loops_per_jiffy = 50000000/HZ; | ||
77 | |||
78 | /* Lookup PCI host bridges */ | ||
79 | powerpmc250_find_bridges(); | ||
80 | |||
81 | #ifdef CONFIG_BLK_DEV_INITRD | ||
82 | if (initrd_start) | ||
83 | ROOT_DEV = Root_RAM0; | ||
84 | else | ||
85 | #endif | ||
86 | #ifdef CONFIG_ROOT_NFS | ||
87 | ROOT_DEV = Root_NFS; | ||
88 | #else | ||
89 | ROOT_DEV = Root_SDA2; | ||
90 | #endif | ||
91 | |||
92 | printk("Force PowerPMC250 port (C) 2001 MontaVista Software, Inc. (source@mvista.com)\n"); | ||
93 | } | ||
94 | |||
95 | #if 0 | ||
96 | /* | ||
97 | * Compute the PrPMC750's bus speed using the baud clock as a | ||
98 | * reference. | ||
99 | */ | ||
100 | unsigned long __init powerpmc250_get_bus_speed(void) | ||
101 | { | ||
102 | unsigned long tbl_start, tbl_end; | ||
103 | unsigned long current_state, old_state, bus_speed; | ||
104 | unsigned char lcr, dll, dlm; | ||
105 | int baud_divisor, count; | ||
106 | |||
107 | /* Read the UART's baud clock divisor */ | ||
108 | lcr = readb(PRPMC750_SERIAL_0_LCR); | ||
109 | writeb(lcr | UART_LCR_DLAB, PRPMC750_SERIAL_0_LCR); | ||
110 | dll = readb(PRPMC750_SERIAL_0_DLL); | ||
111 | dlm = readb(PRPMC750_SERIAL_0_DLM); | ||
112 | writeb(lcr & ~UART_LCR_DLAB, PRPMC750_SERIAL_0_LCR); | ||
113 | baud_divisor = (dlm << 8) | dll; | ||
114 | |||
115 | /* | ||
116 | * Use the baud clock divisor and base baud clock | ||
117 | * to determine the baud rate and use that as | ||
118 | * the number of baud clock edges we use for | ||
119 | * the time base sample. Make it half the baud | ||
120 | * rate. | ||
121 | */ | ||
122 | count = PRPMC750_BASE_BAUD / (baud_divisor * 16); | ||
123 | |||
124 | /* Find the first edge of the baud clock */ | ||
125 | old_state = readb(PRPMC750_STATUS_REG) & PRPMC750_BAUDOUT_MASK; | ||
126 | do { | ||
127 | current_state = readb(PRPMC750_STATUS_REG) & | ||
128 | PRPMC750_BAUDOUT_MASK; | ||
129 | } while(old_state == current_state); | ||
130 | |||
131 | old_state = current_state; | ||
132 | |||
133 | /* Get the starting time base value */ | ||
134 | tbl_start = get_tbl(); | ||
135 | |||
136 | /* | ||
137 | * Loop until we have found a number of edges equal | ||
138 | * to half the count (half the baud rate) | ||
139 | */ | ||
140 | do { | ||
141 | do { | ||
142 | current_state = readb(PRPMC750_STATUS_REG) & | ||
143 | PRPMC750_BAUDOUT_MASK; | ||
144 | } while(old_state == current_state); | ||
145 | old_state = current_state; | ||
146 | } while (--count); | ||
147 | |||
148 | /* Get the ending time base value */ | ||
149 | tbl_end = get_tbl(); | ||
150 | |||
151 | /* Compute bus speed */ | ||
152 | bus_speed = (tbl_end-tbl_start)*128; | ||
153 | |||
154 | return bus_speed; | ||
155 | } | ||
156 | #endif | ||
157 | |||
158 | static void __init | ||
159 | powerpmc250_calibrate_decr(void) | ||
160 | { | ||
161 | unsigned long freq; | ||
162 | int divisor = 4; | ||
163 | |||
164 | //freq = powerpmc250_get_bus_speed(); | ||
165 | #warning hardcoded bus freq | ||
166 | freq = 100000000; | ||
167 | |||
168 | tb_ticks_per_jiffy = freq / (HZ * divisor); | ||
169 | tb_to_us = mulhwu_scale_factor(freq/divisor, 1000000); | ||
170 | } | ||
171 | |||
172 | static void | ||
173 | powerpmc250_restart(char *cmd) | ||
174 | { | ||
175 | local_irq_disable(); | ||
176 | /* Hard reset */ | ||
177 | writeb(0x11, 0xfe000332); | ||
178 | while(1); | ||
179 | } | ||
180 | |||
181 | static void | ||
182 | powerpmc250_halt(void) | ||
183 | { | ||
184 | local_irq_disable(); | ||
185 | while (1); | ||
186 | } | ||
187 | |||
188 | static void | ||
189 | powerpmc250_power_off(void) | ||
190 | { | ||
191 | powerpmc250_halt(); | ||
192 | } | ||
193 | |||
194 | static void __init | ||
195 | powerpmc250_init_IRQ(void) | ||
196 | { | ||
197 | |||
198 | OpenPIC_InitSenses = powerpmc250_openpic_initsenses; | ||
199 | OpenPIC_NumInitSenses = sizeof(powerpmc250_openpic_initsenses); | ||
200 | mpc10x_set_openpic(); | ||
201 | } | ||
202 | |||
203 | /* | ||
204 | * Set BAT 3 to map 0xf0000000 to end of physical memory space. | ||
205 | */ | ||
206 | static __inline__ void | ||
207 | powerpmc250_set_bat(void) | ||
208 | { | ||
209 | unsigned long bat3u, bat3l; | ||
210 | static int mapping_set = 0; | ||
211 | |||
212 | if (!mapping_set) | ||
213 | { | ||
214 | __asm__ __volatile__( | ||
215 | " lis %0,0xf000\n \ | ||
216 | ori %1,%0,0x002a\n \ | ||
217 | ori %0,%0,0x1ffe\n \ | ||
218 | mtspr 0x21e,%0\n \ | ||
219 | mtspr 0x21f,%1\n \ | ||
220 | isync\n \ | ||
221 | sync " | ||
222 | : "=r" (bat3u), "=r" (bat3l)); | ||
223 | |||
224 | mapping_set = 1; | ||
225 | } | ||
226 | return; | ||
227 | } | ||
228 | |||
229 | static unsigned long __init | ||
230 | powerpmc250_find_end_of_memory(void) | ||
231 | { | ||
232 | /* Cover I/O space with a BAT */ | ||
233 | /* yuck, better hope your ram size is a power of 2 -- paulus */ | ||
234 | powerpmc250_set_bat(); | ||
235 | |||
236 | return mpc10x_get_mem_size(MPC10X_MEM_MAP_B); | ||
237 | } | ||
238 | |||
239 | static void __init | ||
240 | powerpmc250_map_io(void) | ||
241 | { | ||
242 | io_block_mapping(0xfe000000, 0xfe000000, 0x02000000, _PAGE_IO); | ||
243 | } | ||
244 | |||
245 | void __init | ||
246 | platform_init(unsigned long r3, unsigned long r4, unsigned long r5, | ||
247 | unsigned long r6, unsigned long r7) | ||
248 | { | ||
249 | parse_bootinfo(find_bootinfo()); | ||
250 | |||
251 | #ifdef CONFIG_BLK_DEV_INITRD | ||
252 | if ( r4 ) | ||
253 | { | ||
254 | initrd_start = r4 + KERNELBASE; | ||
255 | initrd_end = r5 + KERNELBASE; | ||
256 | } | ||
257 | #endif | ||
258 | |||
259 | /* Copy cmd_line parameters */ | ||
260 | if ( r6) | ||
261 | { | ||
262 | *(char *)(r7 + KERNELBASE) = 0; | ||
263 | strcpy(cmd_line, (char *)(r6 + KERNELBASE)); | ||
264 | } | ||
265 | |||
266 | isa_io_base = MPC10X_MAPB_ISA_IO_BASE; | ||
267 | isa_mem_base = MPC10X_MAPB_ISA_MEM_BASE; | ||
268 | pci_dram_offset = MPC10X_MAPB_DRAM_OFFSET; | ||
269 | |||
270 | ppc_md.setup_arch = powerpmc250_setup_arch; | ||
271 | ppc_md.show_cpuinfo = powerpmc250_show_cpuinfo; | ||
272 | ppc_md.init_IRQ = powerpmc250_init_IRQ; | ||
273 | ppc_md.get_irq = openpic_get_irq; | ||
274 | |||
275 | ppc_md.find_end_of_memory = powerpmc250_find_end_of_memory; | ||
276 | ppc_md.setup_io_mappings = powerpmc250_map_io; | ||
277 | |||
278 | ppc_md.restart = powerpmc250_restart; | ||
279 | ppc_md.power_off = powerpmc250_power_off; | ||
280 | ppc_md.halt = powerpmc250_halt; | ||
281 | |||
282 | /* PowerPMC250 has no timekeeper part */ | ||
283 | ppc_md.time_init = NULL; | ||
284 | ppc_md.get_rtc_time = NULL; | ||
285 | ppc_md.set_rtc_time = NULL; | ||
286 | ppc_md.calibrate_decr = powerpmc250_calibrate_decr; | ||
287 | } | ||
288 | |||
289 | |||
290 | /* | ||
291 | * (This used to be arch/ppc/platforms/powerpmc250_pci.c) | ||
292 | * | ||
293 | * PCI support for Force PowerPMC250 | ||
294 | * | ||
295 | */ | ||
296 | |||
297 | #undef DEBUG | ||
298 | #ifdef DEBUG | ||
299 | #define DBG(x...) printk(x) | ||
300 | #else | ||
301 | #define DBG(x...) | ||
302 | #endif /* DEBUG */ | ||
303 | |||
304 | static inline int __init | ||
305 | powerpmc250_map_irq(struct pci_dev *dev, unsigned char idsel, unsigned char pin) | ||
306 | { | ||
307 | static char pci_irq_table[][4] = | ||
308 | /* | ||
309 | * PCI IDSEL/INTPIN->INTLINE | ||
310 | * A B C D | ||
311 | */ | ||
312 | { | ||
313 | {17, 0, 0, 0}, /* Device 11 - 82559 */ | ||
314 | {0, 0, 0, 0}, /* 12 */ | ||
315 | {0, 0, 0, 0}, /* 13 */ | ||
316 | {0, 0, 0, 0}, /* 14 */ | ||
317 | {0, 0, 0, 0}, /* 15 */ | ||
318 | {16, 17, 18, 19}, /* Device 16 - PMC A1?? */ | ||
319 | }; | ||
320 | const long min_idsel = 11, max_idsel = 16, irqs_per_slot = 4; | ||
321 | return PCI_IRQ_TABLE_LOOKUP; | ||
322 | }; | ||
323 | |||
324 | static int | ||
325 | powerpmc250_exclude_device(u_char bus, u_char devfn) | ||
326 | { | ||
327 | /* | ||
328 | * While doing PCI Scan the MPC107 will 'detect' itself as | ||
329 | * device on the PCI Bus, will create an incorrect response and | ||
330 | * later will respond incorrectly to Configuration read coming | ||
331 | * from another device. | ||
332 | * | ||
333 | * The work around is that when doing a PCI Scan one | ||
334 | * should skip its own device number in the scan. | ||
335 | * | ||
336 | * The top IDsel is AD13 and the middle is AD14. | ||
337 | * | ||
338 | * -- Note from force | ||
339 | */ | ||
340 | |||
341 | if ((bus == 0) && (PCI_SLOT(devfn) == 13 || PCI_SLOT(devfn) == 14)) { | ||
342 | return PCIBIOS_DEVICE_NOT_FOUND; | ||
343 | } | ||
344 | else { | ||
345 | return PCIBIOS_SUCCESSFUL; | ||
346 | } | ||
347 | } | ||
348 | |||
349 | void __init | ||
350 | powerpmc250_find_bridges(void) | ||
351 | { | ||
352 | struct pci_controller* hose; | ||
353 | |||
354 | hose = pcibios_alloc_controller(); | ||
355 | if (!hose){ | ||
356 | printk("Can't allocate PCI 'hose' structure!!!\n"); | ||
357 | return; | ||
358 | } | ||
359 | |||
360 | hose->first_busno = 0; | ||
361 | hose->last_busno = 0xff; | ||
362 | |||
363 | if (mpc10x_bridge_init(hose, | ||
364 | MPC10X_MEM_MAP_B, | ||
365 | MPC10X_MEM_MAP_B, | ||
366 | MPC10X_MAPB_EUMB_BASE) == 0) { | ||
367 | |||
368 | hose->mem_resources[0].end = 0xffffffff; | ||
369 | |||
370 | hose->last_busno = pciauto_bus_scan(hose, hose->first_busno); | ||
371 | |||
372 | /* ppc_md.pcibios_fixup = pcore_pcibios_fixup; */ | ||
373 | ppc_md.pci_swizzle = common_swizzle; | ||
374 | |||
375 | ppc_md.pci_exclude_device = powerpmc250_exclude_device; | ||
376 | ppc_md.pci_map_irq = powerpmc250_map_irq; | ||
377 | } else { | ||
378 | if (ppc_md.progress) | ||
379 | ppc_md.progress("Bridge init failed", 0x100); | ||
380 | printk("Host bridge init failed\n"); | ||
381 | } | ||
382 | |||
383 | } | ||
diff --git a/arch/ppc/platforms/powerpmc250.h b/arch/ppc/platforms/powerpmc250.h new file mode 100644 index 000000000000..41a6dc881911 --- /dev/null +++ b/arch/ppc/platforms/powerpmc250.h | |||
@@ -0,0 +1,52 @@ | |||
1 | /* | ||
2 | * include/asm-ppc/platforms/powerpmc250.h | ||
3 | * | ||
4 | * Definitions for Force PowerPMC-250 board support | ||
5 | * | ||
6 | * Author: Troy Benjegerdes <tbenjegerdes@mvista.com> | ||
7 | * | ||
8 | * Borrowed heavily from prpmc750.h by Matt Porter <mporter@mvista.com> | ||
9 | * | ||
10 | * 2001-2004 (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 | #ifndef __ASMPPC_POWERPMC250_H | ||
17 | #define __ASMPPC_POWERPMC250_H | ||
18 | |||
19 | #define POWERPMC250_PCI_CONFIG_ADDR 0x80000cf8 | ||
20 | #define POWERPMC250_PCI_CONFIG_DATA 0x80000cfc | ||
21 | |||
22 | #define POWERPMC250_PCI_PHY_MEM_BASE 0xc0000000 | ||
23 | #define POWERPMC250_PCI_MEM_BASE 0xf0000000 | ||
24 | #define POWERPMC250_PCI_IO_BASE 0x80000000 | ||
25 | |||
26 | #define POWERPMC250_ISA_IO_BASE POWERPMC250_PCI_IO_BASE | ||
27 | #define POWERPMC250_ISA_MEM_BASE POWERPMC250_PCI_MEM_BASE | ||
28 | #define POWERPMC250_PCI_MEM_OFFSET POWERPMC250_PCI_PHY_MEM_BASE | ||
29 | |||
30 | #define POWERPMC250_SYS_MEM_BASE 0x80000000 | ||
31 | |||
32 | #define POWERPMC250_HAWK_SMC_BASE 0xfef80000 | ||
33 | |||
34 | #define POWERPMC250_BASE_BAUD 12288000 | ||
35 | #define POWERPMC250_SERIAL 0xff000000 | ||
36 | #define POWERPMC250_SERIAL_IRQ 20 | ||
37 | |||
38 | /* UART Defines. */ | ||
39 | #define RS_TABLE_SIZE 1 | ||
40 | |||
41 | #define BASE_BAUD (POWERPMC250_BASE_BAUD / 16) | ||
42 | |||
43 | #define STD_COM_FLAGS ASYNC_BOOT_AUTOCONF | ||
44 | |||
45 | #define SERIAL_PORT_DFNS \ | ||
46 | { 0, BASE_BAUD, POWERPMC250_SERIAL, POWERPMC250_SERIAL_IRQ, \ | ||
47 | STD_COM_FLAGS, /* ttyS0 */ \ | ||
48 | iomem_base: (u8 *)POWERPMC250_SERIAL, \ | ||
49 | iomem_reg_shift: 0, \ | ||
50 | io_type: SERIAL_IO_MEM } | ||
51 | |||
52 | #endif /* __ASMPPC_POWERPMC250_H */ | ||
diff --git a/arch/ppc/platforms/pplus.c b/arch/ppc/platforms/pplus.c new file mode 100644 index 000000000000..65705c911795 --- /dev/null +++ b/arch/ppc/platforms/pplus.c | |||
@@ -0,0 +1,917 @@ | |||
1 | /* | ||
2 | * arch/ppc/platforms/pplus.c | ||
3 | * | ||
4 | * Board and PCI setup routines for MCG PowerPlus | ||
5 | * | ||
6 | * Author: Randy Vinson <rvinson@mvista.com> | ||
7 | * | ||
8 | * Derived from original PowerPlus PReP work by | ||
9 | * Cort Dougan, Johnnie Peters, Matt Porter, and | ||
10 | * Troy Benjegerdes. | ||
11 | * | ||
12 | * 2001-2004 (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/config.h> | ||
19 | #include <linux/kernel.h> | ||
20 | #include <linux/interrupt.h> | ||
21 | #include <linux/init.h> | ||
22 | #include <linux/ioport.h> | ||
23 | #include <linux/console.h> | ||
24 | #include <linux/pci.h> | ||
25 | #include <linux/irq.h> | ||
26 | #include <linux/ide.h> | ||
27 | #include <linux/seq_file.h> | ||
28 | #include <linux/root_dev.h> | ||
29 | |||
30 | #include <asm/system.h> | ||
31 | #include <asm/io.h> | ||
32 | #include <asm/pgtable.h> | ||
33 | #include <asm/dma.h> | ||
34 | #include <asm/machdep.h> | ||
35 | #include <asm/prep_nvram.h> | ||
36 | #include <asm/vga.h> | ||
37 | #include <asm/i8259.h> | ||
38 | #include <asm/open_pic.h> | ||
39 | #include <asm/hawk.h> | ||
40 | #include <asm/todc.h> | ||
41 | #include <asm/bootinfo.h> | ||
42 | #include <asm/kgdb.h> | ||
43 | #include <asm/reg.h> | ||
44 | |||
45 | #include "pplus.h" | ||
46 | |||
47 | #undef DUMP_DBATS | ||
48 | |||
49 | TODC_ALLOC(); | ||
50 | |||
51 | extern void pplus_setup_hose(void); | ||
52 | extern void pplus_set_VIA_IDE_native(void); | ||
53 | |||
54 | extern unsigned long loops_per_jiffy; | ||
55 | unsigned char *Motherboard_map_name; | ||
56 | |||
57 | /* Tables for known hardware */ | ||
58 | |||
59 | /* Motorola Mesquite */ | ||
60 | static inline int | ||
61 | mesquite_map_irq(struct pci_dev *dev, unsigned char idsel, unsigned char pin) | ||
62 | { | ||
63 | static char pci_irq_table[][4] = | ||
64 | /* | ||
65 | * MPIC interrupts for various IDSEL values (MPIC IRQ0 = | ||
66 | * Linux IRQ16 (to leave room for ISA IRQs at 0-15). | ||
67 | * PCI IDSEL/INTPIN->INTLINE | ||
68 | * A B C D | ||
69 | */ | ||
70 | { | ||
71 | {18, 0, 0, 0}, /* IDSEL 14 - Enet 0 */ | ||
72 | { 0, 0, 0, 0}, /* IDSEL 15 - unused */ | ||
73 | {19, 19, 19, 19}, /* IDSEL 16 - PMC Slot 1 */ | ||
74 | { 0, 0, 0, 0}, /* IDSEL 17 - unused */ | ||
75 | { 0, 0, 0, 0}, /* IDSEL 18 - unused */ | ||
76 | { 0, 0, 0, 0}, /* IDSEL 19 - unused */ | ||
77 | {24, 25, 26, 27}, /* IDSEL 20 - P2P bridge (to cPCI 1) */ | ||
78 | { 0, 0, 0, 0}, /* IDSEL 21 - unused */ | ||
79 | {28, 29, 30, 31} /* IDSEL 22 - P2P bridge (to cPCI 2) */ | ||
80 | }; | ||
81 | |||
82 | const long min_idsel = 14, max_idsel = 22, irqs_per_slot = 4; | ||
83 | return PCI_IRQ_TABLE_LOOKUP; | ||
84 | } | ||
85 | |||
86 | /* Motorola Sitka */ | ||
87 | static inline int | ||
88 | sitka_map_irq(struct pci_dev *dev, unsigned char idsel, unsigned char pin) | ||
89 | { | ||
90 | static char pci_irq_table[][4] = | ||
91 | /* | ||
92 | * MPIC interrupts for various IDSEL values (MPIC IRQ0 = | ||
93 | * Linux IRQ16 (to leave room for ISA IRQs at 0-15). | ||
94 | * PCI IDSEL/INTPIN->INTLINE | ||
95 | * A B C D | ||
96 | */ | ||
97 | { | ||
98 | {18, 0, 0, 0}, /* IDSEL 14 - Enet 0 */ | ||
99 | { 0, 0, 0, 0}, /* IDSEL 15 - unused */ | ||
100 | {25, 26, 27, 28}, /* IDSEL 16 - PMC Slot 1 */ | ||
101 | {28, 25, 26, 27}, /* IDSEL 17 - PMC Slot 2 */ | ||
102 | { 0, 0, 0, 0}, /* IDSEL 18 - unused */ | ||
103 | { 0, 0, 0, 0}, /* IDSEL 19 - unused */ | ||
104 | {20, 0, 0, 0} /* IDSEL 20 - P2P bridge (to cPCI) */ | ||
105 | }; | ||
106 | |||
107 | const long min_idsel = 14, max_idsel = 20, irqs_per_slot = 4; | ||
108 | return PCI_IRQ_TABLE_LOOKUP; | ||
109 | } | ||
110 | |||
111 | /* Motorola MTX */ | ||
112 | static inline int | ||
113 | MTX_map_irq(struct pci_dev *dev, unsigned char idsel, unsigned char pin) | ||
114 | { | ||
115 | static char pci_irq_table[][4] = | ||
116 | /* | ||
117 | * MPIC interrupts for various IDSEL values (MPIC IRQ0 = | ||
118 | * Linux IRQ16 (to leave room for ISA IRQs at 0-15). | ||
119 | * PCI IDSEL/INTPIN->INTLINE | ||
120 | * A B C D | ||
121 | */ | ||
122 | { | ||
123 | {19, 0, 0, 0}, /* IDSEL 12 - SCSI */ | ||
124 | { 0, 0, 0, 0}, /* IDSEL 13 - unused */ | ||
125 | {18, 0, 0, 0}, /* IDSEL 14 - Enet */ | ||
126 | { 0, 0, 0, 0}, /* IDSEL 15 - unused */ | ||
127 | {25, 26, 27, 28}, /* IDSEL 16 - PMC Slot 1 */ | ||
128 | {26, 27, 28, 25}, /* IDSEL 17 - PMC Slot 2 */ | ||
129 | {27, 28, 25, 26} /* IDSEL 18 - PCI Slot 3 */ | ||
130 | }; | ||
131 | |||
132 | const long min_idsel = 12, max_idsel = 18, irqs_per_slot = 4; | ||
133 | return PCI_IRQ_TABLE_LOOKUP; | ||
134 | } | ||
135 | |||
136 | /* Motorola MTX Plus */ | ||
137 | /* Secondary bus interrupt routing is not supported yet */ | ||
138 | static inline int | ||
139 | MTXplus_map_irq(struct pci_dev *dev, unsigned char idsel, unsigned char pin) | ||
140 | { | ||
141 | static char pci_irq_table[][4] = | ||
142 | /* | ||
143 | * MPIC interrupts for various IDSEL values (MPIC IRQ0 = | ||
144 | * Linux IRQ16 (to leave room for ISA IRQs at 0-15). | ||
145 | * PCI IDSEL/INTPIN->INTLINE | ||
146 | * A B C D | ||
147 | */ | ||
148 | { | ||
149 | {19, 0, 0, 0}, /* IDSEL 12 - SCSI */ | ||
150 | { 0, 0, 0, 0}, /* IDSEL 13 - unused */ | ||
151 | {18, 0, 0, 0}, /* IDSEL 14 - Enet 1 */ | ||
152 | { 0, 0, 0, 0}, /* IDSEL 15 - unused */ | ||
153 | {25, 26, 27, 28}, /* IDSEL 16 - PCI Slot 1P */ | ||
154 | {26, 27, 28, 25}, /* IDSEL 17 - PCI Slot 2P */ | ||
155 | {27, 28, 25, 26}, /* IDSEL 18 - PCI Slot 3P */ | ||
156 | {26, 0, 0, 0}, /* IDSEL 19 - Enet 2 */ | ||
157 | { 0, 0, 0, 0} /* IDSEL 20 - P2P Bridge */ | ||
158 | }; | ||
159 | |||
160 | const long min_idsel = 12, max_idsel = 20, irqs_per_slot = 4; | ||
161 | return PCI_IRQ_TABLE_LOOKUP; | ||
162 | } | ||
163 | |||
164 | static inline int | ||
165 | Genesis2_map_irq(struct pci_dev *dev, unsigned char idsel, unsigned char pin) | ||
166 | { | ||
167 | /* 2600 | ||
168 | * Raven 31 | ||
169 | * ISA 11 | ||
170 | * SCSI 12 - IRQ3 | ||
171 | * Univ 13 | ||
172 | * eth 14 - IRQ2 | ||
173 | * VGA 15 - IRQ4 | ||
174 | * PMC1 16 - IRQ9,10,11,12 = PMC1 A-D | ||
175 | * PMC2 17 - IRQ12,9,10,11 = A-D | ||
176 | * SCSI2 18 - IRQ11 | ||
177 | * eth2 19 - IRQ10 | ||
178 | * PCIX 20 - IRQ9,10,11,12 = PCI A-D | ||
179 | */ | ||
180 | |||
181 | /* 2400 | ||
182 | * Hawk 31 | ||
183 | * ISA 11 | ||
184 | * Univ 13 | ||
185 | * eth 14 - IRQ2 | ||
186 | * PMC1 16 - IRQ9,10,11,12 = PMC A-D | ||
187 | * PMC2 17 - IRQ12,9,10,11 = PMC A-D | ||
188 | * PCIX 20 - IRQ9,10,11,12 = PMC A-D | ||
189 | */ | ||
190 | |||
191 | /* 2300 | ||
192 | * Raven 31 | ||
193 | * ISA 11 | ||
194 | * Univ 13 | ||
195 | * eth 14 - IRQ2 | ||
196 | * PMC1 16 - 9,10,11,12 = A-D | ||
197 | * PMC2 17 - 9,10,11,12 = B,C,D,A | ||
198 | */ | ||
199 | |||
200 | static char pci_irq_table[][4] = | ||
201 | /* | ||
202 | * MPIC interrupts for various IDSEL values (MPIC IRQ0 = | ||
203 | * Linux IRQ16 (to leave room for ISA IRQs at 0-15). | ||
204 | * PCI IDSEL/INTPIN->INTLINE | ||
205 | * A B C D | ||
206 | */ | ||
207 | { | ||
208 | {19, 0, 0, 0}, /* IDSEL 12 - SCSI */ | ||
209 | { 0, 0, 0, 0}, /* IDSEL 13 - Universe PCI - VME */ | ||
210 | {18, 0, 0, 0}, /* IDSEL 14 - Enet 1 */ | ||
211 | { 0, 0, 0, 0}, /* IDSEL 15 - unused */ | ||
212 | {25, 26, 27, 28}, /* IDSEL 16 - PCI/PMC Slot 1P */ | ||
213 | {28, 25, 26, 27}, /* IDSEL 17 - PCI/PMC Slot 2P */ | ||
214 | {27, 28, 25, 26}, /* IDSEL 18 - PCI Slot 3P */ | ||
215 | {26, 0, 0, 0}, /* IDSEL 19 - Enet 2 */ | ||
216 | {25, 26, 27, 28} /* IDSEL 20 - P2P Bridge */ | ||
217 | }; | ||
218 | |||
219 | const long min_idsel = 12, max_idsel = 20, irqs_per_slot = 4; | ||
220 | return PCI_IRQ_TABLE_LOOKUP; | ||
221 | } | ||
222 | |||
223 | #define MOTOROLA_CPUTYPE_REG 0x800 | ||
224 | #define MOTOROLA_BASETYPE_REG 0x803 | ||
225 | #define MPIC_RAVEN_ID 0x48010000 | ||
226 | #define MPIC_HAWK_ID 0x48030000 | ||
227 | #define MOT_PROC2_BIT 0x800 | ||
228 | |||
229 | static u_char pplus_openpic_initsenses[] __initdata = { | ||
230 | (IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE), /* MVME2600_INT_SIO */ | ||
231 | (IRQ_SENSE_EDGE | IRQ_POLARITY_NEGATIVE),/*MVME2600_INT_FALCN_ECC_ERR */ | ||
232 | (IRQ_SENSE_LEVEL | IRQ_POLARITY_NEGATIVE),/*MVME2600_INT_PCI_ETHERNET */ | ||
233 | (IRQ_SENSE_LEVEL | IRQ_POLARITY_NEGATIVE), /* MVME2600_INT_PCI_SCSI */ | ||
234 | (IRQ_SENSE_LEVEL | IRQ_POLARITY_NEGATIVE),/*MVME2600_INT_PCI_GRAPHICS */ | ||
235 | (IRQ_SENSE_LEVEL | IRQ_POLARITY_NEGATIVE), /* MVME2600_INT_PCI_VME0 */ | ||
236 | (IRQ_SENSE_LEVEL | IRQ_POLARITY_NEGATIVE), /* MVME2600_INT_PCI_VME1 */ | ||
237 | (IRQ_SENSE_LEVEL | IRQ_POLARITY_NEGATIVE), /* MVME2600_INT_PCI_VME2 */ | ||
238 | (IRQ_SENSE_LEVEL | IRQ_POLARITY_NEGATIVE), /* MVME2600_INT_PCI_VME3 */ | ||
239 | (IRQ_SENSE_LEVEL | IRQ_POLARITY_NEGATIVE), /* MVME2600_INT_PCI_INTA */ | ||
240 | (IRQ_SENSE_LEVEL | IRQ_POLARITY_NEGATIVE), /* MVME2600_INT_PCI_INTB */ | ||
241 | (IRQ_SENSE_LEVEL | IRQ_POLARITY_NEGATIVE), /* MVME2600_INT_PCI_INTC */ | ||
242 | (IRQ_SENSE_LEVEL | IRQ_POLARITY_NEGATIVE), /* MVME2600_INT_PCI_INTD */ | ||
243 | (IRQ_SENSE_LEVEL | IRQ_POLARITY_NEGATIVE), /* MVME2600_INT_LM_SIG0 */ | ||
244 | (IRQ_SENSE_LEVEL | IRQ_POLARITY_NEGATIVE), /* MVME2600_INT_LM_SIG1 */ | ||
245 | (IRQ_SENSE_LEVEL | IRQ_POLARITY_NEGATIVE), | ||
246 | }; | ||
247 | |||
248 | int mot_entry = -1; | ||
249 | int prep_keybd_present = 1; | ||
250 | int mot_multi = 0; | ||
251 | |||
252 | struct brd_info { | ||
253 | /* 0x100 mask assumes for Raven and Hawk boards that the level/edge | ||
254 | * are set */ | ||
255 | int cpu_type; | ||
256 | /* 0x200 if this board has a Hawk chip. */ | ||
257 | int base_type; | ||
258 | /* or'ed with 0x80 if this board should be checked for multi CPU */ | ||
259 | int max_cpu; | ||
260 | const char *name; | ||
261 | int (*map_irq) (struct pci_dev *, unsigned char, unsigned char); | ||
262 | }; | ||
263 | struct brd_info mot_info[] = { | ||
264 | {0x300, 0x00, 0x00, "MVME 2400", Genesis2_map_irq}, | ||
265 | {0x1E0, 0xE0, 0x00, "Mesquite cPCI (MCP750)", mesquite_map_irq}, | ||
266 | {0x1E0, 0xE1, 0x00, "Sitka cPCI (MCPN750)", sitka_map_irq}, | ||
267 | {0x1E0, 0xE2, 0x00, "Mesquite cPCI (MCP750) w/ HAC", mesquite_map_irq}, | ||
268 | {0x1E0, 0xF6, 0x80, "MTX Plus", MTXplus_map_irq}, | ||
269 | {0x1E0, 0xF6, 0x81, "Dual MTX Plus", MTXplus_map_irq}, | ||
270 | {0x1E0, 0xF7, 0x80, "MTX wo/ Parallel Port", MTX_map_irq}, | ||
271 | {0x1E0, 0xF7, 0x81, "Dual MTX wo/ Parallel Port", MTX_map_irq}, | ||
272 | {0x1E0, 0xF8, 0x80, "MTX w/ Parallel Port", MTX_map_irq}, | ||
273 | {0x1E0, 0xF8, 0x81, "Dual MTX w/ Parallel Port", MTX_map_irq}, | ||
274 | {0x1E0, 0xF9, 0x00, "MVME 2300", Genesis2_map_irq}, | ||
275 | {0x1E0, 0xFA, 0x00, "MVME 2300SC/2600", Genesis2_map_irq}, | ||
276 | {0x1E0, 0xFB, 0x00, "MVME 2600 with MVME712M", Genesis2_map_irq}, | ||
277 | {0x1E0, 0xFC, 0x00, "MVME 2600/2700 with MVME761", Genesis2_map_irq}, | ||
278 | {0x1E0, 0xFD, 0x80, "MVME 3600 with MVME712M", Genesis2_map_irq}, | ||
279 | {0x1E0, 0xFD, 0x81, "MVME 4600 with MVME712M", Genesis2_map_irq}, | ||
280 | {0x1E0, 0xFE, 0x80, "MVME 3600 with MVME761", Genesis2_map_irq}, | ||
281 | {0x1E0, 0xFE, 0x81, "MVME 4600 with MVME761", Genesis2_map_irq}, | ||
282 | {0x000, 0x00, 0x00, "", NULL} | ||
283 | }; | ||
284 | |||
285 | void __init pplus_set_board_type(void) | ||
286 | { | ||
287 | unsigned char cpu_type; | ||
288 | unsigned char base_mod; | ||
289 | int entry; | ||
290 | unsigned short devid; | ||
291 | unsigned long *ProcInfo = NULL; | ||
292 | |||
293 | cpu_type = inb(MOTOROLA_CPUTYPE_REG) & 0xF0; | ||
294 | base_mod = inb(MOTOROLA_BASETYPE_REG); | ||
295 | early_read_config_word(0, 0, 0, PCI_VENDOR_ID, &devid); | ||
296 | |||
297 | for (entry = 0; mot_info[entry].cpu_type != 0; entry++) { | ||
298 | /* Check for Hawk chip */ | ||
299 | if (mot_info[entry].cpu_type & 0x200) { | ||
300 | if (devid != PCI_DEVICE_ID_MOTOROLA_HAWK) | ||
301 | continue; | ||
302 | } else { | ||
303 | /* store the system config register for later use. */ | ||
304 | ProcInfo = | ||
305 | (unsigned long *)ioremap(PPLUS_SYS_CONFIG_REG, 4); | ||
306 | |||
307 | /* Check non hawk boards */ | ||
308 | if ((mot_info[entry].cpu_type & 0xff) != cpu_type) | ||
309 | continue; | ||
310 | |||
311 | if (mot_info[entry].base_type == 0) { | ||
312 | mot_entry = entry; | ||
313 | break; | ||
314 | } | ||
315 | |||
316 | if (mot_info[entry].base_type != base_mod) | ||
317 | continue; | ||
318 | } | ||
319 | |||
320 | if (!(mot_info[entry].max_cpu & 0x80)) { | ||
321 | mot_entry = entry; | ||
322 | break; | ||
323 | } | ||
324 | |||
325 | /* processor 1 not present and max processor zero indicated */ | ||
326 | if ((*ProcInfo & MOT_PROC2_BIT) | ||
327 | && !(mot_info[entry].max_cpu & 0x7f)) { | ||
328 | mot_entry = entry; | ||
329 | break; | ||
330 | } | ||
331 | |||
332 | /* processor 1 present and max processor zero indicated */ | ||
333 | if (!(*ProcInfo & MOT_PROC2_BIT) | ||
334 | && (mot_info[entry].max_cpu & 0x7f)) { | ||
335 | mot_entry = entry; | ||
336 | break; | ||
337 | } | ||
338 | |||
339 | /* Indicate to system if this is a multiprocessor board */ | ||
340 | if (!(*ProcInfo & MOT_PROC2_BIT)) | ||
341 | mot_multi = 1; | ||
342 | } | ||
343 | |||
344 | if (mot_entry == -1) | ||
345 | /* No particular cpu type found - assume Mesquite (MCP750) */ | ||
346 | mot_entry = 1; | ||
347 | |||
348 | Motherboard_map_name = (unsigned char *)mot_info[mot_entry].name; | ||
349 | ppc_md.pci_map_irq = mot_info[mot_entry].map_irq; | ||
350 | } | ||
351 | void __init pplus_pib_init(void) | ||
352 | { | ||
353 | unsigned char reg; | ||
354 | unsigned short short_reg; | ||
355 | |||
356 | struct pci_dev *dev = NULL; | ||
357 | |||
358 | /* | ||
359 | * Perform specific configuration for the Via Tech or | ||
360 | * or Winbond PCI-ISA-Bridge part. | ||
361 | */ | ||
362 | if ((dev = pci_get_device(PCI_VENDOR_ID_VIA, | ||
363 | PCI_DEVICE_ID_VIA_82C586_1, dev))) { | ||
364 | /* | ||
365 | * PPCBUG does not set the enable bits | ||
366 | * for the IDE device. Force them on here. | ||
367 | */ | ||
368 | pci_read_config_byte(dev, 0x40, ®); | ||
369 | |||
370 | reg |= 0x03; /* IDE: Chip Enable Bits */ | ||
371 | pci_write_config_byte(dev, 0x40, reg); | ||
372 | } | ||
373 | |||
374 | if ((dev = pci_get_device(PCI_VENDOR_ID_VIA, | ||
375 | PCI_DEVICE_ID_VIA_82C586_2, | ||
376 | dev)) && (dev->devfn = 0x5a)) { | ||
377 | /* Force correct USB interrupt */ | ||
378 | dev->irq = 11; | ||
379 | pci_write_config_byte(dev, PCI_INTERRUPT_LINE, dev->irq); | ||
380 | } | ||
381 | |||
382 | if ((dev = pci_get_device(PCI_VENDOR_ID_WINBOND, | ||
383 | PCI_DEVICE_ID_WINBOND_83C553, dev))) { | ||
384 | /* Clear PCI Interrupt Routing Control Register. */ | ||
385 | short_reg = 0x0000; | ||
386 | pci_write_config_word(dev, 0x44, short_reg); | ||
387 | /* Route IDE interrupts to IRQ 14 */ | ||
388 | reg = 0xEE; | ||
389 | pci_write_config_byte(dev, 0x43, reg); | ||
390 | } | ||
391 | |||
392 | if ((dev = pci_get_device(PCI_VENDOR_ID_WINBOND, | ||
393 | PCI_DEVICE_ID_WINBOND_82C105, dev))) { | ||
394 | /* | ||
395 | * Disable LEGIRQ mode so PCI INTS are routed | ||
396 | * directly to the 8259 and enable both channels | ||
397 | */ | ||
398 | pci_write_config_dword(dev, 0x40, 0x10ff0033); | ||
399 | |||
400 | /* Force correct IDE interrupt */ | ||
401 | dev->irq = 14; | ||
402 | pci_write_config_byte(dev, PCI_INTERRUPT_LINE, dev->irq); | ||
403 | } | ||
404 | pci_dev_put(dev); | ||
405 | } | ||
406 | |||
407 | void __init pplus_set_VIA_IDE_legacy(void) | ||
408 | { | ||
409 | unsigned short vend, dev; | ||
410 | |||
411 | early_read_config_word(0, 0, PCI_DEVFN(0xb, 1), PCI_VENDOR_ID, &vend); | ||
412 | early_read_config_word(0, 0, PCI_DEVFN(0xb, 1), PCI_DEVICE_ID, &dev); | ||
413 | |||
414 | if ((vend == PCI_VENDOR_ID_VIA) && | ||
415 | (dev == PCI_DEVICE_ID_VIA_82C586_1)) { | ||
416 | unsigned char temp; | ||
417 | |||
418 | /* put back original "standard" port base addresses */ | ||
419 | early_write_config_dword(0, 0, PCI_DEVFN(0xb, 1), | ||
420 | PCI_BASE_ADDRESS_0, 0x1f1); | ||
421 | early_write_config_dword(0, 0, PCI_DEVFN(0xb, 1), | ||
422 | PCI_BASE_ADDRESS_1, 0x3f5); | ||
423 | early_write_config_dword(0, 0, PCI_DEVFN(0xb, 1), | ||
424 | PCI_BASE_ADDRESS_2, 0x171); | ||
425 | early_write_config_dword(0, 0, PCI_DEVFN(0xb, 1), | ||
426 | PCI_BASE_ADDRESS_3, 0x375); | ||
427 | early_write_config_dword(0, 0, PCI_DEVFN(0xb, 1), | ||
428 | PCI_BASE_ADDRESS_4, 0xcc01); | ||
429 | |||
430 | /* put into legacy mode */ | ||
431 | early_read_config_byte(0, 0, PCI_DEVFN(0xb, 1), PCI_CLASS_PROG, | ||
432 | &temp); | ||
433 | temp &= ~0x05; | ||
434 | early_write_config_byte(0, 0, PCI_DEVFN(0xb, 1), PCI_CLASS_PROG, | ||
435 | temp); | ||
436 | } | ||
437 | } | ||
438 | |||
439 | void pplus_set_VIA_IDE_native(void) | ||
440 | { | ||
441 | unsigned short vend, dev; | ||
442 | |||
443 | early_read_config_word(0, 0, PCI_DEVFN(0xb, 1), PCI_VENDOR_ID, &vend); | ||
444 | early_read_config_word(0, 0, PCI_DEVFN(0xb, 1), PCI_DEVICE_ID, &dev); | ||
445 | |||
446 | if ((vend == PCI_VENDOR_ID_VIA) && | ||
447 | (dev == PCI_DEVICE_ID_VIA_82C586_1)) { | ||
448 | unsigned char temp; | ||
449 | |||
450 | /* put into native mode */ | ||
451 | early_read_config_byte(0, 0, PCI_DEVFN(0xb, 1), PCI_CLASS_PROG, | ||
452 | &temp); | ||
453 | temp |= 0x05; | ||
454 | early_write_config_byte(0, 0, PCI_DEVFN(0xb, 1), PCI_CLASS_PROG, | ||
455 | temp); | ||
456 | } | ||
457 | } | ||
458 | |||
459 | void __init pplus_pcibios_fixup(void) | ||
460 | { | ||
461 | |||
462 | unsigned char reg; | ||
463 | unsigned short devid; | ||
464 | unsigned char base_mod; | ||
465 | |||
466 | printk(KERN_INFO "Setting PCI interrupts for a \"%s\"\n", | ||
467 | Motherboard_map_name); | ||
468 | |||
469 | /* Setup the Winbond or Via PIB */ | ||
470 | pplus_pib_init(); | ||
471 | |||
472 | /* Set up floppy in PS/2 mode */ | ||
473 | outb(0x09, SIO_CONFIG_RA); | ||
474 | reg = inb(SIO_CONFIG_RD); | ||
475 | reg = (reg & 0x3F) | 0x40; | ||
476 | outb(reg, SIO_CONFIG_RD); | ||
477 | outb(reg, SIO_CONFIG_RD); /* Have to write twice to change! */ | ||
478 | |||
479 | /* This is a hack. If this is a 2300 or 2400 mot board then there is | ||
480 | * no keyboard controller and we have to indicate that. | ||
481 | */ | ||
482 | |||
483 | early_read_config_word(0, 0, 0, PCI_VENDOR_ID, &devid); | ||
484 | base_mod = inb(MOTOROLA_BASETYPE_REG); | ||
485 | if ((devid == PCI_DEVICE_ID_MOTOROLA_HAWK) || | ||
486 | (base_mod == 0xF9) || (base_mod == 0xFA) || (base_mod == 0xE1)) | ||
487 | prep_keybd_present = 0; | ||
488 | } | ||
489 | |||
490 | void __init pplus_find_bridges(void) | ||
491 | { | ||
492 | struct pci_controller *hose; | ||
493 | |||
494 | hose = pcibios_alloc_controller(); | ||
495 | if (!hose) | ||
496 | return; | ||
497 | |||
498 | hose->first_busno = 0; | ||
499 | hose->last_busno = 0xff; | ||
500 | |||
501 | hose->pci_mem_offset = PREP_ISA_MEM_BASE; | ||
502 | hose->io_base_virt = (void *)PREP_ISA_IO_BASE; | ||
503 | |||
504 | pci_init_resource(&hose->io_resource, PPLUS_PCI_IO_START, | ||
505 | PPLUS_PCI_IO_END, IORESOURCE_IO, "PCI host bridge"); | ||
506 | pci_init_resource(&hose->mem_resources[0], PPLUS_PROC_PCI_MEM_START, | ||
507 | PPLUS_PROC_PCI_MEM_END, IORESOURCE_MEM, | ||
508 | "PCI host bridge"); | ||
509 | |||
510 | hose->io_space.start = PPLUS_PCI_IO_START; | ||
511 | hose->io_space.end = PPLUS_PCI_IO_END; | ||
512 | hose->mem_space.start = PPLUS_PCI_MEM_START; | ||
513 | hose->mem_space.end = PPLUS_PCI_MEM_END - HAWK_MPIC_SIZE; | ||
514 | |||
515 | if (hawk_init(hose, PPLUS_HAWK_PPC_REG_BASE, PPLUS_PROC_PCI_MEM_START, | ||
516 | PPLUS_PROC_PCI_MEM_END - HAWK_MPIC_SIZE, | ||
517 | PPLUS_PROC_PCI_IO_START, PPLUS_PROC_PCI_IO_END, | ||
518 | PPLUS_PROC_PCI_MEM_END - HAWK_MPIC_SIZE + 1) | ||
519 | != 0) { | ||
520 | printk(KERN_CRIT "Could not initialize host bridge\n"); | ||
521 | |||
522 | } | ||
523 | |||
524 | pplus_set_VIA_IDE_legacy(); | ||
525 | |||
526 | hose->last_busno = pciauto_bus_scan(hose, hose->first_busno); | ||
527 | |||
528 | ppc_md.pcibios_fixup = pplus_pcibios_fixup; | ||
529 | ppc_md.pci_swizzle = common_swizzle; | ||
530 | } | ||
531 | |||
532 | static int pplus_show_cpuinfo(struct seq_file *m) | ||
533 | { | ||
534 | seq_printf(m, "vendor\t\t: Motorola MCG\n"); | ||
535 | seq_printf(m, "machine\t\t: %s\n", Motherboard_map_name); | ||
536 | |||
537 | return 0; | ||
538 | } | ||
539 | |||
540 | static void __init pplus_setup_arch(void) | ||
541 | { | ||
542 | struct pci_controller *hose; | ||
543 | |||
544 | if (ppc_md.progress) | ||
545 | ppc_md.progress("pplus_setup_arch: enter", 0); | ||
546 | |||
547 | /* init to some ~sane value until calibrate_delay() runs */ | ||
548 | loops_per_jiffy = 50000000; | ||
549 | |||
550 | if (ppc_md.progress) | ||
551 | ppc_md.progress("pplus_setup_arch: find_bridges", 0); | ||
552 | |||
553 | /* Setup PCI host bridge */ | ||
554 | pplus_find_bridges(); | ||
555 | |||
556 | hose = pci_bus_to_hose(0); | ||
557 | isa_io_base = (ulong) hose->io_base_virt; | ||
558 | |||
559 | if (ppc_md.progress) | ||
560 | ppc_md.progress("pplus_setup_arch: set_board_type", 0); | ||
561 | |||
562 | pplus_set_board_type(); | ||
563 | |||
564 | /* Enable L2. Assume we don't need to flush -- Cort */ | ||
565 | *(unsigned char *)(PPLUS_L2_CONTROL_REG) |= 3; | ||
566 | |||
567 | #ifdef CONFIG_BLK_DEV_INITRD | ||
568 | if (initrd_start) | ||
569 | ROOT_DEV = Root_RAM0; | ||
570 | else | ||
571 | #endif | ||
572 | #ifdef CONFIG_ROOT_NFS | ||
573 | ROOT_DEV = Root_NFS; | ||
574 | #else | ||
575 | ROOT_DEV = Root_SDA2; | ||
576 | #endif | ||
577 | |||
578 | printk(KERN_INFO "Motorola PowerPlus Platform\n"); | ||
579 | printk(KERN_INFO | ||
580 | "Port by MontaVista Software, Inc. (source@mvista.com)\n"); | ||
581 | |||
582 | #ifdef CONFIG_VGA_CONSOLE | ||
583 | /* remap the VGA memory */ | ||
584 | vgacon_remap_base = (unsigned long)ioremap(PPLUS_ISA_MEM_BASE, | ||
585 | 0x08000000); | ||
586 | conswitchp = &vga_con; | ||
587 | #endif | ||
588 | #ifdef CONFIG_PPCBUG_NVRAM | ||
589 | /* Read in NVRAM data */ | ||
590 | init_prep_nvram(); | ||
591 | |||
592 | /* if no bootargs, look in NVRAM */ | ||
593 | if (cmd_line[0] == '\0') { | ||
594 | char *bootargs; | ||
595 | bootargs = prep_nvram_get_var("bootargs"); | ||
596 | if (bootargs != NULL) { | ||
597 | strcpy(cmd_line, bootargs); | ||
598 | /* again.. */ | ||
599 | strcpy(saved_command_line, cmd_line); | ||
600 | } | ||
601 | } | ||
602 | #endif | ||
603 | if (ppc_md.progress) | ||
604 | ppc_md.progress("pplus_setup_arch: exit", 0); | ||
605 | } | ||
606 | |||
607 | static void pplus_restart(char *cmd) | ||
608 | { | ||
609 | unsigned long i = 10000; | ||
610 | |||
611 | local_irq_disable(); | ||
612 | |||
613 | /* set VIA IDE controller into native mode */ | ||
614 | pplus_set_VIA_IDE_native(); | ||
615 | |||
616 | /* set exception prefix high - to the prom */ | ||
617 | _nmask_and_or_msr(0, MSR_IP); | ||
618 | |||
619 | /* make sure bit 0 (reset) is a 0 */ | ||
620 | outb(inb(0x92) & ~1L, 0x92); | ||
621 | /* signal a reset to system control port A - soft reset */ | ||
622 | outb(inb(0x92) | 1, 0x92); | ||
623 | |||
624 | while (i != 0) | ||
625 | i++; | ||
626 | panic("restart failed\n"); | ||
627 | } | ||
628 | |||
629 | static void pplus_halt(void) | ||
630 | { | ||
631 | /* set exception prefix high - to the prom */ | ||
632 | _nmask_and_or_msr(MSR_EE, MSR_IP); | ||
633 | |||
634 | /* make sure bit 0 (reset) is a 0 */ | ||
635 | outb(inb(0x92) & ~1L, 0x92); | ||
636 | /* signal a reset to system control port A - soft reset */ | ||
637 | outb(inb(0x92) | 1, 0x92); | ||
638 | |||
639 | while (1) ; | ||
640 | /* | ||
641 | * Not reached | ||
642 | */ | ||
643 | } | ||
644 | |||
645 | static void pplus_power_off(void) | ||
646 | { | ||
647 | pplus_halt(); | ||
648 | } | ||
649 | |||
650 | static unsigned int pplus_irq_canonicalize(u_int irq) | ||
651 | { | ||
652 | if (irq == 2) | ||
653 | return 9; | ||
654 | else | ||
655 | return irq; | ||
656 | } | ||
657 | |||
658 | static void __init pplus_init_IRQ(void) | ||
659 | { | ||
660 | int i; | ||
661 | |||
662 | if (ppc_md.progress) | ||
663 | ppc_md.progress("init_irq: enter", 0); | ||
664 | |||
665 | OpenPIC_InitSenses = pplus_openpic_initsenses; | ||
666 | OpenPIC_NumInitSenses = sizeof(pplus_openpic_initsenses); | ||
667 | |||
668 | if (OpenPIC_Addr != NULL) { | ||
669 | |||
670 | openpic_set_sources(0, 16, OpenPIC_Addr + 0x10000); | ||
671 | openpic_init(NUM_8259_INTERRUPTS); | ||
672 | openpic_hookup_cascade(NUM_8259_INTERRUPTS, "82c59 cascade", | ||
673 | i8259_irq); | ||
674 | ppc_md.get_irq = openpic_get_irq; | ||
675 | } | ||
676 | |||
677 | for (i = 0; i < NUM_8259_INTERRUPTS; i++) | ||
678 | irq_desc[i].handler = &i8259_pic; | ||
679 | |||
680 | i8259_init(0); | ||
681 | |||
682 | if (ppc_md.progress) | ||
683 | ppc_md.progress("init_irq: exit", 0); | ||
684 | } | ||
685 | |||
686 | #if defined(CONFIG_BLK_DEV_IDE) || defined(CONFIG_BLK_DEV_IDE_MODULE) | ||
687 | /* | ||
688 | * IDE stuff. | ||
689 | */ | ||
690 | static int pplus_ide_default_irq(unsigned long base) | ||
691 | { | ||
692 | switch (base) { | ||
693 | case 0x1f0: | ||
694 | return 14; | ||
695 | case 0x170: | ||
696 | return 15; | ||
697 | default: | ||
698 | return 0; | ||
699 | } | ||
700 | } | ||
701 | |||
702 | static unsigned long pplus_ide_default_io_base(int index) | ||
703 | { | ||
704 | switch (index) { | ||
705 | case 0: | ||
706 | return 0x1f0; | ||
707 | case 1: | ||
708 | return 0x170; | ||
709 | default: | ||
710 | return 0; | ||
711 | } | ||
712 | } | ||
713 | |||
714 | static void __init | ||
715 | pplus_ide_init_hwif_ports(hw_regs_t * hw, unsigned long data_port, | ||
716 | unsigned long ctrl_port, int *irq) | ||
717 | { | ||
718 | unsigned long reg = data_port; | ||
719 | int i; | ||
720 | |||
721 | for (i = IDE_DATA_OFFSET; i <= IDE_STATUS_OFFSET; i++) { | ||
722 | hw->io_ports[i] = reg; | ||
723 | reg += 1; | ||
724 | } | ||
725 | |||
726 | if (ctrl_port) | ||
727 | hw->io_ports[IDE_CONTROL_OFFSET] = ctrl_port; | ||
728 | else | ||
729 | hw->io_ports[IDE_CONTROL_OFFSET] = | ||
730 | hw->io_ports[IDE_DATA_OFFSET] + 0x206; | ||
731 | |||
732 | if (irq != NULL) | ||
733 | *irq = pplus_ide_default_irq(data_port); | ||
734 | } | ||
735 | #endif | ||
736 | |||
737 | #ifdef CONFIG_SMP | ||
738 | /* PowerPlus (MTX) support */ | ||
739 | static int __init smp_pplus_probe(void) | ||
740 | { | ||
741 | extern int mot_multi; | ||
742 | |||
743 | if (mot_multi) { | ||
744 | openpic_request_IPIs(); | ||
745 | smp_hw_index[1] = 1; | ||
746 | return 2; | ||
747 | } | ||
748 | |||
749 | return 1; | ||
750 | } | ||
751 | |||
752 | static void __init smp_pplus_kick_cpu(int nr) | ||
753 | { | ||
754 | *(unsigned long *)KERNELBASE = nr; | ||
755 | asm volatile ("dcbf 0,%0"::"r" (KERNELBASE):"memory"); | ||
756 | printk(KERN_INFO "CPU1 reset, waiting\n"); | ||
757 | } | ||
758 | |||
759 | static void __init smp_pplus_setup_cpu(int cpu_nr) | ||
760 | { | ||
761 | if (OpenPIC_Addr) | ||
762 | do_openpic_setup_cpu(); | ||
763 | } | ||
764 | |||
765 | static struct smp_ops_t pplus_smp_ops = { | ||
766 | smp_openpic_message_pass, | ||
767 | smp_pplus_probe, | ||
768 | smp_pplus_kick_cpu, | ||
769 | smp_pplus_setup_cpu, | ||
770 | .give_timebase = smp_generic_give_timebase, | ||
771 | .take_timebase = smp_generic_take_timebase, | ||
772 | }; | ||
773 | #endif /* CONFIG_SMP */ | ||
774 | |||
775 | #ifdef DUMP_DBATS | ||
776 | static void print_dbat(int idx, u32 bat) | ||
777 | { | ||
778 | |||
779 | char str[64]; | ||
780 | |||
781 | sprintf(str, "DBAT%c%c = 0x%08x\n", | ||
782 | (char)((idx - DBAT0U) / 2) + '0', (idx & 1) ? 'L' : 'U', bat); | ||
783 | ppc_md.progress(str, 0); | ||
784 | } | ||
785 | |||
786 | #define DUMP_DBAT(x) \ | ||
787 | do { \ | ||
788 | u32 __temp = mfspr(x);\ | ||
789 | print_dbat(x, __temp); \ | ||
790 | } while (0) | ||
791 | |||
792 | static void dump_dbats(void) | ||
793 | { | ||
794 | if (ppc_md.progress) { | ||
795 | DUMP_DBAT(DBAT0U); | ||
796 | DUMP_DBAT(DBAT0L); | ||
797 | DUMP_DBAT(DBAT1U); | ||
798 | DUMP_DBAT(DBAT1L); | ||
799 | DUMP_DBAT(DBAT2U); | ||
800 | DUMP_DBAT(DBAT2L); | ||
801 | DUMP_DBAT(DBAT3U); | ||
802 | DUMP_DBAT(DBAT3L); | ||
803 | } | ||
804 | } | ||
805 | #endif | ||
806 | |||
807 | static unsigned long __init pplus_find_end_of_memory(void) | ||
808 | { | ||
809 | unsigned long total; | ||
810 | |||
811 | if (ppc_md.progress) | ||
812 | ppc_md.progress("pplus_find_end_of_memory", 0); | ||
813 | |||
814 | #ifdef DUMP_DBATS | ||
815 | dump_dbats(); | ||
816 | #endif | ||
817 | |||
818 | total = hawk_get_mem_size(PPLUS_HAWK_SMC_BASE); | ||
819 | return (total); | ||
820 | } | ||
821 | |||
822 | static void __init pplus_map_io(void) | ||
823 | { | ||
824 | io_block_mapping(PPLUS_ISA_IO_BASE, PPLUS_ISA_IO_BASE, 0x10000000, | ||
825 | _PAGE_IO); | ||
826 | io_block_mapping(0xfef80000, 0xfef80000, 0x00080000, _PAGE_IO); | ||
827 | } | ||
828 | |||
829 | static void __init pplus_init2(void) | ||
830 | { | ||
831 | #ifdef CONFIG_NVRAM | ||
832 | request_region(PREP_NVRAM_AS0, 0x8, "nvram"); | ||
833 | #endif | ||
834 | request_region(0x20, 0x20, "pic1"); | ||
835 | request_region(0xa0, 0x20, "pic2"); | ||
836 | request_region(0x00, 0x20, "dma1"); | ||
837 | request_region(0x40, 0x20, "timer"); | ||
838 | request_region(0x80, 0x10, "dma page reg"); | ||
839 | request_region(0xc0, 0x20, "dma2"); | ||
840 | } | ||
841 | |||
842 | /* | ||
843 | * Set BAT 2 to access 0x8000000 so progress messages will work and set BAT 3 | ||
844 | * to 0xf0000000 to access Falcon/Raven or Hawk registers | ||
845 | */ | ||
846 | static __inline__ void pplus_set_bat(void) | ||
847 | { | ||
848 | /* wait for all outstanding memory accesses to complete */ | ||
849 | mb(); | ||
850 | |||
851 | /* setup DBATs */ | ||
852 | mtspr(SPRN_DBAT2U, 0x80001ffe); | ||
853 | mtspr(SPRN_DBAT2L, 0x8000002a); | ||
854 | mtspr(SPRN_DBAT3U, 0xf0001ffe); | ||
855 | mtspr(SPRN_DBAT3L, 0xf000002a); | ||
856 | |||
857 | /* wait for updates */ | ||
858 | mb(); | ||
859 | } | ||
860 | |||
861 | void __init | ||
862 | platform_init(unsigned long r3, unsigned long r4, unsigned long r5, | ||
863 | unsigned long r6, unsigned long r7) | ||
864 | { | ||
865 | parse_bootinfo(find_bootinfo()); | ||
866 | |||
867 | /* Map in board regs, etc. */ | ||
868 | pplus_set_bat(); | ||
869 | |||
870 | isa_io_base = PREP_ISA_IO_BASE; | ||
871 | isa_mem_base = PREP_ISA_MEM_BASE; | ||
872 | pci_dram_offset = PREP_PCI_DRAM_OFFSET; | ||
873 | ISA_DMA_THRESHOLD = 0x00ffffff; | ||
874 | DMA_MODE_READ = 0x44; | ||
875 | DMA_MODE_WRITE = 0x48; | ||
876 | |||
877 | ppc_md.setup_arch = pplus_setup_arch; | ||
878 | ppc_md.show_cpuinfo = pplus_show_cpuinfo; | ||
879 | ppc_md.irq_canonicalize = pplus_irq_canonicalize; | ||
880 | ppc_md.init_IRQ = pplus_init_IRQ; | ||
881 | /* this gets changed later on if we have an OpenPIC -- Cort */ | ||
882 | ppc_md.get_irq = i8259_irq; | ||
883 | ppc_md.init = pplus_init2; | ||
884 | |||
885 | ppc_md.restart = pplus_restart; | ||
886 | ppc_md.power_off = pplus_power_off; | ||
887 | ppc_md.halt = pplus_halt; | ||
888 | |||
889 | TODC_INIT(TODC_TYPE_MK48T59, PREP_NVRAM_AS0, PREP_NVRAM_AS1, | ||
890 | PREP_NVRAM_DATA, 8); | ||
891 | |||
892 | ppc_md.time_init = todc_time_init; | ||
893 | ppc_md.set_rtc_time = todc_set_rtc_time; | ||
894 | ppc_md.get_rtc_time = todc_get_rtc_time; | ||
895 | ppc_md.calibrate_decr = todc_calibrate_decr; | ||
896 | ppc_md.nvram_read_val = todc_m48txx_read_val; | ||
897 | ppc_md.nvram_write_val = todc_m48txx_write_val; | ||
898 | |||
899 | ppc_md.find_end_of_memory = pplus_find_end_of_memory; | ||
900 | ppc_md.setup_io_mappings = pplus_map_io; | ||
901 | |||
902 | #if defined(CONFIG_BLK_DEV_IDE) || defined(CONFIG_BLK_DEV_IDE_MODULE) | ||
903 | ppc_ide_md.default_irq = pplus_ide_default_irq; | ||
904 | ppc_ide_md.default_io_base = pplus_ide_default_io_base; | ||
905 | ppc_ide_md.ide_init_hwif = pplus_ide_init_hwif_ports; | ||
906 | #endif | ||
907 | |||
908 | #ifdef CONFIG_SERIAL_TEXT_DEBUG | ||
909 | ppc_md.progress = gen550_progress; | ||
910 | #endif /* CONFIG_SERIAL_TEXT_DEBUG */ | ||
911 | #ifdef CONFIG_KGDB | ||
912 | ppc_md.kgdb_map_scc = gen550_kgdb_map_scc; | ||
913 | #endif | ||
914 | #ifdef CONFIG_SMP | ||
915 | ppc_md.smp_ops = &pplus_smp_ops; | ||
916 | #endif /* CONFIG_SMP */ | ||
917 | } | ||
diff --git a/arch/ppc/platforms/pplus.h b/arch/ppc/platforms/pplus.h new file mode 100644 index 000000000000..90f0cb2d409f --- /dev/null +++ b/arch/ppc/platforms/pplus.h | |||
@@ -0,0 +1,67 @@ | |||
1 | /* | ||
2 | * arch/ppc/platforms/pplus.h | ||
3 | * | ||
4 | * Definitions for Motorola MCG Falcon/Raven & HAWK North Bridge & Memory ctlr. | ||
5 | * | ||
6 | * Author: Mark A. Greerinclude/asm-ppc/hawk.h | ||
7 | * mgreer@mvista.com | ||
8 | * | ||
9 | * Modified by Randy Vinson (rvinson@mvista.com) | ||
10 | * | ||
11 | * 2001-2004 (c) MontaVista, Software, Inc. This file is licensed under | ||
12 | * the terms of the GNU General Public License version 2. This program | ||
13 | * is licensed "as is" without any warranty of any kind, whether express | ||
14 | * or implied. | ||
15 | */ | ||
16 | |||
17 | #ifndef __PPC_PPLUS_H | ||
18 | #define __PPC_PPLUS_H | ||
19 | |||
20 | #include <asm/io.h> | ||
21 | |||
22 | /* | ||
23 | * Due to limiations imposed by legacy hardware (primaryily IDE controllers), | ||
24 | * the PPLUS boards operate using a PReP address map. | ||
25 | * | ||
26 | * From Processor (physical) -> PCI: | ||
27 | * PCI Mem Space: 0xc0000000 - 0xfe000000 -> 0x00000000 - 0x3e000000 (768 MB) | ||
28 | * PCI I/O Space: 0x80000000 - 0x90000000 -> 0x00000000 - 0x10000000 (256 MB) | ||
29 | * Note: Must skip 0xfe000000-0xfe400000 for CONFIG_HIGHMEM/PKMAP area | ||
30 | * | ||
31 | * From PCI -> Processor (physical): | ||
32 | * System Memory: 0x80000000 -> 0x00000000 | ||
33 | */ | ||
34 | |||
35 | #define PPLUS_ISA_MEM_BASE PREP_ISA_MEM_BASE | ||
36 | #define PPLUS_ISA_IO_BASE PREP_ISA_IO_BASE | ||
37 | |||
38 | /* PCI Memory space mapping info */ | ||
39 | #define PPLUS_PCI_MEM_SIZE 0x30000000U | ||
40 | #define PPLUS_PROC_PCI_MEM_START PPLUS_ISA_MEM_BASE | ||
41 | #define PPLUS_PROC_PCI_MEM_END (PPLUS_PROC_PCI_MEM_START + \ | ||
42 | PPLUS_PCI_MEM_SIZE - 1) | ||
43 | #define PPLUS_PCI_MEM_START 0x00000000U | ||
44 | #define PPLUS_PCI_MEM_END (PPLUS_PCI_MEM_START + \ | ||
45 | PPLUS_PCI_MEM_SIZE - 1) | ||
46 | |||
47 | /* PCI I/O space mapping info */ | ||
48 | #define PPLUS_PCI_IO_SIZE 0x10000000U | ||
49 | #define PPLUS_PROC_PCI_IO_START PPLUS_ISA_IO_BASE | ||
50 | #define PPLUS_PROC_PCI_IO_END (PPLUS_PROC_PCI_IO_START + \ | ||
51 | PPLUS_PCI_IO_SIZE - 1) | ||
52 | #define PPLUS_PCI_IO_START 0x00000000U | ||
53 | #define PPLUS_PCI_IO_END (PPLUS_PCI_IO_START + \ | ||
54 | PPLUS_PCI_IO_SIZE - 1) | ||
55 | /* System memory mapping info */ | ||
56 | #define PPLUS_PCI_DRAM_OFFSET PREP_PCI_DRAM_OFFSET | ||
57 | #define PPLUS_PCI_PHY_MEM_OFFSET (PPLUS_ISA_MEM_BASE-PPLUS_PCI_MEM_START) | ||
58 | |||
59 | /* Define base addresses for important sets of registers */ | ||
60 | #define PPLUS_HAWK_SMC_BASE 0xfef80000U | ||
61 | #define PPLUS_HAWK_PPC_REG_BASE 0xfeff0000U | ||
62 | #define PPLUS_SYS_CONFIG_REG 0xfef80400U | ||
63 | #define PPLUS_L2_CONTROL_REG 0x8000081cU | ||
64 | |||
65 | #define PPLUS_VGA_MEM_BASE 0xf0000000U | ||
66 | |||
67 | #endif /* __PPC_PPLUS_H */ | ||
diff --git a/arch/ppc/platforms/pq2ads.c b/arch/ppc/platforms/pq2ads.c new file mode 100644 index 000000000000..6a1475c1e128 --- /dev/null +++ b/arch/ppc/platforms/pq2ads.c | |||
@@ -0,0 +1,26 @@ | |||
1 | /* | ||
2 | * arch/ppc/platforms/pq2ads.c | ||
3 | * | ||
4 | * PQ2ADS platform support | ||
5 | * | ||
6 | * Author: Kumar Gala <kumar.gala@freescale.com> | ||
7 | * Derived from: est8260_setup.c by Allen Curtis | ||
8 | * | ||
9 | * Copyright 2004 Freescale Semiconductor, Inc. | ||
10 | * | ||
11 | * This program is free software; you can redistribute it and/or modify it | ||
12 | * under the terms of the GNU General Public License as published by the | ||
13 | * Free Software Foundation; either version 2 of the License, or (at your | ||
14 | * option) any later version. | ||
15 | */ | ||
16 | |||
17 | #include <linux/init.h> | ||
18 | |||
19 | #include <asm/mpc8260.h> | ||
20 | |||
21 | void __init | ||
22 | m82xx_board_setup(void) | ||
23 | { | ||
24 | /* Enable the 2nd UART port */ | ||
25 | *(volatile uint *)(BCSR_ADDR + 4) &= ~BCSR1_RS232_EN2; | ||
26 | } | ||
diff --git a/arch/ppc/platforms/pq2ads.h b/arch/ppc/platforms/pq2ads.h new file mode 100644 index 000000000000..cf5e5dd06d63 --- /dev/null +++ b/arch/ppc/platforms/pq2ads.h | |||
@@ -0,0 +1,96 @@ | |||
1 | /* | ||
2 | * A collection of structures, addresses, and values associated with | ||
3 | * the Motorola MPC8260ADS/MPC8266ADS-PCI boards. | ||
4 | * Copied from the RPX-Classic and SBS8260 stuff. | ||
5 | * | ||
6 | * Copyright (c) 2001 Dan Malek (dan@mvista.com) | ||
7 | */ | ||
8 | #ifdef __KERNEL__ | ||
9 | #ifndef __MACH_ADS8260_DEFS | ||
10 | #define __MACH_ADS8260_DEFS | ||
11 | |||
12 | #include <linux/config.h> | ||
13 | |||
14 | #include <asm/ppcboot.h> | ||
15 | |||
16 | /* Memory map is configured by the PROM startup. | ||
17 | * We just map a few things we need. The CSR is actually 4 byte-wide | ||
18 | * registers that can be accessed as 8-, 16-, or 32-bit values. | ||
19 | */ | ||
20 | #define CPM_MAP_ADDR ((uint)0xf0000000) | ||
21 | #define BCSR_ADDR ((uint)0xf4500000) | ||
22 | #define BCSR_SIZE ((uint)(32 * 1024)) | ||
23 | |||
24 | #define BOOTROM_RESTART_ADDR ((uint)0xff000104) | ||
25 | |||
26 | /* For our show_cpuinfo hooks. */ | ||
27 | #define CPUINFO_VENDOR "Motorola" | ||
28 | #define CPUINFO_MACHINE "PQ2 ADS PowerPC" | ||
29 | |||
30 | /* The ADS8260 has 16, 32-bit wide control/status registers, accessed | ||
31 | * only on word boundaries. | ||
32 | * Not all are used (yet), or are interesting to us (yet). | ||
33 | */ | ||
34 | |||
35 | /* Things of interest in the CSR. | ||
36 | */ | ||
37 | #define BCSR0_LED0 ((uint)0x02000000) /* 0 == on */ | ||
38 | #define BCSR0_LED1 ((uint)0x01000000) /* 0 == on */ | ||
39 | #define BCSR1_FETHIEN ((uint)0x08000000) /* 0 == enable */ | ||
40 | #define BCSR1_FETH_RST ((uint)0x04000000) /* 0 == reset */ | ||
41 | #define BCSR1_RS232_EN1 ((uint)0x02000000) /* 0 == enable */ | ||
42 | #define BCSR1_RS232_EN2 ((uint)0x01000000) /* 0 == enable */ | ||
43 | #define BCSR3_FETHIEN2 ((uint)0x10000000) /* 0 == enable */ | ||
44 | #define BCSR3_FETH2_RST ((uint)0x80000000) /* 0 == reset */ | ||
45 | |||
46 | #define PHY_INTERRUPT SIU_INT_IRQ7 | ||
47 | |||
48 | #ifdef CONFIG_PCI | ||
49 | /* PCI interrupt controller */ | ||
50 | #define PCI_INT_STAT_REG 0xF8200000 | ||
51 | #define PCI_INT_MASK_REG 0xF8200004 | ||
52 | #define PIRQA (NR_SIU_INTS + 0) | ||
53 | #define PIRQB (NR_SIU_INTS + 1) | ||
54 | #define PIRQC (NR_SIU_INTS + 2) | ||
55 | #define PIRQD (NR_SIU_INTS + 3) | ||
56 | |||
57 | /* | ||
58 | * PCI memory map definitions for MPC8266ADS-PCI. | ||
59 | * | ||
60 | * processor view | ||
61 | * local address PCI address target | ||
62 | * 0x80000000-0x9FFFFFFF 0x80000000-0x9FFFFFFF PCI mem with prefetch | ||
63 | * 0xA0000000-0xBFFFFFFF 0xA0000000-0xBFFFFFFF PCI mem w/o prefetch | ||
64 | * 0xF4000000-0xF7FFFFFF 0x00000000-0x03FFFFFF PCI IO | ||
65 | * | ||
66 | * PCI master view | ||
67 | * local address PCI address target | ||
68 | * 0x00000000-0x1FFFFFFF 0x00000000-0x1FFFFFFF MPC8266 local memory | ||
69 | */ | ||
70 | |||
71 | /* window for a PCI master to access MPC8266 memory */ | ||
72 | #define PCI_SLV_MEM_LOCAL 0x00000000 /* Local base */ | ||
73 | #define PCI_SLV_MEM_BUS 0x00000000 /* PCI base */ | ||
74 | |||
75 | /* window for the processor to access PCI memory with prefetching */ | ||
76 | #define PCI_MSTR_MEM_LOCAL 0x80000000 /* Local base */ | ||
77 | #define PCI_MSTR_MEM_BUS 0x80000000 /* PCI base */ | ||
78 | #define PCI_MSTR_MEM_SIZE 0x20000000 /* 512MB */ | ||
79 | |||
80 | /* window for the processor to access PCI memory without prefetching */ | ||
81 | #define PCI_MSTR_MEMIO_LOCAL 0xA0000000 /* Local base */ | ||
82 | #define PCI_MSTR_MEMIO_BUS 0xA0000000 /* PCI base */ | ||
83 | #define PCI_MSTR_MEMIO_SIZE 0x20000000 /* 512MB */ | ||
84 | |||
85 | /* window for the processor to access PCI I/O */ | ||
86 | #define PCI_MSTR_IO_LOCAL 0xF4000000 /* Local base */ | ||
87 | #define PCI_MSTR_IO_BUS 0x00000000 /* PCI base */ | ||
88 | #define PCI_MSTR_IO_SIZE 0x04000000 /* 64MB */ | ||
89 | |||
90 | #define _IO_BASE PCI_MSTR_IO_LOCAL | ||
91 | #define _ISA_MEM_BASE PCI_MSTR_MEMIO_LOCAL | ||
92 | #define PCI_DRAM_OFFSET PCI_SLV_MEM_BUS | ||
93 | #endif /* CONFIG_PCI */ | ||
94 | |||
95 | #endif /* __MACH_ADS8260_DEFS */ | ||
96 | #endif /* __KERNEL__ */ | ||
diff --git a/arch/ppc/platforms/prep_pci.c b/arch/ppc/platforms/prep_pci.c new file mode 100644 index 000000000000..8cd80eb447bd --- /dev/null +++ b/arch/ppc/platforms/prep_pci.c | |||
@@ -0,0 +1,1336 @@ | |||
1 | /* | ||
2 | * PReP pci functions. | ||
3 | * Originally by Gary Thomas | ||
4 | * rewritten and updated by Cort Dougan (cort@cs.nmt.edu) | ||
5 | * | ||
6 | * The motherboard routes/maps will disappear shortly. -- Cort | ||
7 | */ | ||
8 | |||
9 | #include <linux/config.h> | ||
10 | #include <linux/types.h> | ||
11 | #include <linux/pci.h> | ||
12 | #include <linux/kernel.h> | ||
13 | #include <linux/init.h> | ||
14 | |||
15 | #include <asm/sections.h> | ||
16 | #include <asm/byteorder.h> | ||
17 | #include <asm/io.h> | ||
18 | #include <asm/ptrace.h> | ||
19 | #include <asm/prom.h> | ||
20 | #include <asm/pci-bridge.h> | ||
21 | #include <asm/residual.h> | ||
22 | #include <asm/irq.h> | ||
23 | #include <asm/machdep.h> | ||
24 | #include <asm/open_pic.h> | ||
25 | |||
26 | extern void (*setup_ibm_pci)(char *irq_lo, char *irq_hi); | ||
27 | |||
28 | /* Which PCI interrupt line does a given device [slot] use? */ | ||
29 | /* Note: This really should be two dimensional based in slot/pin used */ | ||
30 | static unsigned char *Motherboard_map; | ||
31 | unsigned char *Motherboard_map_name; | ||
32 | |||
33 | /* How is the 82378 PIRQ mapping setup? */ | ||
34 | static unsigned char *Motherboard_routes; | ||
35 | |||
36 | static void (*Motherboard_non0)(struct pci_dev *); | ||
37 | |||
38 | static void Powerplus_Map_Non0(struct pci_dev *); | ||
39 | |||
40 | /* Used for Motorola to store system config register */ | ||
41 | static unsigned long *ProcInfo; | ||
42 | |||
43 | /* Tables for known hardware */ | ||
44 | |||
45 | /* Motorola PowerStackII - Utah */ | ||
46 | static char Utah_pci_IRQ_map[23] __prepdata = | ||
47 | { | ||
48 | 0, /* Slot 0 - unused */ | ||
49 | 0, /* Slot 1 - unused */ | ||
50 | 5, /* Slot 2 - SCSI - NCR825A */ | ||
51 | 0, /* Slot 3 - unused */ | ||
52 | 3, /* Slot 4 - Ethernet - DEC2114x */ | ||
53 | 0, /* Slot 5 - unused */ | ||
54 | 2, /* Slot 6 - PCI Card slot #1 */ | ||
55 | 3, /* Slot 7 - PCI Card slot #2 */ | ||
56 | 5, /* Slot 8 - PCI Card slot #3 */ | ||
57 | 5, /* Slot 9 - PCI Bridge */ | ||
58 | /* added here in case we ever support PCI bridges */ | ||
59 | /* Secondary PCI bus cards are at slot-9,6 & slot-9,7 */ | ||
60 | 0, /* Slot 10 - unused */ | ||
61 | 0, /* Slot 11 - unused */ | ||
62 | 5, /* Slot 12 - SCSI - NCR825A */ | ||
63 | 0, /* Slot 13 - unused */ | ||
64 | 3, /* Slot 14 - enet */ | ||
65 | 0, /* Slot 15 - unused */ | ||
66 | 2, /* Slot 16 - unused */ | ||
67 | 3, /* Slot 17 - unused */ | ||
68 | 5, /* Slot 18 - unused */ | ||
69 | 0, /* Slot 19 - unused */ | ||
70 | 0, /* Slot 20 - unused */ | ||
71 | 0, /* Slot 21 - unused */ | ||
72 | 0, /* Slot 22 - unused */ | ||
73 | }; | ||
74 | |||
75 | static char Utah_pci_IRQ_routes[] __prepdata = | ||
76 | { | ||
77 | 0, /* Line 0 - Unused */ | ||
78 | 9, /* Line 1 */ | ||
79 | 10, /* Line 2 */ | ||
80 | 11, /* Line 3 */ | ||
81 | 14, /* Line 4 */ | ||
82 | 15, /* Line 5 */ | ||
83 | }; | ||
84 | |||
85 | /* Motorola PowerStackII - Omaha */ | ||
86 | /* no integrated SCSI or ethernet */ | ||
87 | static char Omaha_pci_IRQ_map[23] __prepdata = | ||
88 | { | ||
89 | 0, /* Slot 0 - unused */ | ||
90 | 0, /* Slot 1 - unused */ | ||
91 | 3, /* Slot 2 - Winbond EIDE */ | ||
92 | 0, /* Slot 3 - unused */ | ||
93 | 0, /* Slot 4 - unused */ | ||
94 | 0, /* Slot 5 - unused */ | ||
95 | 1, /* Slot 6 - PCI slot 1 */ | ||
96 | 2, /* Slot 7 - PCI slot 2 */ | ||
97 | 3, /* Slot 8 - PCI slot 3 */ | ||
98 | 4, /* Slot 9 - PCI slot 4 */ /* needs indirect access */ | ||
99 | 0, /* Slot 10 - unused */ | ||
100 | 0, /* Slot 11 - unused */ | ||
101 | 0, /* Slot 12 - unused */ | ||
102 | 0, /* Slot 13 - unused */ | ||
103 | 0, /* Slot 14 - unused */ | ||
104 | 0, /* Slot 15 - unused */ | ||
105 | 1, /* Slot 16 - PCI slot 1 */ | ||
106 | 2, /* Slot 17 - PCI slot 2 */ | ||
107 | 3, /* Slot 18 - PCI slot 3 */ | ||
108 | 4, /* Slot 19 - PCI slot 4 */ /* needs indirect access */ | ||
109 | 0, | ||
110 | 0, | ||
111 | 0, | ||
112 | }; | ||
113 | |||
114 | static char Omaha_pci_IRQ_routes[] __prepdata = | ||
115 | { | ||
116 | 0, /* Line 0 - Unused */ | ||
117 | 9, /* Line 1 */ | ||
118 | 11, /* Line 2 */ | ||
119 | 14, /* Line 3 */ | ||
120 | 15 /* Line 4 */ | ||
121 | }; | ||
122 | |||
123 | /* Motorola PowerStack */ | ||
124 | static char Blackhawk_pci_IRQ_map[19] __prepdata = | ||
125 | { | ||
126 | 0, /* Slot 0 - unused */ | ||
127 | 0, /* Slot 1 - unused */ | ||
128 | 0, /* Slot 2 - unused */ | ||
129 | 0, /* Slot 3 - unused */ | ||
130 | 0, /* Slot 4 - unused */ | ||
131 | 0, /* Slot 5 - unused */ | ||
132 | 0, /* Slot 6 - unused */ | ||
133 | 0, /* Slot 7 - unused */ | ||
134 | 0, /* Slot 8 - unused */ | ||
135 | 0, /* Slot 9 - unused */ | ||
136 | 0, /* Slot 10 - unused */ | ||
137 | 0, /* Slot 11 - unused */ | ||
138 | 3, /* Slot 12 - SCSI */ | ||
139 | 0, /* Slot 13 - unused */ | ||
140 | 1, /* Slot 14 - Ethernet */ | ||
141 | 0, /* Slot 15 - unused */ | ||
142 | 1, /* Slot P7 */ | ||
143 | 2, /* Slot P6 */ | ||
144 | 3, /* Slot P5 */ | ||
145 | }; | ||
146 | |||
147 | static char Blackhawk_pci_IRQ_routes[] __prepdata = | ||
148 | { | ||
149 | 0, /* Line 0 - Unused */ | ||
150 | 9, /* Line 1 */ | ||
151 | 11, /* Line 2 */ | ||
152 | 15, /* Line 3 */ | ||
153 | 15 /* Line 4 */ | ||
154 | }; | ||
155 | |||
156 | /* Motorola Mesquite */ | ||
157 | static char Mesquite_pci_IRQ_map[23] __prepdata = | ||
158 | { | ||
159 | 0, /* Slot 0 - unused */ | ||
160 | 0, /* Slot 1 - unused */ | ||
161 | 0, /* Slot 2 - unused */ | ||
162 | 0, /* Slot 3 - unused */ | ||
163 | 0, /* Slot 4 - unused */ | ||
164 | 0, /* Slot 5 - unused */ | ||
165 | 0, /* Slot 6 - unused */ | ||
166 | 0, /* Slot 7 - unused */ | ||
167 | 0, /* Slot 8 - unused */ | ||
168 | 0, /* Slot 9 - unused */ | ||
169 | 0, /* Slot 10 - unused */ | ||
170 | 0, /* Slot 11 - unused */ | ||
171 | 0, /* Slot 12 - unused */ | ||
172 | 0, /* Slot 13 - unused */ | ||
173 | 2, /* Slot 14 - Ethernet */ | ||
174 | 0, /* Slot 15 - unused */ | ||
175 | 3, /* Slot 16 - PMC */ | ||
176 | 0, /* Slot 17 - unused */ | ||
177 | 0, /* Slot 18 - unused */ | ||
178 | 0, /* Slot 19 - unused */ | ||
179 | 0, /* Slot 20 - unused */ | ||
180 | 0, /* Slot 21 - unused */ | ||
181 | 0, /* Slot 22 - unused */ | ||
182 | }; | ||
183 | |||
184 | /* Motorola Sitka */ | ||
185 | static char Sitka_pci_IRQ_map[21] __prepdata = | ||
186 | { | ||
187 | 0, /* Slot 0 - unused */ | ||
188 | 0, /* Slot 1 - unused */ | ||
189 | 0, /* Slot 2 - unused */ | ||
190 | 0, /* Slot 3 - unused */ | ||
191 | 0, /* Slot 4 - unused */ | ||
192 | 0, /* Slot 5 - unused */ | ||
193 | 0, /* Slot 6 - unused */ | ||
194 | 0, /* Slot 7 - unused */ | ||
195 | 0, /* Slot 8 - unused */ | ||
196 | 0, /* Slot 9 - unused */ | ||
197 | 0, /* Slot 10 - unused */ | ||
198 | 0, /* Slot 11 - unused */ | ||
199 | 0, /* Slot 12 - unused */ | ||
200 | 0, /* Slot 13 - unused */ | ||
201 | 2, /* Slot 14 - Ethernet */ | ||
202 | 0, /* Slot 15 - unused */ | ||
203 | 9, /* Slot 16 - PMC 1 */ | ||
204 | 12, /* Slot 17 - PMC 2 */ | ||
205 | 0, /* Slot 18 - unused */ | ||
206 | 0, /* Slot 19 - unused */ | ||
207 | 4, /* Slot 20 - NT P2P bridge */ | ||
208 | }; | ||
209 | |||
210 | /* Motorola MTX */ | ||
211 | static char MTX_pci_IRQ_map[23] __prepdata = | ||
212 | { | ||
213 | 0, /* Slot 0 - unused */ | ||
214 | 0, /* Slot 1 - unused */ | ||
215 | 0, /* Slot 2 - unused */ | ||
216 | 0, /* Slot 3 - unused */ | ||
217 | 0, /* Slot 4 - unused */ | ||
218 | 0, /* Slot 5 - unused */ | ||
219 | 0, /* Slot 6 - unused */ | ||
220 | 0, /* Slot 7 - unused */ | ||
221 | 0, /* Slot 8 - unused */ | ||
222 | 0, /* Slot 9 - unused */ | ||
223 | 0, /* Slot 10 - unused */ | ||
224 | 0, /* Slot 11 - unused */ | ||
225 | 3, /* Slot 12 - SCSI */ | ||
226 | 0, /* Slot 13 - unused */ | ||
227 | 2, /* Slot 14 - Ethernet */ | ||
228 | 0, /* Slot 15 - unused */ | ||
229 | 9, /* Slot 16 - PCI/PMC slot 1 */ | ||
230 | 10, /* Slot 17 - PCI/PMC slot 2 */ | ||
231 | 11, /* Slot 18 - PCI slot 3 */ | ||
232 | 0, /* Slot 19 - unused */ | ||
233 | 0, /* Slot 20 - unused */ | ||
234 | 0, /* Slot 21 - unused */ | ||
235 | 0, /* Slot 22 - unused */ | ||
236 | }; | ||
237 | |||
238 | /* Motorola MTX Plus */ | ||
239 | /* Secondary bus interrupt routing is not supported yet */ | ||
240 | static char MTXplus_pci_IRQ_map[23] __prepdata = | ||
241 | { | ||
242 | 0, /* Slot 0 - unused */ | ||
243 | 0, /* Slot 1 - unused */ | ||
244 | 0, /* Slot 2 - unused */ | ||
245 | 0, /* Slot 3 - unused */ | ||
246 | 0, /* Slot 4 - unused */ | ||
247 | 0, /* Slot 5 - unused */ | ||
248 | 0, /* Slot 6 - unused */ | ||
249 | 0, /* Slot 7 - unused */ | ||
250 | 0, /* Slot 8 - unused */ | ||
251 | 0, /* Slot 9 - unused */ | ||
252 | 0, /* Slot 10 - unused */ | ||
253 | 0, /* Slot 11 - unused */ | ||
254 | 3, /* Slot 12 - SCSI */ | ||
255 | 0, /* Slot 13 - unused */ | ||
256 | 2, /* Slot 14 - Ethernet 1 */ | ||
257 | 0, /* Slot 15 - unused */ | ||
258 | 9, /* Slot 16 - PCI slot 1P */ | ||
259 | 10, /* Slot 17 - PCI slot 2P */ | ||
260 | 11, /* Slot 18 - PCI slot 3P */ | ||
261 | 10, /* Slot 19 - Ethernet 2 */ | ||
262 | 0, /* Slot 20 - P2P Bridge */ | ||
263 | 0, /* Slot 21 - unused */ | ||
264 | 0, /* Slot 22 - unused */ | ||
265 | }; | ||
266 | |||
267 | static char Raven_pci_IRQ_routes[] __prepdata = | ||
268 | { | ||
269 | 0, /* This is a dummy structure */ | ||
270 | }; | ||
271 | |||
272 | /* Motorola MVME16xx */ | ||
273 | static char Genesis_pci_IRQ_map[16] __prepdata = | ||
274 | { | ||
275 | 0, /* Slot 0 - unused */ | ||
276 | 0, /* Slot 1 - unused */ | ||
277 | 0, /* Slot 2 - unused */ | ||
278 | 0, /* Slot 3 - unused */ | ||
279 | 0, /* Slot 4 - unused */ | ||
280 | 0, /* Slot 5 - unused */ | ||
281 | 0, /* Slot 6 - unused */ | ||
282 | 0, /* Slot 7 - unused */ | ||
283 | 0, /* Slot 8 - unused */ | ||
284 | 0, /* Slot 9 - unused */ | ||
285 | 0, /* Slot 10 - unused */ | ||
286 | 0, /* Slot 11 - unused */ | ||
287 | 3, /* Slot 12 - SCSI */ | ||
288 | 0, /* Slot 13 - unused */ | ||
289 | 1, /* Slot 14 - Ethernet */ | ||
290 | 0, /* Slot 15 - unused */ | ||
291 | }; | ||
292 | |||
293 | static char Genesis_pci_IRQ_routes[] __prepdata = | ||
294 | { | ||
295 | 0, /* Line 0 - Unused */ | ||
296 | 10, /* Line 1 */ | ||
297 | 11, /* Line 2 */ | ||
298 | 14, /* Line 3 */ | ||
299 | 15 /* Line 4 */ | ||
300 | }; | ||
301 | |||
302 | static char Genesis2_pci_IRQ_map[23] __prepdata = | ||
303 | { | ||
304 | 0, /* Slot 0 - unused */ | ||
305 | 0, /* Slot 1 - unused */ | ||
306 | 0, /* Slot 2 - unused */ | ||
307 | 0, /* Slot 3 - unused */ | ||
308 | 0, /* Slot 4 - unused */ | ||
309 | 0, /* Slot 5 - unused */ | ||
310 | 0, /* Slot 6 - unused */ | ||
311 | 0, /* Slot 7 - unused */ | ||
312 | 0, /* Slot 8 - unused */ | ||
313 | 0, /* Slot 9 - unused */ | ||
314 | 0, /* Slot 10 - unused */ | ||
315 | 0, /* Slot 11 - IDE */ | ||
316 | 3, /* Slot 12 - SCSI */ | ||
317 | 5, /* Slot 13 - Universe PCI - VME Bridge */ | ||
318 | 2, /* Slot 14 - Ethernet */ | ||
319 | 0, /* Slot 15 - unused */ | ||
320 | 9, /* Slot 16 - PMC 1 */ | ||
321 | 12, /* Slot 17 - pci */ | ||
322 | 11, /* Slot 18 - pci */ | ||
323 | 10, /* Slot 19 - pci */ | ||
324 | 0, /* Slot 20 - pci */ | ||
325 | 0, /* Slot 21 - unused */ | ||
326 | 0, /* Slot 22 - unused */ | ||
327 | }; | ||
328 | |||
329 | /* Motorola Series-E */ | ||
330 | static char Comet_pci_IRQ_map[23] __prepdata = | ||
331 | { | ||
332 | 0, /* Slot 0 - unused */ | ||
333 | 0, /* Slot 1 - unused */ | ||
334 | 0, /* Slot 2 - unused */ | ||
335 | 0, /* Slot 3 - unused */ | ||
336 | 0, /* Slot 4 - unused */ | ||
337 | 0, /* Slot 5 - unused */ | ||
338 | 0, /* Slot 6 - unused */ | ||
339 | 0, /* Slot 7 - unused */ | ||
340 | 0, /* Slot 8 - unused */ | ||
341 | 0, /* Slot 9 - unused */ | ||
342 | 0, /* Slot 10 - unused */ | ||
343 | 0, /* Slot 11 - unused */ | ||
344 | 3, /* Slot 12 - SCSI */ | ||
345 | 0, /* Slot 13 - unused */ | ||
346 | 1, /* Slot 14 - Ethernet */ | ||
347 | 0, /* Slot 15 - unused */ | ||
348 | 1, /* Slot 16 - PCI slot 1 */ | ||
349 | 2, /* Slot 17 - PCI slot 2 */ | ||
350 | 3, /* Slot 18 - PCI slot 3 */ | ||
351 | 4, /* Slot 19 - PCI bridge */ | ||
352 | 0, | ||
353 | 0, | ||
354 | 0, | ||
355 | }; | ||
356 | |||
357 | static char Comet_pci_IRQ_routes[] __prepdata = | ||
358 | { | ||
359 | 0, /* Line 0 - Unused */ | ||
360 | 10, /* Line 1 */ | ||
361 | 11, /* Line 2 */ | ||
362 | 14, /* Line 3 */ | ||
363 | 15 /* Line 4 */ | ||
364 | }; | ||
365 | |||
366 | /* Motorola Series-EX */ | ||
367 | static char Comet2_pci_IRQ_map[23] __prepdata = | ||
368 | { | ||
369 | 0, /* Slot 0 - unused */ | ||
370 | 0, /* Slot 1 - unused */ | ||
371 | 3, /* Slot 2 - SCSI - NCR825A */ | ||
372 | 0, /* Slot 3 - unused */ | ||
373 | 1, /* Slot 4 - Ethernet - DEC2104X */ | ||
374 | 0, /* Slot 5 - unused */ | ||
375 | 1, /* Slot 6 - PCI slot 1 */ | ||
376 | 2, /* Slot 7 - PCI slot 2 */ | ||
377 | 3, /* Slot 8 - PCI slot 3 */ | ||
378 | 4, /* Slot 9 - PCI bridge */ | ||
379 | 0, /* Slot 10 - unused */ | ||
380 | 0, /* Slot 11 - unused */ | ||
381 | 3, /* Slot 12 - SCSI - NCR825A */ | ||
382 | 0, /* Slot 13 - unused */ | ||
383 | 1, /* Slot 14 - Ethernet - DEC2104X */ | ||
384 | 0, /* Slot 15 - unused */ | ||
385 | 1, /* Slot 16 - PCI slot 1 */ | ||
386 | 2, /* Slot 17 - PCI slot 2 */ | ||
387 | 3, /* Slot 18 - PCI slot 3 */ | ||
388 | 4, /* Slot 19 - PCI bridge */ | ||
389 | 0, | ||
390 | 0, | ||
391 | 0, | ||
392 | }; | ||
393 | |||
394 | static char Comet2_pci_IRQ_routes[] __prepdata = | ||
395 | { | ||
396 | 0, /* Line 0 - Unused */ | ||
397 | 10, /* Line 1 */ | ||
398 | 11, /* Line 2 */ | ||
399 | 14, /* Line 3 */ | ||
400 | 15, /* Line 4 */ | ||
401 | }; | ||
402 | |||
403 | /* | ||
404 | * ibm 830 (and 850?). | ||
405 | * This is actually based on the Carolina motherboard | ||
406 | * -- Cort | ||
407 | */ | ||
408 | static char ibm8xx_pci_IRQ_map[23] __prepdata = { | ||
409 | 0, /* Slot 0 - unused */ | ||
410 | 0, /* Slot 1 - unused */ | ||
411 | 0, /* Slot 2 - unused */ | ||
412 | 0, /* Slot 3 - unused */ | ||
413 | 0, /* Slot 4 - unused */ | ||
414 | 0, /* Slot 5 - unused */ | ||
415 | 0, /* Slot 6 - unused */ | ||
416 | 0, /* Slot 7 - unused */ | ||
417 | 0, /* Slot 8 - unused */ | ||
418 | 0, /* Slot 9 - unused */ | ||
419 | 0, /* Slot 10 - unused */ | ||
420 | 0, /* Slot 11 - FireCoral */ | ||
421 | 4, /* Slot 12 - Ethernet PCIINTD# */ | ||
422 | 2, /* Slot 13 - PCI Slot #2 */ | ||
423 | 2, /* Slot 14 - S3 Video PCIINTD# */ | ||
424 | 0, /* Slot 15 - onboard SCSI (INDI) [1] */ | ||
425 | 3, /* Slot 16 - NCR58C810 RS6000 Only PCIINTC# */ | ||
426 | 0, /* Slot 17 - unused */ | ||
427 | 2, /* Slot 18 - PCI Slot 2 PCIINTx# (See below) */ | ||
428 | 0, /* Slot 19 - unused */ | ||
429 | 0, /* Slot 20 - unused */ | ||
430 | 0, /* Slot 21 - unused */ | ||
431 | 2, /* Slot 22 - PCI slot 1 PCIINTx# (See below) */ | ||
432 | }; | ||
433 | |||
434 | static char ibm8xx_pci_IRQ_routes[] __prepdata = { | ||
435 | 0, /* Line 0 - unused */ | ||
436 | 15, /* Line 1 */ | ||
437 | 15, /* Line 2 */ | ||
438 | 15, /* Line 3 */ | ||
439 | 15, /* Line 4 */ | ||
440 | }; | ||
441 | |||
442 | /* | ||
443 | * a 6015 ibm board | ||
444 | * -- Cort | ||
445 | */ | ||
446 | static char ibm6015_pci_IRQ_map[23] __prepdata = { | ||
447 | 0, /* Slot 0 - unused */ | ||
448 | 0, /* Slot 1 - unused */ | ||
449 | 0, /* Slot 2 - unused */ | ||
450 | 0, /* Slot 3 - unused */ | ||
451 | 0, /* Slot 4 - unused */ | ||
452 | 0, /* Slot 5 - unused */ | ||
453 | 0, /* Slot 6 - unused */ | ||
454 | 0, /* Slot 7 - unused */ | ||
455 | 0, /* Slot 8 - unused */ | ||
456 | 0, /* Slot 9 - unused */ | ||
457 | 0, /* Slot 10 - unused */ | ||
458 | 0, /* Slot 11 - */ | ||
459 | 1, /* Slot 12 - SCSI */ | ||
460 | 2, /* Slot 13 - */ | ||
461 | 2, /* Slot 14 - */ | ||
462 | 1, /* Slot 15 - */ | ||
463 | 1, /* Slot 16 - */ | ||
464 | 0, /* Slot 17 - */ | ||
465 | 2, /* Slot 18 - */ | ||
466 | 0, /* Slot 19 - */ | ||
467 | 0, /* Slot 20 - */ | ||
468 | 0, /* Slot 21 - */ | ||
469 | 2, /* Slot 22 - */ | ||
470 | }; | ||
471 | |||
472 | static char ibm6015_pci_IRQ_routes[] __prepdata = { | ||
473 | 0, /* Line 0 - unused */ | ||
474 | 13, /* Line 1 */ | ||
475 | 15, /* Line 2 */ | ||
476 | 15, /* Line 3 */ | ||
477 | 15, /* Line 4 */ | ||
478 | }; | ||
479 | |||
480 | |||
481 | /* IBM Nobis and Thinkpad 850 */ | ||
482 | static char Nobis_pci_IRQ_map[23] __prepdata ={ | ||
483 | 0, /* Slot 0 - unused */ | ||
484 | 0, /* Slot 1 - unused */ | ||
485 | 0, /* Slot 2 - unused */ | ||
486 | 0, /* Slot 3 - unused */ | ||
487 | 0, /* Slot 4 - unused */ | ||
488 | 0, /* Slot 5 - unused */ | ||
489 | 0, /* Slot 6 - unused */ | ||
490 | 0, /* Slot 7 - unused */ | ||
491 | 0, /* Slot 8 - unused */ | ||
492 | 0, /* Slot 9 - unused */ | ||
493 | 0, /* Slot 10 - unused */ | ||
494 | 0, /* Slot 11 - unused */ | ||
495 | 3, /* Slot 12 - SCSI */ | ||
496 | 0, /* Slot 13 - unused */ | ||
497 | 0, /* Slot 14 - unused */ | ||
498 | 0, /* Slot 15 - unused */ | ||
499 | }; | ||
500 | |||
501 | static char Nobis_pci_IRQ_routes[] __prepdata = { | ||
502 | 0, /* Line 0 - Unused */ | ||
503 | 13, /* Line 1 */ | ||
504 | 13, /* Line 2 */ | ||
505 | 13, /* Line 3 */ | ||
506 | 13 /* Line 4 */ | ||
507 | }; | ||
508 | |||
509 | /* | ||
510 | * IBM RS/6000 43p/140 -- paulus | ||
511 | * XXX we should get all this from the residual data | ||
512 | */ | ||
513 | static char ibm43p_pci_IRQ_map[23] __prepdata = { | ||
514 | 0, /* Slot 0 - unused */ | ||
515 | 0, /* Slot 1 - unused */ | ||
516 | 0, /* Slot 2 - unused */ | ||
517 | 0, /* Slot 3 - unused */ | ||
518 | 0, /* Slot 4 - unused */ | ||
519 | 0, /* Slot 5 - unused */ | ||
520 | 0, /* Slot 6 - unused */ | ||
521 | 0, /* Slot 7 - unused */ | ||
522 | 0, /* Slot 8 - unused */ | ||
523 | 0, /* Slot 9 - unused */ | ||
524 | 0, /* Slot 10 - unused */ | ||
525 | 0, /* Slot 11 - FireCoral ISA bridge */ | ||
526 | 6, /* Slot 12 - Ethernet */ | ||
527 | 0, /* Slot 13 - openpic */ | ||
528 | 0, /* Slot 14 - unused */ | ||
529 | 0, /* Slot 15 - unused */ | ||
530 | 7, /* Slot 16 - NCR58C825a onboard scsi */ | ||
531 | 0, /* Slot 17 - unused */ | ||
532 | 2, /* Slot 18 - PCI Slot 2 PCIINTx# (See below) */ | ||
533 | 0, /* Slot 19 - unused */ | ||
534 | 0, /* Slot 20 - unused */ | ||
535 | 0, /* Slot 21 - unused */ | ||
536 | 1, /* Slot 22 - PCI slot 1 PCIINTx# (See below) */ | ||
537 | }; | ||
538 | |||
539 | static char ibm43p_pci_IRQ_routes[] __prepdata = { | ||
540 | 0, /* Line 0 - unused */ | ||
541 | 15, /* Line 1 */ | ||
542 | 15, /* Line 2 */ | ||
543 | 15, /* Line 3 */ | ||
544 | 15, /* Line 4 */ | ||
545 | }; | ||
546 | |||
547 | /* Motorola PowerPlus architecture PCI IRQ tables */ | ||
548 | /* Interrupt line values for INTA-D on primary/secondary MPIC inputs */ | ||
549 | |||
550 | struct powerplus_irq_list | ||
551 | { | ||
552 | unsigned char primary[4]; /* INT A-D */ | ||
553 | unsigned char secondary[4]; /* INT A-D */ | ||
554 | }; | ||
555 | |||
556 | /* | ||
557 | * For standard PowerPlus boards, bus 0 PCI INTs A-D are routed to | ||
558 | * OpenPIC inputs 9-12. PCI INTs A-D from the on board P2P bridge | ||
559 | * are routed to OpenPIC inputs 5-8. These values are offset by | ||
560 | * 16 in the table to reflect the Linux kernel interrupt value. | ||
561 | */ | ||
562 | struct powerplus_irq_list Powerplus_pci_IRQ_list __prepdata = | ||
563 | { | ||
564 | {25, 26, 27, 28}, | ||
565 | {21, 22, 23, 24} | ||
566 | }; | ||
567 | |||
568 | /* | ||
569 | * For the MCP750 (system slot board), cPCI INTs A-D are routed to | ||
570 | * OpenPIC inputs 8-11 and the PMC INTs A-D are routed to OpenPIC | ||
571 | * input 3. On a hot swap MCP750, the companion card PCI INTs A-D | ||
572 | * are routed to OpenPIC inputs 12-15. These values are offset by | ||
573 | * 16 in the table to reflect the Linux kernel interrupt value. | ||
574 | */ | ||
575 | struct powerplus_irq_list Mesquite_pci_IRQ_list __prepdata = | ||
576 | { | ||
577 | {24, 25, 26, 27}, | ||
578 | {28, 29, 30, 31} | ||
579 | }; | ||
580 | |||
581 | /* | ||
582 | * This table represents the standard PCI swizzle defined in the | ||
583 | * PCI bus specification. | ||
584 | */ | ||
585 | static unsigned char prep_pci_intpins[4][4] __prepdata = | ||
586 | { | ||
587 | { 1, 2, 3, 4}, /* Buses 0, 4, 8, ... */ | ||
588 | { 2, 3, 4, 1}, /* Buses 1, 5, 9, ... */ | ||
589 | { 3, 4, 1, 2}, /* Buses 2, 6, 10 ... */ | ||
590 | { 4, 1, 2, 3}, /* Buses 3, 7, 11 ... */ | ||
591 | }; | ||
592 | |||
593 | /* We have to turn on LEVEL mode for changed IRQ's */ | ||
594 | /* All PCI IRQ's need to be level mode, so this should be something | ||
595 | * other than hard-coded as well... IRQ's are individually mappable | ||
596 | * to either edge or level. | ||
597 | */ | ||
598 | |||
599 | /* | ||
600 | * 8259 edge/level control definitions | ||
601 | */ | ||
602 | #define ISA8259_M_ELCR 0x4d0 | ||
603 | #define ISA8259_S_ELCR 0x4d1 | ||
604 | |||
605 | #define ELCRS_INT15_LVL 0x80 | ||
606 | #define ELCRS_INT14_LVL 0x40 | ||
607 | #define ELCRS_INT12_LVL 0x10 | ||
608 | #define ELCRS_INT11_LVL 0x08 | ||
609 | #define ELCRS_INT10_LVL 0x04 | ||
610 | #define ELCRS_INT9_LVL 0x02 | ||
611 | #define ELCRS_INT8_LVL 0x01 | ||
612 | #define ELCRM_INT7_LVL 0x80 | ||
613 | #define ELCRM_INT5_LVL 0x20 | ||
614 | |||
615 | #if 0 | ||
616 | /* | ||
617 | * PCI config space access. | ||
618 | */ | ||
619 | #define CFGADDR(dev) ((1<<(dev>>3)) | ((dev&7)<<8)) | ||
620 | #define DEVNO(dev) (dev>>3) | ||
621 | |||
622 | #define MIN_DEVNR 11 | ||
623 | #define MAX_DEVNR 22 | ||
624 | |||
625 | static int __prep | ||
626 | prep_read_config(struct pci_bus *bus, unsigned int devfn, int offset, | ||
627 | int len, u32 *val) | ||
628 | { | ||
629 | struct pci_controller *hose = bus->sysdata; | ||
630 | volatile void __iomem *cfg_data; | ||
631 | |||
632 | if (bus->number != 0 || DEVNO(devfn) < MIN_DEVNR | ||
633 | || DEVNO(devfn) > MAX_DEVNR) | ||
634 | return PCIBIOS_DEVICE_NOT_FOUND; | ||
635 | |||
636 | /* | ||
637 | * Note: the caller has already checked that offset is | ||
638 | * suitably aligned and that len is 1, 2 or 4. | ||
639 | */ | ||
640 | cfg_data = hose->cfg_data + CFGADDR(devfn) + offset; | ||
641 | switch (len) { | ||
642 | case 1: | ||
643 | *val = in_8(cfg_data); | ||
644 | break; | ||
645 | case 2: | ||
646 | *val = in_le16(cfg_data); | ||
647 | break; | ||
648 | default: | ||
649 | *val = in_le32(cfg_data); | ||
650 | break; | ||
651 | } | ||
652 | return PCIBIOS_SUCCESSFUL; | ||
653 | } | ||
654 | |||
655 | static int __prep | ||
656 | prep_write_config(struct pci_bus *bus, unsigned int devfn, int offset, | ||
657 | int len, u32 val) | ||
658 | { | ||
659 | struct pci_controller *hose = bus->sysdata; | ||
660 | volatile void __iomem *cfg_data; | ||
661 | |||
662 | if (bus->number != 0 || DEVNO(devfn) < MIN_DEVNR | ||
663 | || DEVNO(devfn) > MAX_DEVNR) | ||
664 | return PCIBIOS_DEVICE_NOT_FOUND; | ||
665 | |||
666 | /* | ||
667 | * Note: the caller has already checked that offset is | ||
668 | * suitably aligned and that len is 1, 2 or 4. | ||
669 | */ | ||
670 | cfg_data = hose->cfg_data + CFGADDR(devfn) + offset; | ||
671 | switch (len) { | ||
672 | case 1: | ||
673 | out_8(cfg_data, val); | ||
674 | break; | ||
675 | case 2: | ||
676 | out_le16(cfg_data, val); | ||
677 | break; | ||
678 | default: | ||
679 | out_le32(cfg_data, val); | ||
680 | break; | ||
681 | } | ||
682 | return PCIBIOS_SUCCESSFUL; | ||
683 | } | ||
684 | |||
685 | static struct pci_ops prep_pci_ops = | ||
686 | { | ||
687 | prep_read_config, | ||
688 | prep_write_config | ||
689 | }; | ||
690 | #endif | ||
691 | |||
692 | #define MOTOROLA_CPUTYPE_REG 0x800 | ||
693 | #define MOTOROLA_BASETYPE_REG 0x803 | ||
694 | #define MPIC_RAVEN_ID 0x48010000 | ||
695 | #define MPIC_HAWK_ID 0x48030000 | ||
696 | #define MOT_PROC2_BIT 0x800 | ||
697 | |||
698 | static u_char prep_openpic_initsenses[] __initdata = { | ||
699 | (IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE), /* MVME2600_INT_SIO */ | ||
700 | (IRQ_SENSE_EDGE | IRQ_POLARITY_NEGATIVE), /* MVME2600_INT_FALCN_ECC_ERR */ | ||
701 | (IRQ_SENSE_LEVEL | IRQ_POLARITY_NEGATIVE), /* MVME2600_INT_PCI_ETHERNET */ | ||
702 | (IRQ_SENSE_LEVEL | IRQ_POLARITY_NEGATIVE), /* MVME2600_INT_PCI_SCSI */ | ||
703 | (IRQ_SENSE_LEVEL | IRQ_POLARITY_NEGATIVE), /* MVME2600_INT_PCI_GRAPHICS */ | ||
704 | (IRQ_SENSE_LEVEL | IRQ_POLARITY_NEGATIVE), /* MVME2600_INT_PCI_VME0 */ | ||
705 | (IRQ_SENSE_LEVEL | IRQ_POLARITY_NEGATIVE), /* MVME2600_INT_PCI_VME1 */ | ||
706 | (IRQ_SENSE_LEVEL | IRQ_POLARITY_NEGATIVE), /* MVME2600_INT_PCI_VME2 */ | ||
707 | (IRQ_SENSE_LEVEL | IRQ_POLARITY_NEGATIVE), /* MVME2600_INT_PCI_VME3 */ | ||
708 | (IRQ_SENSE_LEVEL | IRQ_POLARITY_NEGATIVE), /* MVME2600_INT_PCI_INTA */ | ||
709 | (IRQ_SENSE_LEVEL | IRQ_POLARITY_NEGATIVE), /* MVME2600_INT_PCI_INTB */ | ||
710 | (IRQ_SENSE_LEVEL | IRQ_POLARITY_NEGATIVE), /* MVME2600_INT_PCI_INTC */ | ||
711 | (IRQ_SENSE_LEVEL | IRQ_POLARITY_NEGATIVE), /* MVME2600_INT_PCI_INTD */ | ||
712 | (IRQ_SENSE_LEVEL | IRQ_POLARITY_NEGATIVE), /* MVME2600_INT_LM_SIG0 */ | ||
713 | (IRQ_SENSE_LEVEL | IRQ_POLARITY_NEGATIVE), /* MVME2600_INT_LM_SIG1 */ | ||
714 | }; | ||
715 | |||
716 | #define MOT_RAVEN_PRESENT 0x1 | ||
717 | #define MOT_HAWK_PRESENT 0x2 | ||
718 | |||
719 | int mot_entry = -1; | ||
720 | int prep_keybd_present = 1; | ||
721 | int MotMPIC; | ||
722 | int mot_multi; | ||
723 | |||
724 | int __init | ||
725 | raven_init(void) | ||
726 | { | ||
727 | unsigned int devid; | ||
728 | unsigned int pci_membase; | ||
729 | unsigned char base_mod; | ||
730 | |||
731 | /* Check to see if the Raven chip exists. */ | ||
732 | if ( _prep_type != _PREP_Motorola) { | ||
733 | OpenPIC_Addr = NULL; | ||
734 | return 0; | ||
735 | } | ||
736 | |||
737 | /* Check to see if this board is a type that might have a Raven. */ | ||
738 | if ((inb(MOTOROLA_CPUTYPE_REG) & 0xF0) != 0xE0) { | ||
739 | OpenPIC_Addr = NULL; | ||
740 | return 0; | ||
741 | } | ||
742 | |||
743 | /* Check the first PCI device to see if it is a Raven. */ | ||
744 | early_read_config_dword(NULL, 0, 0, PCI_VENDOR_ID, &devid); | ||
745 | |||
746 | switch (devid & 0xffff0000) { | ||
747 | case MPIC_RAVEN_ID: | ||
748 | MotMPIC = MOT_RAVEN_PRESENT; | ||
749 | break; | ||
750 | case MPIC_HAWK_ID: | ||
751 | MotMPIC = MOT_HAWK_PRESENT; | ||
752 | break; | ||
753 | default: | ||
754 | OpenPIC_Addr = NULL; | ||
755 | return 0; | ||
756 | } | ||
757 | |||
758 | |||
759 | /* Read the memory base register. */ | ||
760 | early_read_config_dword(NULL, 0, 0, PCI_BASE_ADDRESS_1, &pci_membase); | ||
761 | |||
762 | if (pci_membase == 0) { | ||
763 | OpenPIC_Addr = NULL; | ||
764 | return 0; | ||
765 | } | ||
766 | |||
767 | /* Map the Raven MPIC registers to virtual memory. */ | ||
768 | OpenPIC_Addr = ioremap(pci_membase+0xC0000000, 0x22000); | ||
769 | |||
770 | OpenPIC_InitSenses = prep_openpic_initsenses; | ||
771 | OpenPIC_NumInitSenses = sizeof(prep_openpic_initsenses); | ||
772 | |||
773 | ppc_md.get_irq = openpic_get_irq; | ||
774 | |||
775 | /* If raven is present on Motorola store the system config register | ||
776 | * for later use. | ||
777 | */ | ||
778 | ProcInfo = (unsigned long *)ioremap(0xfef80400, 4); | ||
779 | |||
780 | /* Indicate to system if this is a multiprocessor board */ | ||
781 | if (!(*ProcInfo & MOT_PROC2_BIT)) { | ||
782 | mot_multi = 1; | ||
783 | } | ||
784 | |||
785 | /* This is a hack. If this is a 2300 or 2400 mot board then there is | ||
786 | * no keyboard controller and we have to indicate that. | ||
787 | */ | ||
788 | base_mod = inb(MOTOROLA_BASETYPE_REG); | ||
789 | if ((MotMPIC == MOT_HAWK_PRESENT) || (base_mod == 0xF9) || | ||
790 | (base_mod == 0xFA) || (base_mod == 0xE1)) | ||
791 | prep_keybd_present = 0; | ||
792 | |||
793 | return 1; | ||
794 | } | ||
795 | |||
796 | struct mot_info { | ||
797 | int cpu_type; /* 0x100 mask assumes for Raven and Hawk boards that the level/edge are set */ | ||
798 | /* 0x200 if this board has a Hawk chip. */ | ||
799 | int base_type; | ||
800 | int max_cpu; /* ored with 0x80 if this board should be checked for multi CPU */ | ||
801 | const char *name; | ||
802 | unsigned char *map; | ||
803 | unsigned char *routes; | ||
804 | void (*map_non0_bus)(struct pci_dev *); /* For boards with more than bus 0 devices. */ | ||
805 | struct powerplus_irq_list *pci_irq_list; /* List of PCI MPIC inputs */ | ||
806 | unsigned char secondary_bridge_devfn; /* devfn of secondary bus transparent bridge */ | ||
807 | } mot_info[] __prepdata = { | ||
808 | {0x300, 0x00, 0x00, "MVME 2400", Genesis2_pci_IRQ_map, Raven_pci_IRQ_routes, Powerplus_Map_Non0, &Powerplus_pci_IRQ_list, 0xFF}, | ||
809 | {0x010, 0x00, 0x00, "Genesis", Genesis_pci_IRQ_map, Genesis_pci_IRQ_routes, Powerplus_Map_Non0, &Powerplus_pci_IRQ_list, 0x00}, | ||
810 | {0x020, 0x00, 0x00, "Powerstack (Series E)", Comet_pci_IRQ_map, Comet_pci_IRQ_routes, NULL, NULL, 0x00}, | ||
811 | {0x040, 0x00, 0x00, "Blackhawk (Powerstack)", Blackhawk_pci_IRQ_map, Blackhawk_pci_IRQ_routes, NULL, NULL, 0x00}, | ||
812 | {0x050, 0x00, 0x00, "Omaha (PowerStack II Pro3000)", Omaha_pci_IRQ_map, Omaha_pci_IRQ_routes, NULL, NULL, 0x00}, | ||
813 | {0x060, 0x00, 0x00, "Utah (Powerstack II Pro4000)", Utah_pci_IRQ_map, Utah_pci_IRQ_routes, NULL, NULL, 0x00}, | ||
814 | {0x0A0, 0x00, 0x00, "Powerstack (Series EX)", Comet2_pci_IRQ_map, Comet2_pci_IRQ_routes, NULL, NULL, 0x00}, | ||
815 | {0x1E0, 0xE0, 0x00, "Mesquite cPCI (MCP750)", Mesquite_pci_IRQ_map, Raven_pci_IRQ_routes, Powerplus_Map_Non0, &Mesquite_pci_IRQ_list, 0xFF}, | ||
816 | {0x1E0, 0xE1, 0x00, "Sitka cPCI (MCPN750)", Sitka_pci_IRQ_map, Raven_pci_IRQ_routes, Powerplus_Map_Non0, &Powerplus_pci_IRQ_list, 0xFF}, | ||
817 | {0x1E0, 0xE2, 0x00, "Mesquite cPCI (MCP750) w/ HAC", Mesquite_pci_IRQ_map, Raven_pci_IRQ_routes, Powerplus_Map_Non0, &Mesquite_pci_IRQ_list, 0xC0}, | ||
818 | {0x1E0, 0xF6, 0x80, "MTX Plus", MTXplus_pci_IRQ_map, Raven_pci_IRQ_routes, Powerplus_Map_Non0, &Powerplus_pci_IRQ_list, 0xA0}, | ||
819 | {0x1E0, 0xF6, 0x81, "Dual MTX Plus", MTXplus_pci_IRQ_map, Raven_pci_IRQ_routes, Powerplus_Map_Non0, &Powerplus_pci_IRQ_list, 0xA0}, | ||
820 | {0x1E0, 0xF7, 0x80, "MTX wo/ Parallel Port", MTX_pci_IRQ_map, Raven_pci_IRQ_routes, Powerplus_Map_Non0, &Powerplus_pci_IRQ_list, 0x00}, | ||
821 | {0x1E0, 0xF7, 0x81, "Dual MTX wo/ Parallel Port", MTX_pci_IRQ_map, Raven_pci_IRQ_routes, Powerplus_Map_Non0, &Powerplus_pci_IRQ_list, 0x00}, | ||
822 | {0x1E0, 0xF8, 0x80, "MTX w/ Parallel Port", MTX_pci_IRQ_map, Raven_pci_IRQ_routes, Powerplus_Map_Non0, &Powerplus_pci_IRQ_list, 0x00}, | ||
823 | {0x1E0, 0xF8, 0x81, "Dual MTX w/ Parallel Port", MTX_pci_IRQ_map, Raven_pci_IRQ_routes, Powerplus_Map_Non0, &Powerplus_pci_IRQ_list, 0x00}, | ||
824 | {0x1E0, 0xF9, 0x00, "MVME 2300", Genesis2_pci_IRQ_map, Raven_pci_IRQ_routes, Powerplus_Map_Non0, &Powerplus_pci_IRQ_list, 0xFF}, | ||
825 | {0x1E0, 0xFA, 0x00, "MVME 2300SC/2600", Genesis2_pci_IRQ_map, Raven_pci_IRQ_routes, Powerplus_Map_Non0, &Powerplus_pci_IRQ_list, 0xFF}, | ||
826 | {0x1E0, 0xFB, 0x00, "MVME 2600 with MVME712M", Genesis2_pci_IRQ_map, Raven_pci_IRQ_routes, Powerplus_Map_Non0, &Powerplus_pci_IRQ_list, 0xFF}, | ||
827 | {0x1E0, 0xFC, 0x00, "MVME 2600/2700 with MVME761", Genesis2_pci_IRQ_map, Raven_pci_IRQ_routes, Powerplus_Map_Non0, &Powerplus_pci_IRQ_list, 0xFF}, | ||
828 | {0x1E0, 0xFD, 0x80, "MVME 3600 with MVME712M", Genesis2_pci_IRQ_map, Raven_pci_IRQ_routes, Powerplus_Map_Non0, &Powerplus_pci_IRQ_list, 0x00}, | ||
829 | {0x1E0, 0xFD, 0x81, "MVME 4600 with MVME712M", Genesis2_pci_IRQ_map, Raven_pci_IRQ_routes, Powerplus_Map_Non0, &Powerplus_pci_IRQ_list, 0xFF}, | ||
830 | {0x1E0, 0xFE, 0x80, "MVME 3600 with MVME761", Genesis2_pci_IRQ_map, Raven_pci_IRQ_routes, Powerplus_Map_Non0, &Powerplus_pci_IRQ_list, 0xFF}, | ||
831 | {0x1E0, 0xFE, 0x81, "MVME 4600 with MVME761", Genesis2_pci_IRQ_map, Raven_pci_IRQ_routes, Powerplus_Map_Non0, &Powerplus_pci_IRQ_list, 0xFF}, | ||
832 | {0x1E0, 0xFF, 0x00, "MVME 1600-001 or 1600-011", Genesis2_pci_IRQ_map, Raven_pci_IRQ_routes, Powerplus_Map_Non0, &Powerplus_pci_IRQ_list, 0xFF}, | ||
833 | {0x000, 0x00, 0x00, "", NULL, NULL, NULL, NULL, 0x00} | ||
834 | }; | ||
835 | |||
836 | void __init | ||
837 | ibm_prep_init(void) | ||
838 | { | ||
839 | if (have_residual_data) { | ||
840 | u32 addr, real_addr, len, offset; | ||
841 | PPC_DEVICE *mpic; | ||
842 | PnP_TAG_PACKET *pkt; | ||
843 | |||
844 | /* Use the PReP residual data to determine if an OpenPIC is | ||
845 | * present. If so, get the large vendor packet which will | ||
846 | * tell us the base address and length in memory. | ||
847 | * If we are successful, ioremap the memory area and set | ||
848 | * OpenPIC_Addr (this indicates that the OpenPIC was found). | ||
849 | */ | ||
850 | mpic = residual_find_device(-1, NULL, SystemPeripheral, | ||
851 | ProgrammableInterruptController, MPIC, 0); | ||
852 | if (!mpic) | ||
853 | return; | ||
854 | |||
855 | pkt = PnP_find_large_vendor_packet(res->DevicePnPHeap + | ||
856 | mpic->AllocatedOffset, 9, 0); | ||
857 | |||
858 | if (!pkt) | ||
859 | return; | ||
860 | |||
861 | #define p pkt->L4_Pack.L4_Data.L4_PPCPack | ||
862 | if (p.PPCData[1] == 32) { | ||
863 | switch (p.PPCData[0]) { | ||
864 | case 1: offset = PREP_ISA_IO_BASE; break; | ||
865 | case 2: offset = PREP_ISA_MEM_BASE; break; | ||
866 | default: return; /* Not I/O or memory?? */ | ||
867 | } | ||
868 | } | ||
869 | else | ||
870 | return; /* Not a 32-bit address */ | ||
871 | |||
872 | real_addr = ld_le32((unsigned int *) (p.PPCData + 4)); | ||
873 | if (real_addr == 0xffffffff) | ||
874 | return; | ||
875 | |||
876 | /* Adjust address to be as seen by CPU */ | ||
877 | addr = real_addr + offset; | ||
878 | |||
879 | len = ld_le32((unsigned int *) (p.PPCData + 12)); | ||
880 | if (!len) | ||
881 | return; | ||
882 | #undef p | ||
883 | OpenPIC_Addr = ioremap(addr, len); | ||
884 | ppc_md.get_irq = openpic_get_irq; | ||
885 | |||
886 | OpenPIC_InitSenses = prep_openpic_initsenses; | ||
887 | OpenPIC_NumInitSenses = sizeof(prep_openpic_initsenses); | ||
888 | |||
889 | printk(KERN_INFO "MPIC at 0x%08x (0x%08x), length 0x%08x " | ||
890 | "mapped to 0x%p\n", addr, real_addr, len, OpenPIC_Addr); | ||
891 | } | ||
892 | } | ||
893 | |||
894 | static void __init | ||
895 | ibm43p_pci_map_non0(struct pci_dev *dev) | ||
896 | { | ||
897 | unsigned char intpin; | ||
898 | static unsigned char bridge_intrs[4] = { 3, 4, 5, 8 }; | ||
899 | |||
900 | if (dev == NULL) | ||
901 | return; | ||
902 | pci_read_config_byte(dev, PCI_INTERRUPT_PIN, &intpin); | ||
903 | if (intpin < 1 || intpin > 4) | ||
904 | return; | ||
905 | intpin = (PCI_SLOT(dev->devfn) + intpin - 1) & 3; | ||
906 | dev->irq = openpic_to_irq(bridge_intrs[intpin]); | ||
907 | pci_write_config_byte(dev, PCI_INTERRUPT_LINE, dev->irq); | ||
908 | } | ||
909 | |||
910 | void __init | ||
911 | prep_residual_setup_pci(char *irq_edge_mask_lo, char *irq_edge_mask_hi) | ||
912 | { | ||
913 | if (have_residual_data) { | ||
914 | Motherboard_map_name = res->VitalProductData.PrintableModel; | ||
915 | Motherboard_map = NULL; | ||
916 | Motherboard_routes = NULL; | ||
917 | residual_irq_mask(irq_edge_mask_lo, irq_edge_mask_hi); | ||
918 | } | ||
919 | } | ||
920 | |||
921 | void __init | ||
922 | prep_sandalfoot_setup_pci(char *irq_edge_mask_lo, char *irq_edge_mask_hi) | ||
923 | { | ||
924 | Motherboard_map_name = "IBM 6015/7020 (Sandalfoot/Sandalbow)"; | ||
925 | Motherboard_map = ibm6015_pci_IRQ_map; | ||
926 | Motherboard_routes = ibm6015_pci_IRQ_routes; | ||
927 | *irq_edge_mask_lo = 0x00; /* irq's 0-7 all edge-triggered */ | ||
928 | *irq_edge_mask_hi = 0xA0; /* irq's 13, 15 level-triggered */ | ||
929 | } | ||
930 | |||
931 | void __init | ||
932 | prep_thinkpad_setup_pci(char *irq_edge_mask_lo, char *irq_edge_mask_hi) | ||
933 | { | ||
934 | Motherboard_map_name = "IBM Thinkpad 850/860"; | ||
935 | Motherboard_map = Nobis_pci_IRQ_map; | ||
936 | Motherboard_routes = Nobis_pci_IRQ_routes; | ||
937 | *irq_edge_mask_lo = 0x00; /* irq's 0-7 all edge-triggered */ | ||
938 | *irq_edge_mask_hi = 0xA0; /* irq's 13, 15 level-triggered */ | ||
939 | } | ||
940 | |||
941 | void __init | ||
942 | prep_carolina_setup_pci(char *irq_edge_mask_lo, char *irq_edge_mask_hi) | ||
943 | { | ||
944 | Motherboard_map_name = "IBM 7248, PowerSeries 830/850 (Carolina)"; | ||
945 | Motherboard_map = ibm8xx_pci_IRQ_map; | ||
946 | Motherboard_routes = ibm8xx_pci_IRQ_routes; | ||
947 | *irq_edge_mask_lo = 0x00; /* irq's 0-7 all edge-triggered */ | ||
948 | *irq_edge_mask_hi = 0xA4; /* irq's 10, 13, 15 level-triggered */ | ||
949 | } | ||
950 | |||
951 | void __init | ||
952 | prep_tiger1_setup_pci(char *irq_edge_mask_lo, char *irq_edge_mask_hi) | ||
953 | { | ||
954 | Motherboard_map_name = "IBM 43P-140 (Tiger1)"; | ||
955 | Motherboard_map = ibm43p_pci_IRQ_map; | ||
956 | Motherboard_routes = ibm43p_pci_IRQ_routes; | ||
957 | Motherboard_non0 = ibm43p_pci_map_non0; | ||
958 | *irq_edge_mask_lo = 0x00; /* irq's 0-7 all edge-triggered */ | ||
959 | *irq_edge_mask_hi = 0xA0; /* irq's 13, 15 level-triggered */ | ||
960 | } | ||
961 | |||
962 | void __init | ||
963 | prep_route_pci_interrupts(void) | ||
964 | { | ||
965 | unsigned char *ibc_pirq = (unsigned char *)0x80800860; | ||
966 | unsigned char *ibc_pcicon = (unsigned char *)0x80800840; | ||
967 | int i; | ||
968 | |||
969 | if ( _prep_type == _PREP_Motorola) | ||
970 | { | ||
971 | unsigned short irq_mode; | ||
972 | unsigned char cpu_type; | ||
973 | unsigned char base_mod; | ||
974 | int entry; | ||
975 | |||
976 | cpu_type = inb(MOTOROLA_CPUTYPE_REG) & 0xF0; | ||
977 | base_mod = inb(MOTOROLA_BASETYPE_REG); | ||
978 | |||
979 | for (entry = 0; mot_info[entry].cpu_type != 0; entry++) { | ||
980 | if (mot_info[entry].cpu_type & 0x200) { /* Check for Hawk chip */ | ||
981 | if (!(MotMPIC & MOT_HAWK_PRESENT)) | ||
982 | continue; | ||
983 | } else { /* Check non hawk boards */ | ||
984 | if ((mot_info[entry].cpu_type & 0xff) != cpu_type) | ||
985 | continue; | ||
986 | |||
987 | if (mot_info[entry].base_type == 0) { | ||
988 | mot_entry = entry; | ||
989 | break; | ||
990 | } | ||
991 | |||
992 | if (mot_info[entry].base_type != base_mod) | ||
993 | continue; | ||
994 | } | ||
995 | |||
996 | if (!(mot_info[entry].max_cpu & 0x80)) { | ||
997 | mot_entry = entry; | ||
998 | break; | ||
999 | } | ||
1000 | |||
1001 | /* processor 1 not present and max processor zero indicated */ | ||
1002 | if ((*ProcInfo & MOT_PROC2_BIT) && !(mot_info[entry].max_cpu & 0x7f)) { | ||
1003 | mot_entry = entry; | ||
1004 | break; | ||
1005 | } | ||
1006 | |||
1007 | /* processor 1 present and max processor zero indicated */ | ||
1008 | if (!(*ProcInfo & MOT_PROC2_BIT) && (mot_info[entry].max_cpu & 0x7f)) { | ||
1009 | mot_entry = entry; | ||
1010 | break; | ||
1011 | } | ||
1012 | } | ||
1013 | |||
1014 | if (mot_entry == -1) /* No particular cpu type found - assume Blackhawk */ | ||
1015 | mot_entry = 3; | ||
1016 | |||
1017 | Motherboard_map_name = (unsigned char *)mot_info[mot_entry].name; | ||
1018 | Motherboard_map = mot_info[mot_entry].map; | ||
1019 | Motherboard_routes = mot_info[mot_entry].routes; | ||
1020 | Motherboard_non0 = mot_info[mot_entry].map_non0_bus; | ||
1021 | |||
1022 | if (!(mot_info[entry].cpu_type & 0x100)) { | ||
1023 | /* AJF adjust level/edge control according to routes */ | ||
1024 | irq_mode = 0; | ||
1025 | for (i = 1; i <= 4; i++) | ||
1026 | irq_mode |= ( 1 << Motherboard_routes[i] ); | ||
1027 | outb( irq_mode & 0xff, 0x4d0 ); | ||
1028 | outb( (irq_mode >> 8) & 0xff, 0x4d1 ); | ||
1029 | } | ||
1030 | } else if ( _prep_type == _PREP_IBM ) { | ||
1031 | unsigned char irq_edge_mask_lo, irq_edge_mask_hi; | ||
1032 | unsigned short irq_edge_mask; | ||
1033 | int i; | ||
1034 | |||
1035 | setup_ibm_pci(&irq_edge_mask_lo, &irq_edge_mask_hi); | ||
1036 | |||
1037 | outb(inb(0x04d0)|irq_edge_mask_lo, 0x4d0); /* primary 8259 */ | ||
1038 | outb(inb(0x04d1)|irq_edge_mask_hi, 0x4d1); /* cascaded 8259 */ | ||
1039 | |||
1040 | irq_edge_mask = (irq_edge_mask_hi << 8) | irq_edge_mask_lo; | ||
1041 | for (i = 0; i < 16; ++i, irq_edge_mask >>= 1) | ||
1042 | if (irq_edge_mask & 1) | ||
1043 | irq_desc[i].status |= IRQ_LEVEL; | ||
1044 | } else { | ||
1045 | printk("No known machine pci routing!\n"); | ||
1046 | return; | ||
1047 | } | ||
1048 | |||
1049 | /* Set up mapping from slots */ | ||
1050 | if (Motherboard_routes) { | ||
1051 | for (i = 1; i <= 4; i++) | ||
1052 | ibc_pirq[i-1] = Motherboard_routes[i]; | ||
1053 | |||
1054 | /* Enable PCI interrupts */ | ||
1055 | *ibc_pcicon |= 0x20; | ||
1056 | } | ||
1057 | } | ||
1058 | |||
1059 | void __init | ||
1060 | prep_pib_init(void) | ||
1061 | { | ||
1062 | unsigned char reg; | ||
1063 | unsigned short short_reg; | ||
1064 | |||
1065 | struct pci_dev *dev = NULL; | ||
1066 | |||
1067 | if (( _prep_type == _PREP_Motorola) && (OpenPIC_Addr)) { | ||
1068 | /* | ||
1069 | * Perform specific configuration for the Via Tech or | ||
1070 | * or Winbond PCI-ISA-Bridge part. | ||
1071 | */ | ||
1072 | if ((dev = pci_get_device(PCI_VENDOR_ID_VIA, | ||
1073 | PCI_DEVICE_ID_VIA_82C586_1, dev))) { | ||
1074 | /* | ||
1075 | * PPCBUG does not set the enable bits | ||
1076 | * for the IDE device. Force them on here. | ||
1077 | */ | ||
1078 | pci_read_config_byte(dev, 0x40, ®); | ||
1079 | |||
1080 | reg |= 0x03; /* IDE: Chip Enable Bits */ | ||
1081 | pci_write_config_byte(dev, 0x40, reg); | ||
1082 | } | ||
1083 | if ((dev = pci_get_device(PCI_VENDOR_ID_VIA, | ||
1084 | PCI_DEVICE_ID_VIA_82C586_2, | ||
1085 | dev)) && (dev->devfn = 0x5a)) { | ||
1086 | /* Force correct USB interrupt */ | ||
1087 | dev->irq = 11; | ||
1088 | pci_write_config_byte(dev, | ||
1089 | PCI_INTERRUPT_LINE, | ||
1090 | dev->irq); | ||
1091 | } | ||
1092 | if ((dev = pci_get_device(PCI_VENDOR_ID_WINBOND, | ||
1093 | PCI_DEVICE_ID_WINBOND_83C553, dev))) { | ||
1094 | /* Clear PCI Interrupt Routing Control Register. */ | ||
1095 | short_reg = 0x0000; | ||
1096 | pci_write_config_word(dev, 0x44, short_reg); | ||
1097 | if (OpenPIC_Addr){ | ||
1098 | /* Route IDE interrupts to IRQ 14 */ | ||
1099 | reg = 0xEE; | ||
1100 | pci_write_config_byte(dev, 0x43, reg); | ||
1101 | } | ||
1102 | } | ||
1103 | pci_dev_put(dev); | ||
1104 | } | ||
1105 | |||
1106 | if ((dev = pci_get_device(PCI_VENDOR_ID_WINBOND, | ||
1107 | PCI_DEVICE_ID_WINBOND_82C105, dev))){ | ||
1108 | if (OpenPIC_Addr){ | ||
1109 | /* | ||
1110 | * Disable LEGIRQ mode so PCI INTS are routed | ||
1111 | * directly to the 8259 and enable both channels | ||
1112 | */ | ||
1113 | pci_write_config_dword(dev, 0x40, 0x10ff0033); | ||
1114 | |||
1115 | /* Force correct IDE interrupt */ | ||
1116 | dev->irq = 14; | ||
1117 | pci_write_config_byte(dev, | ||
1118 | PCI_INTERRUPT_LINE, | ||
1119 | dev->irq); | ||
1120 | } else { | ||
1121 | /* Enable LEGIRQ for PCI INT -> 8259 IRQ routing */ | ||
1122 | pci_write_config_dword(dev, 0x40, 0x10ff08a1); | ||
1123 | } | ||
1124 | } | ||
1125 | pci_dev_put(dev); | ||
1126 | } | ||
1127 | |||
1128 | static void __init | ||
1129 | Powerplus_Map_Non0(struct pci_dev *dev) | ||
1130 | { | ||
1131 | struct pci_bus *pbus; /* Parent bus structure pointer */ | ||
1132 | struct pci_dev *tdev = dev; /* Temporary device structure */ | ||
1133 | unsigned int devnum; /* Accumulated device number */ | ||
1134 | unsigned char intline; /* Linux interrupt value */ | ||
1135 | unsigned char intpin; /* PCI interrupt pin */ | ||
1136 | |||
1137 | /* Check for valid PCI dev pointer */ | ||
1138 | if (dev == NULL) return; | ||
1139 | |||
1140 | /* Initialize bridge IDSEL variable */ | ||
1141 | devnum = PCI_SLOT(tdev->devfn); | ||
1142 | |||
1143 | /* Read the interrupt pin of the device and adjust for indexing */ | ||
1144 | pci_read_config_byte(dev, PCI_INTERRUPT_PIN, &intpin); | ||
1145 | |||
1146 | /* If device doesn't request an interrupt, return */ | ||
1147 | if ( (intpin < 1) || (intpin > 4) ) | ||
1148 | return; | ||
1149 | |||
1150 | intpin--; | ||
1151 | |||
1152 | /* | ||
1153 | * Walk up to bus 0, adjusting the interrupt pin for the standard | ||
1154 | * PCI bus swizzle. | ||
1155 | */ | ||
1156 | do { | ||
1157 | intpin = (prep_pci_intpins[devnum % 4][intpin]) - 1; | ||
1158 | pbus = tdev->bus; /* up one level */ | ||
1159 | tdev = pbus->self; | ||
1160 | devnum = PCI_SLOT(tdev->devfn); | ||
1161 | } while(tdev->bus->number); | ||
1162 | |||
1163 | /* Use the primary interrupt inputs by default */ | ||
1164 | intline = mot_info[mot_entry].pci_irq_list->primary[intpin]; | ||
1165 | |||
1166 | /* | ||
1167 | * If the board has secondary interrupt inputs, walk the bus and | ||
1168 | * note the devfn of the bridge from bus 0. If it is the same as | ||
1169 | * the devfn of the bus bridge with secondary inputs, use those. | ||
1170 | * Otherwise, assume it's a PMC site and get the interrupt line | ||
1171 | * value from the interrupt routing table. | ||
1172 | */ | ||
1173 | if (mot_info[mot_entry].secondary_bridge_devfn) { | ||
1174 | pbus = dev->bus; | ||
1175 | |||
1176 | while (pbus->primary != 0) | ||
1177 | pbus = pbus->parent; | ||
1178 | |||
1179 | if ((pbus->self)->devfn != 0xA0) { | ||
1180 | if ((pbus->self)->devfn == mot_info[mot_entry].secondary_bridge_devfn) | ||
1181 | intline = mot_info[mot_entry].pci_irq_list->secondary[intpin]; | ||
1182 | else { | ||
1183 | if ((char *)(mot_info[mot_entry].map) == (char *)Mesquite_pci_IRQ_map) | ||
1184 | intline = mot_info[mot_entry].map[((pbus->self)->devfn)/8] + 16; | ||
1185 | else { | ||
1186 | int i; | ||
1187 | for (i=0;i<3;i++) | ||
1188 | intpin = (prep_pci_intpins[devnum % 4][intpin]) - 1; | ||
1189 | intline = mot_info[mot_entry].pci_irq_list->primary[intpin]; | ||
1190 | } | ||
1191 | } | ||
1192 | } | ||
1193 | } | ||
1194 | |||
1195 | /* Write calculated interrupt value to header and device list */ | ||
1196 | dev->irq = intline; | ||
1197 | pci_write_config_byte(dev, PCI_INTERRUPT_LINE, (u8)dev->irq); | ||
1198 | } | ||
1199 | |||
1200 | void __init | ||
1201 | prep_pcibios_fixup(void) | ||
1202 | { | ||
1203 | struct pci_dev *dev = NULL; | ||
1204 | int irq; | ||
1205 | int have_openpic = (OpenPIC_Addr != NULL); | ||
1206 | |||
1207 | prep_route_pci_interrupts(); | ||
1208 | |||
1209 | printk("Setting PCI interrupts for a \"%s\"\n", Motherboard_map_name); | ||
1210 | |||
1211 | /* Iterate through all the PCI devices, setting the IRQ */ | ||
1212 | for_each_pci_dev(dev) { | ||
1213 | /* | ||
1214 | * If we have residual data, then this is easy: query the | ||
1215 | * residual data for the IRQ line allocated to the device. | ||
1216 | * This works the same whether we have an OpenPic or not. | ||
1217 | */ | ||
1218 | if (have_residual_data) { | ||
1219 | irq = residual_pcidev_irq(dev); | ||
1220 | dev->irq = have_openpic ? openpic_to_irq(irq) : irq; | ||
1221 | } | ||
1222 | /* | ||
1223 | * If we don't have residual data, then we need to use | ||
1224 | * tables to determine the IRQ. The table organisation | ||
1225 | * is different depending on whether there is an OpenPIC | ||
1226 | * or not. The tables are only used for bus 0, so check | ||
1227 | * this first. | ||
1228 | */ | ||
1229 | else if (dev->bus->number == 0) { | ||
1230 | irq = Motherboard_map[PCI_SLOT(dev->devfn)]; | ||
1231 | dev->irq = have_openpic ? openpic_to_irq(irq) | ||
1232 | : Motherboard_routes[irq]; | ||
1233 | } | ||
1234 | /* | ||
1235 | * Finally, if we don't have residual data and the bus is | ||
1236 | * non-zero, use the callback (if provided) | ||
1237 | */ | ||
1238 | else { | ||
1239 | if (Motherboard_non0 != NULL) | ||
1240 | Motherboard_non0(dev); | ||
1241 | |||
1242 | continue; | ||
1243 | } | ||
1244 | |||
1245 | pci_write_config_byte(dev, PCI_INTERRUPT_LINE, dev->irq); | ||
1246 | } | ||
1247 | |||
1248 | /* Setup the Winbond or Via PIB */ | ||
1249 | prep_pib_init(); | ||
1250 | } | ||
1251 | |||
1252 | static void __init | ||
1253 | prep_pcibios_after_init(void) | ||
1254 | { | ||
1255 | #if 0 | ||
1256 | struct pci_dev *dev; | ||
1257 | |||
1258 | /* If there is a WD 90C, reset the IO BAR to 0x0 (it started that | ||
1259 | * way, but the PCI layer relocated it because it thought 0x0 was | ||
1260 | * invalid for a BAR). | ||
1261 | * If you don't do this, the card's VGA base will be <IO BAR>+0xc0000 | ||
1262 | * instead of 0xc0000. vgacon.c (for example) is completely unaware of | ||
1263 | * this little quirk. | ||
1264 | */ | ||
1265 | dev = pci_get_device(PCI_VENDOR_ID_WD, PCI_DEVICE_ID_WD_90C, NULL); | ||
1266 | if (dev) { | ||
1267 | dev->resource[1].end -= dev->resource[1].start; | ||
1268 | dev->resource[1].start = 0; | ||
1269 | /* tell the hardware */ | ||
1270 | pci_write_config_dword(dev, PCI_BASE_ADDRESS_1, 0x0); | ||
1271 | pci_dev_put(dev); | ||
1272 | } | ||
1273 | #endif | ||
1274 | } | ||
1275 | |||
1276 | static void __init | ||
1277 | prep_init_resource(struct resource *res, unsigned long start, | ||
1278 | unsigned long end, int flags) | ||
1279 | { | ||
1280 | res->flags = flags; | ||
1281 | res->start = start; | ||
1282 | res->end = end; | ||
1283 | res->name = "PCI host bridge"; | ||
1284 | res->parent = NULL; | ||
1285 | res->sibling = NULL; | ||
1286 | res->child = NULL; | ||
1287 | } | ||
1288 | |||
1289 | void __init | ||
1290 | prep_find_bridges(void) | ||
1291 | { | ||
1292 | struct pci_controller* hose; | ||
1293 | |||
1294 | hose = pcibios_alloc_controller(); | ||
1295 | if (!hose) | ||
1296 | return; | ||
1297 | |||
1298 | hose->first_busno = 0; | ||
1299 | hose->last_busno = 0xff; | ||
1300 | hose->pci_mem_offset = PREP_ISA_MEM_BASE; | ||
1301 | hose->io_base_phys = PREP_ISA_IO_BASE; | ||
1302 | hose->io_base_virt = ioremap(PREP_ISA_IO_BASE, 0x800000); | ||
1303 | prep_init_resource(&hose->io_resource, 0, 0x007fffff, IORESOURCE_IO); | ||
1304 | prep_init_resource(&hose->mem_resources[0], 0xc0000000, 0xfeffffff, | ||
1305 | IORESOURCE_MEM); | ||
1306 | setup_indirect_pci(hose, PREP_ISA_IO_BASE + 0xcf8, | ||
1307 | PREP_ISA_IO_BASE + 0xcfc); | ||
1308 | |||
1309 | printk("PReP architecture\n"); | ||
1310 | |||
1311 | if (have_residual_data) { | ||
1312 | PPC_DEVICE *hostbridge; | ||
1313 | |||
1314 | hostbridge = residual_find_device(PROCESSORDEVICE, NULL, | ||
1315 | BridgeController, PCIBridge, -1, 0); | ||
1316 | if (hostbridge && | ||
1317 | ((hostbridge->DeviceId.Interface == PCIBridgeIndirect) || | ||
1318 | (hostbridge->DeviceId.Interface == PCIBridgeRS6K))) { | ||
1319 | PnP_TAG_PACKET * pkt; | ||
1320 | pkt = PnP_find_large_vendor_packet( | ||
1321 | res->DevicePnPHeap+hostbridge->AllocatedOffset, | ||
1322 | 3, 0); | ||
1323 | if(pkt) { | ||
1324 | #define p pkt->L4_Pack.L4_Data.L4_PPCPack | ||
1325 | setup_indirect_pci(hose, | ||
1326 | ld_le32((unsigned *) (p.PPCData)), | ||
1327 | ld_le32((unsigned *) (p.PPCData+8))); | ||
1328 | #undef p | ||
1329 | } else | ||
1330 | setup_indirect_pci(hose, 0x80000cf8, 0x80000cfc); | ||
1331 | } | ||
1332 | } | ||
1333 | |||
1334 | ppc_md.pcibios_fixup = prep_pcibios_fixup; | ||
1335 | ppc_md.pcibios_after_init = prep_pcibios_after_init; | ||
1336 | } | ||
diff --git a/arch/ppc/platforms/prep_setup.c b/arch/ppc/platforms/prep_setup.c new file mode 100644 index 000000000000..bc926be95472 --- /dev/null +++ b/arch/ppc/platforms/prep_setup.c | |||
@@ -0,0 +1,1181 @@ | |||
1 | /* | ||
2 | * arch/ppc/platforms/setup.c | ||
3 | * | ||
4 | * Copyright (C) 1995 Linus Torvalds | ||
5 | * Adapted from 'alpha' version by Gary Thomas | ||
6 | * Modified by Cort Dougan (cort@cs.nmt.edu) | ||
7 | * | ||
8 | * Support for PReP (Motorola MTX/MVME) | ||
9 | * by Troy Benjegerdes (hozer@drgw.net) | ||
10 | */ | ||
11 | |||
12 | /* | ||
13 | * bootup setup stuff.. | ||
14 | */ | ||
15 | |||
16 | #include <linux/config.h> | ||
17 | #include <linux/delay.h> | ||
18 | #include <linux/module.h> | ||
19 | #include <linux/errno.h> | ||
20 | #include <linux/sched.h> | ||
21 | #include <linux/kernel.h> | ||
22 | #include <linux/mm.h> | ||
23 | #include <linux/stddef.h> | ||
24 | #include <linux/unistd.h> | ||
25 | #include <linux/ptrace.h> | ||
26 | #include <linux/slab.h> | ||
27 | #include <linux/user.h> | ||
28 | #include <linux/a.out.h> | ||
29 | #include <linux/tty.h> | ||
30 | #include <linux/major.h> | ||
31 | #include <linux/interrupt.h> | ||
32 | #include <linux/reboot.h> | ||
33 | #include <linux/init.h> | ||
34 | #include <linux/initrd.h> | ||
35 | #include <linux/ioport.h> | ||
36 | #include <linux/console.h> | ||
37 | #include <linux/timex.h> | ||
38 | #include <linux/pci.h> | ||
39 | #include <linux/ide.h> | ||
40 | #include <linux/seq_file.h> | ||
41 | #include <linux/root_dev.h> | ||
42 | |||
43 | #include <asm/sections.h> | ||
44 | #include <asm/mmu.h> | ||
45 | #include <asm/processor.h> | ||
46 | #include <asm/residual.h> | ||
47 | #include <asm/io.h> | ||
48 | #include <asm/pgtable.h> | ||
49 | #include <asm/cache.h> | ||
50 | #include <asm/dma.h> | ||
51 | #include <asm/machdep.h> | ||
52 | #include <asm/mc146818rtc.h> | ||
53 | #include <asm/mk48t59.h> | ||
54 | #include <asm/prep_nvram.h> | ||
55 | #include <asm/raven.h> | ||
56 | #include <asm/vga.h> | ||
57 | #include <asm/time.h> | ||
58 | #include <asm/mpc10x.h> | ||
59 | #include <asm/i8259.h> | ||
60 | #include <asm/open_pic.h> | ||
61 | #include <asm/pci-bridge.h> | ||
62 | #include <asm/todc.h> | ||
63 | |||
64 | TODC_ALLOC(); | ||
65 | |||
66 | unsigned char ucSystemType; | ||
67 | unsigned char ucBoardRev; | ||
68 | unsigned char ucBoardRevMaj, ucBoardRevMin; | ||
69 | |||
70 | extern unsigned char prep_nvram_read_val(int addr); | ||
71 | extern void prep_nvram_write_val(int addr, | ||
72 | unsigned char val); | ||
73 | extern unsigned char rs_nvram_read_val(int addr); | ||
74 | extern void rs_nvram_write_val(int addr, | ||
75 | unsigned char val); | ||
76 | extern void ibm_prep_init(void); | ||
77 | |||
78 | extern void prep_find_bridges(void); | ||
79 | |||
80 | int _prep_type; | ||
81 | |||
82 | extern void prep_residual_setup_pci(char *irq_edge_mask_lo, char *irq_edge_mask_hi); | ||
83 | extern void prep_sandalfoot_setup_pci(char *irq_edge_mask_lo, char *irq_edge_mask_hi); | ||
84 | extern void prep_thinkpad_setup_pci(char *irq_edge_mask_lo, char *irq_edge_mask_hi); | ||
85 | extern void prep_carolina_setup_pci(char *irq_edge_mask_lo, char *irq_edge_mask_hi); | ||
86 | extern void prep_tiger1_setup_pci(char *irq_edge_mask_lo, char *irq_edge_mask_hi); | ||
87 | |||
88 | |||
89 | #define cached_21 (((char *)(ppc_cached_irq_mask))[3]) | ||
90 | #define cached_A1 (((char *)(ppc_cached_irq_mask))[2]) | ||
91 | |||
92 | /* for the mac fs */ | ||
93 | dev_t boot_dev; | ||
94 | |||
95 | #ifdef CONFIG_SOUND_CS4232 | ||
96 | long ppc_cs4232_dma, ppc_cs4232_dma2; | ||
97 | #endif | ||
98 | |||
99 | extern PTE *Hash, *Hash_end; | ||
100 | extern unsigned long Hash_size, Hash_mask; | ||
101 | extern int probingmem; | ||
102 | extern unsigned long loops_per_jiffy; | ||
103 | |||
104 | #ifdef CONFIG_SOUND_CS4232 | ||
105 | EXPORT_SYMBOL(ppc_cs4232_dma); | ||
106 | EXPORT_SYMBOL(ppc_cs4232_dma2); | ||
107 | #endif | ||
108 | |||
109 | /* useful ISA ports */ | ||
110 | #define PREP_SYSCTL 0x81c | ||
111 | /* present in the IBM reference design; possibly identical in Mot boxes: */ | ||
112 | #define PREP_IBM_SIMM_ID 0x803 /* SIMM size: 32 or 8 MiB */ | ||
113 | #define PREP_IBM_SIMM_PRESENCE 0x804 | ||
114 | #define PREP_IBM_EQUIPMENT 0x80c | ||
115 | #define PREP_IBM_L2INFO 0x80d | ||
116 | #define PREP_IBM_PM1 0x82a /* power management register 1 */ | ||
117 | #define PREP_IBM_PLANAR 0x852 /* planar ID - identifies the motherboard */ | ||
118 | #define PREP_IBM_DISP 0x8c0 /* 4-digit LED display */ | ||
119 | |||
120 | /* Equipment Present Register masks: */ | ||
121 | #define PREP_IBM_EQUIPMENT_RESERVED 0x80 | ||
122 | #define PREP_IBM_EQUIPMENT_SCSIFUSE 0x40 | ||
123 | #define PREP_IBM_EQUIPMENT_L2_COPYBACK 0x08 | ||
124 | #define PREP_IBM_EQUIPMENT_L2_256 0x04 | ||
125 | #define PREP_IBM_EQUIPMENT_CPU 0x02 | ||
126 | #define PREP_IBM_EQUIPMENT_L2 0x01 | ||
127 | |||
128 | /* planar ID values: */ | ||
129 | /* Sandalfoot/Sandalbow (6015/7020) */ | ||
130 | #define PREP_IBM_SANDALFOOT 0xfc | ||
131 | /* Woodfield, Thinkpad 850/860 (6042/7249) */ | ||
132 | #define PREP_IBM_THINKPAD 0xff /* planar ID unimplemented */ | ||
133 | /* PowerSeries 830/850 (6050/6070) */ | ||
134 | #define PREP_IBM_CAROLINA_IDE_0 0xf0 | ||
135 | #define PREP_IBM_CAROLINA_IDE_1 0xf1 | ||
136 | #define PREP_IBM_CAROLINA_IDE_2 0xf2 | ||
137 | #define PREP_IBM_CAROLINA_IDE_3 0xf3 | ||
138 | /* 7248-43P */ | ||
139 | #define PREP_IBM_CAROLINA_SCSI_0 0xf4 | ||
140 | #define PREP_IBM_CAROLINA_SCSI_1 0xf5 | ||
141 | #define PREP_IBM_CAROLINA_SCSI_2 0xf6 | ||
142 | #define PREP_IBM_CAROLINA_SCSI_3 0xf7 /* missing from Carolina Tech Spec */ | ||
143 | /* Tiger1 (7043-140) */ | ||
144 | #define PREP_IBM_TIGER1_133 0xd1 | ||
145 | #define PREP_IBM_TIGER1_166 0xd2 | ||
146 | #define PREP_IBM_TIGER1_180 0xd3 | ||
147 | #define PREP_IBM_TIGER1_xxx 0xd4 /* unknown, but probably exists */ | ||
148 | #define PREP_IBM_TIGER1_333 0xd5 /* missing from Tiger Tech Spec */ | ||
149 | |||
150 | /* setup_ibm_pci: | ||
151 | * set Motherboard_map_name, Motherboard_map, Motherboard_routes. | ||
152 | * return 8259 edge/level masks. | ||
153 | */ | ||
154 | void (*setup_ibm_pci)(char *irq_lo, char *irq_hi); | ||
155 | |||
156 | extern char *Motherboard_map_name; /* for use in *_cpuinfo */ | ||
157 | |||
158 | /* | ||
159 | * As found in the PReP reference implementation. | ||
160 | * Used by Thinkpad, Sandalfoot (6015/7020), and all Motorola PReP. | ||
161 | */ | ||
162 | static void __init | ||
163 | prep_gen_enable_l2(void) | ||
164 | { | ||
165 | outb(inb(PREP_SYSCTL) | 0x3, PREP_SYSCTL); | ||
166 | } | ||
167 | |||
168 | /* Used by Carolina and Tiger1 */ | ||
169 | static void __init | ||
170 | prep_carolina_enable_l2(void) | ||
171 | { | ||
172 | outb(inb(PREP_SYSCTL) | 0xc0, PREP_SYSCTL); | ||
173 | } | ||
174 | |||
175 | /* cpuinfo code common to all IBM PReP */ | ||
176 | static void __prep | ||
177 | prep_ibm_cpuinfo(struct seq_file *m) | ||
178 | { | ||
179 | unsigned int equip_reg = inb(PREP_IBM_EQUIPMENT); | ||
180 | |||
181 | seq_printf(m, "machine\t\t: PReP %s\n", Motherboard_map_name); | ||
182 | |||
183 | seq_printf(m, "upgrade cpu\t: "); | ||
184 | if (equip_reg & PREP_IBM_EQUIPMENT_CPU) { | ||
185 | seq_printf(m, "not "); | ||
186 | } | ||
187 | seq_printf(m, "present\n"); | ||
188 | |||
189 | /* print info about the SCSI fuse */ | ||
190 | seq_printf(m, "scsi fuse\t: "); | ||
191 | if (equip_reg & PREP_IBM_EQUIPMENT_SCSIFUSE) | ||
192 | seq_printf(m, "ok"); | ||
193 | else | ||
194 | seq_printf(m, "bad"); | ||
195 | seq_printf(m, "\n"); | ||
196 | |||
197 | /* print info about SIMMs */ | ||
198 | if (have_residual_data) { | ||
199 | int i; | ||
200 | seq_printf(m, "simms\t\t: "); | ||
201 | for (i = 0; (res->ActualNumMemories) && (i < MAX_MEMS); i++) { | ||
202 | if (res->Memories[i].SIMMSize != 0) | ||
203 | seq_printf(m, "%d:%ldMiB ", i, | ||
204 | (res->Memories[i].SIMMSize > 1024) ? | ||
205 | res->Memories[i].SIMMSize>>20 : | ||
206 | res->Memories[i].SIMMSize); | ||
207 | } | ||
208 | seq_printf(m, "\n"); | ||
209 | } | ||
210 | } | ||
211 | |||
212 | static int __prep | ||
213 | prep_gen_cpuinfo(struct seq_file *m) | ||
214 | { | ||
215 | prep_ibm_cpuinfo(m); | ||
216 | return 0; | ||
217 | } | ||
218 | |||
219 | static int __prep | ||
220 | prep_sandalfoot_cpuinfo(struct seq_file *m) | ||
221 | { | ||
222 | unsigned int equip_reg = inb(PREP_IBM_EQUIPMENT); | ||
223 | |||
224 | prep_ibm_cpuinfo(m); | ||
225 | |||
226 | /* report amount and type of L2 cache present */ | ||
227 | seq_printf(m, "L2 cache\t: "); | ||
228 | if (equip_reg & PREP_IBM_EQUIPMENT_L2) { | ||
229 | seq_printf(m, "not present"); | ||
230 | } else { | ||
231 | if (equip_reg & PREP_IBM_EQUIPMENT_L2_256) | ||
232 | seq_printf(m, "256KiB"); | ||
233 | else | ||
234 | seq_printf(m, "unknown size"); | ||
235 | |||
236 | if (equip_reg & PREP_IBM_EQUIPMENT_L2_COPYBACK) | ||
237 | seq_printf(m, ", copy-back"); | ||
238 | else | ||
239 | seq_printf(m, ", write-through"); | ||
240 | } | ||
241 | seq_printf(m, "\n"); | ||
242 | |||
243 | return 0; | ||
244 | } | ||
245 | |||
246 | static int __prep | ||
247 | prep_thinkpad_cpuinfo(struct seq_file *m) | ||
248 | { | ||
249 | unsigned int equip_reg = inb(PREP_IBM_EQUIPMENT); | ||
250 | char *cpubus_speed, *pci_speed; | ||
251 | |||
252 | prep_ibm_cpuinfo(m); | ||
253 | |||
254 | /* report amount and type of L2 cache present */ | ||
255 | seq_printf(m, "l2 cache\t: "); | ||
256 | if ((equip_reg & 0x1) == 0) { | ||
257 | switch ((equip_reg & 0xc) >> 2) { | ||
258 | case 0x0: | ||
259 | seq_printf(m, "128KiB look-aside 2-way write-through\n"); | ||
260 | break; | ||
261 | case 0x1: | ||
262 | seq_printf(m, "512KiB look-aside direct-mapped write-back\n"); | ||
263 | break; | ||
264 | case 0x2: | ||
265 | seq_printf(m, "256KiB look-aside 2-way write-through\n"); | ||
266 | break; | ||
267 | case 0x3: | ||
268 | seq_printf(m, "256KiB look-aside direct-mapped write-back\n"); | ||
269 | break; | ||
270 | } | ||
271 | } else { | ||
272 | seq_printf(m, "not present\n"); | ||
273 | } | ||
274 | |||
275 | /* report bus speeds because we can */ | ||
276 | if ((equip_reg & 0x80) == 0) { | ||
277 | switch ((equip_reg & 0x30) >> 4) { | ||
278 | case 0x1: | ||
279 | cpubus_speed = "50"; | ||
280 | pci_speed = "25"; | ||
281 | break; | ||
282 | case 0x3: | ||
283 | cpubus_speed = "66"; | ||
284 | pci_speed = "33"; | ||
285 | break; | ||
286 | default: | ||
287 | cpubus_speed = "unknown"; | ||
288 | pci_speed = "unknown"; | ||
289 | break; | ||
290 | } | ||
291 | } else { | ||
292 | switch ((equip_reg & 0x30) >> 4) { | ||
293 | case 0x1: | ||
294 | cpubus_speed = "25"; | ||
295 | pci_speed = "25"; | ||
296 | break; | ||
297 | case 0x2: | ||
298 | cpubus_speed = "60"; | ||
299 | pci_speed = "30"; | ||
300 | break; | ||
301 | case 0x3: | ||
302 | cpubus_speed = "33"; | ||
303 | pci_speed = "33"; | ||
304 | break; | ||
305 | default: | ||
306 | cpubus_speed = "unknown"; | ||
307 | pci_speed = "unknown"; | ||
308 | break; | ||
309 | } | ||
310 | } | ||
311 | seq_printf(m, "60x bus\t\t: %sMHz\n", cpubus_speed); | ||
312 | seq_printf(m, "pci bus\t\t: %sMHz\n", pci_speed); | ||
313 | |||
314 | return 0; | ||
315 | } | ||
316 | |||
317 | static int __prep | ||
318 | prep_carolina_cpuinfo(struct seq_file *m) | ||
319 | { | ||
320 | unsigned int equip_reg = inb(PREP_IBM_EQUIPMENT); | ||
321 | |||
322 | prep_ibm_cpuinfo(m); | ||
323 | |||
324 | /* report amount and type of L2 cache present */ | ||
325 | seq_printf(m, "l2 cache\t: "); | ||
326 | if ((equip_reg & 0x1) == 0) { | ||
327 | unsigned int l2_reg = inb(PREP_IBM_L2INFO); | ||
328 | |||
329 | /* L2 size */ | ||
330 | if ((l2_reg & 0x60) == 0) | ||
331 | seq_printf(m, "256KiB"); | ||
332 | else if ((l2_reg & 0x60) == 0x20) | ||
333 | seq_printf(m, "512KiB"); | ||
334 | else | ||
335 | seq_printf(m, "unknown size"); | ||
336 | |||
337 | /* L2 type */ | ||
338 | if ((l2_reg & 0x3) == 0) | ||
339 | seq_printf(m, ", async"); | ||
340 | else if ((l2_reg & 0x3) == 1) | ||
341 | seq_printf(m, ", sync"); | ||
342 | else | ||
343 | seq_printf(m, ", unknown type"); | ||
344 | |||
345 | seq_printf(m, "\n"); | ||
346 | } else { | ||
347 | seq_printf(m, "not present\n"); | ||
348 | } | ||
349 | |||
350 | return 0; | ||
351 | } | ||
352 | |||
353 | static int __prep | ||
354 | prep_tiger1_cpuinfo(struct seq_file *m) | ||
355 | { | ||
356 | unsigned int l2_reg = inb(PREP_IBM_L2INFO); | ||
357 | |||
358 | prep_ibm_cpuinfo(m); | ||
359 | |||
360 | /* report amount and type of L2 cache present */ | ||
361 | seq_printf(m, "l2 cache\t: "); | ||
362 | if ((l2_reg & 0xf) == 0xf) { | ||
363 | seq_printf(m, "not present\n"); | ||
364 | } else { | ||
365 | if (l2_reg & 0x8) | ||
366 | seq_printf(m, "async, "); | ||
367 | else | ||
368 | seq_printf(m, "sync burst, "); | ||
369 | |||
370 | if (l2_reg & 0x4) | ||
371 | seq_printf(m, "parity, "); | ||
372 | else | ||
373 | seq_printf(m, "no parity, "); | ||
374 | |||
375 | switch (l2_reg & 0x3) { | ||
376 | case 0x0: | ||
377 | seq_printf(m, "256KiB\n"); | ||
378 | break; | ||
379 | case 0x1: | ||
380 | seq_printf(m, "512KiB\n"); | ||
381 | break; | ||
382 | case 0x2: | ||
383 | seq_printf(m, "1MiB\n"); | ||
384 | break; | ||
385 | default: | ||
386 | seq_printf(m, "unknown size\n"); | ||
387 | break; | ||
388 | } | ||
389 | } | ||
390 | |||
391 | return 0; | ||
392 | } | ||
393 | |||
394 | |||
395 | /* Used by all Motorola PReP */ | ||
396 | static int __prep | ||
397 | prep_mot_cpuinfo(struct seq_file *m) | ||
398 | { | ||
399 | unsigned int cachew = *((unsigned char *)CACHECRBA); | ||
400 | |||
401 | seq_printf(m, "machine\t\t: PReP %s\n", Motherboard_map_name); | ||
402 | |||
403 | /* report amount and type of L2 cache present */ | ||
404 | seq_printf(m, "l2 cache\t: "); | ||
405 | switch (cachew & L2CACHE_MASK) { | ||
406 | case L2CACHE_512KB: | ||
407 | seq_printf(m, "512KiB"); | ||
408 | break; | ||
409 | case L2CACHE_256KB: | ||
410 | seq_printf(m, "256KiB"); | ||
411 | break; | ||
412 | case L2CACHE_1MB: | ||
413 | seq_printf(m, "1MiB"); | ||
414 | break; | ||
415 | case L2CACHE_NONE: | ||
416 | seq_printf(m, "none\n"); | ||
417 | goto no_l2; | ||
418 | break; | ||
419 | default: | ||
420 | seq_printf(m, "%x\n", cachew); | ||
421 | } | ||
422 | |||
423 | seq_printf(m, ", parity %s", | ||
424 | (cachew & L2CACHE_PARITY)? "enabled" : "disabled"); | ||
425 | |||
426 | seq_printf(m, " SRAM:"); | ||
427 | |||
428 | switch ( ((cachew & 0xf0) >> 4) & ~(0x3) ) { | ||
429 | case 1: seq_printf(m, "synchronous, parity, flow-through\n"); | ||
430 | break; | ||
431 | case 2: seq_printf(m, "asynchronous, no parity\n"); | ||
432 | break; | ||
433 | case 3: seq_printf(m, "asynchronous, parity\n"); | ||
434 | break; | ||
435 | default:seq_printf(m, "synchronous, pipelined, no parity\n"); | ||
436 | break; | ||
437 | } | ||
438 | |||
439 | no_l2: | ||
440 | /* print info about SIMMs */ | ||
441 | if (have_residual_data) { | ||
442 | int i; | ||
443 | seq_printf(m, "simms\t\t: "); | ||
444 | for (i = 0; (res->ActualNumMemories) && (i < MAX_MEMS); i++) { | ||
445 | if (res->Memories[i].SIMMSize != 0) | ||
446 | seq_printf(m, "%d:%ldM ", i, | ||
447 | (res->Memories[i].SIMMSize > 1024) ? | ||
448 | res->Memories[i].SIMMSize>>20 : | ||
449 | res->Memories[i].SIMMSize); | ||
450 | } | ||
451 | seq_printf(m, "\n"); | ||
452 | } | ||
453 | |||
454 | return 0; | ||
455 | } | ||
456 | |||
457 | static void __prep | ||
458 | prep_restart(char *cmd) | ||
459 | { | ||
460 | #define PREP_SP92 0x92 /* Special Port 92 */ | ||
461 | local_irq_disable(); /* no interrupts */ | ||
462 | |||
463 | /* set exception prefix high - to the prom */ | ||
464 | _nmask_and_or_msr(0, MSR_IP); | ||
465 | |||
466 | /* make sure bit 0 (reset) is a 0 */ | ||
467 | outb( inb(PREP_SP92) & ~1L , PREP_SP92); | ||
468 | /* signal a reset to system control port A - soft reset */ | ||
469 | outb( inb(PREP_SP92) | 1 , PREP_SP92); | ||
470 | |||
471 | while ( 1 ) ; | ||
472 | /* not reached */ | ||
473 | #undef PREP_SP92 | ||
474 | } | ||
475 | |||
476 | static void __prep | ||
477 | prep_halt(void) | ||
478 | { | ||
479 | local_irq_disable(); /* no interrupts */ | ||
480 | |||
481 | /* set exception prefix high - to the prom */ | ||
482 | _nmask_and_or_msr(0, MSR_IP); | ||
483 | |||
484 | while ( 1 ) ; | ||
485 | /* not reached */ | ||
486 | } | ||
487 | |||
488 | /* Carrera is the power manager in the Thinkpads. Unfortunately not much is | ||
489 | * known about it, so we can't power down. | ||
490 | */ | ||
491 | static void __prep | ||
492 | prep_carrera_poweroff(void) | ||
493 | { | ||
494 | prep_halt(); | ||
495 | } | ||
496 | |||
497 | /* | ||
498 | * On most IBM PReP's, power management is handled by a Signetics 87c750 | ||
499 | * behind the Utah component on the ISA bus. To access the 750 you must write | ||
500 | * a series of nibbles to port 0x82a (decoded by the Utah). This is described | ||
501 | * somewhat in the IBM Carolina Technical Specification. | ||
502 | * -Hollis | ||
503 | */ | ||
504 | static void __prep | ||
505 | utah_sig87c750_setbit(unsigned int bytenum, unsigned int bitnum, int value) | ||
506 | { | ||
507 | /* | ||
508 | * byte1: 0 0 0 1 0 d a5 a4 | ||
509 | * byte2: 0 0 0 1 a3 a2 a1 a0 | ||
510 | * | ||
511 | * d = the bit's value, enabled or disabled | ||
512 | * (a5 a4 a3) = the byte number, minus 20 | ||
513 | * (a2 a1 a0) = the bit number | ||
514 | * | ||
515 | * example: set the 5th bit of byte 21 (21.5) | ||
516 | * a5 a4 a3 = 001 (byte 1) | ||
517 | * a2 a1 a0 = 101 (bit 5) | ||
518 | * | ||
519 | * byte1 = 0001 0100 (0x14) | ||
520 | * byte2 = 0001 1101 (0x1d) | ||
521 | */ | ||
522 | unsigned char byte1=0x10, byte2=0x10; | ||
523 | |||
524 | /* the 750's '20.0' is accessed as '0.0' through Utah (which adds 20) */ | ||
525 | bytenum -= 20; | ||
526 | |||
527 | byte1 |= (!!value) << 2; /* set d */ | ||
528 | byte1 |= (bytenum >> 1) & 0x3; /* set a5, a4 */ | ||
529 | |||
530 | byte2 |= (bytenum & 0x1) << 3; /* set a3 */ | ||
531 | byte2 |= bitnum & 0x7; /* set a2, a1, a0 */ | ||
532 | |||
533 | outb(byte1, PREP_IBM_PM1); /* first nibble */ | ||
534 | mb(); | ||
535 | udelay(100); /* important: let controller recover */ | ||
536 | |||
537 | outb(byte2, PREP_IBM_PM1); /* second nibble */ | ||
538 | mb(); | ||
539 | udelay(100); /* important: let controller recover */ | ||
540 | } | ||
541 | |||
542 | static void __prep | ||
543 | prep_sig750_poweroff(void) | ||
544 | { | ||
545 | /* tweak the power manager found in most IBM PRePs (except Thinkpads) */ | ||
546 | |||
547 | local_irq_disable(); | ||
548 | /* set exception prefix high - to the prom */ | ||
549 | _nmask_and_or_msr(0, MSR_IP); | ||
550 | |||
551 | utah_sig87c750_setbit(21, 5, 1); /* set bit 21.5, "PMEXEC_OFF" */ | ||
552 | |||
553 | while (1) ; | ||
554 | /* not reached */ | ||
555 | } | ||
556 | |||
557 | static int __prep | ||
558 | prep_show_percpuinfo(struct seq_file *m, int i) | ||
559 | { | ||
560 | /* PREP's without residual data will give incorrect values here */ | ||
561 | seq_printf(m, "clock\t\t: "); | ||
562 | if (have_residual_data) | ||
563 | seq_printf(m, "%ldMHz\n", | ||
564 | (res->VitalProductData.ProcessorHz > 1024) ? | ||
565 | res->VitalProductData.ProcessorHz / 1000000 : | ||
566 | res->VitalProductData.ProcessorHz); | ||
567 | else | ||
568 | seq_printf(m, "???\n"); | ||
569 | |||
570 | return 0; | ||
571 | } | ||
572 | |||
573 | #ifdef CONFIG_SOUND_CS4232 | ||
574 | static long __init masktoint(unsigned int i) | ||
575 | { | ||
576 | int t = -1; | ||
577 | while (i >> ++t) | ||
578 | ; | ||
579 | return (t-1); | ||
580 | } | ||
581 | |||
582 | /* | ||
583 | * ppc_cs4232_dma and ppc_cs4232_dma2 are used in include/asm/dma.h | ||
584 | * to distinguish sound dma-channels from others. This is because | ||
585 | * blocksize on 16 bit dma-channels 5,6,7 is 128k, but | ||
586 | * the cs4232.c uses 64k like on 8 bit dma-channels 0,1,2,3 | ||
587 | */ | ||
588 | |||
589 | static void __init prep_init_sound(void) | ||
590 | { | ||
591 | PPC_DEVICE *audiodevice = NULL; | ||
592 | |||
593 | /* | ||
594 | * Get the needed resource informations from residual data. | ||
595 | * | ||
596 | */ | ||
597 | if (have_residual_data) | ||
598 | audiodevice = residual_find_device(~0, NULL, | ||
599 | MultimediaController, AudioController, -1, 0); | ||
600 | |||
601 | if (audiodevice != NULL) { | ||
602 | PnP_TAG_PACKET *pkt; | ||
603 | |||
604 | pkt = PnP_find_packet((unsigned char *)&res->DevicePnPHeap[audiodevice->AllocatedOffset], | ||
605 | S5_Packet, 0); | ||
606 | if (pkt != NULL) | ||
607 | ppc_cs4232_dma = masktoint(pkt->S5_Pack.DMAMask); | ||
608 | pkt = PnP_find_packet((unsigned char*)&res->DevicePnPHeap[audiodevice->AllocatedOffset], | ||
609 | S5_Packet, 1); | ||
610 | if (pkt != NULL) | ||
611 | ppc_cs4232_dma2 = masktoint(pkt->S5_Pack.DMAMask); | ||
612 | } | ||
613 | |||
614 | /* | ||
615 | * These are the PReP specs' defaults for the cs4231. We use these | ||
616 | * as fallback incase we don't have residual data. | ||
617 | * At least the IBM Thinkpad 850 with IDE DMA Channels at 6 and 7 | ||
618 | * will use the other values. | ||
619 | */ | ||
620 | if (audiodevice == NULL) { | ||
621 | switch (_prep_type) { | ||
622 | case _PREP_IBM: | ||
623 | ppc_cs4232_dma = 1; | ||
624 | ppc_cs4232_dma2 = -1; | ||
625 | break; | ||
626 | default: | ||
627 | ppc_cs4232_dma = 6; | ||
628 | ppc_cs4232_dma2 = 7; | ||
629 | } | ||
630 | } | ||
631 | |||
632 | /* | ||
633 | * Find a way to push these informations to the cs4232 driver | ||
634 | * Give it out with printk, when not in cmd_line? | ||
635 | * Append it to cmd_line and saved_command_line? | ||
636 | * Format is cs4232=io,irq,dma,dma2 | ||
637 | */ | ||
638 | } | ||
639 | #endif /* CONFIG_SOUND_CS4232 */ | ||
640 | |||
641 | /* | ||
642 | * Fill out screen_info according to the residual data. This allows us to use | ||
643 | * at least vesafb. | ||
644 | */ | ||
645 | static void __init | ||
646 | prep_init_vesa(void) | ||
647 | { | ||
648 | #if (defined(CONFIG_FB_VGA16) || defined(CONFIG_FB_VGA16_MODULE) || \ | ||
649 | defined(CONFIG_FB_VESA)) | ||
650 | PPC_DEVICE *vgadev = NULL; | ||
651 | |||
652 | if (have_residual_data) | ||
653 | vgadev = residual_find_device(~0, NULL, DisplayController, | ||
654 | SVGAController, -1, 0); | ||
655 | |||
656 | if (vgadev != NULL) { | ||
657 | PnP_TAG_PACKET *pkt; | ||
658 | |||
659 | pkt = PnP_find_large_vendor_packet( | ||
660 | (unsigned char *)&res->DevicePnPHeap[vgadev->AllocatedOffset], | ||
661 | 0x04, 0); /* 0x04 = Display Tag */ | ||
662 | if (pkt != NULL) { | ||
663 | unsigned char *ptr = (unsigned char *)pkt; | ||
664 | |||
665 | if (ptr[4]) { | ||
666 | /* graphics mode */ | ||
667 | screen_info.orig_video_isVGA = VIDEO_TYPE_VLFB; | ||
668 | |||
669 | screen_info.lfb_depth = ptr[4] * 8; | ||
670 | |||
671 | screen_info.lfb_width = swab16(*(short *)(ptr+6)); | ||
672 | screen_info.lfb_height = swab16(*(short *)(ptr+8)); | ||
673 | screen_info.lfb_linelength = swab16(*(short *)(ptr+10)); | ||
674 | |||
675 | screen_info.lfb_base = swab32(*(long *)(ptr+12)); | ||
676 | screen_info.lfb_size = swab32(*(long *)(ptr+20)) / 65536; | ||
677 | } | ||
678 | } | ||
679 | } | ||
680 | #endif | ||
681 | } | ||
682 | |||
683 | /* | ||
684 | * Set DBAT 2 to access 0x80000000 so early progress messages will work | ||
685 | */ | ||
686 | static __inline__ void | ||
687 | prep_set_bat(void) | ||
688 | { | ||
689 | /* wait for all outstanding memory access to complete */ | ||
690 | mb(); | ||
691 | |||
692 | /* setup DBATs */ | ||
693 | mtspr(SPRN_DBAT2U, 0x80001ffe); | ||
694 | mtspr(SPRN_DBAT2L, 0x8000002a); | ||
695 | |||
696 | /* wait for updates */ | ||
697 | mb(); | ||
698 | } | ||
699 | |||
700 | /* | ||
701 | * IBM 3-digit status LED | ||
702 | */ | ||
703 | static unsigned int ibm_statusled_base __prepdata; | ||
704 | |||
705 | static void __prep | ||
706 | ibm_statusled_progress(char *s, unsigned short hex); | ||
707 | |||
708 | static int __prep | ||
709 | ibm_statusled_panic(struct notifier_block *dummy1, unsigned long dummy2, | ||
710 | void * dummy3) | ||
711 | { | ||
712 | ibm_statusled_progress(NULL, 0x505); /* SOS */ | ||
713 | return NOTIFY_DONE; | ||
714 | } | ||
715 | |||
716 | static struct notifier_block ibm_statusled_block __prepdata = { | ||
717 | ibm_statusled_panic, | ||
718 | NULL, | ||
719 | INT_MAX /* try to do it first */ | ||
720 | }; | ||
721 | |||
722 | static void __prep | ||
723 | ibm_statusled_progress(char *s, unsigned short hex) | ||
724 | { | ||
725 | static int notifier_installed; | ||
726 | /* | ||
727 | * Progress uses 4 digits and we have only 3. So, we map 0xffff to | ||
728 | * 0xfff for display switch off. Out of range values are mapped to | ||
729 | * 0xeff, as I'm told 0xf00 and above are reserved for hardware codes. | ||
730 | * Install the panic notifier when the display is first switched off. | ||
731 | */ | ||
732 | if (hex == 0xffff) { | ||
733 | hex = 0xfff; | ||
734 | if (!notifier_installed) { | ||
735 | ++notifier_installed; | ||
736 | notifier_chain_register(&panic_notifier_list, | ||
737 | &ibm_statusled_block); | ||
738 | } | ||
739 | } | ||
740 | else | ||
741 | if (hex > 0xfff) | ||
742 | hex = 0xeff; | ||
743 | |||
744 | mb(); | ||
745 | outw(hex, ibm_statusled_base); | ||
746 | } | ||
747 | |||
748 | static void __init | ||
749 | ibm_statusled_init(void) | ||
750 | { | ||
751 | /* | ||
752 | * The IBM 3-digit LED display is specified in the residual data | ||
753 | * as an operator panel device, type "System Status LED". Find | ||
754 | * that device and determine its address. We validate all the | ||
755 | * other parameters on the off-chance another, similar device | ||
756 | * exists. | ||
757 | */ | ||
758 | if (have_residual_data) { | ||
759 | PPC_DEVICE *led; | ||
760 | PnP_TAG_PACKET *pkt; | ||
761 | |||
762 | led = residual_find_device(~0, NULL, SystemPeripheral, | ||
763 | OperatorPanel, SystemStatusLED, 0); | ||
764 | if (!led) | ||
765 | return; | ||
766 | |||
767 | pkt = PnP_find_packet((unsigned char *) | ||
768 | &res->DevicePnPHeap[led->AllocatedOffset], S8_Packet, 0); | ||
769 | if (!pkt) | ||
770 | return; | ||
771 | |||
772 | if (pkt->S8_Pack.IOInfo != ISAAddr16bit) | ||
773 | return; | ||
774 | if (*(unsigned short *)pkt->S8_Pack.RangeMin != | ||
775 | *(unsigned short *)pkt->S8_Pack.RangeMax) | ||
776 | return; | ||
777 | if (pkt->S8_Pack.IOAlign != 2) | ||
778 | return; | ||
779 | if (pkt->S8_Pack.IONum != 2) | ||
780 | return; | ||
781 | |||
782 | ibm_statusled_base = ld_le16((unsigned short *) | ||
783 | (pkt->S8_Pack.RangeMin)); | ||
784 | ppc_md.progress = ibm_statusled_progress; | ||
785 | } | ||
786 | } | ||
787 | |||
788 | static void __init | ||
789 | prep_setup_arch(void) | ||
790 | { | ||
791 | unsigned char reg; | ||
792 | int is_ide=0; | ||
793 | |||
794 | /* init to some ~sane value until calibrate_delay() runs */ | ||
795 | loops_per_jiffy = 50000000; | ||
796 | |||
797 | /* Lookup PCI host bridges */ | ||
798 | prep_find_bridges(); | ||
799 | |||
800 | /* Set up floppy in PS/2 mode */ | ||
801 | outb(0x09, SIO_CONFIG_RA); | ||
802 | reg = inb(SIO_CONFIG_RD); | ||
803 | reg = (reg & 0x3F) | 0x40; | ||
804 | outb(reg, SIO_CONFIG_RD); | ||
805 | outb(reg, SIO_CONFIG_RD); /* Have to write twice to change! */ | ||
806 | |||
807 | switch ( _prep_type ) | ||
808 | { | ||
809 | case _PREP_IBM: | ||
810 | reg = inb(PREP_IBM_PLANAR); | ||
811 | printk(KERN_INFO "IBM planar ID: %02x", reg); | ||
812 | switch (reg) { | ||
813 | case PREP_IBM_SANDALFOOT: | ||
814 | prep_gen_enable_l2(); | ||
815 | setup_ibm_pci = prep_sandalfoot_setup_pci; | ||
816 | ppc_md.power_off = prep_sig750_poweroff; | ||
817 | ppc_md.show_cpuinfo = prep_sandalfoot_cpuinfo; | ||
818 | break; | ||
819 | case PREP_IBM_THINKPAD: | ||
820 | prep_gen_enable_l2(); | ||
821 | setup_ibm_pci = prep_thinkpad_setup_pci; | ||
822 | ppc_md.power_off = prep_carrera_poweroff; | ||
823 | ppc_md.show_cpuinfo = prep_thinkpad_cpuinfo; | ||
824 | break; | ||
825 | default: | ||
826 | if (have_residual_data) { | ||
827 | prep_gen_enable_l2(); | ||
828 | setup_ibm_pci = prep_residual_setup_pci; | ||
829 | ppc_md.power_off = prep_halt; | ||
830 | ppc_md.show_cpuinfo = prep_gen_cpuinfo; | ||
831 | break; | ||
832 | } | ||
833 | else | ||
834 | printk(" - unknown! Assuming Carolina"); | ||
835 | /* fall through */ | ||
836 | case PREP_IBM_CAROLINA_IDE_0: | ||
837 | case PREP_IBM_CAROLINA_IDE_1: | ||
838 | case PREP_IBM_CAROLINA_IDE_2: | ||
839 | case PREP_IBM_CAROLINA_IDE_3: | ||
840 | is_ide = 1; | ||
841 | case PREP_IBM_CAROLINA_SCSI_0: | ||
842 | case PREP_IBM_CAROLINA_SCSI_1: | ||
843 | case PREP_IBM_CAROLINA_SCSI_2: | ||
844 | case PREP_IBM_CAROLINA_SCSI_3: | ||
845 | prep_carolina_enable_l2(); | ||
846 | setup_ibm_pci = prep_carolina_setup_pci; | ||
847 | ppc_md.power_off = prep_sig750_poweroff; | ||
848 | ppc_md.show_cpuinfo = prep_carolina_cpuinfo; | ||
849 | break; | ||
850 | case PREP_IBM_TIGER1_133: | ||
851 | case PREP_IBM_TIGER1_166: | ||
852 | case PREP_IBM_TIGER1_180: | ||
853 | case PREP_IBM_TIGER1_xxx: | ||
854 | case PREP_IBM_TIGER1_333: | ||
855 | prep_carolina_enable_l2(); | ||
856 | setup_ibm_pci = prep_tiger1_setup_pci; | ||
857 | ppc_md.power_off = prep_sig750_poweroff; | ||
858 | ppc_md.show_cpuinfo = prep_tiger1_cpuinfo; | ||
859 | break; | ||
860 | } | ||
861 | printk("\n"); | ||
862 | |||
863 | /* default root device */ | ||
864 | if (is_ide) | ||
865 | ROOT_DEV = MKDEV(IDE0_MAJOR, 3); | ||
866 | else | ||
867 | ROOT_DEV = MKDEV(SCSI_DISK0_MAJOR, 3); | ||
868 | |||
869 | break; | ||
870 | case _PREP_Motorola: | ||
871 | prep_gen_enable_l2(); | ||
872 | ppc_md.power_off = prep_halt; | ||
873 | ppc_md.show_cpuinfo = prep_mot_cpuinfo; | ||
874 | |||
875 | #ifdef CONFIG_BLK_DEV_INITRD | ||
876 | if (initrd_start) | ||
877 | ROOT_DEV = Root_RAM0; | ||
878 | else | ||
879 | #endif | ||
880 | #ifdef CONFIG_ROOT_NFS | ||
881 | ROOT_DEV = Root_NFS; | ||
882 | #else | ||
883 | ROOT_DEV = Root_SDA2; | ||
884 | #endif | ||
885 | break; | ||
886 | } | ||
887 | |||
888 | /* Read in NVRAM data */ | ||
889 | init_prep_nvram(); | ||
890 | |||
891 | /* if no bootargs, look in NVRAM */ | ||
892 | if ( cmd_line[0] == '\0' ) { | ||
893 | char *bootargs; | ||
894 | bootargs = prep_nvram_get_var("bootargs"); | ||
895 | if (bootargs != NULL) { | ||
896 | strcpy(cmd_line, bootargs); | ||
897 | /* again.. */ | ||
898 | strcpy(saved_command_line, cmd_line); | ||
899 | } | ||
900 | } | ||
901 | |||
902 | #ifdef CONFIG_SOUND_CS4232 | ||
903 | prep_init_sound(); | ||
904 | #endif /* CONFIG_SOUND_CS4232 */ | ||
905 | |||
906 | prep_init_vesa(); | ||
907 | |||
908 | switch (_prep_type) { | ||
909 | case _PREP_Motorola: | ||
910 | raven_init(); | ||
911 | break; | ||
912 | case _PREP_IBM: | ||
913 | ibm_prep_init(); | ||
914 | break; | ||
915 | } | ||
916 | |||
917 | #ifdef CONFIG_VGA_CONSOLE | ||
918 | /* vgacon.c needs to know where we mapped IO memory in io_block_mapping() */ | ||
919 | vgacon_remap_base = 0xf0000000; | ||
920 | conswitchp = &vga_con; | ||
921 | #endif | ||
922 | } | ||
923 | |||
924 | /* | ||
925 | * First, see if we can get this information from the residual data. | ||
926 | * This is important on some IBM PReP systems. If we cannot, we let the | ||
927 | * TODC code handle doing this. | ||
928 | */ | ||
929 | static void __init | ||
930 | prep_calibrate_decr(void) | ||
931 | { | ||
932 | if (have_residual_data) { | ||
933 | unsigned long freq, divisor = 4; | ||
934 | |||
935 | if ( res->VitalProductData.ProcessorBusHz ) { | ||
936 | freq = res->VitalProductData.ProcessorBusHz; | ||
937 | printk("time_init: decrementer frequency = %lu.%.6lu MHz\n", | ||
938 | (freq/divisor)/1000000, | ||
939 | (freq/divisor)%1000000); | ||
940 | tb_to_us = mulhwu_scale_factor(freq/divisor, 1000000); | ||
941 | tb_ticks_per_jiffy = freq / HZ / divisor; | ||
942 | } | ||
943 | } | ||
944 | else | ||
945 | todc_calibrate_decr(); | ||
946 | } | ||
947 | |||
948 | static unsigned int __prep | ||
949 | prep_irq_canonicalize(u_int irq) | ||
950 | { | ||
951 | if (irq == 2) | ||
952 | { | ||
953 | return 9; | ||
954 | } | ||
955 | else | ||
956 | { | ||
957 | return irq; | ||
958 | } | ||
959 | } | ||
960 | |||
961 | static void __init | ||
962 | prep_init_IRQ(void) | ||
963 | { | ||
964 | int i; | ||
965 | unsigned int pci_viddid, pci_did; | ||
966 | |||
967 | if (OpenPIC_Addr != NULL) { | ||
968 | openpic_init(NUM_8259_INTERRUPTS); | ||
969 | /* We have a cascade on OpenPIC IRQ 0, Linux IRQ 16 */ | ||
970 | openpic_hookup_cascade(NUM_8259_INTERRUPTS, "82c59 cascade", | ||
971 | i8259_irq); | ||
972 | } | ||
973 | for ( i = 0 ; i < NUM_8259_INTERRUPTS ; i++ ) | ||
974 | irq_desc[i].handler = &i8259_pic; | ||
975 | |||
976 | if (have_residual_data) { | ||
977 | i8259_init(residual_isapic_addr()); | ||
978 | return; | ||
979 | } | ||
980 | |||
981 | /* If we have a Raven PCI bridge or a Hawk PCI bridge / Memory | ||
982 | * controller, we poll (as they have a different int-ack address). */ | ||
983 | early_read_config_dword(NULL, 0, 0, PCI_VENDOR_ID, &pci_viddid); | ||
984 | pci_did = (pci_viddid & 0xffff0000) >> 16; | ||
985 | if (((pci_viddid & 0xffff) == PCI_VENDOR_ID_MOTOROLA) | ||
986 | && ((pci_did == PCI_DEVICE_ID_MOTOROLA_RAVEN) | ||
987 | || (pci_did == PCI_DEVICE_ID_MOTOROLA_HAWK))) | ||
988 | i8259_init(0); | ||
989 | else | ||
990 | /* PCI interrupt ack address given in section 6.1.8 of the | ||
991 | * PReP specification. */ | ||
992 | i8259_init(MPC10X_MAPA_PCI_INTACK_ADDR); | ||
993 | } | ||
994 | |||
995 | #if defined(CONFIG_BLK_DEV_IDE) || defined(CONFIG_BLK_DEV_IDE_MODULE) | ||
996 | /* | ||
997 | * IDE stuff. | ||
998 | */ | ||
999 | static int __prep | ||
1000 | prep_ide_default_irq(unsigned long base) | ||
1001 | { | ||
1002 | switch (base) { | ||
1003 | case 0x1f0: return 13; | ||
1004 | case 0x170: return 13; | ||
1005 | case 0x1e8: return 11; | ||
1006 | case 0x168: return 10; | ||
1007 | case 0xfff0: return 14; /* MCP(N)750 ide0 */ | ||
1008 | case 0xffe0: return 15; /* MCP(N)750 ide1 */ | ||
1009 | default: return 0; | ||
1010 | } | ||
1011 | } | ||
1012 | |||
1013 | static unsigned long __prep | ||
1014 | prep_ide_default_io_base(int index) | ||
1015 | { | ||
1016 | switch (index) { | ||
1017 | case 0: return 0x1f0; | ||
1018 | case 1: return 0x170; | ||
1019 | case 2: return 0x1e8; | ||
1020 | case 3: return 0x168; | ||
1021 | default: | ||
1022 | return 0; | ||
1023 | } | ||
1024 | } | ||
1025 | #endif | ||
1026 | |||
1027 | #ifdef CONFIG_SMP | ||
1028 | /* PReP (MTX) support */ | ||
1029 | static int __init | ||
1030 | smp_prep_probe(void) | ||
1031 | { | ||
1032 | extern int mot_multi; | ||
1033 | |||
1034 | if (mot_multi) { | ||
1035 | openpic_request_IPIs(); | ||
1036 | smp_hw_index[1] = 1; | ||
1037 | return 2; | ||
1038 | } | ||
1039 | |||
1040 | return 1; | ||
1041 | } | ||
1042 | |||
1043 | static void __init | ||
1044 | smp_prep_kick_cpu(int nr) | ||
1045 | { | ||
1046 | *(unsigned long *)KERNELBASE = nr; | ||
1047 | asm volatile("dcbf 0,%0"::"r"(KERNELBASE):"memory"); | ||
1048 | printk("CPU1 released, waiting\n"); | ||
1049 | } | ||
1050 | |||
1051 | static void __init | ||
1052 | smp_prep_setup_cpu(int cpu_nr) | ||
1053 | { | ||
1054 | if (OpenPIC_Addr) | ||
1055 | do_openpic_setup_cpu(); | ||
1056 | } | ||
1057 | |||
1058 | static struct smp_ops_t prep_smp_ops __prepdata = { | ||
1059 | smp_openpic_message_pass, | ||
1060 | smp_prep_probe, | ||
1061 | smp_prep_kick_cpu, | ||
1062 | smp_prep_setup_cpu, | ||
1063 | .give_timebase = smp_generic_give_timebase, | ||
1064 | .take_timebase = smp_generic_take_timebase, | ||
1065 | }; | ||
1066 | #endif /* CONFIG_SMP */ | ||
1067 | |||
1068 | /* | ||
1069 | * Setup the bat mappings we're going to load that cover | ||
1070 | * the io areas. RAM was mapped by mapin_ram(). | ||
1071 | * -- Cort | ||
1072 | */ | ||
1073 | static void __init | ||
1074 | prep_map_io(void) | ||
1075 | { | ||
1076 | io_block_mapping(0x80000000, PREP_ISA_IO_BASE, 0x10000000, _PAGE_IO); | ||
1077 | io_block_mapping(0xf0000000, PREP_ISA_MEM_BASE, 0x08000000, _PAGE_IO); | ||
1078 | } | ||
1079 | |||
1080 | static int __init | ||
1081 | prep_request_io(void) | ||
1082 | { | ||
1083 | if (_machine == _MACH_prep) { | ||
1084 | #ifdef CONFIG_NVRAM | ||
1085 | request_region(PREP_NVRAM_AS0, 0x8, "nvram"); | ||
1086 | #endif | ||
1087 | request_region(0x00,0x20,"dma1"); | ||
1088 | request_region(0x40,0x20,"timer"); | ||
1089 | request_region(0x80,0x10,"dma page reg"); | ||
1090 | request_region(0xc0,0x20,"dma2"); | ||
1091 | } | ||
1092 | |||
1093 | return 0; | ||
1094 | } | ||
1095 | |||
1096 | device_initcall(prep_request_io); | ||
1097 | |||
1098 | void __init | ||
1099 | prep_init(unsigned long r3, unsigned long r4, unsigned long r5, | ||
1100 | unsigned long r6, unsigned long r7) | ||
1101 | { | ||
1102 | #ifdef CONFIG_PREP_RESIDUAL | ||
1103 | /* make a copy of residual data */ | ||
1104 | if ( r3 ) { | ||
1105 | memcpy((void *)res,(void *)(r3+KERNELBASE), | ||
1106 | sizeof(RESIDUAL)); | ||
1107 | } | ||
1108 | #endif | ||
1109 | |||
1110 | isa_io_base = PREP_ISA_IO_BASE; | ||
1111 | isa_mem_base = PREP_ISA_MEM_BASE; | ||
1112 | pci_dram_offset = PREP_PCI_DRAM_OFFSET; | ||
1113 | ISA_DMA_THRESHOLD = 0x00ffffff; | ||
1114 | DMA_MODE_READ = 0x44; | ||
1115 | DMA_MODE_WRITE = 0x48; | ||
1116 | |||
1117 | /* figure out what kind of prep workstation we are */ | ||
1118 | if (have_residual_data) { | ||
1119 | if ( !strncmp(res->VitalProductData.PrintableModel,"IBM",3) ) | ||
1120 | _prep_type = _PREP_IBM; | ||
1121 | else | ||
1122 | _prep_type = _PREP_Motorola; | ||
1123 | } | ||
1124 | else { | ||
1125 | /* assume motorola if no residual (netboot?) */ | ||
1126 | _prep_type = _PREP_Motorola; | ||
1127 | } | ||
1128 | |||
1129 | #ifdef CONFIG_PREP_RESIDUAL | ||
1130 | /* Switch off all residual data processing if the user requests it */ | ||
1131 | if (strstr(cmd_line, "noresidual") != NULL) | ||
1132 | res = NULL; | ||
1133 | #endif | ||
1134 | |||
1135 | /* Initialise progress early to get maximum benefit */ | ||
1136 | prep_set_bat(); | ||
1137 | ibm_statusled_init(); | ||
1138 | |||
1139 | ppc_md.setup_arch = prep_setup_arch; | ||
1140 | ppc_md.show_percpuinfo = prep_show_percpuinfo; | ||
1141 | ppc_md.show_cpuinfo = NULL; /* set in prep_setup_arch() */ | ||
1142 | ppc_md.irq_canonicalize = prep_irq_canonicalize; | ||
1143 | ppc_md.init_IRQ = prep_init_IRQ; | ||
1144 | /* this gets changed later on if we have an OpenPIC -- Cort */ | ||
1145 | ppc_md.get_irq = i8259_irq; | ||
1146 | |||
1147 | ppc_md.phys_mem_access_prot = pci_phys_mem_access_prot; | ||
1148 | |||
1149 | ppc_md.restart = prep_restart; | ||
1150 | ppc_md.power_off = NULL; /* set in prep_setup_arch() */ | ||
1151 | ppc_md.halt = prep_halt; | ||
1152 | |||
1153 | ppc_md.nvram_read_val = prep_nvram_read_val; | ||
1154 | ppc_md.nvram_write_val = prep_nvram_write_val; | ||
1155 | |||
1156 | ppc_md.time_init = todc_time_init; | ||
1157 | if (_prep_type == _PREP_IBM) { | ||
1158 | ppc_md.rtc_read_val = todc_mc146818_read_val; | ||
1159 | ppc_md.rtc_write_val = todc_mc146818_write_val; | ||
1160 | TODC_INIT(TODC_TYPE_MC146818, RTC_PORT(0), NULL, RTC_PORT(1), | ||
1161 | 8); | ||
1162 | } else { | ||
1163 | TODC_INIT(TODC_TYPE_MK48T59, PREP_NVRAM_AS0, PREP_NVRAM_AS1, | ||
1164 | PREP_NVRAM_DATA, 8); | ||
1165 | } | ||
1166 | |||
1167 | ppc_md.calibrate_decr = prep_calibrate_decr; | ||
1168 | ppc_md.set_rtc_time = todc_set_rtc_time; | ||
1169 | ppc_md.get_rtc_time = todc_get_rtc_time; | ||
1170 | |||
1171 | ppc_md.setup_io_mappings = prep_map_io; | ||
1172 | |||
1173 | #if defined(CONFIG_BLK_DEV_IDE) || defined(CONFIG_BLK_DEV_IDE_MODULE) | ||
1174 | ppc_ide_md.default_irq = prep_ide_default_irq; | ||
1175 | ppc_ide_md.default_io_base = prep_ide_default_io_base; | ||
1176 | #endif | ||
1177 | |||
1178 | #ifdef CONFIG_SMP | ||
1179 | ppc_md.smp_ops = &prep_smp_ops; | ||
1180 | #endif /* CONFIG_SMP */ | ||
1181 | } | ||
diff --git a/arch/ppc/platforms/prpmc750.c b/arch/ppc/platforms/prpmc750.c new file mode 100644 index 000000000000..c894e1ab5934 --- /dev/null +++ b/arch/ppc/platforms/prpmc750.c | |||
@@ -0,0 +1,364 @@ | |||
1 | /* | ||
2 | * arch/ppc/platforms/prpmc750_setup.c | ||
3 | * | ||
4 | * Board setup routines for Motorola PrPMC750 | ||
5 | * | ||
6 | * Author: Matt Porter <mporter@mvista.com> | ||
7 | * | ||
8 | * 2001-2004 (c) MontaVista, Software, Inc. This file is licensed under | ||
9 | * the terms of the GNU General Public License version 2. This program | ||
10 | * is licensed "as is" without any warranty of any kind, whether express | ||
11 | * or implied. | ||
12 | */ | ||
13 | |||
14 | #include <linux/config.h> | ||
15 | #include <linux/stddef.h> | ||
16 | #include <linux/kernel.h> | ||
17 | #include <linux/init.h> | ||
18 | #include <linux/errno.h> | ||
19 | #include <linux/reboot.h> | ||
20 | #include <linux/pci.h> | ||
21 | #include <linux/kdev_t.h> | ||
22 | #include <linux/types.h> | ||
23 | #include <linux/major.h> | ||
24 | #include <linux/initrd.h> | ||
25 | #include <linux/console.h> | ||
26 | #include <linux/delay.h> | ||
27 | #include <linux/irq.h> | ||
28 | #include <linux/seq_file.h> | ||
29 | #include <linux/ide.h> | ||
30 | #include <linux/root_dev.h> | ||
31 | #include <linux/slab.h> | ||
32 | |||
33 | #include <asm/byteorder.h> | ||
34 | #include <asm/system.h> | ||
35 | #include <asm/pgtable.h> | ||
36 | #include <asm/page.h> | ||
37 | #include <asm/dma.h> | ||
38 | #include <asm/io.h> | ||
39 | #include <asm/irq.h> | ||
40 | #include <asm/machdep.h> | ||
41 | #include <asm/pci-bridge.h> | ||
42 | #include <asm/uaccess.h> | ||
43 | #include <asm/time.h> | ||
44 | #include <asm/open_pic.h> | ||
45 | #include <asm/bootinfo.h> | ||
46 | #include <asm/hawk.h> | ||
47 | |||
48 | #include "prpmc750.h" | ||
49 | |||
50 | extern unsigned long loops_per_jiffy; | ||
51 | |||
52 | extern void gen550_progress(char *, unsigned short); | ||
53 | |||
54 | static u_char prpmc750_openpic_initsenses[] __initdata = | ||
55 | { | ||
56 | (IRQ_SENSE_LEVEL | IRQ_POLARITY_NEGATIVE), /* PRPMC750_INT_HOSTINT0 */ | ||
57 | (IRQ_SENSE_LEVEL | IRQ_POLARITY_NEGATIVE), /* PRPMC750_INT_UART */ | ||
58 | (IRQ_SENSE_LEVEL | IRQ_POLARITY_NEGATIVE), /* PRPMC750_INT_DEBUGINT */ | ||
59 | (IRQ_SENSE_LEVEL | IRQ_POLARITY_NEGATIVE), /* PRPMC750_INT_HAWK_WDT */ | ||
60 | (IRQ_SENSE_LEVEL | IRQ_POLARITY_NEGATIVE), /* PRPMC750_INT_UNUSED */ | ||
61 | (IRQ_SENSE_LEVEL | IRQ_POLARITY_NEGATIVE), /* PRPMC750_INT_ABORT */ | ||
62 | (IRQ_SENSE_LEVEL | IRQ_POLARITY_NEGATIVE), /* PRPMC750_INT_HOSTINT1 */ | ||
63 | (IRQ_SENSE_LEVEL | IRQ_POLARITY_NEGATIVE), /* PRPMC750_INT_HOSTINT2 */ | ||
64 | (IRQ_SENSE_LEVEL | IRQ_POLARITY_NEGATIVE), /* PRPMC750_INT_HOSTINT3 */ | ||
65 | (IRQ_SENSE_LEVEL | IRQ_POLARITY_NEGATIVE), /* PRPMC750_INT_PMC_INTA */ | ||
66 | (IRQ_SENSE_LEVEL | IRQ_POLARITY_NEGATIVE), /* PRPMC750_INT_PMC_INTB */ | ||
67 | (IRQ_SENSE_LEVEL | IRQ_POLARITY_NEGATIVE), /* PRPMC750_INT_PMC_INTC */ | ||
68 | (IRQ_SENSE_LEVEL | IRQ_POLARITY_NEGATIVE), /* PRPMC750_INT_PMC_INTD */ | ||
69 | (IRQ_SENSE_LEVEL | IRQ_POLARITY_NEGATIVE), /* PRPMC750_INT_UNUSED */ | ||
70 | (IRQ_SENSE_LEVEL | IRQ_POLARITY_NEGATIVE), /* PRPMC750_INT_UNUSED */ | ||
71 | (IRQ_SENSE_LEVEL | IRQ_POLARITY_NEGATIVE), /* PRPMC750_INT_UNUSED */ | ||
72 | }; | ||
73 | |||
74 | /* | ||
75 | * Motorola PrPMC750/PrPMC800 in PrPMCBASE or PrPMC-Carrier | ||
76 | * Combined irq tables. Only Base has IDSEL 14, only Carrier has 21 and 22. | ||
77 | */ | ||
78 | static inline int | ||
79 | prpmc_map_irq(struct pci_dev *dev, unsigned char idsel, unsigned char pin) | ||
80 | { | ||
81 | static char pci_irq_table[][4] = | ||
82 | /* | ||
83 | * PCI IDSEL/INTPIN->INTLINE | ||
84 | * A B C D | ||
85 | */ | ||
86 | { | ||
87 | {12, 0, 0, 0}, /* IDSEL 14 - Ethernet, base */ | ||
88 | {0, 0, 0, 0}, /* IDSEL 15 - unused */ | ||
89 | {10, 11, 12, 9}, /* IDSEL 16 - PMC A1, PMC1 */ | ||
90 | {10, 11, 12, 9}, /* IDSEL 17 - PrPMC-A-B, PMC2-B */ | ||
91 | {11, 12, 9, 10}, /* IDSEL 18 - PMC A1-B, PMC1-B */ | ||
92 | {0, 0, 0, 0}, /* IDSEL 19 - unused */ | ||
93 | {9, 10, 11, 12}, /* IDSEL 20 - P2P Bridge */ | ||
94 | {11, 12, 9, 10}, /* IDSEL 21 - PMC A2, carrier */ | ||
95 | {12, 9, 10, 11}, /* IDSEL 22 - PMC A2-B, carrier */ | ||
96 | }; | ||
97 | const long min_idsel = 14, max_idsel = 22, irqs_per_slot = 4; | ||
98 | return PCI_IRQ_TABLE_LOOKUP; | ||
99 | }; | ||
100 | |||
101 | static void __init prpmc750_pcibios_fixup(void) | ||
102 | { | ||
103 | struct pci_dev *dev; | ||
104 | unsigned short wtmp; | ||
105 | |||
106 | /* | ||
107 | * Kludge to clean up after PPC6BUG which doesn't | ||
108 | * configure the CL5446 VGA card. Also the | ||
109 | * resource subsystem doesn't fixup the | ||
110 | * PCI mem resources on the CL5446. | ||
111 | */ | ||
112 | if ((dev = pci_get_device(PCI_VENDOR_ID_CIRRUS, | ||
113 | PCI_DEVICE_ID_CIRRUS_5446, 0))) { | ||
114 | dev->resource[0].start += PRPMC750_PCI_PHY_MEM_OFFSET; | ||
115 | dev->resource[0].end += PRPMC750_PCI_PHY_MEM_OFFSET; | ||
116 | pci_read_config_word(dev, PCI_COMMAND, &wtmp); | ||
117 | pci_write_config_word(dev, PCI_COMMAND, wtmp | 3); | ||
118 | /* Enable Color mode in MISC reg */ | ||
119 | outb(0x03, 0x3c2); | ||
120 | /* Select DRAM config reg */ | ||
121 | outb(0x0f, 0x3c4); | ||
122 | /* Set proper DRAM config */ | ||
123 | outb(0xdf, 0x3c5); | ||
124 | pci_dev_put(dev); | ||
125 | } | ||
126 | } | ||
127 | |||
128 | void __init prpmc750_find_bridges(void) | ||
129 | { | ||
130 | struct pci_controller *hose; | ||
131 | |||
132 | hose = pcibios_alloc_controller(); | ||
133 | if (!hose) | ||
134 | return; | ||
135 | |||
136 | hose->first_busno = 0; | ||
137 | hose->last_busno = 0xff; | ||
138 | hose->io_base_virt = (void *)PRPMC750_ISA_IO_BASE; | ||
139 | hose->pci_mem_offset = PRPMC750_PCI_PHY_MEM_OFFSET; | ||
140 | |||
141 | pci_init_resource(&hose->io_resource, | ||
142 | PRPMC750_PCI_IO_START, | ||
143 | PRPMC750_PCI_IO_END, | ||
144 | IORESOURCE_IO, "PCI host bridge"); | ||
145 | |||
146 | pci_init_resource(&hose->mem_resources[0], | ||
147 | PRPMC750_PROC_PCI_MEM_START, | ||
148 | PRPMC750_PROC_PCI_MEM_END, | ||
149 | IORESOURCE_MEM, "PCI host bridge"); | ||
150 | |||
151 | hose->io_space.start = PRPMC750_PCI_IO_START; | ||
152 | hose->io_space.end = PRPMC750_PCI_IO_END; | ||
153 | hose->mem_space.start = PRPMC750_PCI_MEM_START; | ||
154 | hose->mem_space.end = PRPMC750_PCI_MEM_END - HAWK_MPIC_SIZE; | ||
155 | |||
156 | if (hawk_init(hose, PRPMC750_HAWK_PPC_REG_BASE, | ||
157 | PRPMC750_PROC_PCI_MEM_START, | ||
158 | PRPMC750_PROC_PCI_MEM_END - HAWK_MPIC_SIZE, | ||
159 | PRPMC750_PROC_PCI_IO_START, PRPMC750_PROC_PCI_IO_END, | ||
160 | PRPMC750_PROC_PCI_MEM_END - HAWK_MPIC_SIZE + 1) | ||
161 | != 0) { | ||
162 | printk(KERN_CRIT "Could not initialize host bridge\n"); | ||
163 | } | ||
164 | |||
165 | hose->last_busno = pciauto_bus_scan(hose, hose->first_busno); | ||
166 | |||
167 | ppc_md.pcibios_fixup = prpmc750_pcibios_fixup; | ||
168 | ppc_md.pci_swizzle = common_swizzle; | ||
169 | ppc_md.pci_map_irq = prpmc_map_irq; | ||
170 | } | ||
171 | static int prpmc750_show_cpuinfo(struct seq_file *m) | ||
172 | { | ||
173 | seq_printf(m, "machine\t\t: PrPMC750\n"); | ||
174 | |||
175 | return 0; | ||
176 | } | ||
177 | |||
178 | static void __init prpmc750_setup_arch(void) | ||
179 | { | ||
180 | /* init to some ~sane value until calibrate_delay() runs */ | ||
181 | loops_per_jiffy = 50000000 / HZ; | ||
182 | |||
183 | /* Lookup PCI host bridges */ | ||
184 | prpmc750_find_bridges(); | ||
185 | |||
186 | #ifdef CONFIG_BLK_DEV_INITRD | ||
187 | if (initrd_start) | ||
188 | ROOT_DEV = Root_RAM0; | ||
189 | else | ||
190 | #endif | ||
191 | #ifdef CONFIG_ROOT_NFS | ||
192 | ROOT_DEV = Root_NFS; | ||
193 | #else | ||
194 | ROOT_DEV = Root_SDA2; | ||
195 | #endif | ||
196 | |||
197 | OpenPIC_InitSenses = prpmc750_openpic_initsenses; | ||
198 | OpenPIC_NumInitSenses = sizeof(prpmc750_openpic_initsenses); | ||
199 | |||
200 | printk(KERN_INFO "Port by MontaVista Software, Inc. " | ||
201 | "(source@mvista.com)\n"); | ||
202 | } | ||
203 | |||
204 | /* | ||
205 | * Compute the PrPMC750's bus speed using the baud clock as a | ||
206 | * reference. | ||
207 | */ | ||
208 | static unsigned long __init prpmc750_get_bus_speed(void) | ||
209 | { | ||
210 | unsigned long tbl_start, tbl_end; | ||
211 | unsigned long current_state, old_state, bus_speed; | ||
212 | unsigned char lcr, dll, dlm; | ||
213 | int baud_divisor, count; | ||
214 | |||
215 | /* Read the UART's baud clock divisor */ | ||
216 | lcr = readb(PRPMC750_SERIAL_0_LCR); | ||
217 | writeb(lcr | UART_LCR_DLAB, PRPMC750_SERIAL_0_LCR); | ||
218 | dll = readb(PRPMC750_SERIAL_0_DLL); | ||
219 | dlm = readb(PRPMC750_SERIAL_0_DLM); | ||
220 | writeb(lcr & ~UART_LCR_DLAB, PRPMC750_SERIAL_0_LCR); | ||
221 | baud_divisor = (dlm << 8) | dll; | ||
222 | |||
223 | /* | ||
224 | * Use the baud clock divisor and base baud clock | ||
225 | * to determine the baud rate and use that as | ||
226 | * the number of baud clock edges we use for | ||
227 | * the time base sample. Make it half the baud | ||
228 | * rate. | ||
229 | */ | ||
230 | count = PRPMC750_BASE_BAUD / (baud_divisor * 16); | ||
231 | |||
232 | /* Find the first edge of the baud clock */ | ||
233 | old_state = readb(PRPMC750_STATUS_REG) & PRPMC750_BAUDOUT_MASK; | ||
234 | do { | ||
235 | current_state = readb(PRPMC750_STATUS_REG) & | ||
236 | PRPMC750_BAUDOUT_MASK; | ||
237 | } while (old_state == current_state); | ||
238 | |||
239 | old_state = current_state; | ||
240 | |||
241 | /* Get the starting time base value */ | ||
242 | tbl_start = get_tbl(); | ||
243 | |||
244 | /* | ||
245 | * Loop until we have found a number of edges equal | ||
246 | * to half the count (half the baud rate) | ||
247 | */ | ||
248 | do { | ||
249 | do { | ||
250 | current_state = readb(PRPMC750_STATUS_REG) & | ||
251 | PRPMC750_BAUDOUT_MASK; | ||
252 | } while (old_state == current_state); | ||
253 | old_state = current_state; | ||
254 | } while (--count); | ||
255 | |||
256 | /* Get the ending time base value */ | ||
257 | tbl_end = get_tbl(); | ||
258 | |||
259 | /* Compute bus speed */ | ||
260 | bus_speed = (tbl_end - tbl_start) * 128; | ||
261 | |||
262 | return bus_speed; | ||
263 | } | ||
264 | |||
265 | static void __init prpmc750_calibrate_decr(void) | ||
266 | { | ||
267 | unsigned long freq; | ||
268 | int divisor = 4; | ||
269 | |||
270 | freq = prpmc750_get_bus_speed(); | ||
271 | |||
272 | tb_ticks_per_jiffy = freq / (HZ * divisor); | ||
273 | tb_to_us = mulhwu_scale_factor(freq / divisor, 1000000); | ||
274 | } | ||
275 | |||
276 | static void prpmc750_restart(char *cmd) | ||
277 | { | ||
278 | local_irq_disable(); | ||
279 | writeb(PRPMC750_MODRST_MASK, PRPMC750_MODRST_REG); | ||
280 | while (1) ; | ||
281 | } | ||
282 | |||
283 | static void prpmc750_halt(void) | ||
284 | { | ||
285 | local_irq_disable(); | ||
286 | while (1) ; | ||
287 | } | ||
288 | |||
289 | static void prpmc750_power_off(void) | ||
290 | { | ||
291 | prpmc750_halt(); | ||
292 | } | ||
293 | |||
294 | static void __init prpmc750_init_IRQ(void) | ||
295 | { | ||
296 | openpic_init(0); | ||
297 | } | ||
298 | |||
299 | /* | ||
300 | * Set BAT 3 to map 0xf0000000 to end of physical memory space. | ||
301 | */ | ||
302 | static __inline__ void prpmc750_set_bat(void) | ||
303 | { | ||
304 | mb(); | ||
305 | mtspr(SPRN_DBAT1U, 0xf0001ffe); | ||
306 | mtspr(SPRN_DBAT1L, 0xf000002a); | ||
307 | mb(); | ||
308 | } | ||
309 | |||
310 | /* | ||
311 | * We need to read the Falcon/Hawk memory controller | ||
312 | * to properly determine this value | ||
313 | */ | ||
314 | static unsigned long __init prpmc750_find_end_of_memory(void) | ||
315 | { | ||
316 | /* Read the memory size from the Hawk SMC */ | ||
317 | return hawk_get_mem_size(PRPMC750_HAWK_SMC_BASE); | ||
318 | } | ||
319 | |||
320 | static void __init prpmc750_map_io(void) | ||
321 | { | ||
322 | io_block_mapping(PRPMC750_ISA_IO_BASE, PRPMC750_ISA_IO_BASE, | ||
323 | 0x10000000, _PAGE_IO); | ||
324 | #if 0 | ||
325 | io_block_mapping(0xf0000000, 0xc0000000, 0x08000000, _PAGE_IO); | ||
326 | #endif | ||
327 | io_block_mapping(0xf8000000, 0xf8000000, 0x08000000, _PAGE_IO); | ||
328 | } | ||
329 | |||
330 | void __init | ||
331 | platform_init(unsigned long r3, unsigned long r4, unsigned long r5, | ||
332 | unsigned long r6, unsigned long r7) | ||
333 | { | ||
334 | parse_bootinfo(find_bootinfo()); | ||
335 | |||
336 | /* Cover the Hawk registers with a BAT */ | ||
337 | prpmc750_set_bat(); | ||
338 | |||
339 | isa_io_base = PRPMC750_ISA_IO_BASE; | ||
340 | isa_mem_base = PRPMC750_ISA_MEM_BASE; | ||
341 | pci_dram_offset = PRPMC750_PCI_DRAM_OFFSET; | ||
342 | |||
343 | ppc_md.setup_arch = prpmc750_setup_arch; | ||
344 | ppc_md.show_cpuinfo = prpmc750_show_cpuinfo; | ||
345 | ppc_md.init_IRQ = prpmc750_init_IRQ; | ||
346 | ppc_md.get_irq = openpic_get_irq; | ||
347 | |||
348 | ppc_md.find_end_of_memory = prpmc750_find_end_of_memory; | ||
349 | ppc_md.setup_io_mappings = prpmc750_map_io; | ||
350 | |||
351 | ppc_md.restart = prpmc750_restart; | ||
352 | ppc_md.power_off = prpmc750_power_off; | ||
353 | ppc_md.halt = prpmc750_halt; | ||
354 | |||
355 | /* PrPMC750 has no timekeeper part */ | ||
356 | ppc_md.time_init = NULL; | ||
357 | ppc_md.get_rtc_time = NULL; | ||
358 | ppc_md.set_rtc_time = NULL; | ||
359 | ppc_md.calibrate_decr = prpmc750_calibrate_decr; | ||
360 | |||
361 | #ifdef CONFIG_SERIAL_TEXT_DEBUG | ||
362 | ppc_md.progress = gen550_progress; | ||
363 | #endif /* CONFIG_SERIAL_TEXT_DEBUG */ | ||
364 | } | ||
diff --git a/arch/ppc/platforms/prpmc750.h b/arch/ppc/platforms/prpmc750.h new file mode 100644 index 000000000000..015b4f52c3eb --- /dev/null +++ b/arch/ppc/platforms/prpmc750.h | |||
@@ -0,0 +1,95 @@ | |||
1 | /* | ||
2 | * include/asm-ppc/platforms/prpmc750.h | ||
3 | * | ||
4 | * Definitions for Motorola PrPMC750 board support | ||
5 | * | ||
6 | * Author: Matt Porter <mporter@mvista.com> | ||
7 | * | ||
8 | * 2001-2004 (c) MontaVista, Software, Inc. This file is licensed under | ||
9 | * the terms of the GNU General Public License version 2. This program | ||
10 | * is licensed "as is" without any warranty of any kind, whether express | ||
11 | * or implied. | ||
12 | */ | ||
13 | |||
14 | #ifdef __KERNEL__ | ||
15 | #ifndef __ASM_PRPMC750_H__ | ||
16 | #define __ASM_PRPMC750_H__ | ||
17 | |||
18 | /* | ||
19 | * Due to limiations imposed by legacy hardware (primaryily IDE controllers), | ||
20 | * the PrPMC750 carrier board operates using a PReP address map. | ||
21 | * | ||
22 | * From Processor (physical) -> PCI: | ||
23 | * PCI Mem Space: 0xc0000000 - 0xfe000000 -> 0x00000000 - 0x3e000000 (768 MB) | ||
24 | * PCI I/O Space: 0x80000000 - 0x90000000 -> 0x00000000 - 0x10000000 (256 MB) | ||
25 | * Note: Must skip 0xfe000000-0xfe400000 for CONFIG_HIGHMEM/PKMAP area | ||
26 | * | ||
27 | * From PCI -> Processor (physical): | ||
28 | * System Memory: 0x80000000 -> 0x00000000 | ||
29 | */ | ||
30 | |||
31 | #define PRPMC750_ISA_IO_BASE PREP_ISA_IO_BASE | ||
32 | #define PRPMC750_ISA_MEM_BASE PREP_ISA_MEM_BASE | ||
33 | |||
34 | /* PCI Memory space mapping info */ | ||
35 | #define PRPMC750_PCI_MEM_SIZE 0x30000000U | ||
36 | #define PRPMC750_PROC_PCI_MEM_START PRPMC750_ISA_MEM_BASE | ||
37 | #define PRPMC750_PROC_PCI_MEM_END (PRPMC750_PROC_PCI_MEM_START + \ | ||
38 | PRPMC750_PCI_MEM_SIZE - 1) | ||
39 | #define PRPMC750_PCI_MEM_START 0x00000000U | ||
40 | #define PRPMC750_PCI_MEM_END (PRPMC750_PCI_MEM_START + \ | ||
41 | PRPMC750_PCI_MEM_SIZE - 1) | ||
42 | |||
43 | /* PCI I/O space mapping info */ | ||
44 | #define PRPMC750_PCI_IO_SIZE 0x10000000U | ||
45 | #define PRPMC750_PROC_PCI_IO_START PRPMC750_ISA_IO_BASE | ||
46 | #define PRPMC750_PROC_PCI_IO_END (PRPMC750_PROC_PCI_IO_START + \ | ||
47 | PRPMC750_PCI_IO_SIZE - 1) | ||
48 | #define PRPMC750_PCI_IO_START 0x00000000U | ||
49 | #define PRPMC750_PCI_IO_END (PRPMC750_PCI_IO_START + \ | ||
50 | PRPMC750_PCI_IO_SIZE - 1) | ||
51 | |||
52 | /* System memory mapping info */ | ||
53 | #define PRPMC750_PCI_DRAM_OFFSET PREP_PCI_DRAM_OFFSET | ||
54 | #define PRPMC750_PCI_PHY_MEM_OFFSET (PRPMC750_ISA_MEM_BASE-PRPMC750_PCI_MEM_START) | ||
55 | |||
56 | /* Register address definitions */ | ||
57 | #define PRPMC750_HAWK_SMC_BASE 0xfef80000U | ||
58 | #define PRPMC750_HAWK_PPC_REG_BASE 0xfeff0000U | ||
59 | |||
60 | #define PRPMC750_BASE_BAUD 1843200 | ||
61 | #define PRPMC750_SERIAL_0 0xfef88000 | ||
62 | #define PRPMC750_SERIAL_0_DLL (PRPMC750_SERIAL_0 + (UART_DLL << 4)) | ||
63 | #define PRPMC750_SERIAL_0_DLM (PRPMC750_SERIAL_0 + (UART_DLM << 4)) | ||
64 | #define PRPMC750_SERIAL_0_LCR (PRPMC750_SERIAL_0 + (UART_LCR << 4)) | ||
65 | |||
66 | #define PRPMC750_STATUS_REG 0xfef88080 | ||
67 | #define PRPMC750_BAUDOUT_MASK 0x02 | ||
68 | #define PRPMC750_MONARCH_MASK 0x01 | ||
69 | |||
70 | #define PRPMC750_MODRST_REG 0xfef880a0 | ||
71 | #define PRPMC750_MODRST_MASK 0x01 | ||
72 | |||
73 | #define PRPMC750_PIRQ_REG 0xfef880b0 | ||
74 | #define PRPMC750_SEL1_MASK 0x02 | ||
75 | #define PRPMC750_SEL0_MASK 0x01 | ||
76 | |||
77 | #define PRPMC750_TBEN_REG 0xfef880c0 | ||
78 | #define PRPMC750_TBEN_MASK 0x01 | ||
79 | |||
80 | /* UART Defines. */ | ||
81 | #define RS_TABLE_SIZE 4 | ||
82 | |||
83 | /* Rate for the 1.8432 Mhz clock for the onboard serial chip */ | ||
84 | #define BASE_BAUD (PRPMC750_BASE_BAUD / 16) | ||
85 | |||
86 | #define STD_COM_FLAGS ASYNC_BOOT_AUTOCONF | ||
87 | |||
88 | #define SERIAL_PORT_DFNS \ | ||
89 | { 0, BASE_BAUD, PRPMC750_SERIAL_0, 1, STD_COM_FLAGS, \ | ||
90 | iomem_base: (unsigned char *)PRPMC750_SERIAL_0, \ | ||
91 | iomem_reg_shift: 4, \ | ||
92 | io_type: SERIAL_IO_MEM } /* ttyS0 */ | ||
93 | |||
94 | #endif /* __ASM_PRPMC750_H__ */ | ||
95 | #endif /* __KERNEL__ */ | ||
diff --git a/arch/ppc/platforms/prpmc800.c b/arch/ppc/platforms/prpmc800.c new file mode 100644 index 000000000000..8b09fa69b35b --- /dev/null +++ b/arch/ppc/platforms/prpmc800.c | |||
@@ -0,0 +1,477 @@ | |||
1 | /* | ||
2 | * arch/ppc/platforms/prpmc800.c | ||
3 | * | ||
4 | * Author: Dale Farnsworth <dale.farnsworth@mvista.com> | ||
5 | * | ||
6 | * 2001-2004 (c) MontaVista, Software, Inc. This file is licensed under | ||
7 | * the terms of the GNU General Public License version 2. This program | ||
8 | * is licensed "as is" without any warranty of any kind, whether express | ||
9 | * or implied. | ||
10 | */ | ||
11 | |||
12 | #include <linux/config.h> | ||
13 | #include <linux/stddef.h> | ||
14 | #include <linux/kernel.h> | ||
15 | #include <linux/init.h> | ||
16 | #include <linux/errno.h> | ||
17 | #include <linux/reboot.h> | ||
18 | #include <linux/pci.h> | ||
19 | #include <linux/kdev_t.h> | ||
20 | #include <linux/types.h> | ||
21 | #include <linux/major.h> | ||
22 | #include <linux/initrd.h> | ||
23 | #include <linux/console.h> | ||
24 | #include <linux/delay.h> | ||
25 | #include <linux/irq.h> | ||
26 | #include <linux/seq_file.h> | ||
27 | #include <linux/ide.h> | ||
28 | #include <linux/root_dev.h> | ||
29 | #include <linux/harrier_defs.h> | ||
30 | |||
31 | #include <asm/byteorder.h> | ||
32 | #include <asm/system.h> | ||
33 | #include <asm/pgtable.h> | ||
34 | #include <asm/page.h> | ||
35 | #include <asm/dma.h> | ||
36 | #include <asm/io.h> | ||
37 | #include <asm/irq.h> | ||
38 | #include <asm/machdep.h> | ||
39 | #include <asm/time.h> | ||
40 | #include <asm/pci-bridge.h> | ||
41 | #include <asm/open_pic.h> | ||
42 | #include <asm/bootinfo.h> | ||
43 | #include <asm/harrier.h> | ||
44 | |||
45 | #include "prpmc800.h" | ||
46 | |||
47 | #define HARRIER_REVI_REG (PRPMC800_HARRIER_XCSR_BASE+HARRIER_REVI_OFF) | ||
48 | #define HARRIER_UCTL_REG (PRPMC800_HARRIER_XCSR_BASE+HARRIER_UCTL_OFF) | ||
49 | #define HARRIER_MISC_CSR_REG (PRPMC800_HARRIER_XCSR_BASE+HARRIER_MISC_CSR_OFF) | ||
50 | #define HARRIER_IFEVP_REG (PRPMC800_HARRIER_MPIC_BASE+HARRIER_MPIC_IFEVP_OFF) | ||
51 | #define HARRIER_IFEDE_REG (PRPMC800_HARRIER_MPIC_BASE+HARRIER_MPIC_IFEDE_OFF) | ||
52 | #define HARRIER_FEEN_REG (PRPMC800_HARRIER_XCSR_BASE+HARRIER_FEEN_OFF) | ||
53 | #define HARRIER_FEMA_REG (PRPMC800_HARRIER_XCSR_BASE+HARRIER_FEMA_OFF) | ||
54 | |||
55 | #define HARRIER_VENI_REG (PRPMC800_HARRIER_XCSR_BASE + HARRIER_VENI_OFF) | ||
56 | #define HARRIER_MISC_CSR (PRPMC800_HARRIER_XCSR_BASE + \ | ||
57 | HARRIER_MISC_CSR_OFF) | ||
58 | |||
59 | #define MONARCH (monarch != 0) | ||
60 | #define NON_MONARCH (monarch == 0) | ||
61 | |||
62 | extern int mpic_init(void); | ||
63 | extern unsigned long loops_per_jiffy; | ||
64 | extern void gen550_progress(char *, unsigned short); | ||
65 | |||
66 | static int monarch = 0; | ||
67 | static int found_self = 0; | ||
68 | static int self = 0; | ||
69 | |||
70 | static u_char prpmc800_openpic_initsenses[] __initdata = | ||
71 | { | ||
72 | (IRQ_SENSE_LEVEL | IRQ_POLARITY_NEGATIVE), /* PRPMC800_INT_HOSTINT0 */ | ||
73 | (IRQ_SENSE_LEVEL | IRQ_POLARITY_NEGATIVE), /* PRPMC800_INT_UNUSED */ | ||
74 | (IRQ_SENSE_LEVEL | IRQ_POLARITY_NEGATIVE), /* PRPMC800_INT_DEBUGINT */ | ||
75 | (IRQ_SENSE_LEVEL | IRQ_POLARITY_NEGATIVE), /* PRPMC800_INT_HARRIER_WDT */ | ||
76 | (IRQ_SENSE_LEVEL | IRQ_POLARITY_NEGATIVE), /* PRPMC800_INT_UNUSED */ | ||
77 | (IRQ_SENSE_LEVEL | IRQ_POLARITY_NEGATIVE), /* PRPMC800_INT_UNUSED */ | ||
78 | (IRQ_SENSE_LEVEL | IRQ_POLARITY_NEGATIVE), /* PRPMC800_INT_HOSTINT1 */ | ||
79 | (IRQ_SENSE_LEVEL | IRQ_POLARITY_NEGATIVE), /* PRPMC800_INT_HOSTINT2 */ | ||
80 | (IRQ_SENSE_LEVEL | IRQ_POLARITY_NEGATIVE), /* PRPMC800_INT_HOSTINT3 */ | ||
81 | (IRQ_SENSE_LEVEL | IRQ_POLARITY_NEGATIVE), /* PRPMC800_INT_PMC_INTA */ | ||
82 | (IRQ_SENSE_LEVEL | IRQ_POLARITY_NEGATIVE), /* PRPMC800_INT_PMC_INTB */ | ||
83 | (IRQ_SENSE_LEVEL | IRQ_POLARITY_NEGATIVE), /* PRPMC800_INT_PMC_INTC */ | ||
84 | (IRQ_SENSE_LEVEL | IRQ_POLARITY_NEGATIVE), /* PRPMC800_INT_PMC_INTD */ | ||
85 | (IRQ_SENSE_LEVEL | IRQ_POLARITY_NEGATIVE), /* PRPMC800_INT_UNUSED */ | ||
86 | (IRQ_SENSE_LEVEL | IRQ_POLARITY_NEGATIVE), /* PRPMC800_INT_UNUSED */ | ||
87 | (IRQ_SENSE_LEVEL | IRQ_POLARITY_NEGATIVE), /* PRPMC800_INT_UNUSED */ | ||
88 | (IRQ_SENSE_LEVEL | IRQ_POLARITY_NEGATIVE), /* PRPMC800_INT_HARRIER_INT (UARTS, ABORT, DMA) */ | ||
89 | }; | ||
90 | |||
91 | /* | ||
92 | * Motorola PrPMC750/PrPMC800 in PrPMCBASE or PrPMC-Carrier | ||
93 | * Combined irq tables. Only Base has IDSEL 14, only Carrier has 21 and 22. | ||
94 | */ | ||
95 | static inline int | ||
96 | prpmc_map_irq(struct pci_dev *dev, unsigned char idsel, unsigned char pin) | ||
97 | { | ||
98 | static char pci_irq_table[][4] = | ||
99 | /* | ||
100 | * PCI IDSEL/INTPIN->INTLINE | ||
101 | * A B C D | ||
102 | */ | ||
103 | { | ||
104 | {12, 0, 0, 0}, /* IDSEL 14 - Ethernet, base */ | ||
105 | {0, 0, 0, 0}, /* IDSEL 15 - unused */ | ||
106 | {10, 11, 12, 9}, /* IDSEL 16 - PMC A1, PMC1 */ | ||
107 | {10, 11, 12, 9}, /* IDSEL 17 - PrPMC-A-B, PMC2-B */ | ||
108 | {11, 12, 9, 10}, /* IDSEL 18 - PMC A1-B, PMC1-B */ | ||
109 | {0, 0, 0, 0}, /* IDSEL 19 - unused */ | ||
110 | {9, 10, 11, 12}, /* IDSEL 20 - P2P Bridge */ | ||
111 | {11, 12, 9, 10}, /* IDSEL 21 - PMC A2, carrier */ | ||
112 | {12, 9, 10, 11}, /* IDSEL 22 - PMC A2-B, carrier */ | ||
113 | }; | ||
114 | const long min_idsel = 14, max_idsel = 22, irqs_per_slot = 4; | ||
115 | return PCI_IRQ_TABLE_LOOKUP; | ||
116 | }; | ||
117 | |||
118 | static int | ||
119 | prpmc_read_config_dword(struct pci_controller *hose, u8 bus, u8 devfn, | ||
120 | int offset, u32 * val) | ||
121 | { | ||
122 | /* paranoia */ | ||
123 | if ((hose == NULL) || | ||
124 | (hose->cfg_addr == NULL) || (hose->cfg_data == NULL)) | ||
125 | return PCIBIOS_DEVICE_NOT_FOUND; | ||
126 | |||
127 | out_be32(hose->cfg_addr, ((offset & 0xfc) << 24) | (devfn << 16) | ||
128 | | ((bus - hose->bus_offset) << 8) | 0x80); | ||
129 | *val = in_le32((u32 *) (hose->cfg_data + (offset & 3))); | ||
130 | |||
131 | return PCIBIOS_SUCCESSFUL; | ||
132 | } | ||
133 | |||
134 | #define HARRIER_PCI_VEND_DEV_ID (PCI_VENDOR_ID_MOTOROLA | \ | ||
135 | (PCI_DEVICE_ID_MOTOROLA_HARRIER << 16)) | ||
136 | static int prpmc_self(u8 bus, u8 devfn) | ||
137 | { | ||
138 | /* | ||
139 | * Harriers always view themselves as being on bus 0. If we're not | ||
140 | * looking at bus 0, we're not going to find ourselves. | ||
141 | */ | ||
142 | if (bus != 0) | ||
143 | return PCIBIOS_DEVICE_NOT_FOUND; | ||
144 | else { | ||
145 | int result; | ||
146 | int val; | ||
147 | struct pci_controller *hose; | ||
148 | |||
149 | hose = pci_bus_to_hose(bus); | ||
150 | |||
151 | /* See if target device is a Harrier */ | ||
152 | result = prpmc_read_config_dword(hose, bus, devfn, | ||
153 | PCI_VENDOR_ID, &val); | ||
154 | if ((result != PCIBIOS_SUCCESSFUL) || | ||
155 | (val != HARRIER_PCI_VEND_DEV_ID)) | ||
156 | return PCIBIOS_DEVICE_NOT_FOUND; | ||
157 | |||
158 | /* | ||
159 | * LBA bit is set if target Harrier == initiating Harrier | ||
160 | * (i.e. if we are reading our own PCI header). | ||
161 | */ | ||
162 | result = prpmc_read_config_dword(hose, bus, devfn, | ||
163 | HARRIER_LBA_OFF, &val); | ||
164 | if ((result != PCIBIOS_SUCCESSFUL) || | ||
165 | ((val & HARRIER_LBA_MSK) != HARRIER_LBA_MSK)) | ||
166 | return PCIBIOS_DEVICE_NOT_FOUND; | ||
167 | |||
168 | /* It's us, save our location for later */ | ||
169 | self = devfn; | ||
170 | found_self = 1; | ||
171 | return PCIBIOS_SUCCESSFUL; | ||
172 | } | ||
173 | } | ||
174 | |||
175 | static int prpmc_exclude_device(u8 bus, u8 devfn) | ||
176 | { | ||
177 | /* | ||
178 | * Monarch is allowed to access all PCI devices. Non-monarch is | ||
179 | * only allowed to access its own Harrier. | ||
180 | */ | ||
181 | |||
182 | if (MONARCH) | ||
183 | return PCIBIOS_SUCCESSFUL; | ||
184 | if (found_self) | ||
185 | if ((bus == 0) && (devfn == self)) | ||
186 | return PCIBIOS_SUCCESSFUL; | ||
187 | else | ||
188 | return PCIBIOS_DEVICE_NOT_FOUND; | ||
189 | else | ||
190 | return prpmc_self(bus, devfn); | ||
191 | } | ||
192 | |||
193 | void __init prpmc800_find_bridges(void) | ||
194 | { | ||
195 | struct pci_controller *hose; | ||
196 | int host_bridge; | ||
197 | |||
198 | hose = pcibios_alloc_controller(); | ||
199 | if (!hose) | ||
200 | return; | ||
201 | |||
202 | hose->first_busno = 0; | ||
203 | hose->last_busno = 0xff; | ||
204 | |||
205 | ppc_md.pci_exclude_device = prpmc_exclude_device; | ||
206 | ppc_md.pcibios_fixup = NULL; | ||
207 | ppc_md.pcibios_fixup_bus = NULL; | ||
208 | ppc_md.pci_swizzle = common_swizzle; | ||
209 | ppc_md.pci_map_irq = prpmc_map_irq; | ||
210 | |||
211 | setup_indirect_pci(hose, | ||
212 | PRPMC800_PCI_CONFIG_ADDR, PRPMC800_PCI_CONFIG_DATA); | ||
213 | |||
214 | /* Get host bridge vendor/dev id */ | ||
215 | |||
216 | host_bridge = in_be32((uint *) (HARRIER_VENI_REG)); | ||
217 | |||
218 | if (host_bridge != HARRIER_VEND_DEV_ID) { | ||
219 | printk(KERN_CRIT "Host bridge 0x%x not supported\n", | ||
220 | host_bridge); | ||
221 | return; | ||
222 | } | ||
223 | |||
224 | monarch = in_be32((uint *) HARRIER_MISC_CSR) & HARRIER_SYSCON; | ||
225 | |||
226 | printk(KERN_INFO "Running as %s.\n", | ||
227 | MONARCH ? "Monarch" : "Non-Monarch"); | ||
228 | |||
229 | hose->io_space.start = PRPMC800_PCI_IO_START; | ||
230 | hose->io_space.end = PRPMC800_PCI_IO_END; | ||
231 | hose->io_base_virt = (void *)PRPMC800_ISA_IO_BASE; | ||
232 | hose->pci_mem_offset = PRPMC800_PCI_PHY_MEM_OFFSET; | ||
233 | |||
234 | pci_init_resource(&hose->io_resource, | ||
235 | PRPMC800_PCI_IO_START, PRPMC800_PCI_IO_END, | ||
236 | IORESOURCE_IO, "PCI host bridge"); | ||
237 | |||
238 | if (MONARCH) { | ||
239 | hose->mem_space.start = PRPMC800_PCI_MEM_START; | ||
240 | hose->mem_space.end = PRPMC800_PCI_MEM_END; | ||
241 | |||
242 | pci_init_resource(&hose->mem_resources[0], | ||
243 | PRPMC800_PCI_MEM_START, | ||
244 | PRPMC800_PCI_MEM_END, | ||
245 | IORESOURCE_MEM, "PCI host bridge"); | ||
246 | |||
247 | if (harrier_init(hose, | ||
248 | PRPMC800_HARRIER_XCSR_BASE, | ||
249 | PRPMC800_PROC_PCI_MEM_START, | ||
250 | PRPMC800_PROC_PCI_MEM_END, | ||
251 | PRPMC800_PROC_PCI_IO_START, | ||
252 | PRPMC800_PROC_PCI_IO_END, | ||
253 | PRPMC800_HARRIER_MPIC_BASE) != 0) | ||
254 | printk(KERN_CRIT "Could not initialize HARRIER " | ||
255 | "bridge\n"); | ||
256 | |||
257 | harrier_release_eready(PRPMC800_HARRIER_XCSR_BASE); | ||
258 | harrier_wait_eready(PRPMC800_HARRIER_XCSR_BASE); | ||
259 | hose->last_busno = pciauto_bus_scan(hose, hose->first_busno); | ||
260 | |||
261 | } else { | ||
262 | pci_init_resource(&hose->mem_resources[0], | ||
263 | PRPMC800_NM_PCI_MEM_START, | ||
264 | PRPMC800_NM_PCI_MEM_END, | ||
265 | IORESOURCE_MEM, "PCI host bridge"); | ||
266 | |||
267 | hose->mem_space.start = PRPMC800_NM_PCI_MEM_START; | ||
268 | hose->mem_space.end = PRPMC800_NM_PCI_MEM_END; | ||
269 | |||
270 | if (harrier_init(hose, | ||
271 | PRPMC800_HARRIER_XCSR_BASE, | ||
272 | PRPMC800_NM_PROC_PCI_MEM_START, | ||
273 | PRPMC800_NM_PROC_PCI_MEM_END, | ||
274 | PRPMC800_PROC_PCI_IO_START, | ||
275 | PRPMC800_PROC_PCI_IO_END, | ||
276 | PRPMC800_HARRIER_MPIC_BASE) != 0) | ||
277 | printk(KERN_CRIT "Could not initialize HARRIER " | ||
278 | "bridge\n"); | ||
279 | |||
280 | harrier_setup_nonmonarch(PRPMC800_HARRIER_XCSR_BASE, | ||
281 | HARRIER_ITSZ_1MB); | ||
282 | harrier_release_eready(PRPMC800_HARRIER_XCSR_BASE); | ||
283 | } | ||
284 | } | ||
285 | |||
286 | static int prpmc800_show_cpuinfo(struct seq_file *m) | ||
287 | { | ||
288 | seq_printf(m, "machine\t\t: PrPMC800\n"); | ||
289 | |||
290 | return 0; | ||
291 | } | ||
292 | |||
293 | static void __init prpmc800_setup_arch(void) | ||
294 | { | ||
295 | /* init to some ~sane value until calibrate_delay() runs */ | ||
296 | loops_per_jiffy = 50000000 / HZ; | ||
297 | |||
298 | /* Lookup PCI host bridges */ | ||
299 | prpmc800_find_bridges(); | ||
300 | |||
301 | #ifdef CONFIG_BLK_DEV_INITRD | ||
302 | if (initrd_start) | ||
303 | ROOT_DEV = Root_RAM0; | ||
304 | else | ||
305 | #endif | ||
306 | #ifdef CONFIG_ROOT_NFS | ||
307 | ROOT_DEV = Root_NFS; | ||
308 | #else | ||
309 | ROOT_DEV = Root_SDA2; | ||
310 | #endif | ||
311 | |||
312 | printk(KERN_INFO "Port by MontaVista Software, Inc. " | ||
313 | "(source@mvista.com)\n"); | ||
314 | } | ||
315 | |||
316 | /* | ||
317 | * Compute the PrPMC800's tbl frequency using the baud clock as a reference. | ||
318 | */ | ||
319 | static void __init prpmc800_calibrate_decr(void) | ||
320 | { | ||
321 | unsigned long tbl_start, tbl_end; | ||
322 | unsigned long current_state, old_state, tb_ticks_per_second; | ||
323 | unsigned int count; | ||
324 | unsigned int harrier_revision; | ||
325 | |||
326 | harrier_revision = readb(HARRIER_REVI_REG); | ||
327 | if (harrier_revision < 2) { | ||
328 | /* XTAL64 was broken in harrier revision 1 */ | ||
329 | printk(KERN_INFO "time_init: Harrier revision %d, assuming " | ||
330 | "100 Mhz bus\n", harrier_revision); | ||
331 | tb_ticks_per_second = 100000000 / 4; | ||
332 | tb_ticks_per_jiffy = tb_ticks_per_second / HZ; | ||
333 | tb_to_us = mulhwu_scale_factor(tb_ticks_per_second, 1000000); | ||
334 | return; | ||
335 | } | ||
336 | |||
337 | /* | ||
338 | * The XTAL64 bit oscillates at the 1/64 the base baud clock | ||
339 | * Set count to XTAL64 cycles per second. Since we'll count | ||
340 | * half-cycles, we'll reach the count in half a second. | ||
341 | */ | ||
342 | count = PRPMC800_BASE_BAUD / 64; | ||
343 | |||
344 | /* Find the first edge of the baud clock */ | ||
345 | old_state = readb(HARRIER_UCTL_REG) & HARRIER_XTAL64_MASK; | ||
346 | do { | ||
347 | current_state = readb(HARRIER_UCTL_REG) & HARRIER_XTAL64_MASK; | ||
348 | } while (old_state == current_state); | ||
349 | |||
350 | old_state = current_state; | ||
351 | |||
352 | /* Get the starting time base value */ | ||
353 | tbl_start = get_tbl(); | ||
354 | |||
355 | /* | ||
356 | * Loop until we have found a number of edges (half-cycles) | ||
357 | * equal to the count (half a second) | ||
358 | */ | ||
359 | do { | ||
360 | do { | ||
361 | current_state = readb(HARRIER_UCTL_REG) & | ||
362 | HARRIER_XTAL64_MASK; | ||
363 | } while (old_state == current_state); | ||
364 | old_state = current_state; | ||
365 | } while (--count); | ||
366 | |||
367 | /* Get the ending time base value */ | ||
368 | tbl_end = get_tbl(); | ||
369 | |||
370 | /* We only counted for half a second, so double to get ticks/second */ | ||
371 | tb_ticks_per_second = (tbl_end - tbl_start) * 2; | ||
372 | tb_ticks_per_jiffy = tb_ticks_per_second / HZ; | ||
373 | tb_to_us = mulhwu_scale_factor(tb_ticks_per_second, 1000000); | ||
374 | } | ||
375 | |||
376 | static void prpmc800_restart(char *cmd) | ||
377 | { | ||
378 | ulong temp; | ||
379 | |||
380 | local_irq_disable(); | ||
381 | temp = in_be32((uint *) HARRIER_MISC_CSR_REG); | ||
382 | temp |= HARRIER_RSTOUT; | ||
383 | out_be32((uint *) HARRIER_MISC_CSR_REG, temp); | ||
384 | while (1) ; | ||
385 | } | ||
386 | |||
387 | static void prpmc800_halt(void) | ||
388 | { | ||
389 | local_irq_disable(); | ||
390 | while (1) ; | ||
391 | } | ||
392 | |||
393 | static void prpmc800_power_off(void) | ||
394 | { | ||
395 | prpmc800_halt(); | ||
396 | } | ||
397 | |||
398 | static void __init prpmc800_init_IRQ(void) | ||
399 | { | ||
400 | OpenPIC_InitSenses = prpmc800_openpic_initsenses; | ||
401 | OpenPIC_NumInitSenses = sizeof(prpmc800_openpic_initsenses); | ||
402 | |||
403 | /* Setup external interrupt sources. */ | ||
404 | openpic_set_sources(0, 16, OpenPIC_Addr + 0x10000); | ||
405 | /* Setup internal UART interrupt source. */ | ||
406 | openpic_set_sources(16, 1, OpenPIC_Addr + 0x10200); | ||
407 | |||
408 | /* Do the MPIC initialization based on the above settings. */ | ||
409 | openpic_init(0); | ||
410 | |||
411 | /* enable functional exceptions for uarts and abort */ | ||
412 | out_8((u8 *) HARRIER_FEEN_REG, (HARRIER_FE_UA0 | HARRIER_FE_UA1)); | ||
413 | out_8((u8 *) HARRIER_FEMA_REG, ~(HARRIER_FE_UA0 | HARRIER_FE_UA1)); | ||
414 | } | ||
415 | |||
416 | /* | ||
417 | * Set BAT 3 to map 0xf0000000 to end of physical memory space. | ||
418 | */ | ||
419 | static __inline__ void prpmc800_set_bat(void) | ||
420 | { | ||
421 | mb(); | ||
422 | mtspr(SPRN_DBAT1U, 0xf0001ffe); | ||
423 | mtspr(SPRN_DBAT1L, 0xf000002a); | ||
424 | mb(); | ||
425 | } | ||
426 | |||
427 | /* | ||
428 | * We need to read the Harrier memory controller | ||
429 | * to properly determine this value | ||
430 | */ | ||
431 | static unsigned long __init prpmc800_find_end_of_memory(void) | ||
432 | { | ||
433 | /* Read the memory size from the Harrier XCSR */ | ||
434 | return harrier_get_mem_size(PRPMC800_HARRIER_XCSR_BASE); | ||
435 | } | ||
436 | |||
437 | static void __init prpmc800_map_io(void) | ||
438 | { | ||
439 | io_block_mapping(0x80000000, 0x80000000, 0x10000000, _PAGE_IO); | ||
440 | io_block_mapping(0xf0000000, 0xf0000000, 0x10000000, _PAGE_IO); | ||
441 | } | ||
442 | |||
443 | void __init | ||
444 | platform_init(unsigned long r3, unsigned long r4, unsigned long r5, | ||
445 | unsigned long r6, unsigned long r7) | ||
446 | { | ||
447 | parse_bootinfo(find_bootinfo()); | ||
448 | |||
449 | prpmc800_set_bat(); | ||
450 | |||
451 | isa_io_base = PRPMC800_ISA_IO_BASE; | ||
452 | isa_mem_base = PRPMC800_ISA_MEM_BASE; | ||
453 | pci_dram_offset = PRPMC800_PCI_DRAM_OFFSET; | ||
454 | |||
455 | ppc_md.setup_arch = prpmc800_setup_arch; | ||
456 | ppc_md.show_cpuinfo = prpmc800_show_cpuinfo; | ||
457 | ppc_md.init_IRQ = prpmc800_init_IRQ; | ||
458 | ppc_md.get_irq = openpic_get_irq; | ||
459 | |||
460 | ppc_md.find_end_of_memory = prpmc800_find_end_of_memory; | ||
461 | ppc_md.setup_io_mappings = prpmc800_map_io; | ||
462 | |||
463 | ppc_md.restart = prpmc800_restart; | ||
464 | ppc_md.power_off = prpmc800_power_off; | ||
465 | ppc_md.halt = prpmc800_halt; | ||
466 | |||
467 | /* PrPMC800 has no timekeeper part */ | ||
468 | ppc_md.time_init = NULL; | ||
469 | ppc_md.get_rtc_time = NULL; | ||
470 | ppc_md.set_rtc_time = NULL; | ||
471 | ppc_md.calibrate_decr = prpmc800_calibrate_decr; | ||
472 | #ifdef CONFIG_SERIAL_TEXT_DEBUG | ||
473 | ppc_md.progress = gen550_progress; | ||
474 | #else /* !CONFIG_SERIAL_TEXT_DEBUG */ | ||
475 | ppc_md.progress = NULL; | ||
476 | #endif /* CONFIG_SERIAL_TEXT_DEBUG */ | ||
477 | } | ||
diff --git a/arch/ppc/platforms/prpmc800.h b/arch/ppc/platforms/prpmc800.h new file mode 100644 index 000000000000..e53ec9b42a35 --- /dev/null +++ b/arch/ppc/platforms/prpmc800.h | |||
@@ -0,0 +1,82 @@ | |||
1 | /* | ||
2 | * include/asm-ppc/platforms/prpmc800.h | ||
3 | * | ||
4 | * Definitions for Motorola PrPMC800 board support | ||
5 | * | ||
6 | * Author: Dale Farnsworth <dale.farnsworth@mvista.com> | ||
7 | * | ||
8 | * 2001-2004 (c) MontaVista, Software, Inc. This file is licensed under | ||
9 | * the terms of the GNU General Public License version 2. This program | ||
10 | * is licensed "as is" without any warranty of any kind, whether express | ||
11 | * or implied. | ||
12 | */ | ||
13 | /* | ||
14 | * From Processor to PCI: | ||
15 | * PCI Mem Space: 0x80000000 - 0xa0000000 -> 0x80000000 - 0xa0000000 (512 MB) | ||
16 | * PCI I/O Space: 0xfe400000 - 0xfeef0000 -> 0x00000000 - 0x00b00000 (11 MB) | ||
17 | * Note: Must skip 0xfe000000-0xfe400000 for CONFIG_HIGHMEM/PKMAP area | ||
18 | * | ||
19 | * From PCI to Processor: | ||
20 | * System Memory: 0x00000000 -> 0x00000000 | ||
21 | */ | ||
22 | |||
23 | #ifndef __ASMPPC_PRPMC800_H | ||
24 | #define __ASMPPC_PRPMC800_H | ||
25 | |||
26 | #define PRPMC800_PCI_CONFIG_ADDR 0xfe000cf8 | ||
27 | #define PRPMC800_PCI_CONFIG_DATA 0xfe000cfc | ||
28 | |||
29 | #define PRPMC800_PROC_PCI_IO_START 0xfe400000U | ||
30 | #define PRPMC800_PROC_PCI_IO_END 0xfeefffffU | ||
31 | #define PRPMC800_PCI_IO_START 0x00000000U | ||
32 | #define PRPMC800_PCI_IO_END 0x00afffffU | ||
33 | |||
34 | #define PRPMC800_PROC_PCI_MEM_START 0x80000000U | ||
35 | #define PRPMC800_PROC_PCI_MEM_END 0x9fffffffU | ||
36 | #define PRPMC800_PCI_MEM_START 0x80000000U | ||
37 | #define PRPMC800_PCI_MEM_END 0x9fffffffU | ||
38 | |||
39 | #define PRPMC800_NM_PROC_PCI_MEM_START 0x40000000U | ||
40 | #define PRPMC800_NM_PROC_PCI_MEM_END 0xdfffffffU | ||
41 | #define PRPMC800_NM_PCI_MEM_START 0x40000000U | ||
42 | #define PRPMC800_NM_PCI_MEM_END 0xdfffffffU | ||
43 | |||
44 | #define PRPMC800_PCI_DRAM_OFFSET 0x00000000U | ||
45 | #define PRPMC800_PCI_PHY_MEM_OFFSET 0x00000000U | ||
46 | |||
47 | #define PRPMC800_ISA_IO_BASE PRPMC800_PROC_PCI_IO_START | ||
48 | #define PRPMC800_ISA_MEM_BASE 0x00000000U | ||
49 | |||
50 | #define PRPMC800_HARRIER_XCSR_BASE HARRIER_DEFAULT_XCSR_BASE | ||
51 | #define PRPMC800_HARRIER_MPIC_BASE 0xff000000 | ||
52 | |||
53 | #define PRPMC800_SERIAL_1 0xfeff00c0 | ||
54 | |||
55 | #define PRPMC800_BASE_BAUD 1843200 | ||
56 | |||
57 | /* | ||
58 | * interrupt vector number and priority for harrier internal interrupt | ||
59 | * sources | ||
60 | */ | ||
61 | #define PRPMC800_INT_IRQ 16 | ||
62 | #define PRPMC800_INT_PRI 15 | ||
63 | |||
64 | /* UART Defines. */ | ||
65 | #define RS_TABLE_SIZE 4 | ||
66 | |||
67 | /* Rate for the 1.8432 Mhz clock for the onboard serial chip */ | ||
68 | #define BASE_BAUD (PRPMC800_BASE_BAUD / 16) | ||
69 | |||
70 | #define STD_COM_FLAGS ASYNC_BOOT_AUTOCONF | ||
71 | |||
72 | /* UARTS are at IRQ 16 */ | ||
73 | #define STD_SERIAL_PORT_DFNS \ | ||
74 | { 0, BASE_BAUD, PRPMC800_SERIAL_1, 16, STD_COM_FLAGS, /* ttyS0 */\ | ||
75 | iomem_base: (unsigned char *)PRPMC800_SERIAL_1, \ | ||
76 | iomem_reg_shift: 0, \ | ||
77 | io_type: SERIAL_IO_MEM }, | ||
78 | |||
79 | #define SERIAL_PORT_DFNS \ | ||
80 | STD_SERIAL_PORT_DFNS | ||
81 | |||
82 | #endif /* __ASMPPC_PRPMC800_H */ | ||
diff --git a/arch/ppc/platforms/radstone_ppc7d.c b/arch/ppc/platforms/radstone_ppc7d.c new file mode 100644 index 000000000000..2a99b43737a8 --- /dev/null +++ b/arch/ppc/platforms/radstone_ppc7d.c | |||
@@ -0,0 +1,1452 @@ | |||
1 | /* | ||
2 | * arch/ppc/platforms/radstone_ppc7d.c | ||
3 | * | ||
4 | * Board setup routines for the Radstone PPC7D boards. | ||
5 | * | ||
6 | * Author: James Chapman <jchapman@katalix.com> | ||
7 | * | ||
8 | * Based on code done by Rabeeh Khoury - rabeeh@galileo.co.il | ||
9 | * Based on code done by - Mark A. Greer <mgreer@mvista.com> | ||
10 | * | ||
11 | * This program is free software; you can redistribute it and/or modify it | ||
12 | * under the terms of the GNU General Public License as published by the | ||
13 | * Free Software Foundation; either version 2 of the License, or (at your | ||
14 | * option) any later version. | ||
15 | */ | ||
16 | |||
17 | /* Radstone PPC7D boards are rugged VME boards with PPC 7447A CPUs, | ||
18 | * Discovery-II, dual gigabit ethernet, dual PMC, USB, keyboard/mouse, | ||
19 | * 4 serial ports, 2 high speed serial ports (MPSCs) and optional | ||
20 | * SCSI / VGA. | ||
21 | */ | ||
22 | |||
23 | #include <linux/config.h> | ||
24 | #include <linux/stddef.h> | ||
25 | #include <linux/kernel.h> | ||
26 | #include <linux/init.h> | ||
27 | #include <linux/errno.h> | ||
28 | #include <linux/reboot.h> | ||
29 | #include <linux/pci.h> | ||
30 | #include <linux/kdev_t.h> | ||
31 | #include <linux/major.h> | ||
32 | #include <linux/initrd.h> | ||
33 | #include <linux/console.h> | ||
34 | #include <linux/delay.h> | ||
35 | #include <linux/irq.h> | ||
36 | #include <linux/ide.h> | ||
37 | #include <linux/seq_file.h> | ||
38 | #include <linux/root_dev.h> | ||
39 | #include <linux/serial.h> | ||
40 | #include <linux/tty.h> /* for linux/serial_core.h */ | ||
41 | #include <linux/serial_core.h> | ||
42 | #include <linux/mv643xx.h> | ||
43 | #include <linux/netdevice.h> | ||
44 | |||
45 | #include <asm/system.h> | ||
46 | #include <asm/pgtable.h> | ||
47 | #include <asm/page.h> | ||
48 | #include <asm/time.h> | ||
49 | #include <asm/dma.h> | ||
50 | #include <asm/io.h> | ||
51 | #include <asm/machdep.h> | ||
52 | #include <asm/prom.h> | ||
53 | #include <asm/smp.h> | ||
54 | #include <asm/vga.h> | ||
55 | #include <asm/open_pic.h> | ||
56 | #include <asm/i8259.h> | ||
57 | #include <asm/todc.h> | ||
58 | #include <asm/bootinfo.h> | ||
59 | #include <asm/mpc10x.h> | ||
60 | #include <asm/pci-bridge.h> | ||
61 | #include <asm/mv64x60.h> | ||
62 | #include <asm/i8259.h> | ||
63 | |||
64 | #include "radstone_ppc7d.h" | ||
65 | |||
66 | #undef DEBUG | ||
67 | |||
68 | #define PPC7D_RST_PIN 17 /* GPP17 */ | ||
69 | |||
70 | extern u32 mv64360_irq_base; | ||
71 | |||
72 | static struct mv64x60_handle bh; | ||
73 | static int ppc7d_has_alma; | ||
74 | |||
75 | extern void gen550_progress(char *, unsigned short); | ||
76 | extern void gen550_init(int, struct uart_port *); | ||
77 | |||
78 | /* residual data */ | ||
79 | unsigned char __res[sizeof(bd_t)]; | ||
80 | |||
81 | /***************************************************************************** | ||
82 | * Serial port code | ||
83 | *****************************************************************************/ | ||
84 | |||
85 | #if defined(CONFIG_KGDB) || defined(CONFIG_SERIAL_TEXT_DEBUG) | ||
86 | static void __init ppc7d_early_serial_map(void) | ||
87 | { | ||
88 | #if defined(CONFIG_SERIAL_MPSC_CONSOLE) | ||
89 | mv64x60_progress_init(CONFIG_MV64X60_NEW_BASE); | ||
90 | #elif defined(CONFIG_SERIAL_8250) | ||
91 | struct uart_port serial_req; | ||
92 | |||
93 | /* Setup serial port access */ | ||
94 | memset(&serial_req, 0, sizeof(serial_req)); | ||
95 | serial_req.uartclk = UART_CLK; | ||
96 | serial_req.irq = 4; | ||
97 | serial_req.flags = STD_COM_FLAGS; | ||
98 | serial_req.iotype = SERIAL_IO_MEM; | ||
99 | serial_req.membase = (u_char *) PPC7D_SERIAL_0; | ||
100 | |||
101 | gen550_init(0, &serial_req); | ||
102 | if (early_serial_setup(&serial_req) != 0) | ||
103 | printk(KERN_ERR "Early serial init of port 0 failed\n"); | ||
104 | |||
105 | /* Assume early_serial_setup() doesn't modify serial_req */ | ||
106 | serial_req.line = 1; | ||
107 | serial_req.irq = 3; | ||
108 | serial_req.membase = (u_char *) PPC7D_SERIAL_1; | ||
109 | |||
110 | gen550_init(1, &serial_req); | ||
111 | if (early_serial_setup(&serial_req) != 0) | ||
112 | printk(KERN_ERR "Early serial init of port 1 failed\n"); | ||
113 | #else | ||
114 | #error CONFIG_KGDB || CONFIG_SERIAL_TEXT_DEBUG has no supported CONFIG_SERIAL_XXX | ||
115 | #endif | ||
116 | } | ||
117 | #endif /* CONFIG_KGDB || CONFIG_SERIAL_TEXT_DEBUG */ | ||
118 | |||
119 | /***************************************************************************** | ||
120 | * Low-level board support code | ||
121 | *****************************************************************************/ | ||
122 | |||
123 | static unsigned long __init ppc7d_find_end_of_memory(void) | ||
124 | { | ||
125 | bd_t *bp = (bd_t *) __res; | ||
126 | |||
127 | if (bp->bi_memsize) | ||
128 | return bp->bi_memsize; | ||
129 | |||
130 | return (256 * 1024 * 1024); | ||
131 | } | ||
132 | |||
133 | static void __init ppc7d_map_io(void) | ||
134 | { | ||
135 | /* remove temporary mapping */ | ||
136 | mtspr(SPRN_DBAT3U, 0x00000000); | ||
137 | mtspr(SPRN_DBAT3L, 0x00000000); | ||
138 | |||
139 | io_block_mapping(0xe8000000, 0xe8000000, 0x08000000, _PAGE_IO); | ||
140 | io_block_mapping(0xfe000000, 0xfe000000, 0x02000000, _PAGE_IO); | ||
141 | } | ||
142 | |||
143 | static void ppc7d_restart(char *cmd) | ||
144 | { | ||
145 | u32 data; | ||
146 | |||
147 | /* Disable GPP17 interrupt */ | ||
148 | data = mv64x60_read(&bh, MV64x60_GPP_INTR_MASK); | ||
149 | data &= ~(1 << PPC7D_RST_PIN); | ||
150 | mv64x60_write(&bh, MV64x60_GPP_INTR_MASK, data); | ||
151 | |||
152 | /* Configure MPP17 as GPP */ | ||
153 | data = mv64x60_read(&bh, MV64x60_MPP_CNTL_2); | ||
154 | data &= ~(0x0000000f << 4); | ||
155 | mv64x60_write(&bh, MV64x60_MPP_CNTL_2, data); | ||
156 | |||
157 | /* Enable pin GPP17 for output */ | ||
158 | data = mv64x60_read(&bh, MV64x60_GPP_IO_CNTL); | ||
159 | data |= (1 << PPC7D_RST_PIN); | ||
160 | mv64x60_write(&bh, MV64x60_GPP_IO_CNTL, data); | ||
161 | |||
162 | /* Toggle GPP9 pin to reset the board */ | ||
163 | mv64x60_write(&bh, MV64x60_GPP_VALUE_CLR, 1 << PPC7D_RST_PIN); | ||
164 | mv64x60_write(&bh, MV64x60_GPP_VALUE_SET, 1 << PPC7D_RST_PIN); | ||
165 | |||
166 | for (;;) ; /* Spin until reset happens */ | ||
167 | /* NOTREACHED */ | ||
168 | } | ||
169 | |||
170 | static void ppc7d_power_off(void) | ||
171 | { | ||
172 | u32 data; | ||
173 | |||
174 | local_irq_disable(); | ||
175 | |||
176 | /* Ensure that internal MV643XX watchdog is disabled. | ||
177 | * The Disco watchdog uses MPP17 on this hardware. | ||
178 | */ | ||
179 | data = mv64x60_read(&bh, MV64x60_MPP_CNTL_2); | ||
180 | data &= ~(0x0000000f << 4); | ||
181 | mv64x60_write(&bh, MV64x60_MPP_CNTL_2, data); | ||
182 | |||
183 | data = mv64x60_read(&bh, MV64x60_WDT_WDC); | ||
184 | if (data & 0x80000000) { | ||
185 | mv64x60_write(&bh, MV64x60_WDT_WDC, 1 << 24); | ||
186 | mv64x60_write(&bh, MV64x60_WDT_WDC, 2 << 24); | ||
187 | } | ||
188 | |||
189 | for (;;) ; /* No way to shut power off with software */ | ||
190 | /* NOTREACHED */ | ||
191 | } | ||
192 | |||
193 | static void ppc7d_halt(void) | ||
194 | { | ||
195 | ppc7d_power_off(); | ||
196 | /* NOTREACHED */ | ||
197 | } | ||
198 | |||
199 | static unsigned long ppc7d_led_no_pulse; | ||
200 | |||
201 | static int __init ppc7d_led_pulse_disable(char *str) | ||
202 | { | ||
203 | ppc7d_led_no_pulse = 1; | ||
204 | return 1; | ||
205 | } | ||
206 | |||
207 | /* This kernel option disables the heartbeat pulsing of a board LED */ | ||
208 | __setup("ledoff", ppc7d_led_pulse_disable); | ||
209 | |||
210 | static void ppc7d_heartbeat(void) | ||
211 | { | ||
212 | u32 data32; | ||
213 | u8 data8; | ||
214 | static int max706_wdog = 0; | ||
215 | |||
216 | /* Unfortunately we can't access the LED control registers | ||
217 | * during early init because they're on the CPLD which is the | ||
218 | * other side of a PCI bridge which goes unreachable during | ||
219 | * PCI scan. So write the LEDs only if the MV64360 watchdog is | ||
220 | * enabled (i.e. userspace apps are running so kernel is up).. | ||
221 | */ | ||
222 | data32 = mv64x60_read(&bh, MV64x60_WDT_WDC); | ||
223 | if (data32 & 0x80000000) { | ||
224 | /* Enable MAX706 watchdog if not done already */ | ||
225 | if (!max706_wdog) { | ||
226 | outb(3, PPC7D_CPLD_RESET); | ||
227 | max706_wdog = 1; | ||
228 | } | ||
229 | |||
230 | /* Hit the MAX706 watchdog */ | ||
231 | outb(0, PPC7D_CPLD_WATCHDOG_TRIG); | ||
232 | |||
233 | /* Pulse LED DS219 if not disabled */ | ||
234 | if (!ppc7d_led_no_pulse) { | ||
235 | static int led_on = 0; | ||
236 | |||
237 | data8 = inb(PPC7D_CPLD_LEDS); | ||
238 | if (led_on) | ||
239 | data8 &= ~PPC7D_CPLD_LEDS_DS219_MASK; | ||
240 | else | ||
241 | data8 |= PPC7D_CPLD_LEDS_DS219_MASK; | ||
242 | |||
243 | outb(data8, PPC7D_CPLD_LEDS); | ||
244 | led_on = !led_on; | ||
245 | } | ||
246 | } | ||
247 | ppc_md.heartbeat_count = ppc_md.heartbeat_reset; | ||
248 | } | ||
249 | |||
250 | static int ppc7d_show_cpuinfo(struct seq_file *m) | ||
251 | { | ||
252 | u8 val; | ||
253 | u8 val1, val2; | ||
254 | static int flash_sizes[4] = { 64, 32, 0, 16 }; | ||
255 | static int flash_banks[4] = { 4, 3, 2, 1 }; | ||
256 | static char *pci_modes[] = { "PCI33", "PCI66", | ||
257 | "Unknown", "Unknown", | ||
258 | "PCIX33", "PCIX66", | ||
259 | "PCIX100", "PCIX133" | ||
260 | }; | ||
261 | |||
262 | seq_printf(m, "vendor\t\t: Radstone Technology\n"); | ||
263 | seq_printf(m, "machine\t\t: PPC7D\n"); | ||
264 | |||
265 | val = inb(PPC7D_CPLD_BOARD_REVISION); | ||
266 | val1 = (val & PPC7D_CPLD_BOARD_REVISION_NUMBER_MASK) >> 5; | ||
267 | val2 = (val & PPC7D_CPLD_BOARD_REVISION_LETTER_MASK); | ||
268 | seq_printf(m, "revision\t: %hd%c%c\n", | ||
269 | val1, | ||
270 | (val2 <= 0x18) ? 'A' + val2 : 'Y', | ||
271 | (val2 > 0x18) ? 'A' + (val2 - 0x19) : ' '); | ||
272 | |||
273 | val = inb(PPC7D_CPLD_MOTHERBOARD_TYPE); | ||
274 | val1 = val & PPC7D_CPLD_MB_TYPE_PLL_MASK; | ||
275 | val2 = val & (PPC7D_CPLD_MB_TYPE_ECC_FITTED_MASK | | ||
276 | PPC7D_CPLD_MB_TYPE_ECC_ENABLE_MASK); | ||
277 | seq_printf(m, "bus speed\t: %dMHz\n", | ||
278 | (val1 == PPC7D_CPLD_MB_TYPE_PLL_133) ? 133 : | ||
279 | (val1 == PPC7D_CPLD_MB_TYPE_PLL_100) ? 100 : | ||
280 | (val1 == PPC7D_CPLD_MB_TYPE_PLL_64) ? 64 : 0); | ||
281 | |||
282 | val = inb(PPC7D_CPLD_MEM_CONFIG_EXTEND); | ||
283 | val1 = val & PPC7D_CPLD_SDRAM_BANK_SIZE_MASK; | ||
284 | seq_printf(m, "SDRAM\t\t: %d%c", | ||
285 | (val1 == PPC7D_CPLD_SDRAM_BANK_SIZE_128M) ? 128 : | ||
286 | (val1 == PPC7D_CPLD_SDRAM_BANK_SIZE_256M) ? 256 : | ||
287 | (val1 == PPC7D_CPLD_SDRAM_BANK_SIZE_512M) ? 512 : 1, | ||
288 | (val1 == PPC7D_CPLD_SDRAM_BANK_SIZE_1G) ? 'G' : 'M'); | ||
289 | if (val2 & PPC7D_CPLD_MB_TYPE_ECC_FITTED_MASK) { | ||
290 | seq_printf(m, " [ECC %sabled]", | ||
291 | (val2 & PPC7D_CPLD_MB_TYPE_ECC_ENABLE_MASK) ? "en" : | ||
292 | "dis"); | ||
293 | } | ||
294 | seq_printf(m, "\n"); | ||
295 | |||
296 | val1 = (val & PPC7D_CPLD_FLASH_DEV_SIZE_MASK); | ||
297 | val2 = (val & PPC7D_CPLD_FLASH_BANK_NUM_MASK) >> 2; | ||
298 | seq_printf(m, "FLASH\t\t: %d banks of %dM, total %dM\n", | ||
299 | flash_banks[val2], flash_sizes[val1], | ||
300 | flash_banks[val2] * flash_sizes[val1]); | ||
301 | |||
302 | val = inb(PPC7D_CPLD_FLASH_WRITE_CNTL); | ||
303 | val1 = inb(PPC7D_CPLD_SW_FLASH_WRITE_PROTECT); | ||
304 | seq_printf(m, " write links\t: %s%s%s%s\n", | ||
305 | (val & PPD7D_CPLD_FLASH_CNTL_WR_LINK_MASK) ? "WRITE " : "", | ||
306 | (val & PPD7D_CPLD_FLASH_CNTL_BOOT_LINK_MASK) ? "BOOT " : "", | ||
307 | (val & PPD7D_CPLD_FLASH_CNTL_USER_LINK_MASK) ? "USER " : "", | ||
308 | (val & (PPD7D_CPLD_FLASH_CNTL_WR_LINK_MASK | | ||
309 | PPD7D_CPLD_FLASH_CNTL_BOOT_LINK_MASK | | ||
310 | PPD7D_CPLD_FLASH_CNTL_USER_LINK_MASK)) == | ||
311 | 0 ? "NONE" : ""); | ||
312 | seq_printf(m, " write sector h/w enables: %s%s%s%s%s\n", | ||
313 | (val & PPD7D_CPLD_FLASH_CNTL_RECO_WR_MASK) ? "RECOVERY " : | ||
314 | "", | ||
315 | (val & PPD7D_CPLD_FLASH_CNTL_BOOT_WR_MASK) ? "BOOT " : "", | ||
316 | (val & PPD7D_CPLD_FLASH_CNTL_USER_WR_MASK) ? "USER " : "", | ||
317 | (val1 & PPC7D_CPLD_FLASH_CNTL_NVRAM_PROT_MASK) ? "NVRAM " : | ||
318 | "", | ||
319 | (((val & | ||
320 | (PPD7D_CPLD_FLASH_CNTL_RECO_WR_MASK | | ||
321 | PPD7D_CPLD_FLASH_CNTL_BOOT_WR_MASK | | ||
322 | PPD7D_CPLD_FLASH_CNTL_BOOT_WR_MASK)) == 0) | ||
323 | && ((val1 & PPC7D_CPLD_FLASH_CNTL_NVRAM_PROT_MASK) == | ||
324 | 0)) ? "NONE" : ""); | ||
325 | val1 = | ||
326 | inb(PPC7D_CPLD_SW_FLASH_WRITE_PROTECT) & | ||
327 | (PPC7D_CPLD_SW_FLASH_WRPROT_SYSBOOT_MASK | | ||
328 | PPC7D_CPLD_SW_FLASH_WRPROT_USER_MASK); | ||
329 | seq_printf(m, " software sector enables: %s%s%s\n", | ||
330 | (val1 & PPC7D_CPLD_SW_FLASH_WRPROT_SYSBOOT_MASK) ? "SYSBOOT " | ||
331 | : "", | ||
332 | (val1 & PPC7D_CPLD_SW_FLASH_WRPROT_USER_MASK) ? "USER " : "", | ||
333 | (val1 == 0) ? "NONE " : ""); | ||
334 | |||
335 | seq_printf(m, "Boot options\t: %s%s%s%s\n", | ||
336 | (val & PPC7D_CPLD_FLASH_CNTL_ALTBOOT_LINK_MASK) ? | ||
337 | "ALTERNATE " : "", | ||
338 | (val & PPC7D_CPLD_FLASH_CNTL_VMEBOOT_LINK_MASK) ? "VME " : | ||
339 | "", | ||
340 | (val & PPC7D_CPLD_FLASH_CNTL_RECBOOT_LINK_MASK) ? "RECOVERY " | ||
341 | : "", | ||
342 | ((val & | ||
343 | (PPC7D_CPLD_FLASH_CNTL_ALTBOOT_LINK_MASK | | ||
344 | PPC7D_CPLD_FLASH_CNTL_VMEBOOT_LINK_MASK | | ||
345 | PPC7D_CPLD_FLASH_CNTL_RECBOOT_LINK_MASK)) == | ||
346 | 0) ? "NONE" : ""); | ||
347 | |||
348 | val = inb(PPC7D_CPLD_EQUIPMENT_PRESENT_1); | ||
349 | seq_printf(m, "Fitted modules\t: %s%s%s%s\n", | ||
350 | (val & PPC7D_CPLD_EQPT_PRES_1_PMC1_MASK) ? "" : "PMC1 ", | ||
351 | (val & PPC7D_CPLD_EQPT_PRES_1_PMC2_MASK) ? "" : "PMC2 ", | ||
352 | (val & PPC7D_CPLD_EQPT_PRES_1_AFIX_MASK) ? "AFIX " : "", | ||
353 | ((val & (PPC7D_CPLD_EQPT_PRES_1_PMC1_MASK | | ||
354 | PPC7D_CPLD_EQPT_PRES_1_PMC2_MASK | | ||
355 | PPC7D_CPLD_EQPT_PRES_1_AFIX_MASK)) == | ||
356 | (PPC7D_CPLD_EQPT_PRES_1_PMC1_MASK | | ||
357 | PPC7D_CPLD_EQPT_PRES_1_PMC2_MASK)) ? "NONE" : ""); | ||
358 | |||
359 | if (val & PPC7D_CPLD_EQPT_PRES_1_AFIX_MASK) { | ||
360 | static const char *ids[] = { | ||
361 | "unknown", | ||
362 | "1553 (Dual Channel)", | ||
363 | "1553 (Single Channel)", | ||
364 | "8-bit SCSI + VGA", | ||
365 | "16-bit SCSI + VGA", | ||
366 | "1553 (Single Channel with sideband)", | ||
367 | "1553 (Dual Channel with sideband)", | ||
368 | NULL | ||
369 | }; | ||
370 | u8 id = __raw_readb((void *)PPC7D_AFIX_REG_BASE + 0x03); | ||
371 | seq_printf(m, "AFIX module\t: 0x%hx [%s]\n", id, | ||
372 | id < 7 ? ids[id] : "unknown"); | ||
373 | } | ||
374 | |||
375 | val = inb(PPC7D_CPLD_PCI_CONFIG); | ||
376 | val1 = (val & PPC7D_CPLD_PCI_CONFIG_PCI0_MASK) >> 4; | ||
377 | val2 = (val & PPC7D_CPLD_PCI_CONFIG_PCI1_MASK); | ||
378 | seq_printf(m, "PCI#0\t\t: %s\nPCI#1\t\t: %s\n", | ||
379 | pci_modes[val1], pci_modes[val2]); | ||
380 | |||
381 | val = inb(PPC7D_CPLD_EQUIPMENT_PRESENT_2); | ||
382 | seq_printf(m, "PMC1\t\t: %s\nPMC2\t\t: %s\n", | ||
383 | (val & PPC7D_CPLD_EQPT_PRES_3_PMC1_V_MASK) ? "3.3v" : "5v", | ||
384 | (val & PPC7D_CPLD_EQPT_PRES_3_PMC2_V_MASK) ? "3.3v" : "5v"); | ||
385 | seq_printf(m, "PMC power source: %s\n", | ||
386 | (val & PPC7D_CPLD_EQPT_PRES_3_PMC_POWER_MASK) ? "VME" : | ||
387 | "internal"); | ||
388 | |||
389 | val = inb(PPC7D_CPLD_EQUIPMENT_PRESENT_4); | ||
390 | val2 = inb(PPC7D_CPLD_EQUIPMENT_PRESENT_2); | ||
391 | seq_printf(m, "Fit options\t: %s%s%s%s%s%s%s\n", | ||
392 | (val & PPC7D_CPLD_EQPT_PRES_4_LPT_MASK) ? "LPT " : "", | ||
393 | (val & PPC7D_CPLD_EQPT_PRES_4_PS2_FITTED) ? "PS2 " : "", | ||
394 | (val & PPC7D_CPLD_EQPT_PRES_4_USB2_FITTED) ? "USB2 " : "", | ||
395 | (val2 & PPC7D_CPLD_EQPT_PRES_2_UNIVERSE_MASK) ? "VME " : "", | ||
396 | (val2 & PPC7D_CPLD_EQPT_PRES_2_COM36_MASK) ? "COM3-6 " : "", | ||
397 | (val2 & PPC7D_CPLD_EQPT_PRES_2_GIGE_MASK) ? "eth0 " : "", | ||
398 | (val2 & PPC7D_CPLD_EQPT_PRES_2_DUALGIGE_MASK) ? "eth1 " : | ||
399 | ""); | ||
400 | |||
401 | val = inb(PPC7D_CPLD_ID_LINK); | ||
402 | val1 = val & (PPC7D_CPLD_ID_LINK_E6_MASK | | ||
403 | PPC7D_CPLD_ID_LINK_E7_MASK | | ||
404 | PPC7D_CPLD_ID_LINK_E12_MASK | | ||
405 | PPC7D_CPLD_ID_LINK_E13_MASK); | ||
406 | |||
407 | val = inb(PPC7D_CPLD_FLASH_WRITE_CNTL) & | ||
408 | (PPD7D_CPLD_FLASH_CNTL_WR_LINK_MASK | | ||
409 | PPD7D_CPLD_FLASH_CNTL_BOOT_LINK_MASK | | ||
410 | PPD7D_CPLD_FLASH_CNTL_USER_LINK_MASK); | ||
411 | |||
412 | seq_printf(m, "Board links present: %s%s%s%s%s%s%s%s\n", | ||
413 | (val1 & PPC7D_CPLD_ID_LINK_E6_MASK) ? "E6 " : "", | ||
414 | (val1 & PPC7D_CPLD_ID_LINK_E7_MASK) ? "E7 " : "", | ||
415 | (val & PPD7D_CPLD_FLASH_CNTL_WR_LINK_MASK) ? "E9 " : "", | ||
416 | (val & PPD7D_CPLD_FLASH_CNTL_BOOT_LINK_MASK) ? "E10 " : "", | ||
417 | (val & PPD7D_CPLD_FLASH_CNTL_USER_LINK_MASK) ? "E11 " : "", | ||
418 | (val1 & PPC7D_CPLD_ID_LINK_E12_MASK) ? "E12 " : "", | ||
419 | (val1 & PPC7D_CPLD_ID_LINK_E13_MASK) ? "E13 " : "", | ||
420 | ((val == 0) && (val1 == 0)) ? "NONE" : ""); | ||
421 | |||
422 | val = inb(PPC7D_CPLD_WDOG_RESETSW_MASK); | ||
423 | seq_printf(m, "Front panel reset switch: %sabled\n", | ||
424 | (val & PPC7D_CPLD_WDOG_RESETSW_MASK) ? "dis" : "en"); | ||
425 | |||
426 | return 0; | ||
427 | } | ||
428 | |||
429 | static void __init ppc7d_calibrate_decr(void) | ||
430 | { | ||
431 | ulong freq; | ||
432 | |||
433 | freq = 100000000 / 4; | ||
434 | |||
435 | pr_debug("time_init: decrementer frequency = %lu.%.6lu MHz\n", | ||
436 | freq / 1000000, freq % 1000000); | ||
437 | |||
438 | tb_ticks_per_jiffy = freq / HZ; | ||
439 | tb_to_us = mulhwu_scale_factor(freq, 1000000); | ||
440 | } | ||
441 | |||
442 | /***************************************************************************** | ||
443 | * Interrupt stuff | ||
444 | *****************************************************************************/ | ||
445 | |||
446 | static irqreturn_t ppc7d_i8259_intr(int irq, void *dev_id, struct pt_regs *regs) | ||
447 | { | ||
448 | u32 temp = mv64x60_read(&bh, MV64x60_GPP_INTR_CAUSE); | ||
449 | if (temp & (1 << 28)) { | ||
450 | i8259_irq(regs); | ||
451 | mv64x60_write(&bh, MV64x60_GPP_INTR_CAUSE, temp & (~(1 << 28))); | ||
452 | return IRQ_HANDLED; | ||
453 | } | ||
454 | |||
455 | return IRQ_NONE; | ||
456 | } | ||
457 | |||
458 | /* | ||
459 | * Each interrupt cause is assigned an IRQ number. | ||
460 | * Southbridge has 16*2 (two 8259's) interrupts. | ||
461 | * Discovery-II has 96 interrupts (cause-hi, cause-lo, gpp x 32). | ||
462 | * If multiple interrupts are pending, get_irq() returns the | ||
463 | * lowest pending irq number first. | ||
464 | * | ||
465 | * | ||
466 | * IRQ # Source Trig Active | ||
467 | * ============================================================= | ||
468 | * | ||
469 | * Southbridge | ||
470 | * ----------- | ||
471 | * IRQ # Source Trig | ||
472 | * ============================================================= | ||
473 | * 0 ISA High Resolution Counter Edge | ||
474 | * 1 Keyboard Edge | ||
475 | * 2 Cascade From (IRQ 8-15) Edge | ||
476 | * 3 Com 2 (Uart 2) Edge | ||
477 | * 4 Com 1 (Uart 1) Edge | ||
478 | * 5 PCI Int D/AFIX IRQZ ID4 (2,7) Level | ||
479 | * 6 GPIO Level | ||
480 | * 7 LPT Edge | ||
481 | * 8 RTC Alarm Edge | ||
482 | * 9 PCI Int A/PMC 2/AFIX IRQW ID1 (2,0) Level | ||
483 | * 10 PCI Int B/PMC 1/AFIX IRQX ID2 (2,1) Level | ||
484 | * 11 USB2 Level | ||
485 | * 12 Mouse Edge | ||
486 | * 13 Reserved internally by Ali M1535+ | ||
487 | * 14 PCI Int C/VME/AFIX IRQY ID3 (2,6) Level | ||
488 | * 15 COM 5/6 Level | ||
489 | * | ||
490 | * 16..112 Discovery-II... | ||
491 | * | ||
492 | * MPP28 Southbridge Edge High | ||
493 | * | ||
494 | * | ||
495 | * Interrupts are cascaded through to the Discovery-II. | ||
496 | * | ||
497 | * PCI --- | ||
498 | * \ | ||
499 | * CPLD --> ALI1535 -------> DISCOVERY-II | ||
500 | * INTF MPP28 | ||
501 | */ | ||
502 | static void __init ppc7d_init_irq(void) | ||
503 | { | ||
504 | int irq; | ||
505 | |||
506 | pr_debug("%s\n", __FUNCTION__); | ||
507 | i8259_init(0); | ||
508 | mv64360_init_irq(); | ||
509 | |||
510 | /* IRQ 0..15 are handled by the cascaded 8259's of the Ali1535 */ | ||
511 | for (irq = 0; irq < 16; irq++) { | ||
512 | irq_desc[irq].handler = &i8259_pic; | ||
513 | } | ||
514 | /* IRQs 5,6,9,10,11,14,15 are level sensitive */ | ||
515 | irq_desc[5].status |= IRQ_LEVEL; | ||
516 | irq_desc[6].status |= IRQ_LEVEL; | ||
517 | irq_desc[9].status |= IRQ_LEVEL; | ||
518 | irq_desc[10].status |= IRQ_LEVEL; | ||
519 | irq_desc[11].status |= IRQ_LEVEL; | ||
520 | irq_desc[14].status |= IRQ_LEVEL; | ||
521 | irq_desc[15].status |= IRQ_LEVEL; | ||
522 | |||
523 | /* GPP28 is edge triggered */ | ||
524 | irq_desc[mv64360_irq_base + MV64x60_IRQ_GPP28].status &= ~IRQ_LEVEL; | ||
525 | } | ||
526 | |||
527 | static u32 ppc7d_irq_canonicalize(u32 irq) | ||
528 | { | ||
529 | if ((irq >= 16) && (irq < (16 + 96))) | ||
530 | irq -= 16; | ||
531 | |||
532 | return irq; | ||
533 | } | ||
534 | |||
535 | static int ppc7d_get_irq(struct pt_regs *regs) | ||
536 | { | ||
537 | int irq; | ||
538 | |||
539 | irq = mv64360_get_irq(regs); | ||
540 | if (irq == (mv64360_irq_base + MV64x60_IRQ_GPP28)) | ||
541 | irq = i8259_irq(regs); | ||
542 | return irq; | ||
543 | } | ||
544 | |||
545 | /* | ||
546 | * 9 PCI Int A/PMC 2/AFIX IRQW ID1 (2,0) Level | ||
547 | * 10 PCI Int B/PMC 1/AFIX IRQX ID2 (2,1) Level | ||
548 | * 14 PCI Int C/VME/AFIX IRQY ID3 (2,6) Level | ||
549 | * 5 PCI Int D/AFIX IRQZ ID4 (2,7) Level | ||
550 | */ | ||
551 | static int __init ppc7d_map_irq(struct pci_dev *dev, unsigned char idsel, | ||
552 | unsigned char pin) | ||
553 | { | ||
554 | static const char pci_irq_table[][4] = | ||
555 | /* | ||
556 | * PCI IDSEL/INTPIN->INTLINE | ||
557 | * A B C D | ||
558 | */ | ||
559 | { | ||
560 | {10, 14, 5, 9}, /* IDSEL 10 - PMC2 / AFIX IRQW */ | ||
561 | {9, 10, 14, 5}, /* IDSEL 11 - PMC1 / AFIX IRQX */ | ||
562 | {5, 9, 10, 14}, /* IDSEL 12 - AFIX IRQY */ | ||
563 | {14, 5, 9, 10}, /* IDSEL 13 - AFIX IRQZ */ | ||
564 | }; | ||
565 | const long min_idsel = 10, max_idsel = 14, irqs_per_slot = 4; | ||
566 | |||
567 | pr_debug("%s: %04x/%04x/%x: idsel=%hx pin=%hu\n", __FUNCTION__, | ||
568 | dev->vendor, dev->device, PCI_FUNC(dev->devfn), idsel, pin); | ||
569 | |||
570 | return PCI_IRQ_TABLE_LOOKUP; | ||
571 | } | ||
572 | |||
573 | void __init ppc7d_intr_setup(void) | ||
574 | { | ||
575 | u32 data; | ||
576 | |||
577 | /* | ||
578 | * Define GPP 28 interrupt polarity as active high | ||
579 | * input signal and level triggered | ||
580 | */ | ||
581 | data = mv64x60_read(&bh, MV64x60_GPP_LEVEL_CNTL); | ||
582 | data &= ~(1 << 28); | ||
583 | mv64x60_write(&bh, MV64x60_GPP_LEVEL_CNTL, data); | ||
584 | data = mv64x60_read(&bh, MV64x60_GPP_IO_CNTL); | ||
585 | data &= ~(1 << 28); | ||
586 | mv64x60_write(&bh, MV64x60_GPP_IO_CNTL, data); | ||
587 | |||
588 | /* Config GPP intr ctlr to respond to level trigger */ | ||
589 | data = mv64x60_read(&bh, MV64x60_COMM_ARBITER_CNTL); | ||
590 | data |= (1 << 10); | ||
591 | mv64x60_write(&bh, MV64x60_COMM_ARBITER_CNTL, data); | ||
592 | |||
593 | /* XXXX Erranum FEr PCI-#8 */ | ||
594 | data = mv64x60_read(&bh, MV64x60_PCI0_CMD); | ||
595 | data &= ~((1 << 5) | (1 << 9)); | ||
596 | mv64x60_write(&bh, MV64x60_PCI0_CMD, data); | ||
597 | data = mv64x60_read(&bh, MV64x60_PCI1_CMD); | ||
598 | data &= ~((1 << 5) | (1 << 9)); | ||
599 | mv64x60_write(&bh, MV64x60_PCI1_CMD, data); | ||
600 | |||
601 | /* | ||
602 | * Dismiss and then enable interrupt on GPP interrupt cause | ||
603 | * for CPU #0 | ||
604 | */ | ||
605 | mv64x60_write(&bh, MV64x60_GPP_INTR_CAUSE, ~(1 << 28)); | ||
606 | data = mv64x60_read(&bh, MV64x60_GPP_INTR_MASK); | ||
607 | data |= (1 << 28); | ||
608 | mv64x60_write(&bh, MV64x60_GPP_INTR_MASK, data); | ||
609 | |||
610 | /* | ||
611 | * Dismiss and then enable interrupt on CPU #0 high cause reg | ||
612 | * BIT27 summarizes GPP interrupts 23-31 | ||
613 | */ | ||
614 | mv64x60_write(&bh, MV64360_IC_MAIN_CAUSE_HI, ~(1 << 27)); | ||
615 | data = mv64x60_read(&bh, MV64360_IC_CPU0_INTR_MASK_HI); | ||
616 | data |= (1 << 27); | ||
617 | mv64x60_write(&bh, MV64360_IC_CPU0_INTR_MASK_HI, data); | ||
618 | } | ||
619 | |||
620 | /***************************************************************************** | ||
621 | * Platform device data fixup routines. | ||
622 | *****************************************************************************/ | ||
623 | |||
624 | #if defined(CONFIG_SERIAL_MPSC) | ||
625 | static void __init ppc7d_fixup_mpsc_pdata(struct platform_device *pdev) | ||
626 | { | ||
627 | struct mpsc_pdata *pdata; | ||
628 | |||
629 | pdata = (struct mpsc_pdata *)pdev->dev.platform_data; | ||
630 | |||
631 | pdata->max_idle = 40; | ||
632 | pdata->default_baud = PPC7D_DEFAULT_BAUD; | ||
633 | pdata->brg_clk_src = PPC7D_MPSC_CLK_SRC; | ||
634 | pdata->brg_clk_freq = PPC7D_MPSC_CLK_FREQ; | ||
635 | |||
636 | return; | ||
637 | } | ||
638 | #endif | ||
639 | |||
640 | #if defined(CONFIG_MV643XX_ETH) | ||
641 | static void __init ppc7d_fixup_eth_pdata(struct platform_device *pdev) | ||
642 | { | ||
643 | struct mv643xx_eth_platform_data *eth_pd; | ||
644 | static u16 phy_addr[] = { | ||
645 | PPC7D_ETH0_PHY_ADDR, | ||
646 | PPC7D_ETH1_PHY_ADDR, | ||
647 | PPC7D_ETH2_PHY_ADDR, | ||
648 | }; | ||
649 | int i; | ||
650 | |||
651 | eth_pd = pdev->dev.platform_data; | ||
652 | eth_pd->force_phy_addr = 1; | ||
653 | eth_pd->phy_addr = phy_addr[pdev->id]; | ||
654 | eth_pd->tx_queue_size = PPC7D_ETH_TX_QUEUE_SIZE; | ||
655 | eth_pd->rx_queue_size = PPC7D_ETH_RX_QUEUE_SIZE; | ||
656 | |||
657 | /* Adjust IRQ by mv64360_irq_base */ | ||
658 | for (i = 0; i < pdev->num_resources; i++) { | ||
659 | struct resource *r = &pdev->resource[i]; | ||
660 | |||
661 | if (r->flags & IORESOURCE_IRQ) { | ||
662 | r->start += mv64360_irq_base; | ||
663 | r->end += mv64360_irq_base; | ||
664 | pr_debug("%s, uses IRQ %d\n", pdev->name, | ||
665 | (int)r->start); | ||
666 | } | ||
667 | } | ||
668 | |||
669 | } | ||
670 | #endif | ||
671 | |||
672 | #if defined(CONFIG_I2C_MV64XXX) | ||
673 | static void __init | ||
674 | ppc7d_fixup_i2c_pdata(struct platform_device *pdev) | ||
675 | { | ||
676 | struct mv64xxx_i2c_pdata *pdata; | ||
677 | int i; | ||
678 | |||
679 | pdata = pdev->dev.platform_data; | ||
680 | if (pdata == NULL) { | ||
681 | pdata = kmalloc(sizeof(*pdata), GFP_KERNEL); | ||
682 | if (pdata == NULL) | ||
683 | return; | ||
684 | |||
685 | memset(pdata, 0, sizeof(*pdata)); | ||
686 | pdev->dev.platform_data = pdata; | ||
687 | } | ||
688 | |||
689 | /* divisors M=8, N=3 for 100kHz I2C from 133MHz system clock */ | ||
690 | pdata->freq_m = 8; | ||
691 | pdata->freq_n = 3; | ||
692 | pdata->timeout = 500; | ||
693 | pdata->retries = 3; | ||
694 | |||
695 | /* Adjust IRQ by mv64360_irq_base */ | ||
696 | for (i = 0; i < pdev->num_resources; i++) { | ||
697 | struct resource *r = &pdev->resource[i]; | ||
698 | |||
699 | if (r->flags & IORESOURCE_IRQ) { | ||
700 | r->start += mv64360_irq_base; | ||
701 | r->end += mv64360_irq_base; | ||
702 | pr_debug("%s, uses IRQ %d\n", pdev->name, (int) r->start); | ||
703 | } | ||
704 | } | ||
705 | } | ||
706 | #endif | ||
707 | |||
708 | static int __init ppc7d_platform_notify(struct device *dev) | ||
709 | { | ||
710 | static struct { | ||
711 | char *bus_id; | ||
712 | void ((*rtn) (struct platform_device * pdev)); | ||
713 | } dev_map[] = { | ||
714 | #if defined(CONFIG_SERIAL_MPSC) | ||
715 | { MPSC_CTLR_NAME ".0", ppc7d_fixup_mpsc_pdata }, | ||
716 | { MPSC_CTLR_NAME ".1", ppc7d_fixup_mpsc_pdata }, | ||
717 | #endif | ||
718 | #if defined(CONFIG_MV643XX_ETH) | ||
719 | { MV643XX_ETH_NAME ".0", ppc7d_fixup_eth_pdata }, | ||
720 | { MV643XX_ETH_NAME ".1", ppc7d_fixup_eth_pdata }, | ||
721 | { MV643XX_ETH_NAME ".2", ppc7d_fixup_eth_pdata }, | ||
722 | #endif | ||
723 | #if defined(CONFIG_I2C_MV64XXX) | ||
724 | { MV64XXX_I2C_CTLR_NAME ".0", ppc7d_fixup_i2c_pdata }, | ||
725 | #endif | ||
726 | }; | ||
727 | struct platform_device *pdev; | ||
728 | int i; | ||
729 | |||
730 | if (dev && dev->bus_id) | ||
731 | for (i = 0; i < ARRAY_SIZE(dev_map); i++) | ||
732 | if (!strncmp(dev->bus_id, dev_map[i].bus_id, | ||
733 | BUS_ID_SIZE)) { | ||
734 | |||
735 | pdev = container_of(dev, | ||
736 | struct platform_device, | ||
737 | dev); | ||
738 | dev_map[i].rtn(pdev); | ||
739 | } | ||
740 | |||
741 | return 0; | ||
742 | } | ||
743 | |||
744 | /***************************************************************************** | ||
745 | * PCI device fixups. | ||
746 | * These aren't really fixups per se. They are used to init devices as they | ||
747 | * are found during PCI scan. | ||
748 | * | ||
749 | * The PPC7D has an HB8 PCI-X bridge which must be set up during a PCI | ||
750 | * scan in order to find other devices on its secondary side. | ||
751 | *****************************************************************************/ | ||
752 | |||
753 | static void __init ppc7d_fixup_hb8(struct pci_dev *dev) | ||
754 | { | ||
755 | u16 val16; | ||
756 | |||
757 | if (dev->bus->number == 0) { | ||
758 | pr_debug("PCI: HB8 init\n"); | ||
759 | |||
760 | pci_write_config_byte(dev, 0x1c, | ||
761 | ((PPC7D_PCI0_IO_START_PCI_ADDR & 0xf000) | ||
762 | >> 8) | 0x01); | ||
763 | pci_write_config_byte(dev, 0x1d, | ||
764 | (((PPC7D_PCI0_IO_START_PCI_ADDR + | ||
765 | PPC7D_PCI0_IO_SIZE - | ||
766 | 1) & 0xf000) >> 8) | 0x01); | ||
767 | pci_write_config_word(dev, 0x30, | ||
768 | PPC7D_PCI0_IO_START_PCI_ADDR >> 16); | ||
769 | pci_write_config_word(dev, 0x32, | ||
770 | ((PPC7D_PCI0_IO_START_PCI_ADDR + | ||
771 | PPC7D_PCI0_IO_SIZE - | ||
772 | 1) >> 16) & 0xffff); | ||
773 | |||
774 | pci_write_config_word(dev, 0x20, | ||
775 | PPC7D_PCI0_MEM0_START_PCI_LO_ADDR >> 16); | ||
776 | pci_write_config_word(dev, 0x22, | ||
777 | ((PPC7D_PCI0_MEM0_START_PCI_LO_ADDR + | ||
778 | PPC7D_PCI0_MEM0_SIZE - | ||
779 | 1) >> 16) & 0xffff); | ||
780 | pci_write_config_word(dev, 0x24, 0); | ||
781 | pci_write_config_word(dev, 0x26, 0); | ||
782 | pci_write_config_dword(dev, 0x28, 0); | ||
783 | pci_write_config_dword(dev, 0x2c, 0); | ||
784 | |||
785 | pci_read_config_word(dev, 0x3e, &val16); | ||
786 | val16 |= ((1 << 5) | (1 << 1)); /* signal master aborts and | ||
787 | * SERR to primary | ||
788 | */ | ||
789 | val16 &= ~(1 << 2); /* ISA disable, so all ISA | ||
790 | * ports forwarded to secondary | ||
791 | */ | ||
792 | pci_write_config_word(dev, 0x3e, val16); | ||
793 | } | ||
794 | } | ||
795 | |||
796 | DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_HINT, 0x0028, ppc7d_fixup_hb8); | ||
797 | |||
798 | /* This should perhaps be a separate driver as we're actually initializing | ||
799 | * the chip for this board here. It's hardly a fixup... | ||
800 | */ | ||
801 | static void __init ppc7d_fixup_ali1535(struct pci_dev *dev) | ||
802 | { | ||
803 | pr_debug("PCI: ALI1535 init\n"); | ||
804 | |||
805 | if (dev->bus->number == 1) { | ||
806 | /* Configure the ISA Port Settings */ | ||
807 | pci_write_config_byte(dev, 0x43, 0x00); | ||
808 | |||
809 | /* Disable PCI Interrupt polling mode */ | ||
810 | pci_write_config_byte(dev, 0x45, 0x00); | ||
811 | |||
812 | /* Multifunction pin select INTFJ -> INTF */ | ||
813 | pci_write_config_byte(dev, 0x78, 0x00); | ||
814 | |||
815 | /* Set PCI INT -> IRQ Routing control in for external | ||
816 | * pins south bridge. | ||
817 | */ | ||
818 | pci_write_config_byte(dev, 0x48, 0x31); /* [7-4] INT B -> IRQ10 | ||
819 | * [3-0] INT A -> IRQ9 | ||
820 | */ | ||
821 | pci_write_config_byte(dev, 0x49, 0x5D); /* [7-4] INT D -> IRQ5 | ||
822 | * [3-0] INT C -> IRQ14 | ||
823 | */ | ||
824 | |||
825 | /* PPC7D setup */ | ||
826 | /* NEC USB device on IRQ 11 (INTE) - INTF disabled */ | ||
827 | pci_write_config_byte(dev, 0x4A, 0x09); | ||
828 | |||
829 | /* GPIO on IRQ 6 */ | ||
830 | pci_write_config_byte(dev, 0x76, 0x07); | ||
831 | |||
832 | /* SIRQ I (COMS 5/6) use IRQ line 15. | ||
833 | * Positive (not subtractive) address decode. | ||
834 | */ | ||
835 | pci_write_config_byte(dev, 0x44, 0x0f); | ||
836 | |||
837 | /* SIRQ II disabled */ | ||
838 | pci_write_config_byte(dev, 0x75, 0x0); | ||
839 | |||
840 | /* On board USB and RTC disabled */ | ||
841 | pci_write_config_word(dev, 0x52, (1 << 14)); | ||
842 | pci_write_config_byte(dev, 0x74, 0x00); | ||
843 | |||
844 | /* On board IDE disabled */ | ||
845 | pci_write_config_byte(dev, 0x58, 0x00); | ||
846 | |||
847 | /* Decode 32-bit addresses */ | ||
848 | pci_write_config_byte(dev, 0x5b, 0); | ||
849 | |||
850 | /* Disable docking IO */ | ||
851 | pci_write_config_word(dev, 0x5c, 0x0000); | ||
852 | |||
853 | /* Disable modem, enable sound */ | ||
854 | pci_write_config_byte(dev, 0x77, (1 << 6)); | ||
855 | |||
856 | /* Disable hot-docking mode */ | ||
857 | pci_write_config_byte(dev, 0x7d, 0x00); | ||
858 | } | ||
859 | } | ||
860 | |||
861 | DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_AL, 0x1533, ppc7d_fixup_ali1535); | ||
862 | |||
863 | static int ppc7d_pci_exclude_device(u8 bus, u8 devfn) | ||
864 | { | ||
865 | /* Early versions of this board were fitted with IBM ALMA | ||
866 | * PCI-VME bridge chips. The PCI config space of these devices | ||
867 | * was not set up correctly and causes PCI scan problems. | ||
868 | */ | ||
869 | if ((bus == 1) && (PCI_SLOT(devfn) == 4) && ppc7d_has_alma) | ||
870 | return PCIBIOS_DEVICE_NOT_FOUND; | ||
871 | |||
872 | return mv64x60_pci_exclude_device(bus, devfn); | ||
873 | } | ||
874 | |||
875 | /* This hook is called when each PCI bus is probed. | ||
876 | */ | ||
877 | static void ppc7d_pci_fixup_bus(struct pci_bus *bus) | ||
878 | { | ||
879 | pr_debug("PCI BUS %hu: %lx/%lx %lx/%lx %lx/%lx %lx/%lx\n", | ||
880 | bus->number, | ||
881 | bus->resource[0] ? bus->resource[0]->start : 0, | ||
882 | bus->resource[0] ? bus->resource[0]->end : 0, | ||
883 | bus->resource[1] ? bus->resource[1]->start : 0, | ||
884 | bus->resource[1] ? bus->resource[1]->end : 0, | ||
885 | bus->resource[2] ? bus->resource[2]->start : 0, | ||
886 | bus->resource[2] ? bus->resource[2]->end : 0, | ||
887 | bus->resource[3] ? bus->resource[3]->start : 0, | ||
888 | bus->resource[3] ? bus->resource[3]->end : 0); | ||
889 | |||
890 | if ((bus->number == 1) && (bus->resource[2] != NULL)) { | ||
891 | /* Hide PCI window 2 of Bus 1 which is used only to | ||
892 | * map legacy ISA memory space. | ||
893 | */ | ||
894 | bus->resource[2]->start = 0; | ||
895 | bus->resource[2]->end = 0; | ||
896 | bus->resource[2]->flags = 0; | ||
897 | } | ||
898 | } | ||
899 | |||
900 | /***************************************************************************** | ||
901 | * Board device setup code | ||
902 | *****************************************************************************/ | ||
903 | |||
904 | void __init ppc7d_setup_peripherals(void) | ||
905 | { | ||
906 | u32 val32; | ||
907 | |||
908 | /* Set up windows for boot CS */ | ||
909 | mv64x60_set_32bit_window(&bh, MV64x60_CPU2BOOT_WIN, | ||
910 | PPC7D_BOOT_WINDOW_BASE, PPC7D_BOOT_WINDOW_SIZE, | ||
911 | 0); | ||
912 | bh.ci->enable_window_32bit(&bh, MV64x60_CPU2BOOT_WIN); | ||
913 | |||
914 | /* Boot firmware configures the following DevCS addresses. | ||
915 | * DevCS0 - board control/status | ||
916 | * DevCS1 - test registers | ||
917 | * DevCS2 - AFIX port/address registers (for identifying) | ||
918 | * DevCS3 - FLASH | ||
919 | * | ||
920 | * We don't use DevCS0, DevCS1. | ||
921 | */ | ||
922 | val32 = mv64x60_read(&bh, MV64360_CPU_BAR_ENABLE); | ||
923 | val32 |= ((1 << 4) | (1 << 5)); | ||
924 | mv64x60_write(&bh, MV64360_CPU_BAR_ENABLE, val32); | ||
925 | mv64x60_write(&bh, MV64x60_CPU2DEV_0_BASE, 0); | ||
926 | mv64x60_write(&bh, MV64x60_CPU2DEV_0_SIZE, 0); | ||
927 | mv64x60_write(&bh, MV64x60_CPU2DEV_1_BASE, 0); | ||
928 | mv64x60_write(&bh, MV64x60_CPU2DEV_1_SIZE, 0); | ||
929 | |||
930 | mv64x60_set_32bit_window(&bh, MV64x60_CPU2DEV_2_WIN, | ||
931 | PPC7D_AFIX_REG_BASE, PPC7D_AFIX_REG_SIZE, 0); | ||
932 | bh.ci->enable_window_32bit(&bh, MV64x60_CPU2DEV_2_WIN); | ||
933 | |||
934 | mv64x60_set_32bit_window(&bh, MV64x60_CPU2DEV_3_WIN, | ||
935 | PPC7D_FLASH_BASE, PPC7D_FLASH_SIZE_ACTUAL, 0); | ||
936 | bh.ci->enable_window_32bit(&bh, MV64x60_CPU2DEV_3_WIN); | ||
937 | |||
938 | mv64x60_set_32bit_window(&bh, MV64x60_CPU2SRAM_WIN, | ||
939 | PPC7D_INTERNAL_SRAM_BASE, MV64360_SRAM_SIZE, | ||
940 | 0); | ||
941 | bh.ci->enable_window_32bit(&bh, MV64x60_CPU2SRAM_WIN); | ||
942 | |||
943 | /* Set up Enet->SRAM window */ | ||
944 | mv64x60_set_32bit_window(&bh, MV64x60_ENET2MEM_4_WIN, | ||
945 | PPC7D_INTERNAL_SRAM_BASE, MV64360_SRAM_SIZE, | ||
946 | 0x2); | ||
947 | bh.ci->enable_window_32bit(&bh, MV64x60_ENET2MEM_4_WIN); | ||
948 | |||
949 | /* Give enet r/w access to memory region */ | ||
950 | val32 = mv64x60_read(&bh, MV64360_ENET2MEM_ACC_PROT_0); | ||
951 | val32 |= (0x3 << (4 << 1)); | ||
952 | mv64x60_write(&bh, MV64360_ENET2MEM_ACC_PROT_0, val32); | ||
953 | val32 = mv64x60_read(&bh, MV64360_ENET2MEM_ACC_PROT_1); | ||
954 | val32 |= (0x3 << (4 << 1)); | ||
955 | mv64x60_write(&bh, MV64360_ENET2MEM_ACC_PROT_1, val32); | ||
956 | val32 = mv64x60_read(&bh, MV64360_ENET2MEM_ACC_PROT_2); | ||
957 | val32 |= (0x3 << (4 << 1)); | ||
958 | mv64x60_write(&bh, MV64360_ENET2MEM_ACC_PROT_2, val32); | ||
959 | |||
960 | val32 = mv64x60_read(&bh, MV64x60_TIMR_CNTR_0_3_CNTL); | ||
961 | val32 &= ~((1 << 0) | (1 << 8) | (1 << 16) | (1 << 24)); | ||
962 | mv64x60_write(&bh, MV64x60_TIMR_CNTR_0_3_CNTL, val32); | ||
963 | |||
964 | /* Enumerate pci bus. | ||
965 | * | ||
966 | * We scan PCI#0 first (the bus with the HB8 and other | ||
967 | * on-board peripherals). We must configure the 64360 before | ||
968 | * each scan, according to the bus number assignments. Busses | ||
969 | * are assigned incrementally, starting at 0. PCI#0 is | ||
970 | * usually assigned bus#0, the secondary side of the HB8 gets | ||
971 | * bus#1 and PCI#1 (second PMC site) gets bus#2. However, if | ||
972 | * any PMC card has a PCI bridge, these bus assignments will | ||
973 | * change. | ||
974 | */ | ||
975 | |||
976 | /* Turn off PCI retries */ | ||
977 | val32 = mv64x60_read(&bh, MV64x60_CPU_CONFIG); | ||
978 | val32 |= (1 << 17); | ||
979 | mv64x60_write(&bh, MV64x60_CPU_CONFIG, val32); | ||
980 | |||
981 | /* Scan PCI#0 */ | ||
982 | mv64x60_set_bus(&bh, 0, 0); | ||
983 | bh.hose_a->first_busno = 0; | ||
984 | bh.hose_a->last_busno = 0xff; | ||
985 | bh.hose_a->last_busno = pciauto_bus_scan(bh.hose_a, 0); | ||
986 | printk(KERN_INFO "PCI#0: first=%d last=%d\n", | ||
987 | bh.hose_a->first_busno, bh.hose_a->last_busno); | ||
988 | |||
989 | /* Scan PCI#1 */ | ||
990 | bh.hose_b->first_busno = bh.hose_a->last_busno + 1; | ||
991 | mv64x60_set_bus(&bh, 1, bh.hose_b->first_busno); | ||
992 | bh.hose_b->last_busno = 0xff; | ||
993 | bh.hose_b->last_busno = pciauto_bus_scan(bh.hose_b, | ||
994 | bh.hose_b->first_busno); | ||
995 | printk(KERN_INFO "PCI#1: first=%d last=%d\n", | ||
996 | bh.hose_b->first_busno, bh.hose_b->last_busno); | ||
997 | |||
998 | /* Turn on PCI retries */ | ||
999 | val32 = mv64x60_read(&bh, MV64x60_CPU_CONFIG); | ||
1000 | val32 &= ~(1 << 17); | ||
1001 | mv64x60_write(&bh, MV64x60_CPU_CONFIG, val32); | ||
1002 | |||
1003 | /* Setup interrupts */ | ||
1004 | ppc7d_intr_setup(); | ||
1005 | } | ||
1006 | |||
1007 | static void __init ppc7d_setup_bridge(void) | ||
1008 | { | ||
1009 | struct mv64x60_setup_info si; | ||
1010 | int i; | ||
1011 | u32 temp; | ||
1012 | |||
1013 | mv64360_irq_base = 16; /* first 16 intrs are 2 x 8259's */ | ||
1014 | |||
1015 | memset(&si, 0, sizeof(si)); | ||
1016 | |||
1017 | si.phys_reg_base = CONFIG_MV64X60_NEW_BASE; | ||
1018 | |||
1019 | si.pci_0.enable_bus = 1; | ||
1020 | si.pci_0.pci_io.cpu_base = PPC7D_PCI0_IO_START_PROC_ADDR; | ||
1021 | si.pci_0.pci_io.pci_base_hi = 0; | ||
1022 | si.pci_0.pci_io.pci_base_lo = PPC7D_PCI0_IO_START_PCI_ADDR; | ||
1023 | si.pci_0.pci_io.size = PPC7D_PCI0_IO_SIZE; | ||
1024 | si.pci_0.pci_io.swap = MV64x60_CPU2PCI_SWAP_NONE; | ||
1025 | si.pci_0.pci_mem[0].cpu_base = PPC7D_PCI0_MEM0_START_PROC_ADDR; | ||
1026 | si.pci_0.pci_mem[0].pci_base_hi = PPC7D_PCI0_MEM0_START_PCI_HI_ADDR; | ||
1027 | si.pci_0.pci_mem[0].pci_base_lo = PPC7D_PCI0_MEM0_START_PCI_LO_ADDR; | ||
1028 | si.pci_0.pci_mem[0].size = PPC7D_PCI0_MEM0_SIZE; | ||
1029 | si.pci_0.pci_mem[0].swap = MV64x60_CPU2PCI_SWAP_NONE; | ||
1030 | si.pci_0.pci_mem[1].cpu_base = PPC7D_PCI0_MEM1_START_PROC_ADDR; | ||
1031 | si.pci_0.pci_mem[1].pci_base_hi = PPC7D_PCI0_MEM1_START_PCI_HI_ADDR; | ||
1032 | si.pci_0.pci_mem[1].pci_base_lo = PPC7D_PCI0_MEM1_START_PCI_LO_ADDR; | ||
1033 | si.pci_0.pci_mem[1].size = PPC7D_PCI0_MEM1_SIZE; | ||
1034 | si.pci_0.pci_mem[1].swap = MV64x60_CPU2PCI_SWAP_NONE; | ||
1035 | si.pci_0.pci_cmd_bits = 0; | ||
1036 | si.pci_0.latency_timer = 0x80; | ||
1037 | |||
1038 | si.pci_1.enable_bus = 1; | ||
1039 | si.pci_1.pci_io.cpu_base = PPC7D_PCI1_IO_START_PROC_ADDR; | ||
1040 | si.pci_1.pci_io.pci_base_hi = 0; | ||
1041 | si.pci_1.pci_io.pci_base_lo = PPC7D_PCI1_IO_START_PCI_ADDR; | ||
1042 | si.pci_1.pci_io.size = PPC7D_PCI1_IO_SIZE; | ||
1043 | si.pci_1.pci_io.swap = MV64x60_CPU2PCI_SWAP_NONE; | ||
1044 | si.pci_1.pci_mem[0].cpu_base = PPC7D_PCI1_MEM0_START_PROC_ADDR; | ||
1045 | si.pci_1.pci_mem[0].pci_base_hi = PPC7D_PCI1_MEM0_START_PCI_HI_ADDR; | ||
1046 | si.pci_1.pci_mem[0].pci_base_lo = PPC7D_PCI1_MEM0_START_PCI_LO_ADDR; | ||
1047 | si.pci_1.pci_mem[0].size = PPC7D_PCI1_MEM0_SIZE; | ||
1048 | si.pci_1.pci_mem[0].swap = MV64x60_CPU2PCI_SWAP_NONE; | ||
1049 | si.pci_1.pci_mem[1].cpu_base = PPC7D_PCI1_MEM1_START_PROC_ADDR; | ||
1050 | si.pci_1.pci_mem[1].pci_base_hi = PPC7D_PCI1_MEM1_START_PCI_HI_ADDR; | ||
1051 | si.pci_1.pci_mem[1].pci_base_lo = PPC7D_PCI1_MEM1_START_PCI_LO_ADDR; | ||
1052 | si.pci_1.pci_mem[1].size = PPC7D_PCI1_MEM1_SIZE; | ||
1053 | si.pci_1.pci_mem[1].swap = MV64x60_CPU2PCI_SWAP_NONE; | ||
1054 | si.pci_1.pci_cmd_bits = 0; | ||
1055 | si.pci_1.latency_timer = 0x80; | ||
1056 | |||
1057 | /* Don't clear the SRAM window since we use it for debug */ | ||
1058 | si.window_preserve_mask_32_lo = (1 << MV64x60_CPU2SRAM_WIN); | ||
1059 | |||
1060 | printk(KERN_INFO "PCI: MV64360 PCI#0 IO at %x, size %x\n", | ||
1061 | si.pci_0.pci_io.cpu_base, si.pci_0.pci_io.size); | ||
1062 | printk(KERN_INFO "PCI: MV64360 PCI#1 IO at %x, size %x\n", | ||
1063 | si.pci_1.pci_io.cpu_base, si.pci_1.pci_io.size); | ||
1064 | |||
1065 | for (i = 0; i < MV64x60_CPU2MEM_WINDOWS; i++) { | ||
1066 | #if defined(CONFIG_NOT_COHERENT_CACHE) | ||
1067 | si.cpu_prot_options[i] = 0; | ||
1068 | si.enet_options[i] = MV64360_ENET2MEM_SNOOP_NONE; | ||
1069 | si.mpsc_options[i] = MV64360_MPSC2MEM_SNOOP_NONE; | ||
1070 | si.idma_options[i] = MV64360_IDMA2MEM_SNOOP_NONE; | ||
1071 | |||
1072 | si.pci_0.acc_cntl_options[i] = | ||
1073 | MV64360_PCI_ACC_CNTL_SNOOP_NONE | | ||
1074 | MV64360_PCI_ACC_CNTL_SWAP_NONE | | ||
1075 | MV64360_PCI_ACC_CNTL_MBURST_128_BYTES | | ||
1076 | MV64360_PCI_ACC_CNTL_RDSIZE_256_BYTES; | ||
1077 | |||
1078 | si.pci_1.acc_cntl_options[i] = | ||
1079 | MV64360_PCI_ACC_CNTL_SNOOP_NONE | | ||
1080 | MV64360_PCI_ACC_CNTL_SWAP_NONE | | ||
1081 | MV64360_PCI_ACC_CNTL_MBURST_128_BYTES | | ||
1082 | MV64360_PCI_ACC_CNTL_RDSIZE_256_BYTES; | ||
1083 | #else | ||
1084 | si.cpu_prot_options[i] = 0; | ||
1085 | /* All PPC7D hardware uses B0 or newer MV64360 silicon which | ||
1086 | * does not have snoop bugs. | ||
1087 | */ | ||
1088 | si.enet_options[i] = MV64360_ENET2MEM_SNOOP_WB; | ||
1089 | si.mpsc_options[i] = MV64360_MPSC2MEM_SNOOP_WB; | ||
1090 | si.idma_options[i] = MV64360_IDMA2MEM_SNOOP_WB; | ||
1091 | |||
1092 | si.pci_0.acc_cntl_options[i] = | ||
1093 | MV64360_PCI_ACC_CNTL_SNOOP_WB | | ||
1094 | MV64360_PCI_ACC_CNTL_SWAP_NONE | | ||
1095 | MV64360_PCI_ACC_CNTL_MBURST_32_BYTES | | ||
1096 | MV64360_PCI_ACC_CNTL_RDSIZE_32_BYTES; | ||
1097 | |||
1098 | si.pci_1.acc_cntl_options[i] = | ||
1099 | MV64360_PCI_ACC_CNTL_SNOOP_WB | | ||
1100 | MV64360_PCI_ACC_CNTL_SWAP_NONE | | ||
1101 | MV64360_PCI_ACC_CNTL_MBURST_32_BYTES | | ||
1102 | MV64360_PCI_ACC_CNTL_RDSIZE_32_BYTES; | ||
1103 | #endif | ||
1104 | } | ||
1105 | |||
1106 | /* Lookup PCI host bridges */ | ||
1107 | if (mv64x60_init(&bh, &si)) | ||
1108 | printk(KERN_ERR "MV64360 initialization failed.\n"); | ||
1109 | |||
1110 | pr_debug("MV64360 regs @ %lx/%p\n", bh.p_base, bh.v_base); | ||
1111 | |||
1112 | /* Enable WB Cache coherency on SRAM */ | ||
1113 | temp = mv64x60_read(&bh, MV64360_SRAM_CONFIG); | ||
1114 | pr_debug("SRAM_CONFIG: %x\n", temp); | ||
1115 | #if defined(CONFIG_NOT_COHERENT_CACHE) | ||
1116 | mv64x60_write(&bh, MV64360_SRAM_CONFIG, temp & ~0x2); | ||
1117 | #else | ||
1118 | mv64x60_write(&bh, MV64360_SRAM_CONFIG, temp | 0x2); | ||
1119 | #endif | ||
1120 | /* If system operates with internal bus arbiter (CPU master | ||
1121 | * control bit8) clear AACK Delay bit [25] in CPU | ||
1122 | * configuration register. | ||
1123 | */ | ||
1124 | temp = mv64x60_read(&bh, MV64x60_CPU_MASTER_CNTL); | ||
1125 | if (temp & (1 << 8)) { | ||
1126 | temp = mv64x60_read(&bh, MV64x60_CPU_CONFIG); | ||
1127 | mv64x60_write(&bh, MV64x60_CPU_CONFIG, (temp & ~(1 << 25))); | ||
1128 | } | ||
1129 | |||
1130 | /* Data and address parity is enabled */ | ||
1131 | temp = mv64x60_read(&bh, MV64x60_CPU_CONFIG); | ||
1132 | mv64x60_write(&bh, MV64x60_CPU_CONFIG, | ||
1133 | (temp | (1 << 26) | (1 << 19))); | ||
1134 | |||
1135 | pci_dram_offset = 0; /* sys mem at same addr on PCI & cpu bus */ | ||
1136 | ppc_md.pci_swizzle = common_swizzle; | ||
1137 | ppc_md.pci_map_irq = ppc7d_map_irq; | ||
1138 | ppc_md.pci_exclude_device = ppc7d_pci_exclude_device; | ||
1139 | |||
1140 | mv64x60_set_bus(&bh, 0, 0); | ||
1141 | bh.hose_a->first_busno = 0; | ||
1142 | bh.hose_a->last_busno = 0xff; | ||
1143 | bh.hose_a->mem_space.start = PPC7D_PCI0_MEM0_START_PCI_LO_ADDR; | ||
1144 | bh.hose_a->mem_space.end = | ||
1145 | PPC7D_PCI0_MEM0_START_PCI_LO_ADDR + PPC7D_PCI0_MEM0_SIZE; | ||
1146 | |||
1147 | /* These will be set later, as a result of PCI0 scan */ | ||
1148 | bh.hose_b->first_busno = 0; | ||
1149 | bh.hose_b->last_busno = 0xff; | ||
1150 | bh.hose_b->mem_space.start = PPC7D_PCI1_MEM0_START_PCI_LO_ADDR; | ||
1151 | bh.hose_b->mem_space.end = | ||
1152 | PPC7D_PCI1_MEM0_START_PCI_LO_ADDR + PPC7D_PCI1_MEM0_SIZE; | ||
1153 | |||
1154 | pr_debug("MV64360: PCI#0 IO decode %08x/%08x IO remap %08x\n", | ||
1155 | mv64x60_read(&bh, 0x48), mv64x60_read(&bh, 0x50), | ||
1156 | mv64x60_read(&bh, 0xf0)); | ||
1157 | } | ||
1158 | |||
1159 | static void __init ppc7d_setup_arch(void) | ||
1160 | { | ||
1161 | int port; | ||
1162 | |||
1163 | loops_per_jiffy = 100000000 / HZ; | ||
1164 | |||
1165 | #ifdef CONFIG_BLK_DEV_INITRD | ||
1166 | if (initrd_start) | ||
1167 | ROOT_DEV = Root_RAM0; | ||
1168 | else | ||
1169 | #endif | ||
1170 | #ifdef CONFIG_ROOT_NFS | ||
1171 | ROOT_DEV = Root_NFS; | ||
1172 | #else | ||
1173 | ROOT_DEV = Root_HDA1; | ||
1174 | #endif | ||
1175 | |||
1176 | if ((cur_cpu_spec[0]->cpu_features & CPU_FTR_SPEC7450) || | ||
1177 | (cur_cpu_spec[0]->cpu_features & CPU_FTR_L3CR)) | ||
1178 | /* 745x is different. We only want to pass along enable. */ | ||
1179 | _set_L2CR(L2CR_L2E); | ||
1180 | else if (cur_cpu_spec[0]->cpu_features & CPU_FTR_L2CR) | ||
1181 | /* All modules have 1MB of L2. We also assume that an | ||
1182 | * L2 divisor of 3 will work. | ||
1183 | */ | ||
1184 | _set_L2CR(L2CR_L2E | L2CR_L2SIZ_1MB | L2CR_L2CLK_DIV3 | ||
1185 | | L2CR_L2RAM_PIPE | L2CR_L2OH_1_0 | L2CR_L2DF); | ||
1186 | |||
1187 | if (cur_cpu_spec[0]->cpu_features & CPU_FTR_L3CR) | ||
1188 | /* No L3 cache */ | ||
1189 | _set_L3CR(0); | ||
1190 | |||
1191 | #ifdef CONFIG_DUMMY_CONSOLE | ||
1192 | conswitchp = &dummy_con; | ||
1193 | #endif | ||
1194 | |||
1195 | /* Lookup PCI host bridges */ | ||
1196 | if (ppc_md.progress) | ||
1197 | ppc_md.progress("ppc7d_setup_arch: calling setup_bridge", 0); | ||
1198 | |||
1199 | ppc7d_setup_bridge(); | ||
1200 | ppc7d_setup_peripherals(); | ||
1201 | |||
1202 | /* Disable ethernet. It might have been setup by the bootrom */ | ||
1203 | for (port = 0; port < 3; port++) | ||
1204 | mv64x60_write(&bh, MV643XX_ETH_RECEIVE_QUEUE_COMMAND_REG(port), | ||
1205 | 0x0000ff00); | ||
1206 | |||
1207 | /* Clear queue pointers to ensure they are all initialized, | ||
1208 | * otherwise since queues 1-7 are unused, they have random | ||
1209 | * pointers which look strange in register dumps. Don't bother | ||
1210 | * with queue 0 since it will be initialized later. | ||
1211 | */ | ||
1212 | for (port = 0; port < 3; port++) { | ||
1213 | mv64x60_write(&bh, | ||
1214 | MV643XX_ETH_RX_CURRENT_QUEUE_DESC_PTR_1(port), | ||
1215 | 0x00000000); | ||
1216 | mv64x60_write(&bh, | ||
1217 | MV643XX_ETH_RX_CURRENT_QUEUE_DESC_PTR_2(port), | ||
1218 | 0x00000000); | ||
1219 | mv64x60_write(&bh, | ||
1220 | MV643XX_ETH_RX_CURRENT_QUEUE_DESC_PTR_3(port), | ||
1221 | 0x00000000); | ||
1222 | mv64x60_write(&bh, | ||
1223 | MV643XX_ETH_RX_CURRENT_QUEUE_DESC_PTR_4(port), | ||
1224 | 0x00000000); | ||
1225 | mv64x60_write(&bh, | ||
1226 | MV643XX_ETH_RX_CURRENT_QUEUE_DESC_PTR_5(port), | ||
1227 | 0x00000000); | ||
1228 | mv64x60_write(&bh, | ||
1229 | MV643XX_ETH_RX_CURRENT_QUEUE_DESC_PTR_6(port), | ||
1230 | 0x00000000); | ||
1231 | mv64x60_write(&bh, | ||
1232 | MV643XX_ETH_RX_CURRENT_QUEUE_DESC_PTR_7(port), | ||
1233 | 0x00000000); | ||
1234 | } | ||
1235 | |||
1236 | printk(KERN_INFO "Radstone Technology PPC7D\n"); | ||
1237 | if (ppc_md.progress) | ||
1238 | ppc_md.progress("ppc7d_setup_arch: exit", 0); | ||
1239 | } | ||
1240 | |||
1241 | /* This kernel command line parameter can be used to have the target | ||
1242 | * wait for a JTAG debugger to attach. Of course, a JTAG debugger | ||
1243 | * with hardware breakpoint support can have the target stop at any | ||
1244 | * location during init, but this is a convenience feature that makes | ||
1245 | * it easier in the common case of loading the code using the ppcboot | ||
1246 | * bootloader.. | ||
1247 | */ | ||
1248 | static unsigned long ppc7d_wait_debugger; | ||
1249 | |||
1250 | static int __init ppc7d_waitdbg(char *str) | ||
1251 | { | ||
1252 | ppc7d_wait_debugger = 1; | ||
1253 | return 1; | ||
1254 | } | ||
1255 | |||
1256 | __setup("waitdbg", ppc7d_waitdbg); | ||
1257 | |||
1258 | /* Second phase board init, called after other (architecture common) | ||
1259 | * low-level services have been initialized. | ||
1260 | */ | ||
1261 | static void ppc7d_init2(void) | ||
1262 | { | ||
1263 | unsigned long flags; | ||
1264 | u32 data; | ||
1265 | u8 data8; | ||
1266 | |||
1267 | pr_debug("%s: enter\n", __FUNCTION__); | ||
1268 | |||
1269 | /* Wait for debugger? */ | ||
1270 | if (ppc7d_wait_debugger) { | ||
1271 | printk("Waiting for debugger...\n"); | ||
1272 | |||
1273 | while (readl(&ppc7d_wait_debugger)) ; | ||
1274 | } | ||
1275 | |||
1276 | /* Hook up i8259 interrupt which is connected to GPP28 */ | ||
1277 | request_irq(mv64360_irq_base + MV64x60_IRQ_GPP28, ppc7d_i8259_intr, | ||
1278 | SA_INTERRUPT, "I8259 (GPP28) interrupt", (void *)0); | ||
1279 | |||
1280 | /* Configure MPP16 as watchdog NMI, MPP17 as watchdog WDE */ | ||
1281 | spin_lock_irqsave(&mv64x60_lock, flags); | ||
1282 | data = mv64x60_read(&bh, MV64x60_MPP_CNTL_2); | ||
1283 | data &= ~(0x0000000f << 0); | ||
1284 | data |= (0x00000004 << 0); | ||
1285 | data &= ~(0x0000000f << 4); | ||
1286 | data |= (0x00000004 << 4); | ||
1287 | mv64x60_write(&bh, MV64x60_MPP_CNTL_2, data); | ||
1288 | spin_unlock_irqrestore(&mv64x60_lock, flags); | ||
1289 | |||
1290 | /* All LEDs off */ | ||
1291 | data8 = inb(PPC7D_CPLD_LEDS); | ||
1292 | data8 &= ~0x08; | ||
1293 | data8 |= 0x07; | ||
1294 | outb(data8, PPC7D_CPLD_LEDS); | ||
1295 | |||
1296 | pr_debug("%s: exit\n", __FUNCTION__); | ||
1297 | } | ||
1298 | |||
1299 | /* Called from machine_init(), early, before any of the __init functions | ||
1300 | * have run. We must init software-configurable pins before other functions | ||
1301 | * such as interrupt controllers are initialised. | ||
1302 | */ | ||
1303 | void __init platform_init(unsigned long r3, unsigned long r4, unsigned long r5, | ||
1304 | unsigned long r6, unsigned long r7) | ||
1305 | { | ||
1306 | u8 val8; | ||
1307 | u8 rev_num; | ||
1308 | |||
1309 | /* Map 0xe0000000-0xffffffff early because we need access to SRAM | ||
1310 | * and the ISA memory space (for serial port) here. This mapping | ||
1311 | * is redone properly in ppc7d_map_io() later. | ||
1312 | */ | ||
1313 | mtspr(SPRN_DBAT3U, 0xe0003fff); | ||
1314 | mtspr(SPRN_DBAT3L, 0xe000002a); | ||
1315 | |||
1316 | /* | ||
1317 | * Zero SRAM. Note that this generates parity errors on | ||
1318 | * internal data path in SRAM if it's first time accessing it | ||
1319 | * after reset. | ||
1320 | * | ||
1321 | * We do this ASAP to avoid parity errors when reading | ||
1322 | * uninitialized SRAM. | ||
1323 | */ | ||
1324 | memset((void *)PPC7D_INTERNAL_SRAM_BASE, 0, MV64360_SRAM_SIZE); | ||
1325 | |||
1326 | pr_debug("platform_init: r3-r7: %lx %lx %lx %lx %lx\n", | ||
1327 | r3, r4, r5, r6, r7); | ||
1328 | |||
1329 | parse_bootinfo(find_bootinfo()); | ||
1330 | |||
1331 | /* ASSUMPTION: If both r3 (bd_t pointer) and r6 (cmdline pointer) | ||
1332 | * are non-zero, then we should use the board info from the bd_t | ||
1333 | * structure and the cmdline pointed to by r6 instead of the | ||
1334 | * information from birecs, if any. Otherwise, use the information | ||
1335 | * from birecs as discovered by the preceeding call to | ||
1336 | * parse_bootinfo(). This rule should work with both PPCBoot, which | ||
1337 | * uses a bd_t board info structure, and the kernel boot wrapper, | ||
1338 | * which uses birecs. | ||
1339 | */ | ||
1340 | if (r3 && r6) { | ||
1341 | bd_t *bp = (bd_t *) __res; | ||
1342 | |||
1343 | /* copy board info structure */ | ||
1344 | memcpy((void *)__res, (void *)(r3 + KERNELBASE), sizeof(bd_t)); | ||
1345 | /* copy command line */ | ||
1346 | *(char *)(r7 + KERNELBASE) = 0; | ||
1347 | strcpy(cmd_line, (char *)(r6 + KERNELBASE)); | ||
1348 | |||
1349 | printk(KERN_INFO "Board info data:-\n"); | ||
1350 | printk(KERN_INFO " Internal freq: %lu MHz, bus freq: %lu MHz\n", | ||
1351 | bp->bi_intfreq, bp->bi_busfreq); | ||
1352 | printk(KERN_INFO " Memory: %lx, size %lx\n", bp->bi_memstart, | ||
1353 | bp->bi_memsize); | ||
1354 | printk(KERN_INFO " Console baudrate: %lu\n", bp->bi_baudrate); | ||
1355 | printk(KERN_INFO " Ethernet address: " | ||
1356 | "%02x:%02x:%02x:%02x:%02x:%02x\n", | ||
1357 | bp->bi_enetaddr[0], bp->bi_enetaddr[1], | ||
1358 | bp->bi_enetaddr[2], bp->bi_enetaddr[3], | ||
1359 | bp->bi_enetaddr[4], bp->bi_enetaddr[5]); | ||
1360 | } | ||
1361 | #ifdef CONFIG_BLK_DEV_INITRD | ||
1362 | /* take care of initrd if we have one */ | ||
1363 | if (r4) { | ||
1364 | initrd_start = r4 + KERNELBASE; | ||
1365 | initrd_end = r5 + KERNELBASE; | ||
1366 | printk(KERN_INFO "INITRD @ %lx/%lx\n", initrd_start, initrd_end); | ||
1367 | } | ||
1368 | #endif /* CONFIG_BLK_DEV_INITRD */ | ||
1369 | |||
1370 | /* Map in board regs, etc. */ | ||
1371 | isa_io_base = 0xe8000000; | ||
1372 | isa_mem_base = 0xe8000000; | ||
1373 | pci_dram_offset = 0x00000000; | ||
1374 | ISA_DMA_THRESHOLD = 0x00ffffff; | ||
1375 | DMA_MODE_READ = 0x44; | ||
1376 | DMA_MODE_WRITE = 0x48; | ||
1377 | |||
1378 | ppc_md.setup_arch = ppc7d_setup_arch; | ||
1379 | ppc_md.init = ppc7d_init2; | ||
1380 | ppc_md.show_cpuinfo = ppc7d_show_cpuinfo; | ||
1381 | ppc_md.irq_canonicalize = ppc7d_irq_canonicalize; | ||
1382 | ppc_md.init_IRQ = ppc7d_init_irq; | ||
1383 | ppc_md.get_irq = ppc7d_get_irq; | ||
1384 | |||
1385 | ppc_md.restart = ppc7d_restart; | ||
1386 | ppc_md.power_off = ppc7d_power_off; | ||
1387 | ppc_md.halt = ppc7d_halt; | ||
1388 | |||
1389 | ppc_md.find_end_of_memory = ppc7d_find_end_of_memory; | ||
1390 | ppc_md.setup_io_mappings = ppc7d_map_io; | ||
1391 | |||
1392 | ppc_md.time_init = NULL; | ||
1393 | ppc_md.set_rtc_time = NULL; | ||
1394 | ppc_md.get_rtc_time = NULL; | ||
1395 | ppc_md.calibrate_decr = ppc7d_calibrate_decr; | ||
1396 | ppc_md.nvram_read_val = NULL; | ||
1397 | ppc_md.nvram_write_val = NULL; | ||
1398 | |||
1399 | ppc_md.heartbeat = ppc7d_heartbeat; | ||
1400 | ppc_md.heartbeat_reset = HZ; | ||
1401 | ppc_md.heartbeat_count = ppc_md.heartbeat_reset; | ||
1402 | |||
1403 | ppc_md.pcibios_fixup_bus = ppc7d_pci_fixup_bus; | ||
1404 | |||
1405 | #if defined(CONFIG_SERIAL_MPSC) || defined(CONFIG_MV643XX_ETH) || \ | ||
1406 | defined(CONFIG_I2C_MV64XXX) | ||
1407 | platform_notify = ppc7d_platform_notify; | ||
1408 | #endif | ||
1409 | |||
1410 | #ifdef CONFIG_SERIAL_MPSC | ||
1411 | /* On PPC7D, we must configure MPSC support via CPLD control | ||
1412 | * registers. | ||
1413 | */ | ||
1414 | outb(PPC7D_CPLD_RTS_COM4_SCLK | | ||
1415 | PPC7D_CPLD_RTS_COM56_ENABLED, PPC7D_CPLD_RTS); | ||
1416 | outb(PPC7D_CPLD_COMS_COM3_TCLKEN | | ||
1417 | PPC7D_CPLD_COMS_COM3_TXEN | | ||
1418 | PPC7D_CPLD_COMS_COM4_TCLKEN | | ||
1419 | PPC7D_CPLD_COMS_COM4_TXEN, PPC7D_CPLD_COMS); | ||
1420 | #endif /* CONFIG_SERIAL_MPSC */ | ||
1421 | |||
1422 | #if defined(CONFIG_KGDB) || defined(CONFIG_SERIAL_TEXT_DEBUG) | ||
1423 | ppc7d_early_serial_map(); | ||
1424 | #ifdef CONFIG_SERIAL_TEXT_DEBUG | ||
1425 | #if defined(CONFIG_SERIAL_MPSC_CONSOLE) | ||
1426 | ppc_md.progress = mv64x60_mpsc_progress; | ||
1427 | #elif defined(CONFIG_SERIAL_8250) | ||
1428 | ppc_md.progress = gen550_progress; | ||
1429 | #else | ||
1430 | #error CONFIG_KGDB || CONFIG_SERIAL_TEXT_DEBUG has no supported CONFIG_SERIAL_XXX | ||
1431 | #endif /* CONFIG_SERIAL_8250 */ | ||
1432 | #endif /* CONFIG_SERIAL_TEXT_DEBUG */ | ||
1433 | #endif /* CONFIG_KGDB || CONFIG_SERIAL_TEXT_DEBUG */ | ||
1434 | |||
1435 | /* Enable write access to user flash. This is necessary for | ||
1436 | * flash probe. | ||
1437 | */ | ||
1438 | val8 = readb((void *)isa_io_base + PPC7D_CPLD_SW_FLASH_WRITE_PROTECT); | ||
1439 | writeb(val8 | (PPC7D_CPLD_SW_FLASH_WRPROT_ENABLED & | ||
1440 | PPC7D_CPLD_SW_FLASH_WRPROT_USER_MASK), | ||
1441 | (void *)isa_io_base + PPC7D_CPLD_SW_FLASH_WRITE_PROTECT); | ||
1442 | |||
1443 | /* Determine if this board has IBM ALMA VME devices */ | ||
1444 | val8 = readb((void *)isa_io_base + PPC7D_CPLD_BOARD_REVISION); | ||
1445 | rev_num = (val8 & PPC7D_CPLD_BOARD_REVISION_NUMBER_MASK) >> 5; | ||
1446 | if (rev_num <= 1) | ||
1447 | ppc7d_has_alma = 1; | ||
1448 | |||
1449 | #ifdef DEBUG | ||
1450 | console_printk[0] = 8; | ||
1451 | #endif | ||
1452 | } | ||
diff --git a/arch/ppc/platforms/radstone_ppc7d.h b/arch/ppc/platforms/radstone_ppc7d.h new file mode 100644 index 000000000000..4546fff2b0c3 --- /dev/null +++ b/arch/ppc/platforms/radstone_ppc7d.h | |||
@@ -0,0 +1,434 @@ | |||
1 | /* | ||
2 | * arch/ppc/platforms/radstone_ppc7d.h | ||
3 | * | ||
4 | * Board definitions for the Radstone PPC7D boards. | ||
5 | * | ||
6 | * Author: James Chapman <jchapman@katalix.com> | ||
7 | * | ||
8 | * Based on code done by Rabeeh Khoury - rabeeh@galileo.co.il | ||
9 | * Based on code done by - Mark A. Greer <mgreer@mvista.com> | ||
10 | * | ||
11 | * This program is free software; you can redistribute it and/or modify it | ||
12 | * under the terms of the GNU General Public License as published by the | ||
13 | * Free Software Foundation; either version 2 of the License, or (at your | ||
14 | * option) any later version. | ||
15 | */ | ||
16 | |||
17 | /* | ||
18 | * The MV64360 has 2 PCI buses each with 1 window from the CPU bus to | ||
19 | * PCI I/O space and 4 windows from the CPU bus to PCI MEM space. | ||
20 | * We'll only use one PCI MEM window on each PCI bus. | ||
21 | * | ||
22 | * This is the CPU physical memory map (windows must be at least 1MB | ||
23 | * and start on a boundary that is a multiple of the window size): | ||
24 | * | ||
25 | * 0xff800000-0xffffffff - Boot window | ||
26 | * 0xff000000-0xff000fff - AFIX registers (DevCS2) | ||
27 | * 0xfef00000-0xfef0ffff - Internal MV64x60 registers | ||
28 | * 0xfef40000-0xfef7ffff - Internal SRAM | ||
29 | * 0xfef00000-0xfef0ffff - MV64360 Registers | ||
30 | * 0x70000000-0x7fffffff - soldered flash (DevCS3) | ||
31 | * 0xe8000000-0xe9ffffff - PCI I/O | ||
32 | * 0x80000000-0xbfffffff - PCI MEM | ||
33 | */ | ||
34 | |||
35 | #ifndef __PPC_PLATFORMS_PPC7D_H | ||
36 | #define __PPC_PLATFORMS_PPC7D_H | ||
37 | |||
38 | #include <asm/ppcboot.h> | ||
39 | |||
40 | /***************************************************************************** | ||
41 | * CPU Physical Memory Map setup. | ||
42 | *****************************************************************************/ | ||
43 | |||
44 | #define PPC7D_BOOT_WINDOW_BASE 0xff800000 | ||
45 | #define PPC7D_AFIX_REG_BASE 0xff000000 | ||
46 | #define PPC7D_INTERNAL_SRAM_BASE 0xfef40000 | ||
47 | #define PPC7D_FLASH_BASE 0x70000000 | ||
48 | |||
49 | #define PPC7D_BOOT_WINDOW_SIZE_ACTUAL 0x00800000 /* 8MB */ | ||
50 | #define PPC7D_FLASH_SIZE_ACTUAL 0x10000000 /* 256MB */ | ||
51 | |||
52 | #define PPC7D_BOOT_WINDOW_SIZE max(MV64360_WINDOW_SIZE_MIN, \ | ||
53 | PPC7D_BOOT_WINDOW_SIZE_ACTUAL) | ||
54 | #define PPC7D_FLASH_SIZE max(MV64360_WINDOW_SIZE_MIN, \ | ||
55 | PPC7D_FLASH_SIZE_ACTUAL) | ||
56 | #define PPC7D_AFIX_REG_SIZE max(MV64360_WINDOW_SIZE_MIN, 0xff) | ||
57 | |||
58 | |||
59 | #define PPC7D_PCI0_MEM0_START_PROC_ADDR 0x80000000UL | ||
60 | #define PPC7D_PCI0_MEM0_START_PCI_HI_ADDR 0x00000000UL | ||
61 | #define PPC7D_PCI0_MEM0_START_PCI_LO_ADDR 0x80000000UL | ||
62 | #define PPC7D_PCI0_MEM0_SIZE 0x20000000UL | ||
63 | #define PPC7D_PCI0_MEM1_START_PROC_ADDR 0xe8010000UL | ||
64 | #define PPC7D_PCI0_MEM1_START_PCI_HI_ADDR 0x00000000UL | ||
65 | #define PPC7D_PCI0_MEM1_START_PCI_LO_ADDR 0x00000000UL | ||
66 | #define PPC7D_PCI0_MEM1_SIZE 0x000f0000UL | ||
67 | #define PPC7D_PCI0_IO_START_PROC_ADDR 0xe8000000UL | ||
68 | #define PPC7D_PCI0_IO_START_PCI_ADDR 0x00000000UL | ||
69 | #define PPC7D_PCI0_IO_SIZE 0x00010000UL | ||
70 | |||
71 | #define PPC7D_PCI1_MEM0_START_PROC_ADDR 0xa0000000UL | ||
72 | #define PPC7D_PCI1_MEM0_START_PCI_HI_ADDR 0x00000000UL | ||
73 | #define PPC7D_PCI1_MEM0_START_PCI_LO_ADDR 0xa0000000UL | ||
74 | #define PPC7D_PCI1_MEM0_SIZE 0x20000000UL | ||
75 | #define PPC7D_PCI1_MEM1_START_PROC_ADDR 0xe9800000UL | ||
76 | #define PPC7D_PCI1_MEM1_START_PCI_HI_ADDR 0x00000000UL | ||
77 | #define PPC7D_PCI1_MEM1_START_PCI_LO_ADDR 0x00000000UL | ||
78 | #define PPC7D_PCI1_MEM1_SIZE 0x00800000UL | ||
79 | #define PPC7D_PCI1_IO_START_PROC_ADDR 0xe9000000UL | ||
80 | #define PPC7D_PCI1_IO_START_PCI_ADDR 0x00000000UL | ||
81 | #define PPC7D_PCI1_IO_SIZE 0x00010000UL | ||
82 | |||
83 | #define PPC7D_DEFAULT_BAUD 9600 | ||
84 | #define PPC7D_MPSC_CLK_SRC 8 /* TCLK */ | ||
85 | #define PPC7D_MPSC_CLK_FREQ 133333333 /* 133.3333... MHz */ | ||
86 | |||
87 | #define PPC7D_ETH0_PHY_ADDR 8 | ||
88 | #define PPC7D_ETH1_PHY_ADDR 9 | ||
89 | #define PPC7D_ETH2_PHY_ADDR 0 | ||
90 | |||
91 | #define PPC7D_ETH_TX_QUEUE_SIZE 400 | ||
92 | #define PPC7D_ETH_RX_QUEUE_SIZE 400 | ||
93 | |||
94 | #define PPC7D_ETH_PORT_CONFIG_VALUE \ | ||
95 | MV64340_ETH_UNICAST_NORMAL_MODE | \ | ||
96 | MV64340_ETH_DEFAULT_RX_QUEUE_0 | \ | ||
97 | MV64340_ETH_DEFAULT_RX_ARP_QUEUE_0 | \ | ||
98 | MV64340_ETH_RECEIVE_BC_IF_NOT_IP_OR_ARP | \ | ||
99 | MV64340_ETH_RECEIVE_BC_IF_IP | \ | ||
100 | MV64340_ETH_RECEIVE_BC_IF_ARP | \ | ||
101 | MV64340_ETH_CAPTURE_TCP_FRAMES_DIS | \ | ||
102 | MV64340_ETH_CAPTURE_UDP_FRAMES_DIS | \ | ||
103 | MV64340_ETH_DEFAULT_RX_TCP_QUEUE_0 | \ | ||
104 | MV64340_ETH_DEFAULT_RX_UDP_QUEUE_0 | \ | ||
105 | MV64340_ETH_DEFAULT_RX_BPDU_QUEUE_0 | ||
106 | |||
107 | #define PPC7D_ETH_PORT_CONFIG_EXTEND_VALUE \ | ||
108 | MV64340_ETH_SPAN_BPDU_PACKETS_AS_NORMAL | \ | ||
109 | MV64340_ETH_PARTITION_DISABLE | ||
110 | |||
111 | #define GT_ETH_IPG_INT_RX(value) \ | ||
112 | ((value & 0x3fff) << 8) | ||
113 | |||
114 | #define PPC7D_ETH_PORT_SDMA_CONFIG_VALUE \ | ||
115 | MV64340_ETH_RX_BURST_SIZE_4_64BIT | \ | ||
116 | GT_ETH_IPG_INT_RX(0) | \ | ||
117 | MV64340_ETH_TX_BURST_SIZE_4_64BIT | ||
118 | |||
119 | #define PPC7D_ETH_PORT_SERIAL_CONTROL_VALUE \ | ||
120 | MV64340_ETH_ENABLE_AUTO_NEG_FOR_DUPLX | \ | ||
121 | MV64340_ETH_DISABLE_AUTO_NEG_FOR_FLOW_CTRL | \ | ||
122 | MV64340_ETH_ADV_SYMMETRIC_FLOW_CTRL | \ | ||
123 | MV64340_ETH_FORCE_FC_MODE_NO_PAUSE_DIS_TX | \ | ||
124 | MV64340_ETH_FORCE_BP_MODE_NO_JAM | \ | ||
125 | (1 << 9) | \ | ||
126 | MV64340_ETH_DO_NOT_FORCE_LINK_FAIL | \ | ||
127 | MV64340_ETH_RETRANSMIT_16_ATTEMPTS | \ | ||
128 | MV64340_ETH_ENABLE_AUTO_NEG_SPEED_GMII | \ | ||
129 | MV64340_ETH_DTE_ADV_0 | \ | ||
130 | MV64340_ETH_DISABLE_AUTO_NEG_BYPASS | \ | ||
131 | MV64340_ETH_AUTO_NEG_NO_CHANGE | \ | ||
132 | MV64340_ETH_MAX_RX_PACKET_9700BYTE | \ | ||
133 | MV64340_ETH_CLR_EXT_LOOPBACK | \ | ||
134 | MV64340_ETH_SET_FULL_DUPLEX_MODE | \ | ||
135 | MV64340_ETH_ENABLE_FLOW_CTRL_TX_RX_IN_FULL_DUPLEX | ||
136 | |||
137 | /***************************************************************************** | ||
138 | * Serial defines. | ||
139 | *****************************************************************************/ | ||
140 | |||
141 | #define PPC7D_SERIAL_0 0xe80003f8 | ||
142 | #define PPC7D_SERIAL_1 0xe80002f8 | ||
143 | |||
144 | #define RS_TABLE_SIZE 2 | ||
145 | |||
146 | /* Rate for the 1.8432 Mhz clock for the onboard serial chip */ | ||
147 | #define UART_CLK 1843200 | ||
148 | #define BASE_BAUD ( UART_CLK / 16 ) | ||
149 | |||
150 | #ifdef CONFIG_SERIAL_DETECT_IRQ | ||
151 | #define STD_COM_FLAGS (ASYNC_BOOT_AUTOCONF|ASYNC_AUTO_IRQ) | ||
152 | #else | ||
153 | #define STD_COM_FLAGS (ASYNC_BOOT_AUTOCONF) | ||
154 | #endif | ||
155 | |||
156 | #define STD_SERIAL_PORT_DFNS \ | ||
157 | { 0, BASE_BAUD, PPC7D_SERIAL_0, 4, STD_COM_FLAGS, /* ttyS0 */ \ | ||
158 | iomem_base: (u8 *)PPC7D_SERIAL_0, \ | ||
159 | io_type: SERIAL_IO_MEM, }, \ | ||
160 | { 0, BASE_BAUD, PPC7D_SERIAL_1, 3, STD_COM_FLAGS, /* ttyS1 */ \ | ||
161 | iomem_base: (u8 *)PPC7D_SERIAL_1, \ | ||
162 | io_type: SERIAL_IO_MEM }, | ||
163 | |||
164 | #define SERIAL_PORT_DFNS \ | ||
165 | STD_SERIAL_PORT_DFNS | ||
166 | |||
167 | /***************************************************************************** | ||
168 | * CPLD defines. | ||
169 | * | ||
170 | * Register map:- | ||
171 | * | ||
172 | * 0000 to 000F South Bridge DMA 1 Control | ||
173 | * 0020 and 0021 South Bridge Interrupt 1 Control | ||
174 | * 0040 to 0043 South Bridge Counter Control | ||
175 | * 0060 Keyboard | ||
176 | * 0061 South Bridge NMI Status and Control | ||
177 | * 0064 Keyboard | ||
178 | * 0071 and 0072 RTC R/W | ||
179 | * 0078 to 007B South Bridge BIOS Timer | ||
180 | * 0080 to 0090 South Bridge DMA Pages | ||
181 | * 00A0 and 00A1 South Bridge Interrupt 2 Control | ||
182 | * 00C0 to 00DE South Bridge DMA 2 Control | ||
183 | * 02E8 to 02EF COM6 R/W | ||
184 | * 02F8 to 02FF South Bridge COM2 R/W | ||
185 | * 03E8 to 03EF COM5 R/W | ||
186 | * 03F8 to 03FF South Bridge COM1 R/W | ||
187 | * 040A South Bridge DMA Scatter/Gather RO | ||
188 | * 040B DMA 1 Extended Mode WO | ||
189 | * 0410 to 043F South Bridge DMA Scatter/Gather | ||
190 | * 0481 to 048B South Bridge DMA High Pages | ||
191 | * 04D0 and 04D1 South Bridge Edge/Level Control | ||
192 | * 04D6 DMA 2 Extended Mode WO | ||
193 | * 0804 Memory Configuration RO | ||
194 | * 0806 Memory Configuration Extend RO | ||
195 | * 0808 SCSI Activity LED R/W | ||
196 | * 080C Equipment Present 1 RO | ||
197 | * 080E Equipment Present 2 RO | ||
198 | * 0810 Equipment Present 3 RO | ||
199 | * 0812 Equipment Present 4 RO | ||
200 | * 0818 Key Lock RO | ||
201 | * 0820 LEDS R/W | ||
202 | * 0824 COMs R/W | ||
203 | * 0826 RTS R/W | ||
204 | * 0828 Reset R/W | ||
205 | * 082C Watchdog Trig R/W | ||
206 | * 082E Interrupt R/W | ||
207 | * 0830 Interrupt Status RO | ||
208 | * 0832 PCI configuration RO | ||
209 | * 0854 Board Revision RO | ||
210 | * 0858 Extended ID RO | ||
211 | * 0864 ID Link RO | ||
212 | * 0866 Motherboard Type RO | ||
213 | * 0868 FLASH Write control RO | ||
214 | * 086A Software FLASH write protect R/W | ||
215 | * 086E FLASH Control R/W | ||
216 | *****************************************************************************/ | ||
217 | |||
218 | #define PPC7D_CPLD_MEM_CONFIG 0x0804 | ||
219 | #define PPC7D_CPLD_MEM_CONFIG_EXTEND 0x0806 | ||
220 | #define PPC7D_CPLD_SCSI_ACTIVITY_LED 0x0808 | ||
221 | #define PPC7D_CPLD_EQUIPMENT_PRESENT_1 0x080C | ||
222 | #define PPC7D_CPLD_EQUIPMENT_PRESENT_2 0x080E | ||
223 | #define PPC7D_CPLD_EQUIPMENT_PRESENT_3 0x0810 | ||
224 | #define PPC7D_CPLD_EQUIPMENT_PRESENT_4 0x0812 | ||
225 | #define PPC7D_CPLD_KEY_LOCK 0x0818 | ||
226 | #define PPC7D_CPLD_LEDS 0x0820 | ||
227 | #define PPC7D_CPLD_COMS 0x0824 | ||
228 | #define PPC7D_CPLD_RTS 0x0826 | ||
229 | #define PPC7D_CPLD_RESET 0x0828 | ||
230 | #define PPC7D_CPLD_WATCHDOG_TRIG 0x082C | ||
231 | #define PPC7D_CPLD_INTR 0x082E | ||
232 | #define PPC7D_CPLD_INTR_STATUS 0x0830 | ||
233 | #define PPC7D_CPLD_PCI_CONFIG 0x0832 | ||
234 | #define PPC7D_CPLD_BOARD_REVISION 0x0854 | ||
235 | #define PPC7D_CPLD_EXTENDED_ID 0x0858 | ||
236 | #define PPC7D_CPLD_ID_LINK 0x0864 | ||
237 | #define PPC7D_CPLD_MOTHERBOARD_TYPE 0x0866 | ||
238 | #define PPC7D_CPLD_FLASH_WRITE_CNTL 0x0868 | ||
239 | #define PPC7D_CPLD_SW_FLASH_WRITE_PROTECT 0x086A | ||
240 | #define PPC7D_CPLD_FLASH_CNTL 0x086E | ||
241 | |||
242 | /* MEMORY_CONFIG_EXTEND */ | ||
243 | #define PPC7D_CPLD_SDRAM_BANK_SIZE_MASK 0xc0 | ||
244 | #define PPC7D_CPLD_SDRAM_BANK_SIZE_128M 0 | ||
245 | #define PPC7D_CPLD_SDRAM_BANK_SIZE_256M 0x40 | ||
246 | #define PPC7D_CPLD_SDRAM_BANK_SIZE_512M 0x80 | ||
247 | #define PPC7D_CPLD_SDRAM_BANK_SIZE_1G 0xc0 | ||
248 | #define PPC7D_CPLD_FLASH_DEV_SIZE_MASK 0x03 | ||
249 | #define PPC7D_CPLD_FLASH_BANK_NUM_MASK 0x0c | ||
250 | #define PPC7D_CPLD_FLASH_DEV_SIZE_64M 0 | ||
251 | #define PPC7D_CPLD_FLASH_DEV_SIZE_32M 1 | ||
252 | #define PPC7D_CPLD_FLASH_DEV_SIZE_16M 3 | ||
253 | #define PPC7D_CPLD_FLASH_BANK_NUM_4 0x00 | ||
254 | #define PPC7D_CPLD_FLASH_BANK_NUM_3 0x04 | ||
255 | #define PPC7D_CPLD_FLASH_BANK_NUM_2 0x08 | ||
256 | #define PPC7D_CPLD_FLASH_BANK_NUM_1 0x0c | ||
257 | |||
258 | /* SCSI_LED */ | ||
259 | #define PPC7D_CPLD_SCSI_ACTIVITY_LED_OFF 0 | ||
260 | #define PPC7D_CPLD_SCSI_ACTIVITY_LED_ON 1 | ||
261 | |||
262 | /* EQUIPMENT_PRESENT_1 */ | ||
263 | #define PPC7D_CPLD_EQPT_PRES_1_FITTED 0 | ||
264 | #define PPC7D_CPLD_EQPT_PRES_1_PMC2_MASK (0x80 >> 2) | ||
265 | #define PPC7D_CPLD_EQPT_PRES_1_PMC1_MASK (0x80 >> 3) | ||
266 | #define PPC7D_CPLD_EQPT_PRES_1_AFIX_MASK (0x80 >> 4) | ||
267 | |||
268 | /* EQUIPMENT_PRESENT_2 */ | ||
269 | #define PPC7D_CPLD_EQPT_PRES_2_FITTED !0 | ||
270 | #define PPC7D_CPLD_EQPT_PRES_2_UNIVERSE_MASK (0x80 >> 0) | ||
271 | #define PPC7D_CPLD_EQPT_PRES_2_COM36_MASK (0x80 >> 2) | ||
272 | #define PPC7D_CPLD_EQPT_PRES_2_GIGE_MASK (0x80 >> 3) | ||
273 | #define PPC7D_CPLD_EQPT_PRES_2_DUALGIGE_MASK (0x80 >> 4) | ||
274 | |||
275 | /* EQUIPMENT_PRESENT_3 */ | ||
276 | #define PPC7D_CPLD_EQPT_PRES_3_PMC2_V_MASK (0x80 >> 3) | ||
277 | #define PPC7D_CPLD_EQPT_PRES_3_PMC2_5V (0 >> 3) | ||
278 | #define PPC7D_CPLD_EQPT_PRES_3_PMC2_3V (0x80 >> 3) | ||
279 | #define PPC7D_CPLD_EQPT_PRES_3_PMC1_V_MASK (0x80 >> 4) | ||
280 | #define PPC7D_CPLD_EQPT_PRES_3_PMC1_5V (0 >> 4) | ||
281 | #define PPC7D_CPLD_EQPT_PRES_3_PMC1_3V (0x80 >> 4) | ||
282 | #define PPC7D_CPLD_EQPT_PRES_3_PMC_POWER_MASK (0x80 >> 5) | ||
283 | #define PPC7D_CPLD_EQPT_PRES_3_PMC_POWER_INTER (0 >> 5) | ||
284 | #define PPC7D_CPLD_EQPT_PRES_3_PMC_POWER_VME (0x80 >> 5) | ||
285 | |||
286 | /* EQUIPMENT_PRESENT_4 */ | ||
287 | #define PPC7D_CPLD_EQPT_PRES_4_LPT_MASK (0x80 >> 2) | ||
288 | #define PPC7D_CPLD_EQPT_PRES_4_LPT_FITTED (0x80 >> 2) | ||
289 | #define PPC7D_CPLD_EQPT_PRES_4_PS2_USB2_MASK (0xc0 >> 6) | ||
290 | #define PPC7D_CPLD_EQPT_PRES_4_PS2_FITTED (0x40 >> 6) | ||
291 | #define PPC7D_CPLD_EQPT_PRES_4_USB2_FITTED (0x80 >> 6) | ||
292 | |||
293 | /* CPLD_LEDS */ | ||
294 | #define PPC7D_CPLD_LEDS_ON (!0) | ||
295 | #define PPC7D_CPLD_LEDS_OFF (0) | ||
296 | #define PPC7D_CPLD_LEDS_NVRAM_PAGE_MASK (0xc0 >> 2) | ||
297 | #define PPC7D_CPLD_LEDS_DS201_MASK (0x80 >> 4) | ||
298 | #define PPC7D_CPLD_LEDS_DS219_MASK (0x80 >> 5) | ||
299 | #define PPC7D_CPLD_LEDS_DS220_MASK (0x80 >> 6) | ||
300 | #define PPC7D_CPLD_LEDS_DS221_MASK (0x80 >> 7) | ||
301 | |||
302 | /* CPLD_COMS */ | ||
303 | #define PPC7D_CPLD_COMS_COM3_TCLKEN (0x80 >> 0) | ||
304 | #define PPC7D_CPLD_COMS_COM3_RTCLKEN (0x80 >> 1) | ||
305 | #define PPC7D_CPLD_COMS_COM3_MODE_MASK (0x80 >> 2) | ||
306 | #define PPC7D_CPLD_COMS_COM3_MODE_RS232 (0) | ||
307 | #define PPC7D_CPLD_COMS_COM3_MODE_RS422 (0x80 >> 2) | ||
308 | #define PPC7D_CPLD_COMS_COM3_TXEN (0x80 >> 3) | ||
309 | #define PPC7D_CPLD_COMS_COM4_TCLKEN (0x80 >> 4) | ||
310 | #define PPC7D_CPLD_COMS_COM4_RTCLKEN (0x80 >> 5) | ||
311 | #define PPC7D_CPLD_COMS_COM4_MODE_MASK (0x80 >> 6) | ||
312 | #define PPC7D_CPLD_COMS_COM4_MODE_RS232 (0) | ||
313 | #define PPC7D_CPLD_COMS_COM4_MODE_RS422 (0x80 >> 6) | ||
314 | #define PPC7D_CPLD_COMS_COM4_TXEN (0x80 >> 7) | ||
315 | |||
316 | /* CPLD_RTS */ | ||
317 | #define PPC7D_CPLD_RTS_COM36_LOOPBACK (0x80 >> 0) | ||
318 | #define PPC7D_CPLD_RTS_COM4_SCLK (0x80 >> 1) | ||
319 | #define PPC7D_CPLD_RTS_COM3_TXFUNC_MASK (0xc0 >> 2) | ||
320 | #define PPC7D_CPLD_RTS_COM3_TXFUNC_DISABLED (0 >> 2) | ||
321 | #define PPC7D_CPLD_RTS_COM3_TXFUNC_ENABLED (0x80 >> 2) | ||
322 | #define PPC7D_CPLD_RTS_COM3_TXFUNC_ENABLED_RTG3 (0xc0 >> 2) | ||
323 | #define PPC7D_CPLD_RTS_COM3_TXFUNC_ENABLED_RTG3S (0xc0 >> 2) | ||
324 | #define PPC7D_CPLD_RTS_COM56_MODE_MASK (0x80 >> 4) | ||
325 | #define PPC7D_CPLD_RTS_COM56_MODE_RS232 (0) | ||
326 | #define PPC7D_CPLD_RTS_COM56_MODE_RS422 (0x80 >> 4) | ||
327 | #define PPC7D_CPLD_RTS_COM56_ENABLE_MASK (0x80 >> 5) | ||
328 | #define PPC7D_CPLD_RTS_COM56_DISABLED (0) | ||
329 | #define PPC7D_CPLD_RTS_COM56_ENABLED (0x80 >> 5) | ||
330 | #define PPC7D_CPLD_RTS_COM4_TXFUNC_MASK (0xc0 >> 6) | ||
331 | #define PPC7D_CPLD_RTS_COM4_TXFUNC_DISABLED (0 >> 6) | ||
332 | #define PPC7D_CPLD_RTS_COM4_TXFUNC_ENABLED (0x80 >> 6) | ||
333 | #define PPC7D_CPLD_RTS_COM4_TXFUNC_ENABLED_RTG3 (0x40 >> 6) | ||
334 | #define PPC7D_CPLD_RTS_COM4_TXFUNC_ENABLED_RTG3S (0x40 >> 6) | ||
335 | |||
336 | /* WATCHDOG_TRIG */ | ||
337 | #define PPC7D_CPLD_WDOG_CAUSE_MASK (0x80 >> 0) | ||
338 | #define PPC7D_CPLD_WDOG_CAUSE_NORMAL_RESET (0 >> 0) | ||
339 | #define PPC7D_CPLD_WDOG_CAUSE_WATCHDOG (0x80 >> 0) | ||
340 | #define PPC7D_CPLD_WDOG_ENABLE_MASK (0x80 >> 6) | ||
341 | #define PPC7D_CPLD_WDOG_ENABLE_OFF (0 >> 6) | ||
342 | #define PPC7D_CPLD_WDOG_ENABLE_ON (0x80 >> 6) | ||
343 | #define PPC7D_CPLD_WDOG_RESETSW_MASK (0x80 >> 7) | ||
344 | #define PPC7D_CPLD_WDOG_RESETSW_OFF (0 >> 7) | ||
345 | #define PPC7D_CPLD_WDOG_RESETSW_ON (0x80 >> 7) | ||
346 | |||
347 | /* Interrupt mask and status bits */ | ||
348 | #define PPC7D_CPLD_INTR_TEMP_MASK (0x80 >> 0) | ||
349 | #define PPC7D_CPLD_INTR_HB8_MASK (0x80 >> 1) | ||
350 | #define PPC7D_CPLD_INTR_PHY1_MASK (0x80 >> 2) | ||
351 | #define PPC7D_CPLD_INTR_PHY0_MASK (0x80 >> 3) | ||
352 | #define PPC7D_CPLD_INTR_ISANMI_MASK (0x80 >> 5) | ||
353 | #define PPC7D_CPLD_INTR_CRITTEMP_MASK (0x80 >> 6) | ||
354 | |||
355 | /* CPLD_INTR */ | ||
356 | #define PPC7D_CPLD_INTR_ENABLE_OFF (0) | ||
357 | #define PPC7D_CPLD_INTR_ENABLE_ON (!0) | ||
358 | |||
359 | /* CPLD_INTR_STATUS */ | ||
360 | #define PPC7D_CPLD_INTR_STATUS_OFF (0) | ||
361 | #define PPC7D_CPLD_INTR_STATUS_ON (!0) | ||
362 | |||
363 | /* CPLD_PCI_CONFIG */ | ||
364 | #define PPC7D_CPLD_PCI_CONFIG_PCI0_MASK 0x70 | ||
365 | #define PPC7D_CPLD_PCI_CONFIG_PCI0_PCI33 0x00 | ||
366 | #define PPC7D_CPLD_PCI_CONFIG_PCI0_PCI66 0x10 | ||
367 | #define PPC7D_CPLD_PCI_CONFIG_PCI0_PCIX33 0x40 | ||
368 | #define PPC7D_CPLD_PCI_CONFIG_PCI0_PCIX66 0x50 | ||
369 | #define PPC7D_CPLD_PCI_CONFIG_PCI0_PCIX100 0x60 | ||
370 | #define PPC7D_CPLD_PCI_CONFIG_PCI0_PCIX133 0x70 | ||
371 | #define PPC7D_CPLD_PCI_CONFIG_PCI1_MASK 0x07 | ||
372 | #define PPC7D_CPLD_PCI_CONFIG_PCI1_PCI33 0x00 | ||
373 | #define PPC7D_CPLD_PCI_CONFIG_PCI1_PCI66 0x01 | ||
374 | #define PPC7D_CPLD_PCI_CONFIG_PCI1_PCIX33 0x04 | ||
375 | #define PPC7D_CPLD_PCI_CONFIG_PCI1_PCIX66 0x05 | ||
376 | #define PPC7D_CPLD_PCI_CONFIG_PCI1_PCIX100 0x06 | ||
377 | #define PPC7D_CPLD_PCI_CONFIG_PCI1_PCIX133 0x07 | ||
378 | |||
379 | /* CPLD_BOARD_REVISION */ | ||
380 | #define PPC7D_CPLD_BOARD_REVISION_NUMBER_MASK 0xe0 | ||
381 | #define PPC7D_CPLD_BOARD_REVISION_LETTER_MASK 0x1f | ||
382 | |||
383 | /* CPLD_EXTENDED_ID */ | ||
384 | #define PPC7D_CPLD_EXTENDED_ID_PPC7D 0x18 | ||
385 | |||
386 | /* CPLD_ID_LINK */ | ||
387 | #define PPC7D_CPLD_ID_LINK_VME64_GAP_MASK (0x80 >> 2) | ||
388 | #define PPC7D_CPLD_ID_LINK_VME64_GA4_MASK (0x80 >> 3) | ||
389 | #define PPC7D_CPLD_ID_LINK_E13_MASK (0x80 >> 4) | ||
390 | #define PPC7D_CPLD_ID_LINK_E12_MASK (0x80 >> 5) | ||
391 | #define PPC7D_CPLD_ID_LINK_E7_MASK (0x80 >> 6) | ||
392 | #define PPC7D_CPLD_ID_LINK_E6_MASK (0x80 >> 7) | ||
393 | |||
394 | /* CPLD_MOTHERBOARD_TYPE */ | ||
395 | #define PPC7D_CPLD_MB_TYPE_ECC_ENABLE_MASK (0x80 >> 0) | ||
396 | #define PPC7D_CPLD_MB_TYPE_ECC_ENABLED (0x80 >> 0) | ||
397 | #define PPC7D_CPLD_MB_TYPE_ECC_DISABLED (0 >> 0) | ||
398 | #define PPC7D_CPLD_MB_TYPE_ECC_FITTED_MASK (0x80 >> 3) | ||
399 | #define PPC7D_CPLD_MB_TYPE_PLL_MASK 0x0c | ||
400 | #define PPC7D_CPLD_MB_TYPE_PLL_133 0x00 | ||
401 | #define PPC7D_CPLD_MB_TYPE_PLL_100 0x08 | ||
402 | #define PPC7D_CPLD_MB_TYPE_PLL_64 0x04 | ||
403 | #define PPC7D_CPLD_MB_TYPE_HW_ID_MASK 0x03 | ||
404 | |||
405 | /* CPLD_FLASH_WRITE_CNTL */ | ||
406 | #define PPD7D_CPLD_FLASH_CNTL_WR_LINK_MASK (0x80 >> 0) | ||
407 | #define PPD7D_CPLD_FLASH_CNTL_WR_LINK_FITTED (0x80 >> 0) | ||
408 | #define PPD7D_CPLD_FLASH_CNTL_BOOT_LINK_MASK (0x80 >> 2) | ||
409 | #define PPD7D_CPLD_FLASH_CNTL_BOOT_LINK_FITTED (0x80 >> 2) | ||
410 | #define PPD7D_CPLD_FLASH_CNTL_USER_LINK_MASK (0x80 >> 3) | ||
411 | #define PPD7D_CPLD_FLASH_CNTL_USER_LINK_FITTED (0x80 >> 3) | ||
412 | #define PPD7D_CPLD_FLASH_CNTL_RECO_WR_MASK (0x80 >> 5) | ||
413 | #define PPD7D_CPLD_FLASH_CNTL_RECO_WR_ENABLED (0x80 >> 5) | ||
414 | #define PPD7D_CPLD_FLASH_CNTL_BOOT_WR_MASK (0x80 >> 6) | ||
415 | #define PPD7D_CPLD_FLASH_CNTL_BOOT_WR_ENABLED (0x80 >> 6) | ||
416 | #define PPD7D_CPLD_FLASH_CNTL_USER_WR_MASK (0x80 >> 7) | ||
417 | #define PPD7D_CPLD_FLASH_CNTL_USER_WR_ENABLED (0x80 >> 7) | ||
418 | |||
419 | /* CPLD_SW_FLASH_WRITE_PROTECT */ | ||
420 | #define PPC7D_CPLD_SW_FLASH_WRPROT_ENABLED (!0) | ||
421 | #define PPC7D_CPLD_SW_FLASH_WRPROT_DISABLED (0) | ||
422 | #define PPC7D_CPLD_SW_FLASH_WRPROT_SYSBOOT_MASK (0x80 >> 6) | ||
423 | #define PPC7D_CPLD_SW_FLASH_WRPROT_USER_MASK (0x80 >> 7) | ||
424 | |||
425 | /* CPLD_FLASH_WRITE_CNTL */ | ||
426 | #define PPC7D_CPLD_FLASH_CNTL_NVRAM_PROT_MASK (0x80 >> 0) | ||
427 | #define PPC7D_CPLD_FLASH_CNTL_NVRAM_DISABLED (0 >> 0) | ||
428 | #define PPC7D_CPLD_FLASH_CNTL_NVRAM_ENABLED (0x80 >> 0) | ||
429 | #define PPC7D_CPLD_FLASH_CNTL_ALTBOOT_LINK_MASK (0x80 >> 1) | ||
430 | #define PPC7D_CPLD_FLASH_CNTL_VMEBOOT_LINK_MASK (0x80 >> 2) | ||
431 | #define PPC7D_CPLD_FLASH_CNTL_RECBOOT_LINK_MASK (0x80 >> 3) | ||
432 | |||
433 | |||
434 | #endif /* __PPC_PLATFORMS_PPC7D_H */ | ||
diff --git a/arch/ppc/platforms/residual.c b/arch/ppc/platforms/residual.c new file mode 100644 index 000000000000..0f84ca603612 --- /dev/null +++ b/arch/ppc/platforms/residual.c | |||
@@ -0,0 +1,1034 @@ | |||
1 | /* | ||
2 | * Code to deal with the PReP residual data. | ||
3 | * | ||
4 | * Written by: Cort Dougan (cort@cs.nmt.edu) | ||
5 | * Improved _greatly_ and rewritten by Gabriel Paubert (paubert@iram.es) | ||
6 | * | ||
7 | * This file is based on the following documentation: | ||
8 | * | ||
9 | * IBM Power Personal Systems Architecture | ||
10 | * Residual Data | ||
11 | * Document Number: PPS-AR-FW0001 | ||
12 | * | ||
13 | * This file is subject to the terms and conditions of the GNU General Public | ||
14 | * License. See the file COPYING in the main directory of this archive | ||
15 | * for more details. | ||
16 | * | ||
17 | */ | ||
18 | |||
19 | #include <linux/string.h> | ||
20 | #include <asm/residual.h> | ||
21 | #include <asm/pnp.h> | ||
22 | #include <asm/byteorder.h> | ||
23 | |||
24 | #include <linux/errno.h> | ||
25 | #include <linux/sched.h> | ||
26 | #include <linux/kernel.h> | ||
27 | #include <linux/mm.h> | ||
28 | #include <linux/stddef.h> | ||
29 | #include <linux/unistd.h> | ||
30 | #include <linux/ptrace.h> | ||
31 | #include <linux/slab.h> | ||
32 | #include <linux/user.h> | ||
33 | #include <linux/a.out.h> | ||
34 | #include <linux/tty.h> | ||
35 | #include <linux/major.h> | ||
36 | #include <linux/interrupt.h> | ||
37 | #include <linux/reboot.h> | ||
38 | #include <linux/init.h> | ||
39 | #include <linux/ioport.h> | ||
40 | #include <linux/pci.h> | ||
41 | #include <linux/ide.h> | ||
42 | |||
43 | #include <asm/sections.h> | ||
44 | #include <asm/mmu.h> | ||
45 | #include <asm/io.h> | ||
46 | #include <asm/pgtable.h> | ||
47 | #include <asm/ide.h> | ||
48 | |||
49 | |||
50 | unsigned char __res[sizeof(RESIDUAL)] __prepdata = {0,}; | ||
51 | RESIDUAL *res = (RESIDUAL *)&__res; | ||
52 | |||
53 | char * PnP_BASE_TYPES[] __initdata = { | ||
54 | "Reserved", | ||
55 | "MassStorageDevice", | ||
56 | "NetworkInterfaceController", | ||
57 | "DisplayController", | ||
58 | "MultimediaController", | ||
59 | "MemoryController", | ||
60 | "BridgeController", | ||
61 | "CommunicationsDevice", | ||
62 | "SystemPeripheral", | ||
63 | "InputDevice", | ||
64 | "ServiceProcessor" | ||
65 | }; | ||
66 | |||
67 | /* Device Sub Type Codes */ | ||
68 | |||
69 | unsigned char * PnP_SUB_TYPES[] __initdata = { | ||
70 | "\001\000SCSIController", | ||
71 | "\001\001IDEController", | ||
72 | "\001\002FloppyController", | ||
73 | "\001\003IPIController", | ||
74 | "\001\200OtherMassStorageController", | ||
75 | "\002\000EthernetController", | ||
76 | "\002\001TokenRingController", | ||
77 | "\002\002FDDIController", | ||
78 | "\002\0x80OtherNetworkController", | ||
79 | "\003\000VGAController", | ||
80 | "\003\001SVGAController", | ||
81 | "\003\002XGAController", | ||
82 | "\003\200OtherDisplayController", | ||
83 | "\004\000VideoController", | ||
84 | "\004\001AudioController", | ||
85 | "\004\200OtherMultimediaController", | ||
86 | "\005\000RAM", | ||
87 | "\005\001FLASH", | ||
88 | "\005\200OtherMemoryDevice", | ||
89 | "\006\000HostProcessorBridge", | ||
90 | "\006\001ISABridge", | ||
91 | "\006\002EISABridge", | ||
92 | "\006\003MicroChannelBridge", | ||
93 | "\006\004PCIBridge", | ||
94 | "\006\005PCMCIABridge", | ||
95 | "\006\006VMEBridge", | ||
96 | "\006\200OtherBridgeDevice", | ||
97 | "\007\000RS232Device", | ||
98 | "\007\001ATCompatibleParallelPort", | ||
99 | "\007\200OtherCommunicationsDevice", | ||
100 | "\010\000ProgrammableInterruptController", | ||
101 | "\010\001DMAController", | ||
102 | "\010\002SystemTimer", | ||
103 | "\010\003RealTimeClock", | ||
104 | "\010\004L2Cache", | ||
105 | "\010\005NVRAM", | ||
106 | "\010\006PowerManagement", | ||
107 | "\010\007CMOS", | ||
108 | "\010\010OperatorPanel", | ||
109 | "\010\011ServiceProcessorClass1", | ||
110 | "\010\012ServiceProcessorClass2", | ||
111 | "\010\013ServiceProcessorClass3", | ||
112 | "\010\014GraphicAssist", | ||
113 | "\010\017SystemPlanar", | ||
114 | "\010\200OtherSystemPeripheral", | ||
115 | "\011\000KeyboardController", | ||
116 | "\011\001Digitizer", | ||
117 | "\011\002MouseController", | ||
118 | "\011\003TabletController", | ||
119 | "\011\0x80OtherInputController", | ||
120 | "\012\000GeneralMemoryController", | ||
121 | NULL | ||
122 | }; | ||
123 | |||
124 | /* Device Interface Type Codes */ | ||
125 | |||
126 | unsigned char * PnP_INTERFACES[] __initdata = { | ||
127 | "\000\000\000General", | ||
128 | "\001\000\000GeneralSCSI", | ||
129 | "\001\001\000GeneralIDE", | ||
130 | "\001\001\001ATACompatible", | ||
131 | |||
132 | "\001\002\000GeneralFloppy", | ||
133 | "\001\002\001Compatible765", | ||
134 | "\001\002\002NS398_Floppy", /* NS Super I/O wired to use index | ||
135 | register at port 398 and data | ||
136 | register at port 399 */ | ||
137 | "\001\002\003NS26E_Floppy", /* Ports 26E and 26F */ | ||
138 | "\001\002\004NS15C_Floppy", /* Ports 15C and 15D */ | ||
139 | "\001\002\005NS2E_Floppy", /* Ports 2E and 2F */ | ||
140 | "\001\002\006CHRP_Floppy", /* CHRP Floppy in PR*P system */ | ||
141 | |||
142 | "\001\003\000GeneralIPI", | ||
143 | |||
144 | "\002\000\000GeneralEther", | ||
145 | "\002\001\000GeneralToken", | ||
146 | "\002\002\000GeneralFDDI", | ||
147 | |||
148 | "\003\000\000GeneralVGA", | ||
149 | "\003\001\000GeneralSVGA", | ||
150 | "\003\002\000GeneralXGA", | ||
151 | |||
152 | "\004\000\000GeneralVideo", | ||
153 | "\004\001\000GeneralAudio", | ||
154 | "\004\001\001CS4232Audio", /* CS 4232 Plug 'n Play Configured */ | ||
155 | |||
156 | "\005\000\000GeneralRAM", | ||
157 | /* This one is obviously wrong ! */ | ||
158 | "\005\000\000PCIMemoryController", /* PCI Config Method */ | ||
159 | "\005\000\001RS6KMemoryController", /* RS6K Config Method */ | ||
160 | "\005\001\000GeneralFLASH", | ||
161 | |||
162 | "\006\000\000GeneralHostBridge", | ||
163 | "\006\001\000GeneralISABridge", | ||
164 | "\006\002\000GeneralEISABridge", | ||
165 | "\006\003\000GeneralMCABridge", | ||
166 | /* GeneralPCIBridge = 0, */ | ||
167 | "\006\004\000PCIBridgeDirect", | ||
168 | "\006\004\001PCIBridgeIndirect", | ||
169 | "\006\004\002PCIBridgeRS6K", | ||
170 | "\006\005\000GeneralPCMCIABridge", | ||
171 | "\006\006\000GeneralVMEBridge", | ||
172 | |||
173 | "\007\000\000GeneralRS232", | ||
174 | "\007\000\001COMx", | ||
175 | "\007\000\002Compatible16450", | ||
176 | "\007\000\003Compatible16550", | ||
177 | "\007\000\004NS398SerPort", /* NS Super I/O wired to use index | ||
178 | register at port 398 and data | ||
179 | register at port 399 */ | ||
180 | "\007\000\005NS26ESerPort", /* Ports 26E and 26F */ | ||
181 | "\007\000\006NS15CSerPort", /* Ports 15C and 15D */ | ||
182 | "\007\000\007NS2ESerPort", /* Ports 2E and 2F */ | ||
183 | |||
184 | "\007\001\000GeneralParPort", | ||
185 | "\007\001\001LPTx", | ||
186 | "\007\001\002NS398ParPort", /* NS Super I/O wired to use index | ||
187 | register at port 398 and data | ||
188 | register at port 399 */ | ||
189 | "\007\001\003NS26EParPort", /* Ports 26E and 26F */ | ||
190 | "\007\001\004NS15CParPort", /* Ports 15C and 15D */ | ||
191 | "\007\001\005NS2EParPort", /* Ports 2E and 2F */ | ||
192 | |||
193 | "\010\000\000GeneralPIC", | ||
194 | "\010\000\001ISA_PIC", | ||
195 | "\010\000\002EISA_PIC", | ||
196 | "\010\000\003MPIC", | ||
197 | "\010\000\004RS6K_PIC", | ||
198 | |||
199 | "\010\001\000GeneralDMA", | ||
200 | "\010\001\001ISA_DMA", | ||
201 | "\010\001\002EISA_DMA", | ||
202 | |||
203 | "\010\002\000GeneralTimer", | ||
204 | "\010\002\001ISA_Timer", | ||
205 | "\010\002\002EISA_Timer", | ||
206 | "\010\003\000GeneralRTC", | ||
207 | "\010\003\001ISA_RTC", | ||
208 | |||
209 | "\010\004\001StoreThruOnly", | ||
210 | "\010\004\002StoreInEnabled", | ||
211 | "\010\004\003RS6KL2Cache", | ||
212 | |||
213 | "\010\005\000IndirectNVRAM", /* Indirectly addressed */ | ||
214 | "\010\005\001DirectNVRAM", /* Memory Mapped */ | ||
215 | "\010\005\002IndirectNVRAM24", /* Indirectly addressed - 24 bit */ | ||
216 | |||
217 | "\010\006\000GeneralPowerManagement", | ||
218 | "\010\006\001EPOWPowerManagement", | ||
219 | "\010\006\002PowerControl", // d1378 | ||
220 | |||
221 | "\010\007\000GeneralCMOS", | ||
222 | |||
223 | "\010\010\000GeneralOPPanel", | ||
224 | "\010\010\001HarddiskLight", | ||
225 | "\010\010\002CDROMLight", | ||
226 | "\010\010\003PowerLight", | ||
227 | "\010\010\004KeyLock", | ||
228 | "\010\010\005ANDisplay", /* AlphaNumeric Display */ | ||
229 | "\010\010\006SystemStatusLED", /* 3 digit 7 segment LED */ | ||
230 | "\010\010\007CHRP_SystemStatusLED", /* CHRP LEDs in PR*P system */ | ||
231 | |||
232 | "\010\011\000GeneralServiceProcessor", | ||
233 | "\010\012\000GeneralServiceProcessor", | ||
234 | "\010\013\000GeneralServiceProcessor", | ||
235 | |||
236 | "\010\014\001TransferData", | ||
237 | "\010\014\002IGMC32", | ||
238 | "\010\014\003IGMC64", | ||
239 | |||
240 | "\010\017\000GeneralSystemPlanar", /* 10/5/95 */ | ||
241 | NULL | ||
242 | }; | ||
243 | |||
244 | static const unsigned char __init *PnP_SUB_TYPE_STR(unsigned char BaseType, | ||
245 | unsigned char SubType) { | ||
246 | unsigned char ** s=PnP_SUB_TYPES; | ||
247 | while (*s && !((*s)[0]==BaseType | ||
248 | && (*s)[1]==SubType)) s++; | ||
249 | if (*s) return *s+2; | ||
250 | else return("Unknown !"); | ||
251 | }; | ||
252 | |||
253 | static const unsigned char __init *PnP_INTERFACE_STR(unsigned char BaseType, | ||
254 | unsigned char SubType, | ||
255 | unsigned char Interface) { | ||
256 | unsigned char ** s=PnP_INTERFACES; | ||
257 | while (*s && !((*s)[0]==BaseType | ||
258 | && (*s)[1]==SubType | ||
259 | && (*s)[2]==Interface)) s++; | ||
260 | if (*s) return *s+3; | ||
261 | else return NULL; | ||
262 | }; | ||
263 | |||
264 | static void __init printsmallvendor(PnP_TAG_PACKET *pkt, int size) { | ||
265 | int i, c; | ||
266 | char decomp[4]; | ||
267 | #define p pkt->S14_Pack.S14_Data.S14_PPCPack | ||
268 | switch(p.Type) { | ||
269 | case 1: | ||
270 | /* Decompress first 3 chars */ | ||
271 | c = *(unsigned short *)p.PPCData; | ||
272 | decomp[0]='A'-1+((c>>10)&0x1F); | ||
273 | decomp[1]='A'-1+((c>>5)&0x1F); | ||
274 | decomp[2]='A'-1+(c&0x1F); | ||
275 | decomp[3]=0; | ||
276 | printk(" Chip identification: %s%4.4X\n", | ||
277 | decomp, ld_le16((unsigned short *)(p.PPCData+2))); | ||
278 | break; | ||
279 | default: | ||
280 | printk(" Small vendor item type 0x%2.2x, data (hex): ", | ||
281 | p.Type); | ||
282 | for(i=0; i<size-2; i++) printk("%2.2x ", p.PPCData[i]); | ||
283 | printk("\n"); | ||
284 | break; | ||
285 | } | ||
286 | #undef p | ||
287 | } | ||
288 | |||
289 | static void __init printsmallpacket(PnP_TAG_PACKET * pkt, int size) { | ||
290 | static const unsigned char * intlevel[] = {"high", "low"}; | ||
291 | static const unsigned char * intsense[] = {"edge", "level"}; | ||
292 | |||
293 | switch (tag_small_item_name(pkt->S1_Pack.Tag)) { | ||
294 | case PnPVersion: | ||
295 | printk(" PnPversion 0x%x.%x\n", | ||
296 | pkt->S1_Pack.Version[0], /* How to interpret version ? */ | ||
297 | pkt->S1_Pack.Version[1]); | ||
298 | break; | ||
299 | // case Logicaldevice: | ||
300 | break; | ||
301 | // case CompatibleDevice: | ||
302 | break; | ||
303 | case IRQFormat: | ||
304 | #define p pkt->S4_Pack | ||
305 | printk(" IRQ Mask 0x%4.4x, %s %s sensitive\n", | ||
306 | ld_le16((unsigned short *)p.IRQMask), | ||
307 | intlevel[(size>3) ? !(p.IRQInfo&0x05) : 0], | ||
308 | intsense[(size>3) ? !(p.IRQInfo&0x03) : 0]); | ||
309 | #undef p | ||
310 | break; | ||
311 | case DMAFormat: | ||
312 | #define p pkt->S5_Pack | ||
313 | printk(" DMA channel mask 0x%2.2x, info 0x%2.2x\n", | ||
314 | p.DMAMask, p.DMAInfo); | ||
315 | #undef p | ||
316 | break; | ||
317 | case StartDepFunc: | ||
318 | printk("Start dependent function:\n"); | ||
319 | break; | ||
320 | case EndDepFunc: | ||
321 | printk("End dependent function\n"); | ||
322 | break; | ||
323 | case IOPort: | ||
324 | #define p pkt->S8_Pack | ||
325 | printk(" Variable (%d decoded bits) I/O port\n" | ||
326 | " from 0x%4.4x to 0x%4.4x, alignment %d, %d ports\n", | ||
327 | p.IOInfo&ISAAddr16bit?16:10, | ||
328 | ld_le16((unsigned short *)p.RangeMin), | ||
329 | ld_le16((unsigned short *)p.RangeMax), | ||
330 | p.IOAlign, p.IONum); | ||
331 | #undef p | ||
332 | break; | ||
333 | case FixedIOPort: | ||
334 | #define p pkt->S9_Pack | ||
335 | printk(" Fixed (10 decoded bits) I/O port from %3.3x to %3.3x\n", | ||
336 | (p.Range[1]<<8)|p.Range[0], | ||
337 | ((p.Range[1]<<8)|p.Range[0])+p.IONum-1); | ||
338 | #undef p | ||
339 | break; | ||
340 | case Res1: | ||
341 | case Res2: | ||
342 | case Res3: | ||
343 | printk(" Undefined packet type %d!\n", | ||
344 | tag_small_item_name(pkt->S1_Pack.Tag)); | ||
345 | break; | ||
346 | case SmallVendorItem: | ||
347 | printsmallvendor(pkt,size); | ||
348 | break; | ||
349 | default: | ||
350 | printk(" Type 0x2.2x%d, size=%d\n", | ||
351 | pkt->S1_Pack.Tag, size); | ||
352 | break; | ||
353 | } | ||
354 | } | ||
355 | |||
356 | static void __init printlargevendor(PnP_TAG_PACKET * pkt, int size) { | ||
357 | static const unsigned char * addrtype[] = {"I/O", "Memory", "System"}; | ||
358 | static const unsigned char * inttype[] = {"8259", "MPIC", "RS6k BUID %d"}; | ||
359 | static const unsigned char * convtype[] = {"Bus Memory", "Bus I/O", "DMA"}; | ||
360 | static const unsigned char * transtype[] = {"direct", "mapped", "direct-store segment"}; | ||
361 | static const unsigned char * L2type[] = {"WriteThru", "CopyBack"}; | ||
362 | static const unsigned char * L2assoc[] = {"DirectMapped", "2-way set"}; | ||
363 | |||
364 | int i; | ||
365 | char tmpstr[30], *t; | ||
366 | #define p pkt->L4_Pack.L4_Data.L4_PPCPack | ||
367 | switch(p.Type) { | ||
368 | case 2: | ||
369 | printk(" %d K %s %s L2 cache, %d/%d bytes line/sector size\n", | ||
370 | ld_le32((unsigned int *)p.PPCData), | ||
371 | L2type[p.PPCData[10]-1], | ||
372 | L2assoc[p.PPCData[4]-1], | ||
373 | ld_le16((unsigned short *)p.PPCData+3), | ||
374 | ld_le16((unsigned short *)p.PPCData+4)); | ||
375 | break; | ||
376 | case 3: | ||
377 | printk(" PCI Bridge parameters\n" | ||
378 | " ConfigBaseAddress %0x\n" | ||
379 | " ConfigBaseData %0x\n" | ||
380 | " Bus number %d\n", | ||
381 | ld_le32((unsigned int *)p.PPCData), | ||
382 | ld_le32((unsigned int *)(p.PPCData+8)), | ||
383 | p.PPCData[16]); | ||
384 | for(i=20; i<size-4; i+=12) { | ||
385 | int j, first; | ||
386 | if(p.PPCData[i]) printk(" PCI Slot %d", p.PPCData[i]); | ||
387 | else printk (" Integrated PCI device"); | ||
388 | for(j=0, first=1, t=tmpstr; j<4; j++) { | ||
389 | int line=ld_le16((unsigned short *)(p.PPCData+i+4)+j); | ||
390 | if(line!=0xffff){ | ||
391 | if(first) first=0; else *t++='/'; | ||
392 | *t++='A'+j; | ||
393 | } | ||
394 | } | ||
395 | *t='\0'; | ||
396 | printk(" DevFunc 0x%x interrupt line(s) %s routed to", | ||
397 | p.PPCData[i+1],tmpstr); | ||
398 | sprintf(tmpstr, | ||
399 | inttype[p.PPCData[i+2]-1], | ||
400 | p.PPCData[i+3]); | ||
401 | printk(" %s line(s) ", | ||
402 | tmpstr); | ||
403 | for(j=0, first=1, t=tmpstr; j<4; j++) { | ||
404 | int line=ld_le16((unsigned short *)(p.PPCData+i+4)+j); | ||
405 | if(line!=0xffff){ | ||
406 | if(first) first=0; else *t++='/'; | ||
407 | t+=sprintf(t,"%d(%c)", | ||
408 | line&0x7fff, | ||
409 | line&0x8000?'E':'L'); | ||
410 | } | ||
411 | } | ||
412 | printk("%s\n",tmpstr); | ||
413 | } | ||
414 | break; | ||
415 | case 5: | ||
416 | printk(" Bridge address translation, %s decoding:\n" | ||
417 | " Processor Bus Size Conversion Translation\n" | ||
418 | " 0x%8.8x 0x%8.8x 0x%8.8x %s %s\n", | ||
419 | p.PPCData[0]&1 ? "positive" : "subtractive", | ||
420 | ld_le32((unsigned int *)p.PPCData+1), | ||
421 | ld_le32((unsigned int *)p.PPCData+3), | ||
422 | ld_le32((unsigned int *)p.PPCData+5), | ||
423 | convtype[p.PPCData[2]-1], | ||
424 | transtype[p.PPCData[1]-1]); | ||
425 | break; | ||
426 | case 6: | ||
427 | printk(" Bus speed %d Hz, %d slot(s)\n", | ||
428 | ld_le32((unsigned int *)p.PPCData), | ||
429 | p.PPCData[4]); | ||
430 | break; | ||
431 | case 7: | ||
432 | printk(" SCSI buses: %d, id(s):", p.PPCData[0]); | ||
433 | for(i=1; i<=p.PPCData[0]; i++) | ||
434 | printk(" %d%c", p.PPCData[i], i==p.PPCData[0] ? '\n' : ','); | ||
435 | break; | ||
436 | case 9: | ||
437 | printk(" %s address (%d bits), at 0x%x size 0x%x bytes\n", | ||
438 | addrtype[p.PPCData[0]-1], | ||
439 | p.PPCData[1], | ||
440 | ld_le32((unsigned int *)(p.PPCData+4)), | ||
441 | ld_le32((unsigned int *)(p.PPCData+12))); | ||
442 | break; | ||
443 | case 10: | ||
444 | sprintf(tmpstr, | ||
445 | inttype[p.PPCData[0]-1], | ||
446 | p.PPCData[1]); | ||
447 | |||
448 | printk(" ISA interrupts routed to %s\n" | ||
449 | " lines", | ||
450 | tmpstr); | ||
451 | for(i=0; i<16; i++) { | ||
452 | int line=ld_le16((unsigned short *)p.PPCData+i+1); | ||
453 | if (line!=0xffff) printk(" %d(IRQ%d)", line, i); | ||
454 | } | ||
455 | printk("\n"); | ||
456 | break; | ||
457 | default: | ||
458 | printk(" Large vendor item type 0x%2.2x\n Data (hex):", | ||
459 | p.Type); | ||
460 | for(i=0; i<size-4; i++) printk(" %2.2x", p.PPCData[i]); | ||
461 | printk("\n"); | ||
462 | #undef p | ||
463 | } | ||
464 | } | ||
465 | |||
466 | static void __init printlargepacket(PnP_TAG_PACKET * pkt, int size) { | ||
467 | switch (tag_large_item_name(pkt->S1_Pack.Tag)) { | ||
468 | case LargeVendorItem: | ||
469 | printlargevendor(pkt, size); | ||
470 | break; | ||
471 | default: | ||
472 | printk(" Type 0x2.2x%d, size=%d\n", | ||
473 | pkt->S1_Pack.Tag, size); | ||
474 | break; | ||
475 | } | ||
476 | } | ||
477 | |||
478 | static void __init printpackets(PnP_TAG_PACKET * pkt, const char * cat) | ||
479 | { | ||
480 | if (pkt->S1_Pack.Tag== END_TAG) { | ||
481 | printk(" No packets describing %s resources.\n", cat); | ||
482 | return; | ||
483 | } | ||
484 | printk( " Packets describing %s resources:\n",cat); | ||
485 | do { | ||
486 | int size; | ||
487 | if (tag_type(pkt->S1_Pack.Tag)) { | ||
488 | size= 3 + | ||
489 | pkt->L1_Pack.Count0 + | ||
490 | pkt->L1_Pack.Count1*256; | ||
491 | printlargepacket(pkt, size); | ||
492 | } else { | ||
493 | size=tag_small_count(pkt->S1_Pack.Tag)+1; | ||
494 | printsmallpacket(pkt, size); | ||
495 | } | ||
496 | pkt = (PnP_TAG_PACKET *)((unsigned char *) pkt + size); | ||
497 | } while (pkt->S1_Pack.Tag != END_TAG); | ||
498 | } | ||
499 | |||
500 | void __init print_residual_device_info(void) | ||
501 | { | ||
502 | int i; | ||
503 | PPC_DEVICE *dev; | ||
504 | #define did dev->DeviceId | ||
505 | |||
506 | /* make sure we have residual data first */ | ||
507 | if (!have_residual_data) | ||
508 | return; | ||
509 | |||
510 | printk("Residual: %ld devices\n", res->ActualNumDevices); | ||
511 | for ( i = 0; | ||
512 | i < res->ActualNumDevices ; | ||
513 | i++) | ||
514 | { | ||
515 | char decomp[4], sn[20]; | ||
516 | const char * s; | ||
517 | dev = &res->Devices[i]; | ||
518 | s = PnP_INTERFACE_STR(did.BaseType, did.SubType, | ||
519 | did.Interface); | ||
520 | if(!s) { | ||
521 | sprintf(sn, "interface %d", did.Interface); | ||
522 | s=sn; | ||
523 | } | ||
524 | if ( did.BusId & PCIDEVICE ) | ||
525 | printk("PCI Device, Bus %d, DevFunc 0x%x:", | ||
526 | dev->BusAccess.PCIAccess.BusNumber, | ||
527 | dev->BusAccess.PCIAccess.DevFuncNumber); | ||
528 | if ( did.BusId & PNPISADEVICE ) printk("PNPISA Device:"); | ||
529 | if ( did.BusId & ISADEVICE ) | ||
530 | printk("ISA Device, Slot %d, LogicalDev %d:", | ||
531 | dev->BusAccess.ISAAccess.SlotNumber, | ||
532 | dev->BusAccess.ISAAccess.LogicalDevNumber); | ||
533 | if ( did.BusId & EISADEVICE ) printk("EISA Device:"); | ||
534 | if ( did.BusId & PROCESSORDEVICE ) | ||
535 | printk("ProcBus Device, Bus %d, BUID %d: ", | ||
536 | dev->BusAccess.ProcBusAccess.BusNumber, | ||
537 | dev->BusAccess.ProcBusAccess.BUID); | ||
538 | if ( did.BusId & PCMCIADEVICE ) printk("PCMCIA "); | ||
539 | if ( did.BusId & VMEDEVICE ) printk("VME "); | ||
540 | if ( did.BusId & MCADEVICE ) printk("MCA "); | ||
541 | if ( did.BusId & MXDEVICE ) printk("MX "); | ||
542 | /* Decompress first 3 chars */ | ||
543 | decomp[0]='A'-1+((did.DevId>>26)&0x1F); | ||
544 | decomp[1]='A'-1+((did.DevId>>21)&0x1F); | ||
545 | decomp[2]='A'-1+((did.DevId>>16)&0x1F); | ||
546 | decomp[3]=0; | ||
547 | printk(" %s%4.4lX, %s, %s, %s\n", | ||
548 | decomp, did.DevId&0xffff, | ||
549 | PnP_BASE_TYPES[did.BaseType], | ||
550 | PnP_SUB_TYPE_STR(did.BaseType,did.SubType), | ||
551 | s); | ||
552 | if ( dev->AllocatedOffset ) | ||
553 | printpackets( (union _PnP_TAG_PACKET *) | ||
554 | &res->DevicePnPHeap[dev->AllocatedOffset], | ||
555 | "allocated"); | ||
556 | if ( dev->PossibleOffset ) | ||
557 | printpackets( (union _PnP_TAG_PACKET *) | ||
558 | &res->DevicePnPHeap[dev->PossibleOffset], | ||
559 | "possible"); | ||
560 | if ( dev->CompatibleOffset ) | ||
561 | printpackets( (union _PnP_TAG_PACKET *) | ||
562 | &res->DevicePnPHeap[dev->CompatibleOffset], | ||
563 | "compatible"); | ||
564 | } | ||
565 | } | ||
566 | |||
567 | |||
568 | #if 0 | ||
569 | static void __init printVPD(void) { | ||
570 | #define vpd res->VitalProductData | ||
571 | int ps=vpd.PageSize, i, j; | ||
572 | static const char* Usage[]={ | ||
573 | "FirmwareStack", "FirmwareHeap", "FirmwareCode", "BootImage", | ||
574 | "Free", "Unpopulated", "ISAAddr", "PCIConfig", | ||
575 | "IOMemory", "SystemIO", "SystemRegs", "PCIAddr", | ||
576 | "UnPopSystemRom", "SystemROM", "ResumeBlock", "Other" | ||
577 | }; | ||
578 | static const unsigned char *FWMan[]={ | ||
579 | "IBM", "Motorola", "FirmWorks", "Bull" | ||
580 | }; | ||
581 | static const unsigned char *FWFlags[]={ | ||
582 | "Conventional", "OpenFirmware", "Diagnostics", "LowDebug", | ||
583 | "MultiBoot", "LowClient", "Hex41", "FAT", | ||
584 | "ISO9660", "SCSI_ID_Override", "Tape_Boot", "FW_Boot_Path" | ||
585 | }; | ||
586 | static const unsigned char *ESM[]={ | ||
587 | "Port92", "PCIConfigA8", "FF001030", "????????" | ||
588 | }; | ||
589 | static const unsigned char *SIOM[]={ | ||
590 | "Port850", "????????", "PCIConfigA8", "????????" | ||
591 | }; | ||
592 | |||
593 | printk("Model: %s\n",vpd.PrintableModel); | ||
594 | printk("Serial: %s\n", vpd.Serial); | ||
595 | printk("FirmwareSupplier: %s\n", FWMan[vpd.FirmwareSupplier]); | ||
596 | printk("FirmwareFlags:"); | ||
597 | for(j=0; j<12; j++) { | ||
598 | if (vpd.FirmwareSupports & (1<<j)) { | ||
599 | printk(" %s%c", FWFlags[j], | ||
600 | vpd.FirmwareSupports&(-2<<j) ? ',' : '\n'); | ||
601 | } | ||
602 | } | ||
603 | printk("NVRamSize: %ld\n", vpd.NvramSize); | ||
604 | printk("SIMMslots: %ld\n", vpd.NumSIMMSlots); | ||
605 | printk("EndianSwitchMethod: %s\n", | ||
606 | ESM[vpd.EndianSwitchMethod>2 ? 2 : vpd.EndianSwitchMethod]); | ||
607 | printk("SpreadIOMethod: %s\n", | ||
608 | SIOM[vpd.SpreadIOMethod>3 ? 3 : vpd.SpreadIOMethod]); | ||
609 | printk("Processor/Bus frequencies (Hz): %ld/%ld\n", | ||
610 | vpd.ProcessorHz, vpd.ProcessorBusHz); | ||
611 | printk("Time Base Divisor: %ld\n", vpd.TimeBaseDivisor); | ||
612 | printk("WordWidth, PageSize: %ld, %d\n", vpd.WordWidth, ps); | ||
613 | printk("Cache sector size, Lock granularity: %ld, %ld\n", | ||
614 | vpd.CoherenceBlockSize, vpd.GranuleSize); | ||
615 | for (i=0; i<res->ActualNumMemSegs; i++) { | ||
616 | int mask=res->Segs[i].Usage, first, j; | ||
617 | printk("%8.8lx-%8.8lx ", | ||
618 | res->Segs[i].BasePage*ps, | ||
619 | (res->Segs[i].PageCount+res->Segs[i].BasePage)*ps-1); | ||
620 | for(j=15, first=1; j>=0; j--) { | ||
621 | if (mask&(1<<j)) { | ||
622 | if (first) first=0; | ||
623 | else printk(", "); | ||
624 | printk("%s", Usage[j]); | ||
625 | } | ||
626 | } | ||
627 | printk("\n"); | ||
628 | } | ||
629 | } | ||
630 | |||
631 | /* | ||
632 | * Spit out some info about residual data | ||
633 | */ | ||
634 | void print_residual_device_info(void) | ||
635 | { | ||
636 | int i; | ||
637 | union _PnP_TAG_PACKET *pkt; | ||
638 | PPC_DEVICE *dev; | ||
639 | #define did dev->DeviceId | ||
640 | |||
641 | /* make sure we have residual data first */ | ||
642 | if (!have_residual_data) | ||
643 | return; | ||
644 | printk("Residual: %ld devices\n", res->ActualNumDevices); | ||
645 | for ( i = 0; | ||
646 | i < res->ActualNumDevices ; | ||
647 | i++) | ||
648 | { | ||
649 | dev = &res->Devices[i]; | ||
650 | /* | ||
651 | * pci devices | ||
652 | */ | ||
653 | if ( did.BusId & PCIDEVICE ) | ||
654 | { | ||
655 | printk("PCI Device:"); | ||
656 | /* unknown vendor */ | ||
657 | if ( !strncmp( "Unknown", pci_strvendor(did.DevId>>16), 7) ) | ||
658 | printk(" id %08lx types %d/%d", did.DevId, | ||
659 | did.BaseType, did.SubType); | ||
660 | /* known vendor */ | ||
661 | else | ||
662 | printk(" %s %s", | ||
663 | pci_strvendor(did.DevId>>16), | ||
664 | pci_strdev(did.DevId>>16, | ||
665 | did.DevId&0xffff) | ||
666 | ); | ||
667 | |||
668 | if ( did.BusId & PNPISADEVICE ) | ||
669 | { | ||
670 | printk(" pnp:"); | ||
671 | /* get pnp info on the device */ | ||
672 | pkt = (union _PnP_TAG_PACKET *) | ||
673 | &res->DevicePnPHeap[dev->AllocatedOffset]; | ||
674 | for (; pkt->S1_Pack.Tag != DF_END_TAG; | ||
675 | pkt++ ) | ||
676 | { | ||
677 | if ( (pkt->S1_Pack.Tag == S4_Packet) || | ||
678 | (pkt->S1_Pack.Tag == S4_Packet_flags) ) | ||
679 | printk(" irq %02x%02x", | ||
680 | pkt->S4_Pack.IRQMask[0], | ||
681 | pkt->S4_Pack.IRQMask[1]); | ||
682 | } | ||
683 | } | ||
684 | printk("\n"); | ||
685 | continue; | ||
686 | } | ||
687 | /* | ||
688 | * isa devices | ||
689 | */ | ||
690 | if ( did.BusId & ISADEVICE ) | ||
691 | { | ||
692 | printk("ISA Device: basetype: %d subtype: %d", | ||
693 | did.BaseType, did.SubType); | ||
694 | printk("\n"); | ||
695 | continue; | ||
696 | } | ||
697 | /* | ||
698 | * eisa devices | ||
699 | */ | ||
700 | if ( did.BusId & EISADEVICE ) | ||
701 | { | ||
702 | printk("EISA Device: basetype: %d subtype: %d", | ||
703 | did.BaseType, did.SubType); | ||
704 | printk("\n"); | ||
705 | continue; | ||
706 | } | ||
707 | /* | ||
708 | * proc bus devices | ||
709 | */ | ||
710 | if ( did.BusId & PROCESSORDEVICE ) | ||
711 | { | ||
712 | printk("ProcBus Device: basetype: %d subtype: %d", | ||
713 | did.BaseType, did.SubType); | ||
714 | printk("\n"); | ||
715 | continue; | ||
716 | } | ||
717 | /* | ||
718 | * pcmcia devices | ||
719 | */ | ||
720 | if ( did.BusId & PCMCIADEVICE ) | ||
721 | { | ||
722 | printk("PCMCIA Device: basetype: %d subtype: %d", | ||
723 | did.BaseType, did.SubType); | ||
724 | printk("\n"); | ||
725 | continue; | ||
726 | } | ||
727 | printk("Unknown bus access device: busid %lx\n", | ||
728 | did.BusId); | ||
729 | } | ||
730 | } | ||
731 | #endif | ||
732 | |||
733 | /* Returns the device index in the residual data, | ||
734 | any of the search items may be set as -1 for wildcard, | ||
735 | DevID number field (second halfword) is big endian ! | ||
736 | |||
737 | Examples: | ||
738 | - search for the Interrupt controller (8259 type), 2 methods: | ||
739 | 1) i8259 = residual_find_device(~0, | ||
740 | NULL, | ||
741 | SystemPeripheral, | ||
742 | ProgrammableInterruptController, | ||
743 | ISA_PIC, | ||
744 | 0); | ||
745 | 2) i8259 = residual_find_device(~0, "PNP0000", -1, -1, -1, 0) | ||
746 | |||
747 | - search for the first two serial devices, whatever their type) | ||
748 | iserial1 = residual_find_device(~0,NULL, | ||
749 | CommunicationsDevice, | ||
750 | RS232Device, | ||
751 | -1, 0) | ||
752 | iserial2 = residual_find_device(~0,NULL, | ||
753 | CommunicationsDevice, | ||
754 | RS232Device, | ||
755 | -1, 1) | ||
756 | - but search for typical COM1 and COM2 is not easy due to the | ||
757 | fact that the interface may be anything and the name "PNP0500" or | ||
758 | "PNP0501". Quite bad. | ||
759 | |||
760 | */ | ||
761 | |||
762 | /* devid are easier to uncompress than to compress, so to minimize bloat | ||
763 | in this rarely used area we unencode and compare */ | ||
764 | |||
765 | /* in residual data number is big endian in the device table and | ||
766 | little endian in the heap, so we use two parameters to avoid writing | ||
767 | two very similar functions */ | ||
768 | |||
769 | static int __init same_DevID(unsigned short vendor, | ||
770 | unsigned short Number, | ||
771 | char * str) | ||
772 | { | ||
773 | static unsigned const char hexdigit[]="0123456789ABCDEF"; | ||
774 | if (strlen(str)!=7) return 0; | ||
775 | if ( ( ((vendor>>10)&0x1f)+'A'-1 == str[0]) && | ||
776 | ( ((vendor>>5)&0x1f)+'A'-1 == str[1]) && | ||
777 | ( (vendor&0x1f)+'A'-1 == str[2]) && | ||
778 | (hexdigit[(Number>>12)&0x0f] == str[3]) && | ||
779 | (hexdigit[(Number>>8)&0x0f] == str[4]) && | ||
780 | (hexdigit[(Number>>4)&0x0f] == str[5]) && | ||
781 | (hexdigit[Number&0x0f] == str[6]) ) return 1; | ||
782 | return 0; | ||
783 | } | ||
784 | |||
785 | PPC_DEVICE __init *residual_find_device(unsigned long BusMask, | ||
786 | unsigned char * DevID, | ||
787 | int BaseType, | ||
788 | int SubType, | ||
789 | int Interface, | ||
790 | int n) | ||
791 | { | ||
792 | int i; | ||
793 | if (!have_residual_data) return NULL; | ||
794 | for (i=0; i<res->ActualNumDevices; i++) { | ||
795 | #define Dev res->Devices[i].DeviceId | ||
796 | if ( (Dev.BusId&BusMask) && | ||
797 | (BaseType==-1 || Dev.BaseType==BaseType) && | ||
798 | (SubType==-1 || Dev.SubType==SubType) && | ||
799 | (Interface==-1 || Dev.Interface==Interface) && | ||
800 | (DevID==NULL || same_DevID((Dev.DevId>>16)&0xffff, | ||
801 | Dev.DevId&0xffff, DevID)) && | ||
802 | !(n--) ) return res->Devices+i; | ||
803 | #undef Dev | ||
804 | } | ||
805 | return NULL; | ||
806 | } | ||
807 | |||
808 | PPC_DEVICE __init *residual_find_device_id(unsigned long BusMask, | ||
809 | unsigned short DevID, | ||
810 | int BaseType, | ||
811 | int SubType, | ||
812 | int Interface, | ||
813 | int n) | ||
814 | { | ||
815 | int i; | ||
816 | if (!have_residual_data) return NULL; | ||
817 | for (i=0; i<res->ActualNumDevices; i++) { | ||
818 | #define Dev res->Devices[i].DeviceId | ||
819 | if ( (Dev.BusId&BusMask) && | ||
820 | (BaseType==-1 || Dev.BaseType==BaseType) && | ||
821 | (SubType==-1 || Dev.SubType==SubType) && | ||
822 | (Interface==-1 || Dev.Interface==Interface) && | ||
823 | (DevID==0xffff || (Dev.DevId&0xffff) == DevID) && | ||
824 | !(n--) ) return res->Devices+i; | ||
825 | #undef Dev | ||
826 | } | ||
827 | return NULL; | ||
828 | } | ||
829 | |||
830 | static int __init | ||
831 | residual_scan_pcibridge(PnP_TAG_PACKET * pkt, struct pci_dev *dev) | ||
832 | { | ||
833 | int irq = -1; | ||
834 | |||
835 | #define data pkt->L4_Pack.L4_Data.L4_PPCPack.PPCData | ||
836 | if (dev->bus->number == data[16]) { | ||
837 | int i, size; | ||
838 | |||
839 | size = 3 + ld_le16((u_short *) (&pkt->L4_Pack.Count0)); | ||
840 | for (i = 20; i < size - 4; i += 12) { | ||
841 | unsigned char pin; | ||
842 | int line_irq; | ||
843 | |||
844 | if (dev->devfn != data[i + 1]) | ||
845 | continue; | ||
846 | |||
847 | pci_read_config_byte(dev, PCI_INTERRUPT_PIN, &pin); | ||
848 | if (pin) { | ||
849 | line_irq = ld_le16((unsigned short *) | ||
850 | (&data[i + 4 + 2 * (pin - 1)])); | ||
851 | irq = (line_irq == 0xffff) ? 0 | ||
852 | : line_irq & 0x7fff; | ||
853 | } else | ||
854 | irq = 0; | ||
855 | |||
856 | break; | ||
857 | } | ||
858 | } | ||
859 | #undef data | ||
860 | |||
861 | return irq; | ||
862 | } | ||
863 | |||
864 | int __init | ||
865 | residual_pcidev_irq(struct pci_dev *dev) | ||
866 | { | ||
867 | int i = 0; | ||
868 | int irq = -1; | ||
869 | PPC_DEVICE *bridge; | ||
870 | |||
871 | while ((bridge = residual_find_device | ||
872 | (-1, NULL, BridgeController, PCIBridge, -1, i++))) { | ||
873 | |||
874 | PnP_TAG_PACKET *pkt; | ||
875 | if (bridge->AllocatedOffset) { | ||
876 | pkt = PnP_find_large_vendor_packet(res->DevicePnPHeap + | ||
877 | bridge->AllocatedOffset, 3, 0); | ||
878 | if (!pkt) | ||
879 | continue; | ||
880 | |||
881 | irq = residual_scan_pcibridge(pkt, dev); | ||
882 | if (irq != -1) | ||
883 | break; | ||
884 | } | ||
885 | } | ||
886 | |||
887 | return (irq < 0) ? 0 : irq; | ||
888 | } | ||
889 | |||
890 | void __init residual_irq_mask(char *irq_edge_mask_lo, char *irq_edge_mask_hi) | ||
891 | { | ||
892 | PPC_DEVICE *dev; | ||
893 | int i = 0; | ||
894 | unsigned short irq_mask = 0x000; /* default to edge */ | ||
895 | |||
896 | while ((dev = residual_find_device(-1, NULL, -1, -1, -1, i++))) { | ||
897 | PnP_TAG_PACKET *pkt; | ||
898 | unsigned short mask; | ||
899 | int size; | ||
900 | int offset = dev->AllocatedOffset; | ||
901 | |||
902 | if (!offset) | ||
903 | continue; | ||
904 | |||
905 | pkt = PnP_find_packet(res->DevicePnPHeap + offset, | ||
906 | IRQFormat, 0); | ||
907 | if (!pkt) | ||
908 | continue; | ||
909 | |||
910 | size = tag_small_count(pkt->S1_Pack.Tag) + 1; | ||
911 | mask = ld_le16((unsigned short *)pkt->S4_Pack.IRQMask); | ||
912 | if (size > 3 && (pkt->S4_Pack.IRQInfo & 0x0c)) | ||
913 | irq_mask |= mask; | ||
914 | } | ||
915 | |||
916 | *irq_edge_mask_lo = irq_mask & 0xff; | ||
917 | *irq_edge_mask_hi = irq_mask >> 8; | ||
918 | } | ||
919 | |||
920 | unsigned int __init residual_isapic_addr(void) | ||
921 | { | ||
922 | PPC_DEVICE *isapic; | ||
923 | PnP_TAG_PACKET *pkt; | ||
924 | unsigned int addr; | ||
925 | |||
926 | isapic = residual_find_device(~0, NULL, SystemPeripheral, | ||
927 | ProgrammableInterruptController, | ||
928 | ISA_PIC, 0); | ||
929 | if (!isapic) | ||
930 | goto unknown; | ||
931 | |||
932 | pkt = PnP_find_large_vendor_packet(res->DevicePnPHeap + | ||
933 | isapic->AllocatedOffset, 9, 0); | ||
934 | if (!pkt) | ||
935 | goto unknown; | ||
936 | |||
937 | #define p pkt->L4_Pack.L4_Data.L4_PPCPack | ||
938 | /* Must be 32-bit system address */ | ||
939 | if (!((p.PPCData[0] == 3) && (p.PPCData[1] == 32))) | ||
940 | goto unknown; | ||
941 | |||
942 | /* It doesn't seem to work where length != 1 (what can I say? :-/ ) */ | ||
943 | if (ld_le32((unsigned int *)(p.PPCData + 12)) != 1) | ||
944 | goto unknown; | ||
945 | |||
946 | addr = ld_le32((unsigned int *) (p.PPCData + 4)); | ||
947 | #undef p | ||
948 | return addr; | ||
949 | unknown: | ||
950 | return 0; | ||
951 | } | ||
952 | |||
953 | PnP_TAG_PACKET *PnP_find_packet(unsigned char *p, | ||
954 | unsigned packet_tag, | ||
955 | int n) | ||
956 | { | ||
957 | unsigned mask, masked_tag, size; | ||
958 | if(!p) return NULL; | ||
959 | if (tag_type(packet_tag)) mask=0xff; else mask=0xF8; | ||
960 | masked_tag = packet_tag&mask; | ||
961 | for(; *p != END_TAG; p+=size) { | ||
962 | if ((*p & mask) == masked_tag && !(n--)) | ||
963 | return (PnP_TAG_PACKET *) p; | ||
964 | if (tag_type(*p)) | ||
965 | size=ld_le16((unsigned short *)(p+1))+3; | ||
966 | else | ||
967 | size=tag_small_count(*p)+1; | ||
968 | } | ||
969 | return NULL; /* not found */ | ||
970 | } | ||
971 | |||
972 | PnP_TAG_PACKET __init *PnP_find_small_vendor_packet(unsigned char *p, | ||
973 | unsigned packet_type, | ||
974 | int n) | ||
975 | { | ||
976 | int next=0; | ||
977 | while (p) { | ||
978 | p = (unsigned char *) PnP_find_packet(p, 0x70, next); | ||
979 | if (p && p[1]==packet_type && !(n--)) | ||
980 | return (PnP_TAG_PACKET *) p; | ||
981 | next = 1; | ||
982 | }; | ||
983 | return NULL; /* not found */ | ||
984 | } | ||
985 | |||
986 | PnP_TAG_PACKET __init *PnP_find_large_vendor_packet(unsigned char *p, | ||
987 | unsigned packet_type, | ||
988 | int n) | ||
989 | { | ||
990 | int next=0; | ||
991 | while (p) { | ||
992 | p = (unsigned char *) PnP_find_packet(p, 0x84, next); | ||
993 | if (p && p[3]==packet_type && !(n--)) | ||
994 | return (PnP_TAG_PACKET *) p; | ||
995 | next = 1; | ||
996 | }; | ||
997 | return NULL; /* not found */ | ||
998 | } | ||
999 | |||
1000 | #ifdef CONFIG_PROC_PREPRESIDUAL | ||
1001 | static int proc_prep_residual_read(char * buf, char ** start, off_t off, | ||
1002 | int count, int *eof, void *data) | ||
1003 | { | ||
1004 | int n; | ||
1005 | |||
1006 | n = res->ResidualLength - off; | ||
1007 | if (n < 0) { | ||
1008 | *eof = 1; | ||
1009 | n = 0; | ||
1010 | } | ||
1011 | else { | ||
1012 | if (n > count) | ||
1013 | n = count; | ||
1014 | else | ||
1015 | *eof = 1; | ||
1016 | |||
1017 | memcpy(buf, (char *)res + off, n); | ||
1018 | *start = buf; | ||
1019 | } | ||
1020 | |||
1021 | return n; | ||
1022 | } | ||
1023 | |||
1024 | int __init | ||
1025 | proc_prep_residual_init(void) | ||
1026 | { | ||
1027 | if (have_residual_data) | ||
1028 | create_proc_read_entry("residual", S_IRUGO, NULL, | ||
1029 | proc_prep_residual_read, NULL); | ||
1030 | return 0; | ||
1031 | } | ||
1032 | |||
1033 | __initcall(proc_prep_residual_init); | ||
1034 | #endif | ||
diff --git a/arch/ppc/platforms/rpx8260.h b/arch/ppc/platforms/rpx8260.h new file mode 100644 index 000000000000..843494a50ef3 --- /dev/null +++ b/arch/ppc/platforms/rpx8260.h | |||
@@ -0,0 +1,81 @@ | |||
1 | /* | ||
2 | * A collection of structures, addresses, and values associated with | ||
3 | * the Embedded Planet RPX6 (or RPX Super) MPC8260 board. | ||
4 | * Copied from the RPX-Classic and SBS8260 stuff. | ||
5 | * | ||
6 | * Copyright (c) 2001 Dan Malek <dan@embeddededge.com> | ||
7 | */ | ||
8 | #ifdef __KERNEL__ | ||
9 | #ifndef __ASM_PLATFORMS_RPX8260_H__ | ||
10 | #define __ASM_PLATFORMS_RPX8260_H__ | ||
11 | |||
12 | /* A Board Information structure that is given to a program when | ||
13 | * prom starts it up. | ||
14 | */ | ||
15 | typedef struct bd_info { | ||
16 | unsigned int bi_memstart; /* Memory start address */ | ||
17 | unsigned int bi_memsize; /* Memory (end) size in bytes */ | ||
18 | unsigned int bi_nvsize; /* NVRAM size in bytes (can be 0) */ | ||
19 | unsigned int bi_intfreq; /* Internal Freq, in Hz */ | ||
20 | unsigned int bi_busfreq; /* Bus Freq, in MHz */ | ||
21 | unsigned int bi_cpmfreq; /* CPM Freq, in MHz */ | ||
22 | unsigned int bi_brgfreq; /* BRG Freq, in MHz */ | ||
23 | unsigned int bi_vco; /* VCO Out from PLL */ | ||
24 | unsigned int bi_baudrate; /* Default console baud rate */ | ||
25 | unsigned int bi_immr; /* IMMR when called from boot rom */ | ||
26 | unsigned char bi_enetaddr[6]; | ||
27 | } bd_t; | ||
28 | |||
29 | extern bd_t m8xx_board_info; | ||
30 | |||
31 | /* Memory map is configured by the PROM startup. | ||
32 | * We just map a few things we need. The CSR is actually 4 byte-wide | ||
33 | * registers that can be accessed as 8-, 16-, or 32-bit values. | ||
34 | */ | ||
35 | #define CPM_MAP_ADDR ((uint)0xf0000000) | ||
36 | #define RPX_CSR_ADDR ((uint)0xfa000000) | ||
37 | #define RPX_CSR_SIZE ((uint)(512 * 1024)) | ||
38 | #define RPX_NVRTC_ADDR ((uint)0xfa080000) | ||
39 | #define RPX_NVRTC_SIZE ((uint)(512 * 1024)) | ||
40 | |||
41 | /* The RPX6 has 16, byte wide control/status registers. | ||
42 | * Not all are used (yet). | ||
43 | */ | ||
44 | extern volatile u_char *rpx6_csr_addr; | ||
45 | |||
46 | /* Things of interest in the CSR. | ||
47 | */ | ||
48 | #define BCSR0_ID_MASK ((u_char)0xf0) /* Read only */ | ||
49 | #define BCSR0_SWITCH_MASK ((u_char)0x0f) /* Read only */ | ||
50 | #define BCSR1_XCVR_SMC1 ((u_char)0x80) | ||
51 | #define BCSR1_XCVR_SMC2 ((u_char)0x40) | ||
52 | #define BCSR2_FLASH_WENABLE ((u_char)0x20) | ||
53 | #define BCSR2_NVRAM_ENABLE ((u_char)0x10) | ||
54 | #define BCSR2_ALT_IRQ2 ((u_char)0x08) | ||
55 | #define BCSR2_ALT_IRQ3 ((u_char)0x04) | ||
56 | #define BCSR2_PRST ((u_char)0x02) /* Force reset */ | ||
57 | #define BCSR2_ENPRST ((u_char)0x01) /* Enable POR */ | ||
58 | #define BCSR3_MODCLK_MASK ((u_char)0xe0) | ||
59 | #define BCSR3_ENCLKHDR ((u_char)0x10) | ||
60 | #define BCSR3_LED5 ((u_char)0x04) /* 0 == on */ | ||
61 | #define BCSR3_LED6 ((u_char)0x02) /* 0 == on */ | ||
62 | #define BCSR3_LED7 ((u_char)0x01) /* 0 == on */ | ||
63 | #define BCSR4_EN_PHY ((u_char)0x80) /* Enable PHY */ | ||
64 | #define BCSR4_EN_MII ((u_char)0x40) /* Enable PHY */ | ||
65 | #define BCSR4_MII_READ ((u_char)0x04) | ||
66 | #define BCSR4_MII_MDC ((u_char)0x02) | ||
67 | #define BCSR4_MII_MDIO ((u_char)0x01) | ||
68 | #define BCSR13_FETH_IRQMASK ((u_char)0xf0) | ||
69 | #define BCSR15_FETH_IRQ ((u_char)0x20) | ||
70 | |||
71 | #define PHY_INTERRUPT SIU_INT_IRQ7 | ||
72 | |||
73 | /* For our show_cpuinfo hooks. */ | ||
74 | #define CPUINFO_VENDOR "Embedded Planet" | ||
75 | #define CPUINFO_MACHINE "EP8260 PowerPC" | ||
76 | |||
77 | /* Warm reset vector. */ | ||
78 | #define BOOTROM_RESTART_ADDR ((uint)0xfff00104) | ||
79 | |||
80 | #endif /* __ASM_PLATFORMS_RPX8260_H__ */ | ||
81 | #endif /* __KERNEL__ */ | ||
diff --git a/arch/ppc/platforms/rpxclassic.h b/arch/ppc/platforms/rpxclassic.h new file mode 100644 index 000000000000..6daa109491c4 --- /dev/null +++ b/arch/ppc/platforms/rpxclassic.h | |||
@@ -0,0 +1,119 @@ | |||
1 | /* | ||
2 | * A collection of structures, addresses, and values associated with | ||
3 | * the RPCG RPX-Classic board. Copied from the RPX-Lite stuff. | ||
4 | * | ||
5 | * Copyright (c) 1998 Dan Malek (dmalek@jlc.net) | ||
6 | */ | ||
7 | #ifdef __KERNEL__ | ||
8 | #ifndef __MACH_RPX_DEFS | ||
9 | #define __MACH_RPX_DEFS | ||
10 | |||
11 | #include <linux/config.h> | ||
12 | |||
13 | #ifndef __ASSEMBLY__ | ||
14 | /* A Board Information structure that is given to a program when | ||
15 | * prom starts it up. | ||
16 | */ | ||
17 | typedef struct bd_info { | ||
18 | unsigned int bi_memstart; /* Memory start address */ | ||
19 | unsigned int bi_memsize; /* Memory (end) size in bytes */ | ||
20 | unsigned int bi_intfreq; /* Internal Freq, in Hz */ | ||
21 | unsigned int bi_busfreq; /* Bus Freq, in Hz */ | ||
22 | unsigned char bi_enetaddr[6]; | ||
23 | unsigned int bi_baudrate; | ||
24 | } bd_t; | ||
25 | |||
26 | extern bd_t m8xx_board_info; | ||
27 | |||
28 | /* Memory map is configured by the PROM startup. | ||
29 | * We just map a few things we need. The CSR is actually 4 byte-wide | ||
30 | * registers that can be accessed as 8-, 16-, or 32-bit values. | ||
31 | */ | ||
32 | #define PCI_ISA_IO_ADDR ((unsigned)0x80000000) | ||
33 | #define PCI_ISA_IO_SIZE ((uint)(512 * 1024 * 1024)) | ||
34 | #define PCI_ISA_MEM_ADDR ((unsigned)0xc0000000) | ||
35 | #define PCI_ISA_MEM_SIZE ((uint)(512 * 1024 * 1024)) | ||
36 | #define RPX_CSR_ADDR ((uint)0xfa400000) | ||
37 | #define RPX_CSR_SIZE ((uint)(4 * 1024)) | ||
38 | #define IMAP_ADDR ((uint)0xfa200000) | ||
39 | #define IMAP_SIZE ((uint)(64 * 1024)) | ||
40 | #define PCI_CSR_ADDR ((uint)0x80000000) | ||
41 | #define PCI_CSR_SIZE ((uint)(64 * 1024)) | ||
42 | #define PCMCIA_MEM_ADDR ((uint)0xe0000000) | ||
43 | #define PCMCIA_MEM_SIZE ((uint)(64 * 1024)) | ||
44 | #define PCMCIA_IO_ADDR ((uint)0xe4000000) | ||
45 | #define PCMCIA_IO_SIZE ((uint)(4 * 1024)) | ||
46 | #define PCMCIA_ATTRB_ADDR ((uint)0xe8000000) | ||
47 | #define PCMCIA_ATTRB_SIZE ((uint)(4 * 1024)) | ||
48 | |||
49 | /* Things of interest in the CSR. | ||
50 | */ | ||
51 | #define BCSR0_ETHEN ((uint)0x80000000) | ||
52 | #define BCSR0_ETHLPBK ((uint)0x40000000) | ||
53 | #define BCSR0_COLTESTDIS ((uint)0x20000000) | ||
54 | #define BCSR0_FULLDPLXDIS ((uint)0x10000000) | ||
55 | #define BCSR0_ENFLSHSEL ((uint)0x04000000) | ||
56 | #define BCSR0_FLASH_SEL ((uint)0x02000000) | ||
57 | #define BCSR0_ENMONXCVR ((uint)0x01000000) | ||
58 | |||
59 | #define BCSR0_PCMCIAVOLT ((uint)0x000f0000) /* CLLF */ | ||
60 | #define BCSR0_PCMCIA3VOLT ((uint)0x000a0000) /* CLLF */ | ||
61 | #define BCSR0_PCMCIA5VOLT ((uint)0x00060000) /* CLLF */ | ||
62 | |||
63 | #define BCSR1_IPB5SEL ((uint)0x00100000) | ||
64 | #define BCSR1_PCVCTL4 ((uint)0x00080000) | ||
65 | #define BCSR1_PCVCTL5 ((uint)0x00040000) | ||
66 | #define BCSR1_PCVCTL6 ((uint)0x00020000) | ||
67 | #define BCSR1_PCVCTL7 ((uint)0x00010000) | ||
68 | |||
69 | #define BCSR2_EN232XCVR ((uint)0x00008000) | ||
70 | #define BCSR2_QSPACESEL ((uint)0x00004000) | ||
71 | #define BCSR2_FETHLEDMODE ((uint)0x00000800) /* CLLF */ | ||
72 | |||
73 | #if defined(CONFIG_HTDMSOUND) | ||
74 | #include <platforms/rpxhiox.h> | ||
75 | #endif | ||
76 | |||
77 | /* define IO_BASE for pcmcia, CLLF only */ | ||
78 | #if !defined(CONFIG_PCI) | ||
79 | #define _IO_BASE 0x80000000 | ||
80 | #define _IO_BASE_SIZE 0x1000 | ||
81 | |||
82 | /* for pcmcia sandisk */ | ||
83 | #ifdef CONFIG_IDE | ||
84 | # define MAX_HWIFS 1 | ||
85 | #endif | ||
86 | #endif | ||
87 | |||
88 | /* Interrupt level assignments. | ||
89 | */ | ||
90 | #define FEC_INTERRUPT SIU_LEVEL1 /* FEC interrupt */ | ||
91 | |||
92 | |||
93 | /* CPM Ethernet through SCCx. | ||
94 | * | ||
95 | * Bits in parallel I/O port registers that have to be set/cleared | ||
96 | * to configure the pins for SCC1 use. | ||
97 | */ | ||
98 | #define PA_ENET_RXD ((ushort)0x0001) | ||
99 | #define PA_ENET_TXD ((ushort)0x0002) | ||
100 | #define PA_ENET_TCLK ((ushort)0x0200) | ||
101 | #define PA_ENET_RCLK ((ushort)0x0800) | ||
102 | #define PB_ENET_TENA ((uint)0x00001000) | ||
103 | #define PC_ENET_CLSN ((ushort)0x0010) | ||
104 | #define PC_ENET_RENA ((ushort)0x0020) | ||
105 | |||
106 | /* Control bits in the SICR to route TCLK (CLK2) and RCLK (CLK4) to | ||
107 | * SCC1. Also, make sure GR1 (bit 24) and SC1 (bit 25) are zero. | ||
108 | */ | ||
109 | #define SICR_ENET_MASK ((uint)0x000000ff) | ||
110 | #define SICR_ENET_CLKRT ((uint)0x0000003d) | ||
111 | |||
112 | /* We don't use the 8259. | ||
113 | */ | ||
114 | |||
115 | #define NR_8259_INTS 0 | ||
116 | |||
117 | #endif /* !__ASSEMBLY__ */ | ||
118 | #endif /* __MACH_RPX_DEFS */ | ||
119 | #endif /* __KERNEL__ */ | ||
diff --git a/arch/ppc/platforms/rpxhiox.h b/arch/ppc/platforms/rpxhiox.h new file mode 100644 index 000000000000..c3fa5a653762 --- /dev/null +++ b/arch/ppc/platforms/rpxhiox.h | |||
@@ -0,0 +1,41 @@ | |||
1 | /* | ||
2 | * The Embedded Planet HIOX expansion card definitions. | ||
3 | * There were a few different versions of these cards, but only | ||
4 | * the one that escaped real production is defined here. | ||
5 | * | ||
6 | * Copyright (c) 2000 Dan Malek (dmalek@jlc.net) | ||
7 | */ | ||
8 | #ifndef __MACH_RPX_HIOX_DEFS | ||
9 | #define __MACH_RPX_HIOX_DEFS | ||
10 | |||
11 | #define HIOX_CSR_ADDR ((uint)0xfac00000) | ||
12 | #define HIOX_CSR_SIZE ((uint)(4 * 1024)) | ||
13 | #define HIOX_CSR0_ADDR HIOX_CSR_ADDR | ||
14 | #define HIOX_CSR4_ADDR ((uint)0xfac00004) | ||
15 | |||
16 | #define HIOX_CSR0_DEFAULT ((uint)0x380f3c00) | ||
17 | #define HIOX_CSR0_ENSCC2 ((uint)0x80000000) | ||
18 | #define HIOX_CSR0_ENSMC2 ((uint)0x04000000) | ||
19 | #define HIOX_CSR0_ENVDOCLK ((uint)0x02000000) | ||
20 | #define HIOX_CSR0_VDORST_HL ((uint)0x01000000) | ||
21 | #define HIOX_CSR0_RS232SEL ((uint)0x0000c000) | ||
22 | #define HIOX_CSR0_SCC3SEL ((uint)0x0000c000) | ||
23 | #define HIOX_CSR0_SMC1SEL ((uint)0x00008000) | ||
24 | #define HIOX_CSR0_SCC1SEL ((uint)0x00004000) | ||
25 | #define HIOX_CSR0_ENTOUCH ((uint)0x00000080) | ||
26 | #define HIOX_CSR0_PDOWN100 ((uint)0x00000060) | ||
27 | #define HIOX_CSR0_PDOWN10 ((uint)0x00000040) | ||
28 | #define HIOX_CSR0_PDOWN1 ((uint)0x00000020) | ||
29 | #define HIOX_CSR0_TSELSPI ((uint)0x00000010) | ||
30 | #define HIOX_CSR0_TIRQSTAT ((uint)0x00000008) | ||
31 | #define HIOX_CSR4_DEFAULT ((uint)0x00000000) | ||
32 | #define HIOX_CSR4_ENTIRQ2 ((uint)0x20000000) | ||
33 | #define HIOX_CSR4_ENTIRQ3 ((uint)0x10000000) | ||
34 | #define HIOX_CSR4_ENAUDIO ((uint)0x00000080) | ||
35 | #define HIOX_CSR4_RSTAUDIO ((uint)0x00000040) /* 0 == reset */ | ||
36 | #define HIOX_CSR4_AUDCLKHI ((uint)0x00000020) | ||
37 | #define HIOX_CSR4_AUDSPISEL ((uint)0x00000010) | ||
38 | #define HIOX_CSR4_AUDIRQSTAT ((uint)0x00000008) | ||
39 | #define HIOX_CSR4_AUDCLKSEL ((uint)0x00000007) | ||
40 | |||
41 | #endif | ||
diff --git a/arch/ppc/platforms/rpxlite.h b/arch/ppc/platforms/rpxlite.h new file mode 100644 index 000000000000..deee5bd36aa8 --- /dev/null +++ b/arch/ppc/platforms/rpxlite.h | |||
@@ -0,0 +1,96 @@ | |||
1 | /* | ||
2 | * A collection of structures, addresses, and values associated with | ||
3 | * the RPCG RPX-Lite board. Copied from the MBX stuff. | ||
4 | * | ||
5 | * Copyright (c) 1998 Dan Malek (dmalek@jlc.net) | ||
6 | */ | ||
7 | #ifdef __KERNEL__ | ||
8 | #ifndef __MACH_RPX_DEFS | ||
9 | #define __MACH_RPX_DEFS | ||
10 | |||
11 | #include <linux/config.h> | ||
12 | |||
13 | #ifndef __ASSEMBLY__ | ||
14 | /* A Board Information structure that is given to a program when | ||
15 | * prom starts it up. | ||
16 | */ | ||
17 | typedef struct bd_info { | ||
18 | unsigned int bi_memstart; /* Memory start address */ | ||
19 | unsigned int bi_memsize; /* Memory (end) size in bytes */ | ||
20 | unsigned int bi_intfreq; /* Internal Freq, in Hz */ | ||
21 | unsigned int bi_busfreq; /* Bus Freq, in Hz */ | ||
22 | unsigned char bi_enetaddr[6]; | ||
23 | unsigned int bi_baudrate; | ||
24 | } bd_t; | ||
25 | |||
26 | extern bd_t m8xx_board_info; | ||
27 | |||
28 | /* Memory map is configured by the PROM startup. | ||
29 | * We just map a few things we need. The CSR is actually 4 byte-wide | ||
30 | * registers that can be accessed as 8-, 16-, or 32-bit values. | ||
31 | */ | ||
32 | #define RPX_CSR_ADDR ((uint)0xfa400000) | ||
33 | #define RPX_CSR_SIZE ((uint)(4 * 1024)) | ||
34 | #define IMAP_ADDR ((uint)0xfa200000) | ||
35 | #define IMAP_SIZE ((uint)(64 * 1024)) | ||
36 | #define PCMCIA_MEM_ADDR ((uint)0x04000000) | ||
37 | #define PCMCIA_MEM_SIZE ((uint)(64 * 1024)) | ||
38 | #define PCMCIA_IO_ADDR ((uint)0x04400000) | ||
39 | #define PCMCIA_IO_SIZE ((uint)(4 * 1024)) | ||
40 | |||
41 | /* Things of interest in the CSR. | ||
42 | */ | ||
43 | #define BCSR0_ETHEN ((uint)0x80000000) | ||
44 | #define BCSR0_ETHLPBK ((uint)0x40000000) | ||
45 | #define BCSR0_COLTESTDIS ((uint)0x20000000) | ||
46 | #define BCSR0_FULLDPLXDIS ((uint)0x10000000) | ||
47 | #define BCSR0_LEDOFF ((uint)0x08000000) | ||
48 | #define BCSR0_USBDISABLE ((uint)0x04000000) | ||
49 | #define BCSR0_USBHISPEED ((uint)0x02000000) | ||
50 | #define BCSR0_USBPWREN ((uint)0x01000000) | ||
51 | #define BCSR0_PCMCIAVOLT ((uint)0x000f0000) | ||
52 | #define BCSR0_PCMCIA3VOLT ((uint)0x000a0000) | ||
53 | #define BCSR0_PCMCIA5VOLT ((uint)0x00060000) | ||
54 | |||
55 | #define BCSR1_IPB5SEL ((uint)0x00100000) | ||
56 | #define BCSR1_PCVCTL4 ((uint)0x00080000) | ||
57 | #define BCSR1_PCVCTL5 ((uint)0x00040000) | ||
58 | #define BCSR1_PCVCTL6 ((uint)0x00020000) | ||
59 | #define BCSR1_PCVCTL7 ((uint)0x00010000) | ||
60 | |||
61 | #if defined(CONFIG_HTDMSOUND) | ||
62 | #include <platforms/rpxhiox.h> | ||
63 | #endif | ||
64 | |||
65 | /* define IO_BASE for pcmcia */ | ||
66 | #define _IO_BASE 0x80000000 | ||
67 | #define _IO_BASE_SIZE 0x1000 | ||
68 | |||
69 | #ifdef CONFIG_IDE | ||
70 | # define MAX_HWIFS 1 | ||
71 | #endif | ||
72 | |||
73 | /* CPM Ethernet through SCCx. | ||
74 | * | ||
75 | * This ENET stuff is for the MPC850 with ethernet on SCC2. Some of | ||
76 | * this may be unique to the RPX-Lite configuration. | ||
77 | * Note TENA is on Port B. | ||
78 | */ | ||
79 | #define PA_ENET_RXD ((ushort)0x0004) | ||
80 | #define PA_ENET_TXD ((ushort)0x0008) | ||
81 | #define PA_ENET_TCLK ((ushort)0x0200) | ||
82 | #define PA_ENET_RCLK ((ushort)0x0800) | ||
83 | #define PB_ENET_TENA ((uint)0x00002000) | ||
84 | #define PC_ENET_CLSN ((ushort)0x0040) | ||
85 | #define PC_ENET_RENA ((ushort)0x0080) | ||
86 | |||
87 | #define SICR_ENET_MASK ((uint)0x0000ff00) | ||
88 | #define SICR_ENET_CLKRT ((uint)0x00003d00) | ||
89 | |||
90 | /* We don't use the 8259. | ||
91 | */ | ||
92 | #define NR_8259_INTS 0 | ||
93 | |||
94 | #endif /* !__ASSEMBLY__ */ | ||
95 | #endif /* __MACH_RPX_DEFS */ | ||
96 | #endif /* __KERNEL__ */ | ||
diff --git a/arch/ppc/platforms/sandpoint.c b/arch/ppc/platforms/sandpoint.c new file mode 100644 index 000000000000..531bfa0e4512 --- /dev/null +++ b/arch/ppc/platforms/sandpoint.c | |||
@@ -0,0 +1,742 @@ | |||
1 | /* | ||
2 | * arch/ppc/platforms/sandpoint_setup.c | ||
3 | * | ||
4 | * Board setup routines for the Motorola SPS Sandpoint Test Platform. | ||
5 | * | ||
6 | * Author: Mark A. Greer | ||
7 | * mgreer@mvista.com | ||
8 | * | ||
9 | * 2000-2003 (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 | /* | ||
16 | * This file adds support for the Motorola SPS Sandpoint Test Platform. | ||
17 | * These boards have a PPMC slot for the processor so any combination | ||
18 | * of cpu and host bridge can be attached. This port is for an 8240 PPMC | ||
19 | * module from Motorola SPS and other closely related cpu/host bridge | ||
20 | * combinations (e.g., 750/755/7400 with MPC107 host bridge). | ||
21 | * The sandpoint itself has a Windbond 83c553 (PCI-ISA bridge, 2 DMA ctlrs, 2 | ||
22 | * cascaded 8259 interrupt ctlrs, 8254 Timer/Counter, and an IDE ctlr), a | ||
23 | * National 87308 (RTC, 2 UARTs, Keyboard & mouse ctlrs, and a floppy ctlr), | ||
24 | * and 4 PCI slots (only 2 of which are usable; the other 2 are keyed for 3.3V | ||
25 | * but are really 5V). | ||
26 | * | ||
27 | * The firmware on the sandpoint is called DINK (not my acronym :). This port | ||
28 | * depends on DINK to do some basic initialization (e.g., initialize the memory | ||
29 | * ctlr) and to ensure that the processor is using MAP B (CHRP map). | ||
30 | * | ||
31 | * The switch settings for the Sandpoint board MUST be as follows: | ||
32 | * S3: down | ||
33 | * S4: up | ||
34 | * S5: up | ||
35 | * S6: down | ||
36 | * | ||
37 | * 'down' is in the direction from the PCI slots towards the PPMC slot; | ||
38 | * 'up' is in the direction from the PPMC slot towards the PCI slots. | ||
39 | * Be careful, the way the sandpoint board is installed in XT chasses will | ||
40 | * make the directions reversed. | ||
41 | * | ||
42 | * Since Motorola listened to our suggestions for improvement, we now have | ||
43 | * the Sandpoint X3 board. All of the PCI slots are available, it uses | ||
44 | * the serial interrupt interface (just a hardware thing we need to | ||
45 | * configure properly). | ||
46 | * | ||
47 | * Use the default X3 switch settings. The interrupts are then: | ||
48 | * EPIC Source | ||
49 | * 0 SIOINT (8259, active low) | ||
50 | * 1 PCI #1 | ||
51 | * 2 PCI #2 | ||
52 | * 3 PCI #3 | ||
53 | * 4 PCI #4 | ||
54 | * 7 Winbond INTC (IDE interrupt) | ||
55 | * 8 Winbond INTD (IDE interrupt) | ||
56 | * | ||
57 | * | ||
58 | * Motorola has finally released a version of DINK32 that correctly | ||
59 | * (seemingly) initalizes the memory controller correctly, regardless | ||
60 | * of the amount of memory in the system. Once a method of determining | ||
61 | * what version of DINK initializes the system for us, if applicable, is | ||
62 | * found, we can hopefully stop hardcoding 32MB of RAM. | ||
63 | */ | ||
64 | |||
65 | #include <linux/config.h> | ||
66 | #include <linux/stddef.h> | ||
67 | #include <linux/kernel.h> | ||
68 | #include <linux/init.h> | ||
69 | #include <linux/errno.h> | ||
70 | #include <linux/reboot.h> | ||
71 | #include <linux/pci.h> | ||
72 | #include <linux/kdev_t.h> | ||
73 | #include <linux/major.h> | ||
74 | #include <linux/initrd.h> | ||
75 | #include <linux/console.h> | ||
76 | #include <linux/delay.h> | ||
77 | #include <linux/irq.h> | ||
78 | #include <linux/ide.h> | ||
79 | #include <linux/seq_file.h> | ||
80 | #include <linux/root_dev.h> | ||
81 | #include <linux/serial.h> | ||
82 | #include <linux/tty.h> /* for linux/serial_core.h */ | ||
83 | #include <linux/serial_core.h> | ||
84 | |||
85 | #include <asm/system.h> | ||
86 | #include <asm/pgtable.h> | ||
87 | #include <asm/page.h> | ||
88 | #include <asm/time.h> | ||
89 | #include <asm/dma.h> | ||
90 | #include <asm/io.h> | ||
91 | #include <asm/machdep.h> | ||
92 | #include <asm/prom.h> | ||
93 | #include <asm/smp.h> | ||
94 | #include <asm/vga.h> | ||
95 | #include <asm/open_pic.h> | ||
96 | #include <asm/i8259.h> | ||
97 | #include <asm/todc.h> | ||
98 | #include <asm/bootinfo.h> | ||
99 | #include <asm/mpc10x.h> | ||
100 | #include <asm/pci-bridge.h> | ||
101 | #include <asm/kgdb.h> | ||
102 | |||
103 | #include "sandpoint.h" | ||
104 | |||
105 | /* Set non-zero if an X2 Sandpoint detected. */ | ||
106 | static int sandpoint_is_x2; | ||
107 | |||
108 | unsigned char __res[sizeof(bd_t)]; | ||
109 | |||
110 | static void sandpoint_halt(void); | ||
111 | static void sandpoint_probe_type(void); | ||
112 | |||
113 | /* | ||
114 | * Define all of the IRQ senses and polarities. Taken from the | ||
115 | * Sandpoint X3 User's manual. | ||
116 | */ | ||
117 | static u_char sandpoint_openpic_initsenses[] __initdata = { | ||
118 | (IRQ_SENSE_LEVEL | IRQ_POLARITY_NEGATIVE), /* 0: SIOINT */ | ||
119 | (IRQ_SENSE_LEVEL | IRQ_POLARITY_NEGATIVE), /* 2: PCI Slot 1 */ | ||
120 | (IRQ_SENSE_LEVEL | IRQ_POLARITY_NEGATIVE), /* 3: PCI Slot 2 */ | ||
121 | (IRQ_SENSE_LEVEL | IRQ_POLARITY_NEGATIVE), /* 4: PCI Slot 3 */ | ||
122 | (IRQ_SENSE_LEVEL | IRQ_POLARITY_NEGATIVE), /* 5: PCI Slot 4 */ | ||
123 | (IRQ_SENSE_LEVEL | IRQ_POLARITY_NEGATIVE), /* 8: IDE (INT C) */ | ||
124 | (IRQ_SENSE_LEVEL | IRQ_POLARITY_NEGATIVE) /* 9: IDE (INT D) */ | ||
125 | }; | ||
126 | |||
127 | /* | ||
128 | * Motorola SPS Sandpoint interrupt routing. | ||
129 | */ | ||
130 | static inline int | ||
131 | x3_map_irq(struct pci_dev *dev, unsigned char idsel, unsigned char pin) | ||
132 | { | ||
133 | static char pci_irq_table[][4] = | ||
134 | /* | ||
135 | * PCI IDSEL/INTPIN->INTLINE | ||
136 | * A B C D | ||
137 | */ | ||
138 | { | ||
139 | { 16, 0, 0, 0 }, /* IDSEL 11 - i8259 on Winbond */ | ||
140 | { 0, 0, 0, 0 }, /* IDSEL 12 - unused */ | ||
141 | { 18, 21, 20, 19 }, /* IDSEL 13 - PCI slot 1 */ | ||
142 | { 19, 18, 21, 20 }, /* IDSEL 14 - PCI slot 2 */ | ||
143 | { 20, 19, 18, 21 }, /* IDSEL 15 - PCI slot 3 */ | ||
144 | { 21, 20, 19, 18 }, /* IDSEL 16 - PCI slot 4 */ | ||
145 | }; | ||
146 | |||
147 | const long min_idsel = 11, max_idsel = 16, irqs_per_slot = 4; | ||
148 | return PCI_IRQ_TABLE_LOOKUP; | ||
149 | } | ||
150 | |||
151 | static inline int | ||
152 | x2_map_irq(struct pci_dev *dev, unsigned char idsel, unsigned char pin) | ||
153 | { | ||
154 | static char pci_irq_table[][4] = | ||
155 | /* | ||
156 | * PCI IDSEL/INTPIN->INTLINE | ||
157 | * A B C D | ||
158 | */ | ||
159 | { | ||
160 | { 18, 0, 0, 0 }, /* IDSEL 11 - i8259 on Windbond */ | ||
161 | { 0, 0, 0, 0 }, /* IDSEL 12 - unused */ | ||
162 | { 16, 17, 18, 19 }, /* IDSEL 13 - PCI slot 1 */ | ||
163 | { 17, 18, 19, 16 }, /* IDSEL 14 - PCI slot 2 */ | ||
164 | { 18, 19, 16, 17 }, /* IDSEL 15 - PCI slot 3 */ | ||
165 | { 19, 16, 17, 18 }, /* IDSEL 16 - PCI slot 4 */ | ||
166 | }; | ||
167 | |||
168 | const long min_idsel = 11, max_idsel = 16, irqs_per_slot = 4; | ||
169 | return PCI_IRQ_TABLE_LOOKUP; | ||
170 | } | ||
171 | |||
172 | static void __init | ||
173 | sandpoint_setup_winbond_83553(struct pci_controller *hose) | ||
174 | { | ||
175 | int devfn; | ||
176 | |||
177 | /* | ||
178 | * Route IDE interrupts directly to the 8259's IRQ 14 & 15. | ||
179 | * We can't route the IDE interrupt to PCI INTC# or INTD# because those | ||
180 | * woule interfere with the PMC's INTC# and INTD# lines. | ||
181 | */ | ||
182 | /* | ||
183 | * Winbond Fcn 0 | ||
184 | */ | ||
185 | devfn = PCI_DEVFN(11,0); | ||
186 | |||
187 | early_write_config_byte(hose, | ||
188 | 0, | ||
189 | devfn, | ||
190 | 0x43, /* IDE Interrupt Routing Control */ | ||
191 | 0xef); | ||
192 | early_write_config_word(hose, | ||
193 | 0, | ||
194 | devfn, | ||
195 | 0x44, /* PCI Interrupt Routing Control */ | ||
196 | 0x0000); | ||
197 | |||
198 | /* Want ISA memory cycles to be forwarded to PCI bus */ | ||
199 | early_write_config_byte(hose, | ||
200 | 0, | ||
201 | devfn, | ||
202 | 0x48, /* ISA-to-PCI Addr Decoder Control */ | ||
203 | 0xf0); | ||
204 | |||
205 | /* Enable Port 92. */ | ||
206 | early_write_config_byte(hose, | ||
207 | 0, | ||
208 | devfn, | ||
209 | 0x4e, /* AT System Control Register */ | ||
210 | 0x06); | ||
211 | /* | ||
212 | * Winbond Fcn 1 | ||
213 | */ | ||
214 | devfn = PCI_DEVFN(11,1); | ||
215 | |||
216 | /* Put IDE controller into native mode. */ | ||
217 | early_write_config_byte(hose, | ||
218 | 0, | ||
219 | devfn, | ||
220 | 0x09, /* Programming interface Register */ | ||
221 | 0x8f); | ||
222 | |||
223 | /* Init IRQ routing, enable both ports, disable fast 16 */ | ||
224 | early_write_config_dword(hose, | ||
225 | 0, | ||
226 | devfn, | ||
227 | 0x40, /* IDE Control/Status Register */ | ||
228 | 0x00ff0011); | ||
229 | return; | ||
230 | } | ||
231 | |||
232 | /* On the sandpoint X2, we must avoid sending configuration cycles to | ||
233 | * device #12 (IDSEL addr = AD12). | ||
234 | */ | ||
235 | static int | ||
236 | x2_exclude_device(u_char bus, u_char devfn) | ||
237 | { | ||
238 | if ((bus == 0) && (PCI_SLOT(devfn) == SANDPOINT_HOST_BRIDGE_IDSEL)) | ||
239 | return PCIBIOS_DEVICE_NOT_FOUND; | ||
240 | else | ||
241 | return PCIBIOS_SUCCESSFUL; | ||
242 | } | ||
243 | |||
244 | static void __init | ||
245 | sandpoint_find_bridges(void) | ||
246 | { | ||
247 | struct pci_controller *hose; | ||
248 | |||
249 | hose = pcibios_alloc_controller(); | ||
250 | |||
251 | if (!hose) | ||
252 | return; | ||
253 | |||
254 | hose->first_busno = 0; | ||
255 | hose->last_busno = 0xff; | ||
256 | |||
257 | if (mpc10x_bridge_init(hose, | ||
258 | MPC10X_MEM_MAP_B, | ||
259 | MPC10X_MEM_MAP_B, | ||
260 | MPC10X_MAPB_EUMB_BASE) == 0) { | ||
261 | |||
262 | /* Do early winbond init, then scan PCI bus */ | ||
263 | sandpoint_setup_winbond_83553(hose); | ||
264 | hose->last_busno = pciauto_bus_scan(hose, hose->first_busno); | ||
265 | |||
266 | ppc_md.pcibios_fixup = NULL; | ||
267 | ppc_md.pcibios_fixup_bus = NULL; | ||
268 | ppc_md.pci_swizzle = common_swizzle; | ||
269 | if (sandpoint_is_x2) { | ||
270 | ppc_md.pci_map_irq = x2_map_irq; | ||
271 | ppc_md.pci_exclude_device = x2_exclude_device; | ||
272 | } else | ||
273 | ppc_md.pci_map_irq = x3_map_irq; | ||
274 | } | ||
275 | else { | ||
276 | if (ppc_md.progress) | ||
277 | ppc_md.progress("Bridge init failed", 0x100); | ||
278 | printk("Host bridge init failed\n"); | ||
279 | } | ||
280 | |||
281 | return; | ||
282 | } | ||
283 | |||
284 | static void __init | ||
285 | sandpoint_setup_arch(void) | ||
286 | { | ||
287 | /* Probe for Sandpoint model */ | ||
288 | sandpoint_probe_type(); | ||
289 | if (sandpoint_is_x2) | ||
290 | epic_serial_mode = 0; | ||
291 | |||
292 | loops_per_jiffy = 100000000 / HZ; | ||
293 | |||
294 | #ifdef CONFIG_BLK_DEV_INITRD | ||
295 | if (initrd_start) | ||
296 | ROOT_DEV = Root_RAM0; | ||
297 | else | ||
298 | #endif | ||
299 | #ifdef CONFIG_ROOT_NFS | ||
300 | ROOT_DEV = Root_NFS; | ||
301 | #else | ||
302 | ROOT_DEV = Root_HDA1; | ||
303 | #endif | ||
304 | |||
305 | /* Lookup PCI host bridges */ | ||
306 | sandpoint_find_bridges(); | ||
307 | |||
308 | printk(KERN_INFO "Motorola SPS Sandpoint Test Platform\n"); | ||
309 | printk(KERN_INFO "Port by MontaVista Software, Inc. (source@mvista.com)\n"); | ||
310 | |||
311 | /* DINK32 12.3 and below do not correctly enable any caches. | ||
312 | * We will do this now with good known values. Future versions | ||
313 | * of DINK32 are supposed to get this correct. | ||
314 | */ | ||
315 | if (cpu_has_feature(CPU_FTR_SPEC7450)) | ||
316 | /* 745x is different. We only want to pass along enable. */ | ||
317 | _set_L2CR(L2CR_L2E); | ||
318 | else if (cpu_has_feature(CPU_FTR_L2CR)) | ||
319 | /* All modules have 1MB of L2. We also assume that an | ||
320 | * L2 divisor of 3 will work. | ||
321 | */ | ||
322 | _set_L2CR(L2CR_L2E | L2CR_L2SIZ_1MB | L2CR_L2CLK_DIV3 | ||
323 | | L2CR_L2RAM_PIPE | L2CR_L2OH_1_0 | L2CR_L2DF); | ||
324 | #if 0 | ||
325 | /* Untested right now. */ | ||
326 | if (cpu_has_feature(CPU_FTR_L3CR)) { | ||
327 | /* Magic value. */ | ||
328 | _set_L3CR(0x8f032000); | ||
329 | } | ||
330 | #endif | ||
331 | } | ||
332 | |||
333 | #define SANDPOINT_87308_CFG_ADDR 0x15c | ||
334 | #define SANDPOINT_87308_CFG_DATA 0x15d | ||
335 | |||
336 | #define SANDPOINT_87308_CFG_INB(addr, byte) { \ | ||
337 | outb((addr), SANDPOINT_87308_CFG_ADDR); \ | ||
338 | (byte) = inb(SANDPOINT_87308_CFG_DATA); \ | ||
339 | } | ||
340 | |||
341 | #define SANDPOINT_87308_CFG_OUTB(addr, byte) { \ | ||
342 | outb((addr), SANDPOINT_87308_CFG_ADDR); \ | ||
343 | outb((byte), SANDPOINT_87308_CFG_DATA); \ | ||
344 | } | ||
345 | |||
346 | #define SANDPOINT_87308_SELECT_DEV(dev_num) { \ | ||
347 | SANDPOINT_87308_CFG_OUTB(0x07, (dev_num)); \ | ||
348 | } | ||
349 | |||
350 | #define SANDPOINT_87308_DEV_ENABLE(dev_num) { \ | ||
351 | SANDPOINT_87308_SELECT_DEV(dev_num); \ | ||
352 | SANDPOINT_87308_CFG_OUTB(0x30, 0x01); \ | ||
353 | } | ||
354 | |||
355 | /* | ||
356 | * To probe the Sandpoint type, we need to check for a connection between GPIO | ||
357 | * pins 6 and 7 on the NS87308 SuperIO. | ||
358 | */ | ||
359 | static void __init sandpoint_probe_type(void) | ||
360 | { | ||
361 | u8 x; | ||
362 | /* First, ensure that the GPIO pins are enabled. */ | ||
363 | SANDPOINT_87308_SELECT_DEV(0x07); /* Select GPIO logical device */ | ||
364 | SANDPOINT_87308_CFG_OUTB(0x60, 0x07); /* Base address 0x700 */ | ||
365 | SANDPOINT_87308_CFG_OUTB(0x61, 0x00); | ||
366 | SANDPOINT_87308_CFG_OUTB(0x30, 0x01); /* Enable */ | ||
367 | |||
368 | /* Now, set pin 7 to output and pin 6 to input. */ | ||
369 | outb((inb(0x701) | 0x80) & 0xbf, 0x701); | ||
370 | /* Set push-pull output */ | ||
371 | outb(inb(0x702) | 0x80, 0x702); | ||
372 | /* Set pull-up on input */ | ||
373 | outb(inb(0x703) | 0x40, 0x703); | ||
374 | /* Set output high and check */ | ||
375 | x = inb(0x700); | ||
376 | outb(x | 0x80, 0x700); | ||
377 | x = inb(0x700); | ||
378 | sandpoint_is_x2 = ! (x & 0x40); | ||
379 | if (ppc_md.progress && sandpoint_is_x2) | ||
380 | ppc_md.progress("High output says X2", 0); | ||
381 | /* Set output low and check */ | ||
382 | outb(x & 0x7f, 0x700); | ||
383 | sandpoint_is_x2 |= inb(0x700) & 0x40; | ||
384 | if (ppc_md.progress && sandpoint_is_x2) | ||
385 | ppc_md.progress("Low output says X2", 0); | ||
386 | if (ppc_md.progress && ! sandpoint_is_x2) | ||
387 | ppc_md.progress("Sandpoint is X3", 0); | ||
388 | } | ||
389 | |||
390 | /* | ||
391 | * Fix IDE interrupts. | ||
392 | */ | ||
393 | static int __init | ||
394 | sandpoint_fix_winbond_83553(void) | ||
395 | { | ||
396 | /* Make some 8259 interrupt level sensitive */ | ||
397 | outb(0xe0, 0x4d0); | ||
398 | outb(0xde, 0x4d1); | ||
399 | |||
400 | return 0; | ||
401 | } | ||
402 | |||
403 | arch_initcall(sandpoint_fix_winbond_83553); | ||
404 | |||
405 | /* | ||
406 | * Initialize the ISA devices on the Nat'l PC87308VUL SuperIO chip. | ||
407 | */ | ||
408 | static int __init | ||
409 | sandpoint_setup_natl_87308(void) | ||
410 | { | ||
411 | u_char reg; | ||
412 | |||
413 | /* | ||
414 | * Enable all the devices on the Super I/O chip. | ||
415 | */ | ||
416 | SANDPOINT_87308_SELECT_DEV(0x00); /* Select kbd logical device */ | ||
417 | SANDPOINT_87308_CFG_OUTB(0xf0, 0x00); /* Set KBC clock to 8 Mhz */ | ||
418 | SANDPOINT_87308_DEV_ENABLE(0x00); /* Enable keyboard */ | ||
419 | SANDPOINT_87308_DEV_ENABLE(0x01); /* Enable mouse */ | ||
420 | SANDPOINT_87308_DEV_ENABLE(0x02); /* Enable rtc */ | ||
421 | SANDPOINT_87308_DEV_ENABLE(0x03); /* Enable fdc (floppy) */ | ||
422 | SANDPOINT_87308_DEV_ENABLE(0x04); /* Enable parallel */ | ||
423 | SANDPOINT_87308_DEV_ENABLE(0x05); /* Enable UART 2 */ | ||
424 | SANDPOINT_87308_CFG_OUTB(0xf0, 0x82); /* Enable bank select regs */ | ||
425 | SANDPOINT_87308_DEV_ENABLE(0x06); /* Enable UART 1 */ | ||
426 | SANDPOINT_87308_CFG_OUTB(0xf0, 0x82); /* Enable bank select regs */ | ||
427 | |||
428 | /* Set up floppy in PS/2 mode */ | ||
429 | outb(0x09, SIO_CONFIG_RA); | ||
430 | reg = inb(SIO_CONFIG_RD); | ||
431 | reg = (reg & 0x3F) | 0x40; | ||
432 | outb(reg, SIO_CONFIG_RD); | ||
433 | outb(reg, SIO_CONFIG_RD); /* Have to write twice to change! */ | ||
434 | |||
435 | return 0; | ||
436 | } | ||
437 | |||
438 | arch_initcall(sandpoint_setup_natl_87308); | ||
439 | |||
440 | static int __init | ||
441 | sandpoint_request_io(void) | ||
442 | { | ||
443 | request_region(0x00,0x20,"dma1"); | ||
444 | request_region(0x20,0x20,"pic1"); | ||
445 | request_region(0x40,0x20,"timer"); | ||
446 | request_region(0x80,0x10,"dma page reg"); | ||
447 | request_region(0xa0,0x20,"pic2"); | ||
448 | request_region(0xc0,0x20,"dma2"); | ||
449 | |||
450 | return 0; | ||
451 | } | ||
452 | |||
453 | arch_initcall(sandpoint_request_io); | ||
454 | |||
455 | /* | ||
456 | * Interrupt setup and service. Interrrupts on the Sandpoint come | ||
457 | * from the four PCI slots plus the 8259 in the Winbond Super I/O (SIO). | ||
458 | * The 8259 is cascaded from EPIC IRQ0, IRQ1-4 map to PCI slots 1-4, | ||
459 | * IDE is on EPIC 7 and 8. | ||
460 | */ | ||
461 | static void __init | ||
462 | sandpoint_init_IRQ(void) | ||
463 | { | ||
464 | int i; | ||
465 | |||
466 | OpenPIC_InitSenses = sandpoint_openpic_initsenses; | ||
467 | OpenPIC_NumInitSenses = sizeof(sandpoint_openpic_initsenses); | ||
468 | |||
469 | mpc10x_set_openpic(); | ||
470 | openpic_hookup_cascade(sandpoint_is_x2 ? 17 : NUM_8259_INTERRUPTS, "82c59 cascade", | ||
471 | i8259_irq); | ||
472 | |||
473 | /* | ||
474 | * openpic_init() has set up irq_desc[16-31] to be openpic | ||
475 | * interrupts. We need to set irq_desc[0-15] to be i8259 | ||
476 | * interrupts. | ||
477 | */ | ||
478 | for(i=0; i < NUM_8259_INTERRUPTS; i++) | ||
479 | irq_desc[i].handler = &i8259_pic; | ||
480 | |||
481 | /* | ||
482 | * The EPIC allows for a read in the range of 0xFEF00000 -> | ||
483 | * 0xFEFFFFFF to generate a PCI interrupt-acknowledge transaction. | ||
484 | */ | ||
485 | i8259_init(0xfef00000); | ||
486 | } | ||
487 | |||
488 | static u32 | ||
489 | sandpoint_irq_canonicalize(u32 irq) | ||
490 | { | ||
491 | if (irq == 2) | ||
492 | return 9; | ||
493 | else | ||
494 | return irq; | ||
495 | } | ||
496 | |||
497 | static unsigned long __init | ||
498 | sandpoint_find_end_of_memory(void) | ||
499 | { | ||
500 | bd_t *bp = (bd_t *)__res; | ||
501 | |||
502 | if (bp->bi_memsize) | ||
503 | return bp->bi_memsize; | ||
504 | |||
505 | /* DINK32 13.0 correctly initalizes things, so iff you use | ||
506 | * this you _should_ be able to change this instead of a | ||
507 | * hardcoded value. */ | ||
508 | #if 0 | ||
509 | return mpc10x_get_mem_size(MPC10X_MEM_MAP_B); | ||
510 | #else | ||
511 | return 32*1024*1024; | ||
512 | #endif | ||
513 | } | ||
514 | |||
515 | static void __init | ||
516 | sandpoint_map_io(void) | ||
517 | { | ||
518 | io_block_mapping(0xfe000000, 0xfe000000, 0x02000000, _PAGE_IO); | ||
519 | } | ||
520 | |||
521 | static void | ||
522 | sandpoint_restart(char *cmd) | ||
523 | { | ||
524 | local_irq_disable(); | ||
525 | |||
526 | /* Set exception prefix high - to the firmware */ | ||
527 | _nmask_and_or_msr(0, MSR_IP); | ||
528 | |||
529 | /* Reset system via Port 92 */ | ||
530 | outb(0x00, 0x92); | ||
531 | outb(0x01, 0x92); | ||
532 | for(;;); /* Spin until reset happens */ | ||
533 | } | ||
534 | |||
535 | static void | ||
536 | sandpoint_power_off(void) | ||
537 | { | ||
538 | local_irq_disable(); | ||
539 | for(;;); /* No way to shut power off with software */ | ||
540 | /* NOTREACHED */ | ||
541 | } | ||
542 | |||
543 | static void | ||
544 | sandpoint_halt(void) | ||
545 | { | ||
546 | sandpoint_power_off(); | ||
547 | /* NOTREACHED */ | ||
548 | } | ||
549 | |||
550 | static int | ||
551 | sandpoint_show_cpuinfo(struct seq_file *m) | ||
552 | { | ||
553 | seq_printf(m, "vendor\t\t: Motorola SPS\n"); | ||
554 | seq_printf(m, "machine\t\t: Sandpoint\n"); | ||
555 | |||
556 | return 0; | ||
557 | } | ||
558 | |||
559 | #if defined(CONFIG_BLK_DEV_IDE) || defined(CONFIG_BLK_DEV_IDE_MODULE) | ||
560 | /* | ||
561 | * IDE support. | ||
562 | */ | ||
563 | static int sandpoint_ide_ports_known = 0; | ||
564 | static unsigned long sandpoint_ide_regbase[MAX_HWIFS]; | ||
565 | static unsigned long sandpoint_ide_ctl_regbase[MAX_HWIFS]; | ||
566 | static unsigned long sandpoint_idedma_regbase; | ||
567 | |||
568 | static void | ||
569 | sandpoint_ide_probe(void) | ||
570 | { | ||
571 | struct pci_dev *pdev = pci_get_device(PCI_VENDOR_ID_WINBOND, | ||
572 | PCI_DEVICE_ID_WINBOND_82C105, NULL); | ||
573 | |||
574 | if (pdev) { | ||
575 | sandpoint_ide_regbase[0]=pdev->resource[0].start; | ||
576 | sandpoint_ide_regbase[1]=pdev->resource[2].start; | ||
577 | sandpoint_ide_ctl_regbase[0]=pdev->resource[1].start; | ||
578 | sandpoint_ide_ctl_regbase[1]=pdev->resource[3].start; | ||
579 | sandpoint_idedma_regbase=pdev->resource[4].start; | ||
580 | pci_dev_put(pdev); | ||
581 | } | ||
582 | |||
583 | sandpoint_ide_ports_known = 1; | ||
584 | } | ||
585 | |||
586 | static int | ||
587 | sandpoint_ide_default_irq(unsigned long base) | ||
588 | { | ||
589 | if (sandpoint_ide_ports_known == 0) | ||
590 | sandpoint_ide_probe(); | ||
591 | |||
592 | if (base == sandpoint_ide_regbase[0]) | ||
593 | return SANDPOINT_IDE_INT0; | ||
594 | else if (base == sandpoint_ide_regbase[1]) | ||
595 | return SANDPOINT_IDE_INT1; | ||
596 | else | ||
597 | return 0; | ||
598 | } | ||
599 | |||
600 | static unsigned long | ||
601 | sandpoint_ide_default_io_base(int index) | ||
602 | { | ||
603 | if (sandpoint_ide_ports_known == 0) | ||
604 | sandpoint_ide_probe(); | ||
605 | |||
606 | return sandpoint_ide_regbase[index]; | ||
607 | } | ||
608 | |||
609 | static void __init | ||
610 | sandpoint_ide_init_hwif_ports(hw_regs_t *hw, unsigned long data_port, | ||
611 | unsigned long ctrl_port, int *irq) | ||
612 | { | ||
613 | unsigned long reg = data_port; | ||
614 | uint alt_status_base; | ||
615 | int i; | ||
616 | |||
617 | for (i = IDE_DATA_OFFSET; i <= IDE_STATUS_OFFSET; i++) { | ||
618 | hw->io_ports[i] = reg++; | ||
619 | } | ||
620 | |||
621 | if (data_port == sandpoint_ide_regbase[0]) { | ||
622 | alt_status_base = sandpoint_ide_ctl_regbase[0] + 2; | ||
623 | hw->irq = 14; | ||
624 | } | ||
625 | else if (data_port == sandpoint_ide_regbase[1]) { | ||
626 | alt_status_base = sandpoint_ide_ctl_regbase[1] + 2; | ||
627 | hw->irq = 15; | ||
628 | } | ||
629 | else { | ||
630 | alt_status_base = 0; | ||
631 | hw->irq = 0; | ||
632 | } | ||
633 | |||
634 | if (ctrl_port) { | ||
635 | hw->io_ports[IDE_CONTROL_OFFSET] = ctrl_port; | ||
636 | } else { | ||
637 | hw->io_ports[IDE_CONTROL_OFFSET] = alt_status_base; | ||
638 | } | ||
639 | |||
640 | if (irq != NULL) { | ||
641 | *irq = hw->irq; | ||
642 | } | ||
643 | } | ||
644 | #endif | ||
645 | |||
646 | /* | ||
647 | * Set BAT 3 to map 0xf8000000 to end of physical memory space 1-to-1. | ||
648 | */ | ||
649 | static __inline__ void | ||
650 | sandpoint_set_bat(void) | ||
651 | { | ||
652 | unsigned long bat3u, bat3l; | ||
653 | |||
654 | __asm__ __volatile__( | ||
655 | " lis %0,0xf800\n \ | ||
656 | ori %1,%0,0x002a\n \ | ||
657 | ori %0,%0,0x0ffe\n \ | ||
658 | mtspr 0x21e,%0\n \ | ||
659 | mtspr 0x21f,%1\n \ | ||
660 | isync\n \ | ||
661 | sync " | ||
662 | : "=r" (bat3u), "=r" (bat3l)); | ||
663 | } | ||
664 | |||
665 | TODC_ALLOC(); | ||
666 | |||
667 | void __init | ||
668 | platform_init(unsigned long r3, unsigned long r4, unsigned long r5, | ||
669 | unsigned long r6, unsigned long r7) | ||
670 | { | ||
671 | parse_bootinfo(find_bootinfo()); | ||
672 | |||
673 | /* ASSUMPTION: If both r3 (bd_t pointer) and r6 (cmdline pointer) | ||
674 | * are non-zero, then we should use the board info from the bd_t | ||
675 | * structure and the cmdline pointed to by r6 instead of the | ||
676 | * information from birecs, if any. Otherwise, use the information | ||
677 | * from birecs as discovered by the preceeding call to | ||
678 | * parse_bootinfo(). This rule should work with both PPCBoot, which | ||
679 | * uses a bd_t board info structure, and the kernel boot wrapper, | ||
680 | * which uses birecs. | ||
681 | */ | ||
682 | if (r3 && r6) { | ||
683 | /* copy board info structure */ | ||
684 | memcpy( (void *)__res,(void *)(r3+KERNELBASE), sizeof(bd_t) ); | ||
685 | /* copy command line */ | ||
686 | *(char *)(r7+KERNELBASE) = 0; | ||
687 | strcpy(cmd_line, (char *)(r6+KERNELBASE)); | ||
688 | } | ||
689 | |||
690 | #ifdef CONFIG_BLK_DEV_INITRD | ||
691 | /* take care of initrd if we have one */ | ||
692 | if (r4) { | ||
693 | initrd_start = r4 + KERNELBASE; | ||
694 | initrd_end = r5 + KERNELBASE; | ||
695 | } | ||
696 | #endif /* CONFIG_BLK_DEV_INITRD */ | ||
697 | |||
698 | /* Map in board regs, etc. */ | ||
699 | sandpoint_set_bat(); | ||
700 | |||
701 | isa_io_base = MPC10X_MAPB_ISA_IO_BASE; | ||
702 | isa_mem_base = MPC10X_MAPB_ISA_MEM_BASE; | ||
703 | pci_dram_offset = MPC10X_MAPB_DRAM_OFFSET; | ||
704 | ISA_DMA_THRESHOLD = 0x00ffffff; | ||
705 | DMA_MODE_READ = 0x44; | ||
706 | DMA_MODE_WRITE = 0x48; | ||
707 | |||
708 | ppc_md.setup_arch = sandpoint_setup_arch; | ||
709 | ppc_md.show_cpuinfo = sandpoint_show_cpuinfo; | ||
710 | ppc_md.irq_canonicalize = sandpoint_irq_canonicalize; | ||
711 | ppc_md.init_IRQ = sandpoint_init_IRQ; | ||
712 | ppc_md.get_irq = openpic_get_irq; | ||
713 | |||
714 | ppc_md.restart = sandpoint_restart; | ||
715 | ppc_md.power_off = sandpoint_power_off; | ||
716 | ppc_md.halt = sandpoint_halt; | ||
717 | |||
718 | ppc_md.find_end_of_memory = sandpoint_find_end_of_memory; | ||
719 | ppc_md.setup_io_mappings = sandpoint_map_io; | ||
720 | |||
721 | TODC_INIT(TODC_TYPE_PC97307, 0x70, 0x00, 0x71, 8); | ||
722 | ppc_md.time_init = todc_time_init; | ||
723 | ppc_md.set_rtc_time = todc_set_rtc_time; | ||
724 | ppc_md.get_rtc_time = todc_get_rtc_time; | ||
725 | ppc_md.calibrate_decr = todc_calibrate_decr; | ||
726 | |||
727 | ppc_md.nvram_read_val = todc_mc146818_read_val; | ||
728 | ppc_md.nvram_write_val = todc_mc146818_write_val; | ||
729 | |||
730 | #ifdef CONFIG_KGDB | ||
731 | ppc_md.kgdb_map_scc = gen550_kgdb_map_scc; | ||
732 | #endif | ||
733 | #ifdef CONFIG_SERIAL_TEXT_DEBUG | ||
734 | ppc_md.progress = gen550_progress; | ||
735 | #endif | ||
736 | |||
737 | #if defined(CONFIG_BLK_DEV_IDE) || defined(CONFIG_BLK_DEV_IDE_MODULE) | ||
738 | ppc_ide_md.default_irq = sandpoint_ide_default_irq; | ||
739 | ppc_ide_md.default_io_base = sandpoint_ide_default_io_base; | ||
740 | ppc_ide_md.ide_init_hwif = sandpoint_ide_init_hwif_ports; | ||
741 | #endif | ||
742 | } | ||
diff --git a/arch/ppc/platforms/sandpoint.h b/arch/ppc/platforms/sandpoint.h new file mode 100644 index 000000000000..f4e982cb69df --- /dev/null +++ b/arch/ppc/platforms/sandpoint.h | |||
@@ -0,0 +1,80 @@ | |||
1 | /* | ||
2 | * arch/ppc/platforms/sandpoint.h | ||
3 | * | ||
4 | * Definitions for Motorola SPS Sandpoint Test Platform | ||
5 | * | ||
6 | * Author: Mark A. Greer | ||
7 | * mgreer@mvista.com | ||
8 | * | ||
9 | * 2000-2003 (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 | /* | ||
16 | * Sandpoint uses the CHRP map (Map B). | ||
17 | */ | ||
18 | |||
19 | #ifndef __PPC_PLATFORMS_SANDPOINT_H | ||
20 | #define __PPC_PLATFORMS_SANDPOINT_H | ||
21 | |||
22 | #include <asm/ppcboot.h> | ||
23 | |||
24 | #if 0 | ||
25 | /* The Sandpoint X3 allows the IDE interrupt to be directly connected | ||
26 | * from the Windbond (PCI INTC or INTD) to the serial EPIC. Someday | ||
27 | * we should try this, but it was easier to use the existing 83c553 | ||
28 | * initialization than change it to route the different interrupts :-). | ||
29 | * -- Dan | ||
30 | */ | ||
31 | #define SANDPOINT_IDE_INT0 23 /* EPIC 7 */ | ||
32 | #define SANDPOINT_IDE_INT1 24 /* EPIC 8 */ | ||
33 | #else | ||
34 | #define SANDPOINT_IDE_INT0 14 /* 8259 Test */ | ||
35 | #define SANDPOINT_IDE_INT1 15 /* 8259 Test */ | ||
36 | #endif | ||
37 | |||
38 | /* | ||
39 | * The sandpoint boards have processor modules that either have an 8240 or | ||
40 | * an MPC107 host bridge on them. These bridges have an IDSEL line that allows | ||
41 | * them to respond to PCI transactions as if they were a normal PCI devices. | ||
42 | * However, the processor on the processor side of the bridge can not reach | ||
43 | * out onto the PCI bus and then select the bridge or bad things will happen | ||
44 | * (documented in the 8240 and 107 manuals). | ||
45 | * Because of this, we always skip the bridge PCI device when accessing the | ||
46 | * PCI bus. The PCI slot that the bridge occupies is defined by the macro | ||
47 | * below. | ||
48 | */ | ||
49 | #define SANDPOINT_HOST_BRIDGE_IDSEL 12 | ||
50 | |||
51 | /* | ||
52 | * Serial defines. | ||
53 | */ | ||
54 | #define SANDPOINT_SERIAL_0 0xfe0003f8 | ||
55 | #define SANDPOINT_SERIAL_1 0xfe0002f8 | ||
56 | |||
57 | #define RS_TABLE_SIZE 2 | ||
58 | |||
59 | /* Rate for the 1.8432 Mhz clock for the onboard serial chip */ | ||
60 | #define BASE_BAUD ( 1843200 / 16 ) | ||
61 | #define UART_CLK 1843200 | ||
62 | |||
63 | #ifdef CONFIG_SERIAL_DETECT_IRQ | ||
64 | #define STD_COM_FLAGS (ASYNC_BOOT_AUTOCONF|ASYNC_AUTO_IRQ) | ||
65 | #else | ||
66 | #define STD_COM_FLAGS (ASYNC_BOOT_AUTOCONF) | ||
67 | #endif | ||
68 | |||
69 | #define STD_SERIAL_PORT_DFNS \ | ||
70 | { 0, BASE_BAUD, SANDPOINT_SERIAL_0, 4, STD_COM_FLAGS, /* ttyS0 */ \ | ||
71 | iomem_base: (u8 *)SANDPOINT_SERIAL_0, \ | ||
72 | io_type: SERIAL_IO_MEM }, \ | ||
73 | { 0, BASE_BAUD, SANDPOINT_SERIAL_1, 3, STD_COM_FLAGS, /* ttyS1 */ \ | ||
74 | iomem_base: (u8 *)SANDPOINT_SERIAL_1, \ | ||
75 | io_type: SERIAL_IO_MEM }, | ||
76 | |||
77 | #define SERIAL_PORT_DFNS \ | ||
78 | STD_SERIAL_PORT_DFNS | ||
79 | |||
80 | #endif /* __PPC_PLATFORMS_SANDPOINT_H */ | ||
diff --git a/arch/ppc/platforms/sbc82xx.c b/arch/ppc/platforms/sbc82xx.c new file mode 100644 index 000000000000..74c9ff72c3dd --- /dev/null +++ b/arch/ppc/platforms/sbc82xx.c | |||
@@ -0,0 +1,259 @@ | |||
1 | /* | ||
2 | * arch/ppc/platforms/sbc82xx.c | ||
3 | * | ||
4 | * SBC82XX platform support | ||
5 | * | ||
6 | * Author: Guy Streeter <streeter@redhat.com> | ||
7 | * | ||
8 | * Derived from: est8260_setup.c by Allen Curtis, ONZ | ||
9 | * | ||
10 | * Copyright 2004 Red Hat, Inc. | ||
11 | * | ||
12 | * This program is free software; you can redistribute it and/or modify it | ||
13 | * under the terms of the GNU General Public License as published by the | ||
14 | * Free Software Foundation; either version 2 of the License, or (at your | ||
15 | * option) any later version. | ||
16 | */ | ||
17 | |||
18 | #include <linux/config.h> | ||
19 | #include <linux/stddef.h> | ||
20 | #include <linux/interrupt.h> | ||
21 | #include <linux/irq.h> | ||
22 | #include <linux/init.h> | ||
23 | #include <linux/pci.h> | ||
24 | |||
25 | #include <asm/mpc8260.h> | ||
26 | #include <asm/machdep.h> | ||
27 | #include <asm/io.h> | ||
28 | #include <asm/todc.h> | ||
29 | #include <asm/immap_cpm2.h> | ||
30 | #include <asm/pci.h> | ||
31 | |||
32 | static void (*callback_init_IRQ)(void); | ||
33 | |||
34 | extern unsigned char __res[sizeof(bd_t)]; | ||
35 | |||
36 | extern void (*late_time_init)(void); | ||
37 | |||
38 | #ifdef CONFIG_GEN_RTC | ||
39 | TODC_ALLOC(); | ||
40 | |||
41 | /* | ||
42 | * Timer init happens before mem_init but after paging init, so we cannot | ||
43 | * directly use ioremap() at that time. | ||
44 | * late_time_init() is call after paging init. | ||
45 | */ | ||
46 | |||
47 | static void sbc82xx_time_init(void) | ||
48 | { | ||
49 | volatile memctl_cpm2_t *mc = &cpm2_immr->im_memctl; | ||
50 | |||
51 | /* Set up CS11 for RTC chip */ | ||
52 | mc->memc_br11=0; | ||
53 | mc->memc_or11=0xffff0836; | ||
54 | mc->memc_br11=SBC82xx_TODC_NVRAM_ADDR | 0x0801; | ||
55 | |||
56 | TODC_INIT(TODC_TYPE_MK48T59, 0, 0, SBC82xx_TODC_NVRAM_ADDR, 0); | ||
57 | |||
58 | todc_info->nvram_data = | ||
59 | (unsigned int)ioremap(todc_info->nvram_data, 0x2000); | ||
60 | BUG_ON(!todc_info->nvram_data); | ||
61 | ppc_md.get_rtc_time = todc_get_rtc_time; | ||
62 | ppc_md.set_rtc_time = todc_set_rtc_time; | ||
63 | ppc_md.nvram_read_val = todc_direct_read_val; | ||
64 | ppc_md.nvram_write_val = todc_direct_write_val; | ||
65 | todc_time_init(); | ||
66 | } | ||
67 | #endif /* CONFIG_GEN_RTC */ | ||
68 | |||
69 | static volatile char *sbc82xx_i8259_map; | ||
70 | static char sbc82xx_i8259_mask = 0xff; | ||
71 | static DEFINE_SPINLOCK(sbc82xx_i8259_lock); | ||
72 | |||
73 | static void sbc82xx_i8259_mask_and_ack_irq(unsigned int irq_nr) | ||
74 | { | ||
75 | unsigned long flags; | ||
76 | |||
77 | irq_nr -= NR_SIU_INTS; | ||
78 | |||
79 | spin_lock_irqsave(&sbc82xx_i8259_lock, flags); | ||
80 | sbc82xx_i8259_mask |= 1 << irq_nr; | ||
81 | (void) sbc82xx_i8259_map[1]; /* Dummy read */ | ||
82 | sbc82xx_i8259_map[1] = sbc82xx_i8259_mask; | ||
83 | sbc82xx_i8259_map[0] = 0x20; /* OCW2: Non-specific EOI */ | ||
84 | spin_unlock_irqrestore(&sbc82xx_i8259_lock, flags); | ||
85 | } | ||
86 | |||
87 | static void sbc82xx_i8259_mask_irq(unsigned int irq_nr) | ||
88 | { | ||
89 | unsigned long flags; | ||
90 | |||
91 | irq_nr -= NR_SIU_INTS; | ||
92 | |||
93 | spin_lock_irqsave(&sbc82xx_i8259_lock, flags); | ||
94 | sbc82xx_i8259_mask |= 1 << irq_nr; | ||
95 | sbc82xx_i8259_map[1] = sbc82xx_i8259_mask; | ||
96 | spin_unlock_irqrestore(&sbc82xx_i8259_lock, flags); | ||
97 | } | ||
98 | |||
99 | static void sbc82xx_i8259_unmask_irq(unsigned int irq_nr) | ||
100 | { | ||
101 | unsigned long flags; | ||
102 | |||
103 | irq_nr -= NR_SIU_INTS; | ||
104 | |||
105 | spin_lock_irqsave(&sbc82xx_i8259_lock, flags); | ||
106 | sbc82xx_i8259_mask &= ~(1 << irq_nr); | ||
107 | sbc82xx_i8259_map[1] = sbc82xx_i8259_mask; | ||
108 | spin_unlock_irqrestore(&sbc82xx_i8259_lock, flags); | ||
109 | } | ||
110 | |||
111 | static void sbc82xx_i8259_end_irq(unsigned int irq) | ||
112 | { | ||
113 | if (!(irq_desc[irq].status & (IRQ_DISABLED|IRQ_INPROGRESS)) | ||
114 | && irq_desc[irq].action) | ||
115 | sbc82xx_i8259_unmask_irq(irq); | ||
116 | } | ||
117 | |||
118 | |||
119 | struct hw_interrupt_type sbc82xx_i8259_ic = { | ||
120 | .typename = " i8259 ", | ||
121 | .enable = sbc82xx_i8259_unmask_irq, | ||
122 | .disable = sbc82xx_i8259_mask_irq, | ||
123 | .ack = sbc82xx_i8259_mask_and_ack_irq, | ||
124 | .end = sbc82xx_i8259_end_irq, | ||
125 | }; | ||
126 | |||
127 | static irqreturn_t sbc82xx_i8259_demux(int irq, void *dev_id, struct pt_regs *regs) | ||
128 | { | ||
129 | spin_lock(&sbc82xx_i8259_lock); | ||
130 | |||
131 | sbc82xx_i8259_map[0] = 0x0c; /* OCW3: Read IR register on RD# pulse */ | ||
132 | irq = sbc82xx_i8259_map[0] & 7; /* Read IRR */ | ||
133 | |||
134 | if (irq == 7) { | ||
135 | /* Possible spurious interrupt */ | ||
136 | int isr; | ||
137 | sbc82xx_i8259_map[0] = 0x0b; /* OCW3: Read IS register on RD# pulse */ | ||
138 | isr = sbc82xx_i8259_map[0]; /* Read ISR */ | ||
139 | |||
140 | if (!(isr & 0x80)) { | ||
141 | printk(KERN_INFO "Spurious i8259 interrupt\n"); | ||
142 | return IRQ_HANDLED; | ||
143 | } | ||
144 | } | ||
145 | __do_IRQ(NR_SIU_INTS + irq, regs); | ||
146 | return IRQ_HANDLED; | ||
147 | } | ||
148 | |||
149 | static struct irqaction sbc82xx_i8259_irqaction = { | ||
150 | .handler = sbc82xx_i8259_demux, | ||
151 | .flags = SA_INTERRUPT, | ||
152 | .mask = CPU_MASK_NONE, | ||
153 | .name = "i8259 demux", | ||
154 | }; | ||
155 | |||
156 | void __init sbc82xx_init_IRQ(void) | ||
157 | { | ||
158 | volatile memctl_cpm2_t *mc = &cpm2_immr->im_memctl; | ||
159 | volatile intctl_cpm2_t *ic = &cpm2_immr->im_intctl; | ||
160 | int i; | ||
161 | |||
162 | callback_init_IRQ(); | ||
163 | |||
164 | /* u-boot doesn't always set the board up correctly */ | ||
165 | mc->memc_br5 = 0; | ||
166 | mc->memc_or5 = 0xfff00856; | ||
167 | mc->memc_br5 = 0x22000801; | ||
168 | |||
169 | sbc82xx_i8259_map = ioremap(0x22008000, 2); | ||
170 | if (!sbc82xx_i8259_map) { | ||
171 | printk(KERN_CRIT "Mapping i8259 interrupt controller failed\n"); | ||
172 | return; | ||
173 | } | ||
174 | |||
175 | /* Set up the interrupt handlers for the i8259 IRQs */ | ||
176 | for (i = NR_SIU_INTS; i < NR_SIU_INTS + 8; i++) { | ||
177 | irq_desc[i].handler = &sbc82xx_i8259_ic; | ||
178 | irq_desc[i].status |= IRQ_LEVEL; | ||
179 | } | ||
180 | |||
181 | /* make IRQ6 level sensitive */ | ||
182 | ic->ic_siexr &= ~(1 << (14 - (SIU_INT_IRQ6 - SIU_INT_IRQ1))); | ||
183 | irq_desc[SIU_INT_IRQ6].status |= IRQ_LEVEL; | ||
184 | |||
185 | /* Initialise the i8259 */ | ||
186 | sbc82xx_i8259_map[0] = 0x1b; /* ICW1: Level, no cascade, ICW4 */ | ||
187 | sbc82xx_i8259_map[1] = 0x00; /* ICW2: vector base */ | ||
188 | /* No ICW3 (no cascade) */ | ||
189 | sbc82xx_i8259_map[1] = 0x01; /* ICW4: 8086 mode, normal EOI */ | ||
190 | |||
191 | sbc82xx_i8259_map[0] = 0x0b; /* OCW3: Read IS register on RD# pulse */ | ||
192 | |||
193 | sbc82xx_i8259_map[1] = sbc82xx_i8259_mask; /* Set interrupt mask */ | ||
194 | |||
195 | /* Request cascade IRQ */ | ||
196 | if (setup_irq(SIU_INT_IRQ6, &sbc82xx_i8259_irqaction)) { | ||
197 | printk("Installation of i8259 IRQ demultiplexer failed.\n"); | ||
198 | } | ||
199 | } | ||
200 | |||
201 | static int sbc82xx_pci_map_irq(struct pci_dev *dev, unsigned char idsel, | ||
202 | unsigned char pin) | ||
203 | { | ||
204 | static char pci_irq_table[][4] = { | ||
205 | /* | ||
206 | * PCI IDSEL/INTPIN->INTLINE | ||
207 | * A B C D | ||
208 | */ | ||
209 | { SBC82xx_PIRQA, SBC82xx_PIRQB, SBC82xx_PIRQC, SBC82xx_PIRQD }, /* IDSEL 16 - PMC slot */ | ||
210 | { SBC82xx_PC_IRQA, SBC82xx_PC_IRQB, -1, -1 }, /* IDSEL 17 - CardBus */ | ||
211 | { SBC82xx_PIRQA, SBC82xx_PIRQB, SBC82xx_PIRQC, SBC82xx_PIRQD }, /* IDSEL 18 - PCI-X bridge */ | ||
212 | }; | ||
213 | |||
214 | const long min_idsel = 16, max_idsel = 18, irqs_per_slot = 4; | ||
215 | |||
216 | return PCI_IRQ_TABLE_LOOKUP; | ||
217 | } | ||
218 | |||
219 | static void __devinit quirk_sbc8260_cardbus(struct pci_dev *pdev) | ||
220 | { | ||
221 | uint32_t ctrl; | ||
222 | |||
223 | if (pdev->bus->number != 0 || pdev->devfn != PCI_DEVFN(17, 0)) | ||
224 | return; | ||
225 | |||
226 | printk(KERN_INFO "Setting up CardBus controller\n"); | ||
227 | |||
228 | /* Set P2CCLK bit in System Control Register */ | ||
229 | pci_read_config_dword(pdev, 0x80, &ctrl); | ||
230 | ctrl |= (1<<27); | ||
231 | pci_write_config_dword(pdev, 0x80, ctrl); | ||
232 | |||
233 | /* Set MFUNC up for PCI IRQ routing via INTA and INTB, and LEDs. */ | ||
234 | pci_write_config_dword(pdev, 0x8c, 0x00c01d22); | ||
235 | |||
236 | } | ||
237 | DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_TI, PCI_DEVICE_ID_TI_1420, quirk_sbc8260_cardbus); | ||
238 | |||
239 | void __init | ||
240 | m82xx_board_init(void) | ||
241 | { | ||
242 | /* u-boot may be using one of the FCC Ethernet devices. | ||
243 | Use the MAC address to the SCC. */ | ||
244 | __res[offsetof(bd_t, bi_enetaddr[5])] &= ~3; | ||
245 | |||
246 | /* Anything special for this platform */ | ||
247 | callback_init_IRQ = ppc_md.init_IRQ; | ||
248 | |||
249 | ppc_md.init_IRQ = sbc82xx_init_IRQ; | ||
250 | ppc_md.pci_map_irq = sbc82xx_pci_map_irq; | ||
251 | #ifdef CONFIG_GEN_RTC | ||
252 | ppc_md.time_init = NULL; | ||
253 | ppc_md.get_rtc_time = NULL; | ||
254 | ppc_md.set_rtc_time = NULL; | ||
255 | ppc_md.nvram_read_val = NULL; | ||
256 | ppc_md.nvram_write_val = NULL; | ||
257 | late_time_init = sbc82xx_time_init; | ||
258 | #endif /* CONFIG_GEN_RTC */ | ||
259 | } | ||
diff --git a/arch/ppc/platforms/sbc82xx.h b/arch/ppc/platforms/sbc82xx.h new file mode 100644 index 000000000000..e4042d4995f6 --- /dev/null +++ b/arch/ppc/platforms/sbc82xx.h | |||
@@ -0,0 +1,36 @@ | |||
1 | /* Board information for the SBCPowerQUICCII, which should be generic for | ||
2 | * all 8260 boards. The IMMR is now given to us so the hard define | ||
3 | * will soon be removed. All of the clock values are computed from | ||
4 | * the configuration SCMR and the Power-On-Reset word. | ||
5 | */ | ||
6 | |||
7 | #ifndef __PPC_SBC82xx_H__ | ||
8 | #define __PPC_SBC82xx_H__ | ||
9 | |||
10 | #include <asm/ppcboot.h> | ||
11 | |||
12 | #define CPM_MAP_ADDR 0xf0000000 | ||
13 | |||
14 | #define SBC82xx_TODC_NVRAM_ADDR 0xd0000000 | ||
15 | |||
16 | #define SBC82xx_MACADDR_NVRAM_FCC1 0x220000c9 /* JP6B */ | ||
17 | #define SBC82xx_MACADDR_NVRAM_SCC1 0x220000cf /* JP6A */ | ||
18 | #define SBC82xx_MACADDR_NVRAM_FCC2 0x220000d5 /* JP7A */ | ||
19 | #define SBC82xx_MACADDR_NVRAM_FCC3 0x220000db /* JP7B */ | ||
20 | |||
21 | /* For our show_cpuinfo hooks. */ | ||
22 | #define CPUINFO_VENDOR "Wind River" | ||
23 | #define CPUINFO_MACHINE "SBC PowerQUICC II" | ||
24 | |||
25 | #define BOOTROM_RESTART_ADDR ((uint)0x40000104) | ||
26 | |||
27 | #define SBC82xx_PC_IRQA (NR_SIU_INTS+0) | ||
28 | #define SBC82xx_PC_IRQB (NR_SIU_INTS+1) | ||
29 | #define SBC82xx_MPC185_IRQ (NR_SIU_INTS+2) | ||
30 | #define SBC82xx_ATM_IRQ (NR_SIU_INTS+3) | ||
31 | #define SBC82xx_PIRQA (NR_SIU_INTS+4) | ||
32 | #define SBC82xx_PIRQB (NR_SIU_INTS+5) | ||
33 | #define SBC82xx_PIRQC (NR_SIU_INTS+6) | ||
34 | #define SBC82xx_PIRQD (NR_SIU_INTS+7) | ||
35 | |||
36 | #endif /* __PPC_SBC82xx_H__ */ | ||
diff --git a/arch/ppc/platforms/sbs8260.h b/arch/ppc/platforms/sbs8260.h new file mode 100644 index 000000000000..d51427a0f0d4 --- /dev/null +++ b/arch/ppc/platforms/sbs8260.h | |||
@@ -0,0 +1,28 @@ | |||
1 | #ifndef __ASSEMBLY__ | ||
2 | /* Board information for various SBS 8260 cards, which should be generic for | ||
3 | * all 8260 boards. The IMMR is now given to us so the hard define | ||
4 | * will soon be removed. All of the clock values are computed from | ||
5 | * the configuration SCMR and the Power-On-Reset word. | ||
6 | */ | ||
7 | |||
8 | #define CPM_MAP_ADDR ((uint)0xfe000000) | ||
9 | |||
10 | |||
11 | /* A Board Information structure that is given to a program when | ||
12 | * prom starts it up. | ||
13 | */ | ||
14 | typedef struct bd_info { | ||
15 | unsigned int bi_memstart; /* Memory start address */ | ||
16 | unsigned int bi_memsize; /* Memory (end) size in bytes */ | ||
17 | unsigned int bi_intfreq; /* Internal Freq, in Hz */ | ||
18 | unsigned int bi_busfreq; /* Bus Freq, in MHz */ | ||
19 | unsigned int bi_cpmfreq; /* CPM Freq, in MHz */ | ||
20 | unsigned int bi_brgfreq; /* BRG Freq, in MHz */ | ||
21 | unsigned int bi_vco; /* VCO Out from PLL */ | ||
22 | unsigned int bi_baudrate; /* Default console baud rate */ | ||
23 | unsigned int bi_immr; /* IMMR when called from boot rom */ | ||
24 | unsigned char bi_enetaddr[6]; | ||
25 | } bd_t; | ||
26 | |||
27 | extern bd_t m8xx_board_info; | ||
28 | #endif /* !__ASSEMBLY__ */ | ||
diff --git a/arch/ppc/platforms/spd8xx.h b/arch/ppc/platforms/spd8xx.h new file mode 100644 index 000000000000..ed48d144f415 --- /dev/null +++ b/arch/ppc/platforms/spd8xx.h | |||
@@ -0,0 +1,92 @@ | |||
1 | /* | ||
2 | * Speech Design SPD8xxTS board specific definitions | ||
3 | * | ||
4 | * Copyright (c) 2000,2001 Wolfgang Denk (wd@denx.de) | ||
5 | */ | ||
6 | |||
7 | #ifdef __KERNEL__ | ||
8 | #ifndef __ASM_SPD8XX_H__ | ||
9 | #define __ASM_SPD8XX_H__ | ||
10 | |||
11 | #include <linux/config.h> | ||
12 | |||
13 | #include <asm/ppcboot.h> | ||
14 | |||
15 | #ifndef __ASSEMBLY__ | ||
16 | #define SPD_IMMR_BASE 0xFFF00000 /* phys. addr of IMMR */ | ||
17 | #define SPD_IMAP_SIZE (64 * 1024) /* size of mapped area */ | ||
18 | |||
19 | #define IMAP_ADDR SPD_IMMR_BASE /* physical base address of IMMR area */ | ||
20 | #define IMAP_SIZE SPD_IMAP_SIZE /* mapped size of IMMR area */ | ||
21 | |||
22 | #define PCMCIA_MEM_ADDR ((uint)0xFE100000) | ||
23 | #define PCMCIA_MEM_SIZE ((uint)(64 * 1024)) | ||
24 | |||
25 | #define IDE0_INTERRUPT 10 /* = IRQ5 */ | ||
26 | #define IDE1_INTERRUPT 12 /* = IRQ6 */ | ||
27 | #define CPM_INTERRUPT 13 /* = SIU_LEVEL6 (was: SIU_LEVEL2) */ | ||
28 | |||
29 | /* override the default number of IDE hardware interfaces */ | ||
30 | #define MAX_HWIFS 2 | ||
31 | |||
32 | /* | ||
33 | * Definitions for IDE0 Interface | ||
34 | */ | ||
35 | #define IDE0_BASE_OFFSET 0x0000 /* Offset in PCMCIA memory */ | ||
36 | #define IDE0_DATA_REG_OFFSET 0x0000 | ||
37 | #define IDE0_ERROR_REG_OFFSET 0x0081 | ||
38 | #define IDE0_NSECTOR_REG_OFFSET 0x0082 | ||
39 | #define IDE0_SECTOR_REG_OFFSET 0x0083 | ||
40 | #define IDE0_LCYL_REG_OFFSET 0x0084 | ||
41 | #define IDE0_HCYL_REG_OFFSET 0x0085 | ||
42 | #define IDE0_SELECT_REG_OFFSET 0x0086 | ||
43 | #define IDE0_STATUS_REG_OFFSET 0x0087 | ||
44 | #define IDE0_CONTROL_REG_OFFSET 0x0106 | ||
45 | #define IDE0_IRQ_REG_OFFSET 0x000A /* not used */ | ||
46 | |||
47 | /* | ||
48 | * Definitions for IDE1 Interface | ||
49 | */ | ||
50 | #define IDE1_BASE_OFFSET 0x0C00 /* Offset in PCMCIA memory */ | ||
51 | #define IDE1_DATA_REG_OFFSET 0x0000 | ||
52 | #define IDE1_ERROR_REG_OFFSET 0x0081 | ||
53 | #define IDE1_NSECTOR_REG_OFFSET 0x0082 | ||
54 | #define IDE1_SECTOR_REG_OFFSET 0x0083 | ||
55 | #define IDE1_LCYL_REG_OFFSET 0x0084 | ||
56 | #define IDE1_HCYL_REG_OFFSET 0x0085 | ||
57 | #define IDE1_SELECT_REG_OFFSET 0x0086 | ||
58 | #define IDE1_STATUS_REG_OFFSET 0x0087 | ||
59 | #define IDE1_CONTROL_REG_OFFSET 0x0106 | ||
60 | #define IDE1_IRQ_REG_OFFSET 0x000A /* not used */ | ||
61 | |||
62 | /* CPM Ethernet through SCCx. | ||
63 | * | ||
64 | * Bits in parallel I/O port registers that have to be set/cleared | ||
65 | * to configure the pins for SCC2 use. | ||
66 | */ | ||
67 | #define PA_ENET_MDC ((ushort)0x0001) /* PA 15 !!! */ | ||
68 | #define PA_ENET_MDIO ((ushort)0x0002) /* PA 14 !!! */ | ||
69 | #define PA_ENET_RXD ((ushort)0x0004) /* PA 13 */ | ||
70 | #define PA_ENET_TXD ((ushort)0x0008) /* PA 12 */ | ||
71 | #define PA_ENET_RCLK ((ushort)0x0200) /* PA 6 */ | ||
72 | #define PA_ENET_TCLK ((ushort)0x0400) /* PA 5 */ | ||
73 | |||
74 | #define PB_ENET_TENA ((uint)0x00002000) /* PB 18 */ | ||
75 | |||
76 | #define PC_ENET_CLSN ((ushort)0x0040) /* PC 9 */ | ||
77 | #define PC_ENET_RENA ((ushort)0x0080) /* PC 8 */ | ||
78 | #define PC_ENET_RESET ((ushort)0x0100) /* PC 7 !!! */ | ||
79 | |||
80 | /* Control bits in the SICR to route TCLK (CLK3) and RCLK (CLK2) to | ||
81 | * SCC2. Also, make sure GR2 (bit 16) and SC2 (bit 17) are zero. | ||
82 | */ | ||
83 | #define SICR_ENET_MASK ((uint)0x0000ff00) | ||
84 | #define SICR_ENET_CLKRT ((uint)0x00002E00) | ||
85 | |||
86 | /* We don't use the 8259. | ||
87 | */ | ||
88 | #define NR_8259_INTS 0 | ||
89 | |||
90 | #endif /* !__ASSEMBLY__ */ | ||
91 | #endif /* __ASM_SPD8XX_H__ */ | ||
92 | #endif /* __KERNEL__ */ | ||
diff --git a/arch/ppc/platforms/spruce.c b/arch/ppc/platforms/spruce.c new file mode 100644 index 000000000000..5ad70d357cb9 --- /dev/null +++ b/arch/ppc/platforms/spruce.c | |||
@@ -0,0 +1,325 @@ | |||
1 | /* | ||
2 | * arch/ppc/platforms/spruce.c | ||
3 | * | ||
4 | * Board and PCI setup routines for IBM Spruce | ||
5 | * | ||
6 | * Author: MontaVista Software <source@mvista.com> | ||
7 | * | ||
8 | * 2000-2004 (c) MontaVista, Software, Inc. This file is licensed under | ||
9 | * the terms of the GNU General Public License version 2. This program | ||
10 | * is licensed "as is" without any warranty of any kind, whether express | ||
11 | * or implied. | ||
12 | */ | ||
13 | |||
14 | #include <linux/config.h> | ||
15 | #include <linux/stddef.h> | ||
16 | #include <linux/kernel.h> | ||
17 | #include <linux/init.h> | ||
18 | #include <linux/errno.h> | ||
19 | #include <linux/reboot.h> | ||
20 | #include <linux/pci.h> | ||
21 | #include <linux/kdev_t.h> | ||
22 | #include <linux/types.h> | ||
23 | #include <linux/major.h> | ||
24 | #include <linux/initrd.h> | ||
25 | #include <linux/console.h> | ||
26 | #include <linux/delay.h> | ||
27 | #include <linux/seq_file.h> | ||
28 | #include <linux/ide.h> | ||
29 | #include <linux/root_dev.h> | ||
30 | #include <linux/serial.h> | ||
31 | #include <linux/tty.h> | ||
32 | #include <linux/serial_core.h> | ||
33 | |||
34 | #include <asm/system.h> | ||
35 | #include <asm/pgtable.h> | ||
36 | #include <asm/page.h> | ||
37 | #include <asm/dma.h> | ||
38 | #include <asm/io.h> | ||
39 | #include <asm/machdep.h> | ||
40 | #include <asm/time.h> | ||
41 | #include <asm/todc.h> | ||
42 | #include <asm/bootinfo.h> | ||
43 | #include <asm/kgdb.h> | ||
44 | |||
45 | #include <syslib/cpc700.h> | ||
46 | |||
47 | #include "spruce.h" | ||
48 | |||
49 | static inline int | ||
50 | spruce_map_irq(struct pci_dev *dev, unsigned char idsel, unsigned char pin) | ||
51 | { | ||
52 | static char pci_irq_table[][4] = | ||
53 | /* | ||
54 | * PCI IDSEL/INTPIN->INTLINE | ||
55 | * A B C D | ||
56 | */ | ||
57 | { | ||
58 | {23, 24, 25, 26}, /* IDSEL 1 - PCI slot 3 */ | ||
59 | {24, 25, 26, 23}, /* IDSEL 2 - PCI slot 2 */ | ||
60 | {25, 26, 23, 24}, /* IDSEL 3 - PCI slot 1 */ | ||
61 | {26, 23, 24, 25}, /* IDSEL 4 - PCI slot 0 */ | ||
62 | }; | ||
63 | |||
64 | const long min_idsel = 1, max_idsel = 4, irqs_per_slot = 4; | ||
65 | return PCI_IRQ_TABLE_LOOKUP; | ||
66 | } | ||
67 | |||
68 | static void __init | ||
69 | spruce_setup_hose(void) | ||
70 | { | ||
71 | struct pci_controller *hose; | ||
72 | |||
73 | /* Setup hose */ | ||
74 | hose = pcibios_alloc_controller(); | ||
75 | if (!hose) | ||
76 | return; | ||
77 | |||
78 | hose->first_busno = 0; | ||
79 | hose->last_busno = 0xff; | ||
80 | |||
81 | pci_init_resource(&hose->io_resource, | ||
82 | SPRUCE_PCI_LOWER_IO, | ||
83 | SPRUCE_PCI_UPPER_IO, | ||
84 | IORESOURCE_IO, | ||
85 | "PCI host bridge"); | ||
86 | |||
87 | pci_init_resource(&hose->mem_resources[0], | ||
88 | SPRUCE_PCI_LOWER_MEM, | ||
89 | SPRUCE_PCI_UPPER_MEM, | ||
90 | IORESOURCE_MEM, | ||
91 | "PCI host bridge"); | ||
92 | |||
93 | hose->io_space.start = SPRUCE_PCI_LOWER_IO; | ||
94 | hose->io_space.end = SPRUCE_PCI_UPPER_IO; | ||
95 | hose->mem_space.start = SPRUCE_PCI_LOWER_MEM; | ||
96 | hose->mem_space.end = SPRUCE_PCI_UPPER_MEM; | ||
97 | hose->io_base_virt = (void *)SPRUCE_ISA_IO_BASE; | ||
98 | |||
99 | setup_indirect_pci(hose, | ||
100 | SPRUCE_PCI_CONFIG_ADDR, | ||
101 | SPRUCE_PCI_CONFIG_DATA); | ||
102 | |||
103 | hose->last_busno = pciauto_bus_scan(hose, hose->first_busno); | ||
104 | |||
105 | ppc_md.pci_swizzle = common_swizzle; | ||
106 | ppc_md.pci_map_irq = spruce_map_irq; | ||
107 | } | ||
108 | |||
109 | /* | ||
110 | * CPC700 PIC interrupt programming table | ||
111 | * | ||
112 | * First entry is the sensitivity (level/edge), second is the polarity. | ||
113 | */ | ||
114 | unsigned int cpc700_irq_assigns[32][2] = { | ||
115 | { 1, 1 }, /* IRQ 0: ECC Correctable Error - rising edge */ | ||
116 | { 1, 1 }, /* IRQ 1: PCI Write Mem Range - rising edge */ | ||
117 | { 0, 1 }, /* IRQ 2: PCI Write Command Reg - active high */ | ||
118 | { 0, 1 }, /* IRQ 3: UART 0 - active high */ | ||
119 | { 0, 1 }, /* IRQ 4: UART 1 - active high */ | ||
120 | { 0, 1 }, /* IRQ 5: ICC 0 - active high */ | ||
121 | { 0, 1 }, /* IRQ 6: ICC 1 - active high */ | ||
122 | { 0, 1 }, /* IRQ 7: GPT Compare 0 - active high */ | ||
123 | { 0, 1 }, /* IRQ 8: GPT Compare 1 - active high */ | ||
124 | { 0, 1 }, /* IRQ 9: GPT Compare 2 - active high */ | ||
125 | { 0, 1 }, /* IRQ 10: GPT Compare 3 - active high */ | ||
126 | { 0, 1 }, /* IRQ 11: GPT Compare 4 - active high */ | ||
127 | { 0, 1 }, /* IRQ 12: GPT Capture 0 - active high */ | ||
128 | { 0, 1 }, /* IRQ 13: GPT Capture 1 - active high */ | ||
129 | { 0, 1 }, /* IRQ 14: GPT Capture 2 - active high */ | ||
130 | { 0, 1 }, /* IRQ 15: GPT Capture 3 - active high */ | ||
131 | { 0, 1 }, /* IRQ 16: GPT Capture 4 - active high */ | ||
132 | { 0, 0 }, /* IRQ 17: Reserved */ | ||
133 | { 0, 0 }, /* IRQ 18: Reserved */ | ||
134 | { 0, 0 }, /* IRQ 19: Reserved */ | ||
135 | { 0, 1 }, /* IRQ 20: FPGA EXT_IRQ0 - active high */ | ||
136 | { 1, 1 }, /* IRQ 21: Mouse - rising edge */ | ||
137 | { 1, 1 }, /* IRQ 22: Keyboard - rising edge */ | ||
138 | { 0, 0 }, /* IRQ 23: PCI Slot 3 - active low */ | ||
139 | { 0, 0 }, /* IRQ 24: PCI Slot 2 - active low */ | ||
140 | { 0, 0 }, /* IRQ 25: PCI Slot 1 - active low */ | ||
141 | { 0, 0 }, /* IRQ 26: PCI Slot 0 - active low */ | ||
142 | }; | ||
143 | |||
144 | static void __init | ||
145 | spruce_calibrate_decr(void) | ||
146 | { | ||
147 | int freq, divisor = 4; | ||
148 | |||
149 | /* determine processor bus speed */ | ||
150 | freq = SPRUCE_BUS_SPEED; | ||
151 | tb_ticks_per_jiffy = freq / HZ / divisor; | ||
152 | tb_to_us = mulhwu_scale_factor(freq/divisor, 1000000); | ||
153 | } | ||
154 | |||
155 | static int | ||
156 | spruce_show_cpuinfo(struct seq_file *m) | ||
157 | { | ||
158 | seq_printf(m, "vendor\t\t: IBM\n"); | ||
159 | seq_printf(m, "machine\t\t: Spruce\n"); | ||
160 | |||
161 | return 0; | ||
162 | } | ||
163 | |||
164 | static void __init | ||
165 | spruce_early_serial_map(void) | ||
166 | { | ||
167 | u32 uart_clk; | ||
168 | struct uart_port serial_req; | ||
169 | |||
170 | if (SPRUCE_UARTCLK_IS_33M(readb(SPRUCE_FPGA_REG_A))) | ||
171 | uart_clk = SPRUCE_BAUD_33M * 16; | ||
172 | else | ||
173 | uart_clk = SPRUCE_BAUD_30M * 16; | ||
174 | |||
175 | /* Setup serial port access */ | ||
176 | memset(&serial_req, 0, sizeof(serial_req)); | ||
177 | serial_req.uartclk = uart_clk; | ||
178 | serial_req.irq = UART0_INT; | ||
179 | serial_req.flags = ASYNC_BOOT_AUTOCONF; | ||
180 | serial_req.iotype = SERIAL_IO_MEM; | ||
181 | serial_req.membase = (u_char *)UART0_IO_BASE; | ||
182 | serial_req.regshift = 0; | ||
183 | |||
184 | #if defined(CONFIG_KGDB) || defined(CONFIG_SERIAL_TEXT_DEBUG) | ||
185 | gen550_init(0, &serial_req); | ||
186 | #endif | ||
187 | #ifdef CONFIG_SERIAL_8250 | ||
188 | if (early_serial_setup(&serial_req) != 0) | ||
189 | printk("Early serial init of port 0 failed\n"); | ||
190 | #endif | ||
191 | |||
192 | /* Assume early_serial_setup() doesn't modify serial_req */ | ||
193 | serial_req.line = 1; | ||
194 | serial_req.irq = UART1_INT; | ||
195 | serial_req.membase = (u_char *)UART1_IO_BASE; | ||
196 | |||
197 | #if defined(CONFIG_KGDB) || defined(CONFIG_SERIAL_TEXT_DEBUG) | ||
198 | gen550_init(1, &serial_req); | ||
199 | #endif | ||
200 | #ifdef CONFIG_SERIAL_8250 | ||
201 | if (early_serial_setup(&serial_req) != 0) | ||
202 | printk("Early serial init of port 1 failed\n"); | ||
203 | #endif | ||
204 | } | ||
205 | |||
206 | TODC_ALLOC(); | ||
207 | |||
208 | static void __init | ||
209 | spruce_setup_arch(void) | ||
210 | { | ||
211 | /* Setup TODC access */ | ||
212 | TODC_INIT(TODC_TYPE_DS1643, 0, 0, SPRUCE_RTC_BASE_ADDR, 8); | ||
213 | |||
214 | /* init to some ~sane value until calibrate_delay() runs */ | ||
215 | loops_per_jiffy = 50000000 / HZ; | ||
216 | |||
217 | /* Setup PCI host bridge */ | ||
218 | spruce_setup_hose(); | ||
219 | |||
220 | #ifdef CONFIG_BLK_DEV_INITRD | ||
221 | if (initrd_start) | ||
222 | ROOT_DEV = Root_RAM0; | ||
223 | else | ||
224 | #endif | ||
225 | #ifdef CONFIG_ROOT_NFS | ||
226 | ROOT_DEV = Root_NFS; | ||
227 | #else | ||
228 | ROOT_DEV = Root_SDA1; | ||
229 | #endif | ||
230 | |||
231 | /* Identify the system */ | ||
232 | printk(KERN_INFO "System Identification: IBM Spruce\n"); | ||
233 | printk(KERN_INFO "Port by MontaVista Software, Inc. (source@mvista.com)\n"); | ||
234 | } | ||
235 | |||
236 | static void | ||
237 | spruce_restart(char *cmd) | ||
238 | { | ||
239 | local_irq_disable(); | ||
240 | |||
241 | /* SRR0 has system reset vector, SRR1 has default MSR value */ | ||
242 | /* rfi restores MSR from SRR1 and sets the PC to the SRR0 value */ | ||
243 | __asm__ __volatile__ | ||
244 | ("\n\ | ||
245 | lis 3,0xfff0 \n\ | ||
246 | ori 3,3,0x0100 \n\ | ||
247 | mtspr 26,3 \n\ | ||
248 | li 3,0 \n\ | ||
249 | mtspr 27,3 \n\ | ||
250 | rfi \n\ | ||
251 | "); | ||
252 | for(;;); | ||
253 | } | ||
254 | |||
255 | static void | ||
256 | spruce_power_off(void) | ||
257 | { | ||
258 | for(;;); | ||
259 | } | ||
260 | |||
261 | static void | ||
262 | spruce_halt(void) | ||
263 | { | ||
264 | spruce_restart(NULL); | ||
265 | } | ||
266 | |||
267 | static void __init | ||
268 | spruce_map_io(void) | ||
269 | { | ||
270 | io_block_mapping(SPRUCE_PCI_IO_BASE, SPRUCE_PCI_PHY_IO_BASE, | ||
271 | 0x08000000, _PAGE_IO); | ||
272 | } | ||
273 | |||
274 | /* | ||
275 | * Set BAT 3 to map 0xf8000000 to end of physical memory space 1-to-1. | ||
276 | */ | ||
277 | static __inline__ void | ||
278 | spruce_set_bat(void) | ||
279 | { | ||
280 | mb(); | ||
281 | mtspr(SPRN_DBAT1U, 0xf8000ffe); | ||
282 | mtspr(SPRN_DBAT1L, 0xf800002a); | ||
283 | mb(); | ||
284 | } | ||
285 | |||
286 | void __init | ||
287 | platform_init(unsigned long r3, unsigned long r4, unsigned long r5, | ||
288 | unsigned long r6, unsigned long r7) | ||
289 | { | ||
290 | parse_bootinfo(find_bootinfo()); | ||
291 | |||
292 | /* Map in board regs, etc. */ | ||
293 | spruce_set_bat(); | ||
294 | |||
295 | isa_io_base = SPRUCE_ISA_IO_BASE; | ||
296 | pci_dram_offset = SPRUCE_PCI_SYS_MEM_BASE; | ||
297 | |||
298 | ppc_md.setup_arch = spruce_setup_arch; | ||
299 | ppc_md.show_cpuinfo = spruce_show_cpuinfo; | ||
300 | ppc_md.init_IRQ = cpc700_init_IRQ; | ||
301 | ppc_md.get_irq = cpc700_get_irq; | ||
302 | |||
303 | ppc_md.setup_io_mappings = spruce_map_io; | ||
304 | |||
305 | ppc_md.restart = spruce_restart; | ||
306 | ppc_md.power_off = spruce_power_off; | ||
307 | ppc_md.halt = spruce_halt; | ||
308 | |||
309 | ppc_md.time_init = todc_time_init; | ||
310 | ppc_md.set_rtc_time = todc_set_rtc_time; | ||
311 | ppc_md.get_rtc_time = todc_get_rtc_time; | ||
312 | ppc_md.calibrate_decr = spruce_calibrate_decr; | ||
313 | |||
314 | ppc_md.nvram_read_val = todc_direct_read_val; | ||
315 | ppc_md.nvram_write_val = todc_direct_write_val; | ||
316 | |||
317 | spruce_early_serial_map(); | ||
318 | |||
319 | #ifdef CONFIG_SERIAL_TEXT_DEBUG | ||
320 | ppc_md.progress = gen550_progress; | ||
321 | #endif /* CONFIG_SERIAL_TEXT_DEBUG */ | ||
322 | #ifdef CONFIG_KGDB | ||
323 | ppc_md.kgdb_map_scc = gen550_kgdb_map_scc; | ||
324 | #endif | ||
325 | } | ||
diff --git a/arch/ppc/platforms/spruce.h b/arch/ppc/platforms/spruce.h new file mode 100644 index 000000000000..a31ff7ee698f --- /dev/null +++ b/arch/ppc/platforms/spruce.h | |||
@@ -0,0 +1,71 @@ | |||
1 | /* | ||
2 | * include/asm-ppc/platforms/spruce.h | ||
3 | * | ||
4 | * Definitions for IBM Spruce reference board support | ||
5 | * | ||
6 | * Authors: Matt Porter and Johnnie Peters | ||
7 | * mporter@mvista.com | ||
8 | * jpeters@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 | #ifdef __KERNEL__ | ||
17 | #ifndef __ASM_SPRUCE_H__ | ||
18 | #define __ASM_SPRUCE_H__ | ||
19 | |||
20 | #define SPRUCE_PCI_CONFIG_ADDR 0xfec00000 | ||
21 | #define SPRUCE_PCI_CONFIG_DATA 0xfec00004 | ||
22 | |||
23 | #define SPRUCE_PCI_PHY_IO_BASE 0xf8000000 | ||
24 | #define SPRUCE_PCI_IO_BASE SPRUCE_PCI_PHY_IO_BASE | ||
25 | |||
26 | #define SPRUCE_PCI_SYS_MEM_BASE 0x00000000 | ||
27 | |||
28 | #define SPRUCE_PCI_LOWER_MEM 0x80000000 | ||
29 | #define SPRUCE_PCI_UPPER_MEM 0x9fffffff | ||
30 | #define SPRUCE_PCI_LOWER_IO 0x00000000 | ||
31 | #define SPRUCE_PCI_UPPER_IO 0x03ffffff | ||
32 | |||
33 | #define SPRUCE_ISA_IO_BASE SPRUCE_PCI_IO_BASE | ||
34 | |||
35 | #define SPRUCE_MEM_SIZE 0x04000000 | ||
36 | #define SPRUCE_BUS_SPEED 66666667 | ||
37 | |||
38 | #define SPRUCE_NVRAM_BASE_ADDR 0xff800000 | ||
39 | #define SPRUCE_RTC_BASE_ADDR SPRUCE_NVRAM_BASE_ADDR | ||
40 | |||
41 | /* | ||
42 | * Serial port defines | ||
43 | */ | ||
44 | #define SPRUCE_FPGA_REG_A 0xff820000 | ||
45 | #define SPRUCE_UARTCLK_33M 0x02 | ||
46 | #define SPRUCE_UARTCLK_IS_33M(reg) (reg & SPRUCE_UARTCLK_33M) | ||
47 | |||
48 | #define UART0_IO_BASE 0xff600300 | ||
49 | #define UART1_IO_BASE 0xff600400 | ||
50 | |||
51 | #define RS_TABLE_SIZE 2 | ||
52 | |||
53 | #define SPRUCE_BAUD_33M (33000000/64) | ||
54 | #define SPRUCE_BAUD_30M (30000000/64) | ||
55 | #define BASE_BAUD SPRUCE_BAUD_33M | ||
56 | |||
57 | #define UART0_INT 3 | ||
58 | #define UART1_INT 4 | ||
59 | |||
60 | #define STD_UART_OP(num) \ | ||
61 | { 0, BASE_BAUD, 0, UART##num##_INT, \ | ||
62 | ASYNC_BOOT_AUTOCONF, \ | ||
63 | iomem_base: (unsigned char *) UART##num##_IO_BASE, \ | ||
64 | io_type: SERIAL_IO_MEM}, | ||
65 | |||
66 | #define SERIAL_PORT_DFNS \ | ||
67 | STD_UART_OP(0) \ | ||
68 | STD_UART_OP(1) | ||
69 | |||
70 | #endif /* __ASM_SPRUCE_H__ */ | ||
71 | #endif /* __KERNEL__ */ | ||
diff --git a/arch/ppc/platforms/tqm8260.h b/arch/ppc/platforms/tqm8260.h new file mode 100644 index 000000000000..c7a78a646c66 --- /dev/null +++ b/arch/ppc/platforms/tqm8260.h | |||
@@ -0,0 +1,23 @@ | |||
1 | /* | ||
2 | * TQM8260 board specific definitions | ||
3 | * | ||
4 | * Copyright (c) 2001 Wolfgang Denk (wd@denx.de) | ||
5 | */ | ||
6 | |||
7 | #ifndef __TQM8260_PLATFORM | ||
8 | #define __TQM8260_PLATFORM | ||
9 | |||
10 | #include <linux/config.h> | ||
11 | |||
12 | #include <asm/ppcboot.h> | ||
13 | |||
14 | #define CPM_MAP_ADDR ((uint)0xFFF00000) | ||
15 | #define PHY_INTERRUPT 25 | ||
16 | |||
17 | /* For our show_cpuinfo hooks. */ | ||
18 | #define CPUINFO_VENDOR "IN2 Systems" | ||
19 | #define CPUINFO_MACHINE "TQM8260 PowerPC" | ||
20 | |||
21 | #define BOOTROM_RESTART_ADDR ((uint)0x40000104) | ||
22 | |||
23 | #endif /* __TQM8260_PLATFORM */ | ||
diff --git a/arch/ppc/platforms/tqm8260_setup.c b/arch/ppc/platforms/tqm8260_setup.c new file mode 100644 index 000000000000..a8880bfc034b --- /dev/null +++ b/arch/ppc/platforms/tqm8260_setup.c | |||
@@ -0,0 +1,44 @@ | |||
1 | /* | ||
2 | * arch/ppc/platforms/tqm8260_setup.c | ||
3 | * | ||
4 | * TQM8260 platform support | ||
5 | * | ||
6 | * Author: Allen Curtis <acurtis@onz.com> | ||
7 | * Derived from: m8260_setup.c by Dan Malek, MVista | ||
8 | * | ||
9 | * Copyright 2002 Ones and Zeros, Inc. | ||
10 | * | ||
11 | * This program is free software; you can redistribute it and/or modify it | ||
12 | * under the terms of the GNU General Public License as published by the | ||
13 | * Free Software Foundation; either version 2 of the License, or (at your | ||
14 | * option) any later version. | ||
15 | */ | ||
16 | |||
17 | #include <linux/init.h> | ||
18 | |||
19 | #include <asm/immap_cpm2.h> | ||
20 | #include <asm/mpc8260.h> | ||
21 | #include <asm/machdep.h> | ||
22 | |||
23 | static int | ||
24 | tqm8260_set_rtc_time(unsigned long time) | ||
25 | { | ||
26 | ((cpm2_map_t *)CPM_MAP_ADDR)->im_sit.sit_tmcnt = time; | ||
27 | ((cpm2_map_t *)CPM_MAP_ADDR)->im_sit.sit_tmcntsc = 0x3; | ||
28 | |||
29 | return(0); | ||
30 | } | ||
31 | |||
32 | static unsigned long | ||
33 | tqm8260_get_rtc_time(void) | ||
34 | { | ||
35 | return ((cpm2_map_t *)CPM_MAP_ADDR)->im_sit.sit_tmcnt; | ||
36 | } | ||
37 | |||
38 | void __init | ||
39 | m82xx_board_init(void) | ||
40 | { | ||
41 | /* Anything special for this platform */ | ||
42 | ppc_md.set_rtc_time = tqm8260_set_rtc_time; | ||
43 | ppc_md.get_rtc_time = tqm8260_get_rtc_time; | ||
44 | } | ||
diff --git a/arch/ppc/platforms/tqm8xx.h b/arch/ppc/platforms/tqm8xx.h new file mode 100644 index 000000000000..2150dc87b18f --- /dev/null +++ b/arch/ppc/platforms/tqm8xx.h | |||
@@ -0,0 +1,179 @@ | |||
1 | /* | ||
2 | * TQM8xx(L) board specific definitions | ||
3 | * | ||
4 | * Copyright (c) 1999-2002 Wolfgang Denk (wd@denx.de) | ||
5 | */ | ||
6 | |||
7 | #ifdef __KERNEL__ | ||
8 | #ifndef __MACH_TQM8xx_H | ||
9 | #define __MACH_TQM8xx_H | ||
10 | |||
11 | #include <linux/config.h> | ||
12 | |||
13 | #include <asm/ppcboot.h> | ||
14 | |||
15 | #ifndef __ASSEMBLY__ | ||
16 | #define TQM_IMMR_BASE 0xFFF00000 /* phys. addr of IMMR */ | ||
17 | #define TQM_IMAP_SIZE (64 * 1024) /* size of mapped area */ | ||
18 | |||
19 | #define IMAP_ADDR TQM_IMMR_BASE /* physical base address of IMMR area */ | ||
20 | #define IMAP_SIZE TQM_IMAP_SIZE /* mapped size of IMMR area */ | ||
21 | |||
22 | /*----------------------------------------------------------------------- | ||
23 | * PCMCIA stuff | ||
24 | *----------------------------------------------------------------------- | ||
25 | * | ||
26 | */ | ||
27 | #define PCMCIA_MEM_SIZE ( 64 << 20 ) | ||
28 | |||
29 | #ifndef CONFIG_KUP4K | ||
30 | # define MAX_HWIFS 1 /* overwrite default in include/asm-ppc/ide.h */ | ||
31 | |||
32 | #else /* CONFIG_KUP4K */ | ||
33 | |||
34 | # define MAX_HWIFS 2 /* overwrite default in include/asm-ppc/ide.h */ | ||
35 | # ifndef __ASSEMBLY__ | ||
36 | # include <asm/8xx_immap.h> | ||
37 | static __inline__ void ide_led(int on) | ||
38 | { | ||
39 | volatile immap_t *immap = (immap_t *)IMAP_ADDR; | ||
40 | |||
41 | if (on) { | ||
42 | immap->im_ioport.iop_padat &= ~0x80; | ||
43 | } else { | ||
44 | immap->im_ioport.iop_padat |= 0x80; | ||
45 | } | ||
46 | } | ||
47 | # endif /* __ASSEMBLY__ */ | ||
48 | # define IDE_LED(x) ide_led((x)) | ||
49 | #endif /* CONFIG_KUP4K */ | ||
50 | |||
51 | /* | ||
52 | * Definitions for IDE0 Interface | ||
53 | */ | ||
54 | #define IDE0_BASE_OFFSET 0 | ||
55 | #define IDE0_DATA_REG_OFFSET (PCMCIA_MEM_SIZE + 0x320) | ||
56 | #define IDE0_ERROR_REG_OFFSET (2 * PCMCIA_MEM_SIZE + 0x320 + 1) | ||
57 | #define IDE0_NSECTOR_REG_OFFSET (2 * PCMCIA_MEM_SIZE + 0x320 + 2) | ||
58 | #define IDE0_SECTOR_REG_OFFSET (2 * PCMCIA_MEM_SIZE + 0x320 + 3) | ||
59 | #define IDE0_LCYL_REG_OFFSET (2 * PCMCIA_MEM_SIZE + 0x320 + 4) | ||
60 | #define IDE0_HCYL_REG_OFFSET (2 * PCMCIA_MEM_SIZE + 0x320 + 5) | ||
61 | #define IDE0_SELECT_REG_OFFSET (2 * PCMCIA_MEM_SIZE + 0x320 + 6) | ||
62 | #define IDE0_STATUS_REG_OFFSET (2 * PCMCIA_MEM_SIZE + 0x320 + 7) | ||
63 | #define IDE0_CONTROL_REG_OFFSET 0x0106 | ||
64 | #define IDE0_IRQ_REG_OFFSET 0x000A /* not used */ | ||
65 | |||
66 | /* define IO_BASE for PCMCIA */ | ||
67 | #define _IO_BASE 0x80000000 | ||
68 | #define _IO_BASE_SIZE (64<<10) | ||
69 | |||
70 | #define FEC_INTERRUPT 9 /* = SIU_LEVEL4 */ | ||
71 | #define PHY_INTERRUPT 12 /* = IRQ6 */ | ||
72 | #define IDE0_INTERRUPT 13 | ||
73 | |||
74 | #ifdef CONFIG_IDE | ||
75 | #endif | ||
76 | |||
77 | /*----------------------------------------------------------------------- | ||
78 | * CPM Ethernet through SCCx. | ||
79 | *----------------------------------------------------------------------- | ||
80 | * | ||
81 | */ | ||
82 | |||
83 | /*** TQM823L, TQM850L ***********************************************/ | ||
84 | |||
85 | #if defined(CONFIG_TQM823L) || defined(CONFIG_TQM850L) | ||
86 | /* Bits in parallel I/O port registers that have to be set/cleared | ||
87 | * to configure the pins for SCC1 use. | ||
88 | */ | ||
89 | #define PA_ENET_RXD ((ushort)0x0004) /* PA 13 */ | ||
90 | #define PA_ENET_TXD ((ushort)0x0008) /* PA 12 */ | ||
91 | #define PA_ENET_RCLK ((ushort)0x0100) /* PA 7 */ | ||
92 | #define PA_ENET_TCLK ((ushort)0x0400) /* PA 5 */ | ||
93 | |||
94 | #define PB_ENET_TENA ((uint)0x00002000) /* PB 18 */ | ||
95 | |||
96 | #define PC_ENET_CLSN ((ushort)0x0040) /* PC 9 */ | ||
97 | #define PC_ENET_RENA ((ushort)0x0080) /* PC 8 */ | ||
98 | |||
99 | /* Control bits in the SICR to route TCLK (CLK3) and RCLK (CLK1) to | ||
100 | * SCC2. Also, make sure GR2 (bit 16) and SC2 (bit 17) are zero. | ||
101 | */ | ||
102 | #define SICR_ENET_MASK ((uint)0x0000ff00) | ||
103 | #define SICR_ENET_CLKRT ((uint)0x00002600) | ||
104 | #endif /* CONFIG_TQM823L, CONFIG_TQM850L */ | ||
105 | |||
106 | /*** TQM860L ********************************************************/ | ||
107 | |||
108 | #ifdef CONFIG_TQM860L | ||
109 | /* Bits in parallel I/O port registers that have to be set/cleared | ||
110 | * to configure the pins for SCC1 use. | ||
111 | */ | ||
112 | #define PA_ENET_RXD ((ushort)0x0001) /* PA 15 */ | ||
113 | #define PA_ENET_TXD ((ushort)0x0002) /* PA 14 */ | ||
114 | #define PA_ENET_RCLK ((ushort)0x0100) /* PA 7 */ | ||
115 | #define PA_ENET_TCLK ((ushort)0x0400) /* PA 5 */ | ||
116 | |||
117 | #define PC_ENET_TENA ((ushort)0x0001) /* PC 15 */ | ||
118 | #define PC_ENET_CLSN ((ushort)0x0010) /* PC 11 */ | ||
119 | #define PC_ENET_RENA ((ushort)0x0020) /* PC 10 */ | ||
120 | |||
121 | /* Control bits in the SICR to route TCLK (CLK3) and RCLK (CLK1) to | ||
122 | * SCC1. Also, make sure GR1 (bit 24) and SC1 (bit 25) are zero. | ||
123 | */ | ||
124 | #define SICR_ENET_MASK ((uint)0x000000ff) | ||
125 | #define SICR_ENET_CLKRT ((uint)0x00000026) | ||
126 | #endif /* CONFIG_TQM860L */ | ||
127 | |||
128 | /*** FPS850L *********************************************************/ | ||
129 | |||
130 | #ifdef CONFIG_FPS850L | ||
131 | /* Bits in parallel I/O port registers that have to be set/cleared | ||
132 | * to configure the pins for SCC1 use. | ||
133 | */ | ||
134 | #define PA_ENET_RXD ((ushort)0x0004) /* PA 13 */ | ||
135 | #define PA_ENET_TXD ((ushort)0x0008) /* PA 12 */ | ||
136 | #define PA_ENET_RCLK ((ushort)0x0100) /* PA 7 */ | ||
137 | #define PA_ENET_TCLK ((ushort)0x0400) /* PA 5 */ | ||
138 | |||
139 | #define PC_ENET_TENA ((ushort)0x0002) /* PC 14 */ | ||
140 | #define PC_ENET_CLSN ((ushort)0x0040) /* PC 9 */ | ||
141 | #define PC_ENET_RENA ((ushort)0x0080) /* PC 8 */ | ||
142 | |||
143 | /* Control bits in the SICR to route TCLK (CLK2) and RCLK (CLK4) to | ||
144 | * SCC2. Also, make sure GR2 (bit 16) and SC2 (bit 17) are zero. | ||
145 | */ | ||
146 | #define SICR_ENET_MASK ((uint)0x0000ff00) | ||
147 | #define SICR_ENET_CLKRT ((uint)0x00002600) | ||
148 | #endif /* CONFIG_FPS850L */ | ||
149 | |||
150 | /*** SM850 *********************************************************/ | ||
151 | |||
152 | /* The SM850 Service Module uses SCC2 for IrDA and SCC3 for Ethernet */ | ||
153 | |||
154 | #ifdef CONFIG_SM850 | ||
155 | #define PB_ENET_RXD ((uint)0x00000004) /* PB 29 */ | ||
156 | #define PB_ENET_TXD ((uint)0x00000002) /* PB 30 */ | ||
157 | #define PA_ENET_RCLK ((ushort)0x0100) /* PA 7 */ | ||
158 | #define PA_ENET_TCLK ((ushort)0x0400) /* PA 5 */ | ||
159 | |||
160 | #define PC_ENET_LBK ((ushort)0x0008) /* PC 12 */ | ||
161 | #define PC_ENET_TENA ((ushort)0x0004) /* PC 13 */ | ||
162 | |||
163 | #define PC_ENET_RENA ((ushort)0x0800) /* PC 4 */ | ||
164 | #define PC_ENET_CLSN ((ushort)0x0400) /* PC 5 */ | ||
165 | |||
166 | /* Control bits in the SICR to route TCLK (CLK3) and RCLK (CLK1) to | ||
167 | * SCC3. Also, make sure GR3 (bit 8) and SC3 (bit 9) are zero. | ||
168 | */ | ||
169 | #define SICR_ENET_MASK ((uint)0x00FF0000) | ||
170 | #define SICR_ENET_CLKRT ((uint)0x00260000) | ||
171 | #endif /* CONFIG_SM850 */ | ||
172 | |||
173 | /* We don't use the 8259. | ||
174 | */ | ||
175 | #define NR_8259_INTS 0 | ||
176 | |||
177 | #endif /* !__ASSEMBLY__ */ | ||
178 | #endif /* __MACH_TQM8xx_H */ | ||
179 | #endif /* __KERNEL__ */ | ||