aboutsummaryrefslogtreecommitdiffstats
path: root/arch/powerpc/platforms/82xx
diff options
context:
space:
mode:
authorScott Wood <scottwood@freescale.com>2007-09-14 16:41:56 -0400
committerKumar Gala <galak@kernel.crashing.org>2007-10-04 12:02:44 -0400
commite00c5498a2a614931cbb7d88a53979d5d47594e1 (patch)
treea3c106ef1de3abea61f9e2b2ad23af90d7f9e3e8 /arch/powerpc/platforms/82xx
parent11c146cc19df337f4af42dade9e4fca33c5a54ee (diff)
[POWERPC] mpc82xx: Update mpc8272ads, and factor out PCI and reset.
1. PCI and reset are factored out into pq2.c. I renamed them from m82xx to pq2 because they won't work on the Integrated Host Processor line of 82xx chips (i.e. 8240, 8245, and such). 2. The PCI PIC, which is nominally board-specific, is used on multiple boards, and thus is used into pq2ads-pci-pic.c. 3. The new CPM binding is used. 4. General cleanup. Signed-off-by: Scott Wood <scottwood@freescale.com> Signed-off-by: Kumar Gala <galak@kernel.crashing.org>
Diffstat (limited to 'arch/powerpc/platforms/82xx')
-rw-r--r--arch/powerpc/platforms/82xx/Kconfig5
-rw-r--r--arch/powerpc/platforms/82xx/Makefile2
-rw-r--r--arch/powerpc/platforms/82xx/mpc8272_ads.c668
-rw-r--r--arch/powerpc/platforms/82xx/pq2.c82
-rw-r--r--arch/powerpc/platforms/82xx/pq2.h20
-rw-r--r--arch/powerpc/platforms/82xx/pq2ads-pci-pic.c195
-rw-r--r--arch/powerpc/platforms/82xx/pq2ads.h2
7 files changed, 424 insertions, 550 deletions
diff --git a/arch/powerpc/platforms/82xx/Kconfig b/arch/powerpc/platforms/82xx/Kconfig
index f260c014ff2a..03f5aeb5fa40 100644
--- a/arch/powerpc/platforms/82xx/Kconfig
+++ b/arch/powerpc/platforms/82xx/Kconfig
@@ -10,6 +10,8 @@ config MPC8272_ADS
10 select 8272 10 select 8272
11 select 8260 11 select 8260
12 select FSL_SOC 12 select FSL_SOC
13 select PQ2_ADS_PCI_PIC if PCI
14 select PPC_CPM_NEW_BINDING
13 help 15 help
14 This option enables support for the MPC8272 ADS board 16 This option enables support for the MPC8272 ADS board
15 17
@@ -34,3 +36,6 @@ config 8272
34 help 36 help
35 The MPC8272 CPM has a different internal dpram setup than other CPM2 37 The MPC8272 CPM has a different internal dpram setup than other CPM2
36 devices 38 devices
39
40config PQ2_ADS_PCI_PIC
41 bool
diff --git a/arch/powerpc/platforms/82xx/Makefile b/arch/powerpc/platforms/82xx/Makefile
index 9b7c851ce6f1..bfcb64cdbd83 100644
--- a/arch/powerpc/platforms/82xx/Makefile
+++ b/arch/powerpc/platforms/82xx/Makefile
@@ -2,3 +2,5 @@
2# Makefile for the PowerPC 82xx linux kernel. 2# Makefile for the PowerPC 82xx linux kernel.
3# 3#
4obj-$(CONFIG_MPC8272_ADS) += mpc8272_ads.o 4obj-$(CONFIG_MPC8272_ADS) += mpc8272_ads.o
5obj-$(CONFIG_CPM2) += pq2.o
6obj-$(CONFIG_PQ2_ADS_PCI_PIC) += pq2ads-pci-pic.o
diff --git a/arch/powerpc/platforms/82xx/mpc8272_ads.c b/arch/powerpc/platforms/82xx/mpc8272_ads.c
index 4de76dad31b2..fd83440eb287 100644
--- a/arch/powerpc/platforms/82xx/mpc8272_ads.c
+++ b/arch/powerpc/platforms/82xx/mpc8272_ads.c
@@ -1,9 +1,10 @@
1/* 1/*
2 * MPC8272_ads setup and early boot code plus other random bits. 2 * MPC8272 ADS board support
3 * 3 *
4 * Author: Vitaly Bordug <vbordug@ru.mvista.com> 4 * Copyright 2007 Freescale Semiconductor, Inc.
5 * m82xx_restart fix by Wade Farnsworth <wfarnsworth@mvista.com> 5 * Author: Scott Wood <scottwood@freescale.com>
6 * 6 *
7 * Based on code by Vitaly Bordug <vbordug@ru.mvista.com>
7 * Copyright (c) 2006 MontaVista Software, Inc. 8 * Copyright (c) 2006 MontaVista Software, Inc.
8 * 9 *
9 * This program is free software; you can redistribute it and/or modify it 10 * This program is free software; you can redistribute it and/or modify it
@@ -12,613 +13,184 @@
12 * option) any later version. 13 * option) any later version.
13 */ 14 */
14 15
15#include <linux/stddef.h>
16#include <linux/kernel.h>
17#include <linux/init.h> 16#include <linux/init.h>
18#include <linux/errno.h>
19#include <linux/reboot.h>
20#include <linux/pci.h>
21#include <linux/interrupt.h> 17#include <linux/interrupt.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/seq_file.h>
27#include <linux/root_dev.h>
28#include <linux/initrd.h>
29#include <linux/module.h>
30#include <linux/fsl_devices.h> 18#include <linux/fsl_devices.h>
31#include <linux/fs_uart_pd.h> 19#include <linux/of_platform.h>
20#include <linux/io.h>
32 21
33#include <asm/system.h>
34#include <asm/pgtable.h>
35#include <asm/page.h>
36#include <asm/atomic.h>
37#include <asm/time.h>
38#include <asm/io.h>
39#include <asm/machdep.h>
40#include <asm/pci-bridge.h>
41#include <asm/mpc8260.h>
42#include <asm/irq.h>
43#include <mm/mmu_decl.h>
44#include <asm/prom.h>
45#include <asm/cpm2.h> 22#include <asm/cpm2.h>
46#include <asm/udbg.h> 23#include <asm/udbg.h>
47#include <asm/i8259.h> 24#include <asm/machdep.h>
48#include <linux/fs_enet_pd.h> 25#include <asm/time.h>
26
27#include <platforms/82xx/pq2.h>
49 28
50#include <sysdev/fsl_soc.h> 29#include <sysdev/fsl_soc.h>
51#include <sysdev/cpm2_pic.h> 30#include <sysdev/cpm2_pic.h>
52 31
53#include "pq2ads.h" 32#include "pq2ads.h"
54 33#include "pq2.h"
55#ifdef CONFIG_PCI
56static uint pci_clk_frq;
57static struct {
58 unsigned long *pci_int_stat_reg;
59 unsigned long *pci_int_mask_reg;
60} pci_regs;
61
62static unsigned long pci_int_base;
63static struct irq_host *pci_pic_host;
64#endif
65 34
66static void __init mpc8272_ads_pic_init(void) 35static void __init mpc8272_ads_pic_init(void)
67{ 36{
68 struct device_node *np = of_find_compatible_node(NULL, "cpm-pic", "CPM2"); 37 struct device_node *np = of_find_compatible_node(NULL, NULL,
69 struct resource r; 38 "fsl,cpm2-pic");
70 cpm2_map_t *cpm_reg; 39 if (!np) {
71 40 printk(KERN_ERR "PIC init: can not find fsl,cpm2-pic node\n");
72 if (np == NULL) {
73 printk(KERN_ERR "PIC init: can not find cpm-pic node\n");
74 return;
75 }
76 if (of_address_to_resource(np, 0, &r)) {
77 printk(KERN_ERR "PIC init: invalid resource\n");
78 of_node_put(np);
79 return; 41 return;
80 } 42 }
43
81 cpm2_pic_init(np); 44 cpm2_pic_init(np);
82 of_node_put(np); 45 of_node_put(np);
83 46
84 /* Initialize the default interrupt mapping priorities,
85 * in case the boot rom changed something on us.
86 */
87 cpm_reg = (cpm2_map_t *) ioremap(get_immrbase(), sizeof(cpm2_map_t));
88 cpm_reg->im_intctl.ic_siprr = 0x05309770;
89 iounmap(cpm_reg);
90#ifdef CONFIG_PCI
91 /* Initialize stuff for the 82xx CPLD IC and install demux */ 47 /* Initialize stuff for the 82xx CPLD IC and install demux */
92 m82xx_pci_init_irq(); 48 pq2ads_pci_init_irq();
93#endif
94} 49}
95 50
96static void init_fcc1_ioports(struct fs_platform_info *fpi) 51struct cpm_pin {
97{ 52 int port, pin, flags;
98 struct io_port *io; 53};
99 u32 tempval;
100 cpm2_map_t *immap = ioremap(get_immrbase(), sizeof(cpm2_map_t));
101 struct device_node *np;
102 struct resource r;
103 u32 *bcsr;
104
105 np = of_find_node_by_type(NULL, "memory");
106 if (!np) {
107 printk(KERN_INFO "No memory node in device tree\n");
108 return;
109 }
110 if (of_address_to_resource(np, 1, &r)) {
111 printk(KERN_INFO "No memory reg property [1] in devicetree\n");
112 return;
113 }
114 of_node_put(np);
115 bcsr = ioremap(r.start + 4, sizeof(u32));
116 io = &immap->im_ioport;
117
118 /* Enable the PHY */
119 clrbits32(bcsr, BCSR1_FETHIEN);
120 setbits32(bcsr, BCSR1_FETH_RST);
121
122 /* FCC1 pins are on port A/C. */
123 /* Configure port A and C pins for FCC1 Ethernet. */
124
125 tempval = in_be32(&io->iop_pdira);
126 tempval &= ~PA1_DIRA0;
127 tempval |= PA1_DIRA1;
128 out_be32(&io->iop_pdira, tempval);
129
130 tempval = in_be32(&io->iop_psora);
131 tempval &= ~PA1_PSORA0;
132 tempval |= PA1_PSORA1;
133 out_be32(&io->iop_psora, tempval);
134
135 setbits32(&io->iop_ppara, PA1_DIRA0 | PA1_DIRA1);
136
137 /* Alter clocks */
138 tempval = PC_CLK(fpi->clk_tx - 8) | PC_CLK(fpi->clk_rx - 8);
139
140 clrbits32(&io->iop_psorc, tempval);
141 clrbits32(&io->iop_pdirc, tempval);
142 setbits32(&io->iop_pparc, tempval);
143
144 cpm2_clk_setup(CPM_CLK_FCC1, fpi->clk_rx, CPM_CLK_RX);
145 cpm2_clk_setup(CPM_CLK_FCC1, fpi->clk_tx, CPM_CLK_TX);
146 54
147 iounmap(bcsr); 55static struct cpm_pin mpc8272_ads_pins[] = {
148 iounmap(immap); 56 /* SCC1 */
149} 57 {3, 30, CPM_PIN_OUTPUT | CPM_PIN_SECONDARY},
58 {3, 31, CPM_PIN_INPUT | CPM_PIN_PRIMARY},
59
60 /* SCC4 */
61 {3, 21, CPM_PIN_OUTPUT | CPM_PIN_PRIMARY},
62 {3, 22, CPM_PIN_INPUT | CPM_PIN_PRIMARY},
63
64 /* FCC1 */
65 {0, 14, CPM_PIN_INPUT | CPM_PIN_PRIMARY},
66 {0, 15, CPM_PIN_INPUT | CPM_PIN_PRIMARY},
67 {0, 16, CPM_PIN_INPUT | CPM_PIN_PRIMARY},
68 {0, 17, CPM_PIN_INPUT | CPM_PIN_PRIMARY},
69 {0, 18, CPM_PIN_OUTPUT | CPM_PIN_PRIMARY},
70 {0, 19, CPM_PIN_OUTPUT | CPM_PIN_PRIMARY},
71 {0, 20, CPM_PIN_OUTPUT | CPM_PIN_PRIMARY},
72 {0, 21, CPM_PIN_OUTPUT | CPM_PIN_PRIMARY},
73 {0, 26, CPM_PIN_INPUT | CPM_PIN_SECONDARY},
74 {0, 27, CPM_PIN_INPUT | CPM_PIN_SECONDARY},
75 {0, 28, CPM_PIN_OUTPUT | CPM_PIN_SECONDARY},
76 {0, 29, CPM_PIN_OUTPUT | CPM_PIN_SECONDARY},
77 {0, 30, CPM_PIN_INPUT | CPM_PIN_SECONDARY},
78 {0, 31, CPM_PIN_INPUT | CPM_PIN_SECONDARY},
79 {2, 21, CPM_PIN_INPUT | CPM_PIN_PRIMARY},
80 {2, 22, CPM_PIN_INPUT | CPM_PIN_PRIMARY},
81
82 /* FCC2 */
83 {1, 18, CPM_PIN_INPUT | CPM_PIN_PRIMARY},
84 {1, 19, CPM_PIN_INPUT | CPM_PIN_PRIMARY},
85 {1, 20, CPM_PIN_INPUT | CPM_PIN_PRIMARY},
86 {1, 21, CPM_PIN_INPUT | CPM_PIN_PRIMARY},
87 {1, 22, CPM_PIN_OUTPUT | CPM_PIN_PRIMARY},
88 {1, 23, CPM_PIN_OUTPUT | CPM_PIN_PRIMARY},
89 {1, 24, CPM_PIN_OUTPUT | CPM_PIN_PRIMARY},
90 {1, 25, CPM_PIN_OUTPUT | CPM_PIN_PRIMARY},
91 {1, 26, CPM_PIN_INPUT | CPM_PIN_PRIMARY},
92 {1, 27, CPM_PIN_INPUT | CPM_PIN_PRIMARY},
93 {1, 28, CPM_PIN_INPUT | CPM_PIN_PRIMARY},
94 {1, 29, CPM_PIN_OUTPUT | CPM_PIN_SECONDARY},
95 {1, 30, CPM_PIN_INPUT | CPM_PIN_PRIMARY},
96 {1, 31, CPM_PIN_OUTPUT | CPM_PIN_PRIMARY},
97 {2, 16, CPM_PIN_INPUT | CPM_PIN_PRIMARY},
98 {2, 17, CPM_PIN_INPUT | CPM_PIN_PRIMARY},
99};
150 100
151static void init_fcc2_ioports(struct fs_platform_info *fpi) 101static void __init init_ioports(void)
152{ 102{
153 cpm2_map_t *immap = ioremap(get_immrbase(), sizeof(cpm2_map_t)); 103 int i;
154 struct device_node *np;
155 struct resource r;
156 u32 *bcsr;
157
158 struct io_port *io;
159 u32 tempval;
160
161 np = of_find_node_by_type(NULL, "memory");
162 if (!np) {
163 printk(KERN_INFO "No memory node in device tree\n");
164 return;
165 }
166 if (of_address_to_resource(np, 1, &r)) {
167 printk(KERN_INFO "No memory reg property [1] in devicetree\n");
168 return;
169 }
170 of_node_put(np);
171 io = &immap->im_ioport;
172 bcsr = ioremap(r.start + 12, sizeof(u32));
173
174 /* Enable the PHY */
175 clrbits32(bcsr, BCSR3_FETHIEN2);
176 setbits32(bcsr, BCSR3_FETH2_RST);
177
178 /* FCC2 are port B/C. */
179 /* Configure port A and C pins for FCC2 Ethernet. */
180
181 tempval = in_be32(&io->iop_pdirb);
182 tempval &= ~PB2_DIRB0;
183 tempval |= PB2_DIRB1;
184 out_be32(&io->iop_pdirb, tempval);
185
186 tempval = in_be32(&io->iop_psorb);
187 tempval &= ~PB2_PSORB0;
188 tempval |= PB2_PSORB1;
189 out_be32(&io->iop_psorb, tempval);
190
191 setbits32(&io->iop_pparb, PB2_DIRB0 | PB2_DIRB1);
192
193 tempval = PC_CLK(fpi->clk_tx - 8) | PC_CLK(fpi->clk_rx - 8);
194
195 /* Alter clocks */
196 clrbits32(&io->iop_psorc, tempval);
197 clrbits32(&io->iop_pdirc, tempval);
198 setbits32(&io->iop_pparc, tempval);
199
200 cpm2_clk_setup(CPM_CLK_FCC2, fpi->clk_rx, CPM_CLK_RX);
201 cpm2_clk_setup(CPM_CLK_FCC2, fpi->clk_tx, CPM_CLK_TX);
202
203 iounmap(bcsr);
204 iounmap(immap);
205}
206 104
207void init_fcc_ioports(struct fs_platform_info *fpi) 105 for (i = 0; i < ARRAY_SIZE(mpc8272_ads_pins); i++) {
208{ 106 struct cpm_pin *pin = &mpc8272_ads_pins[i];
209 int fcc_no = fs_get_fcc_index(fpi->fs_no); 107 cpm2_set_pin(pin->port, pin->pin, pin->flags);
210
211 switch (fcc_no) {
212 case 0:
213 init_fcc1_ioports(fpi);
214 break;
215 case 1:
216 init_fcc2_ioports(fpi);
217 break;
218 default:
219 printk(KERN_ERR "init_fcc_ioports: invalid FCC number\n");
220 return;
221 } 108 }
222}
223 109
224static void init_scc1_uart_ioports(struct fs_uart_platform_info *data) 110 cpm2_clk_setup(CPM_CLK_SCC1, CPM_BRG1, CPM_CLK_RX);
225{ 111 cpm2_clk_setup(CPM_CLK_SCC1, CPM_BRG1, CPM_CLK_TX);
226 cpm2_map_t *immap = ioremap(get_immrbase(), sizeof(cpm2_map_t)); 112 cpm2_clk_setup(CPM_CLK_SCC4, CPM_BRG4, CPM_CLK_RX);
227 113 cpm2_clk_setup(CPM_CLK_SCC4, CPM_BRG4, CPM_CLK_TX);
228 /* SCC1 is only on port D */ 114 cpm2_clk_setup(CPM_CLK_FCC1, CPM_CLK11, CPM_CLK_RX);
229 setbits32(&immap->im_ioport.iop_ppard, 0x00000003); 115 cpm2_clk_setup(CPM_CLK_FCC1, CPM_CLK10, CPM_CLK_TX);
230 clrbits32(&immap->im_ioport.iop_psord, 0x00000001); 116 cpm2_clk_setup(CPM_CLK_FCC2, CPM_CLK15, CPM_CLK_RX);
231 setbits32(&immap->im_ioport.iop_psord, 0x00000002); 117 cpm2_clk_setup(CPM_CLK_FCC2, CPM_CLK16, CPM_CLK_TX);
232 clrbits32(&immap->im_ioport.iop_pdird, 0x00000001);
233 setbits32(&immap->im_ioport.iop_pdird, 0x00000002);
234
235 clrbits32(&immap->im_cpmux.cmx_scr, (0x00000007 << (4 - data->clk_tx)));
236 clrbits32(&immap->im_cpmux.cmx_scr, (0x00000038 << (4 - data->clk_rx)));
237 setbits32(&immap->im_cpmux.cmx_scr,
238 ((data->clk_tx - 1) << (4 - data->clk_tx)));
239 setbits32(&immap->im_cpmux.cmx_scr,
240 ((data->clk_rx - 1) << (4 - data->clk_rx)));
241
242 iounmap(immap);
243} 118}
244 119
245static void init_scc4_uart_ioports(struct fs_uart_platform_info *data) 120static void __init mpc8272_ads_setup_arch(void)
246{ 121{
247 cpm2_map_t *immap = ioremap(get_immrbase(), sizeof(cpm2_map_t)); 122 struct device_node *np;
248 123 __be32 __iomem *bcsr;
249 setbits32(&immap->im_ioport.iop_ppard, 0x00000600);
250 clrbits32(&immap->im_ioport.iop_psord, 0x00000600);
251 clrbits32(&immap->im_ioport.iop_pdird, 0x00000200);
252 setbits32(&immap->im_ioport.iop_pdird, 0x00000400);
253
254 clrbits32(&immap->im_cpmux.cmx_scr, (0x00000007 << (4 - data->clk_tx)));
255 clrbits32(&immap->im_cpmux.cmx_scr, (0x00000038 << (4 - data->clk_rx)));
256 setbits32(&immap->im_cpmux.cmx_scr,
257 ((data->clk_tx - 1) << (4 - data->clk_tx)));
258 setbits32(&immap->im_cpmux.cmx_scr,
259 ((data->clk_rx - 1) << (4 - data->clk_rx)));
260
261 iounmap(immap);
262}
263 124
264void init_scc_ioports(struct fs_uart_platform_info *data) 125 if (ppc_md.progress)
265{ 126 ppc_md.progress("mpc8272_ads_setup_arch()", 0);
266 int scc_no = fs_get_scc_index(data->fs_no);
267
268 switch (scc_no) {
269 case 0:
270 init_scc1_uart_ioports(data);
271 data->brg = data->clk_rx;
272 break;
273 case 3:
274 init_scc4_uart_ioports(data);
275 data->brg = data->clk_rx;
276 break;
277 default:
278 printk(KERN_ERR "init_scc_ioports: invalid SCC number\n");
279 return;
280 }
281}
282 127
283void __init m82xx_board_setup(void) 128 cpm2_reset();
284{
285 cpm2_map_t *immap = ioremap(get_immrbase(), sizeof(cpm2_map_t));
286 struct device_node *np;
287 struct resource r;
288 u32 *bcsr;
289 129
290 np = of_find_node_by_type(NULL, "memory"); 130 np = of_find_compatible_node(NULL, NULL, "fsl,mpc8272ads-bcsr");
291 if (!np) { 131 if (!np) {
292 printk(KERN_INFO "No memory node in device tree\n"); 132 printk(KERN_ERR "No bcsr in device tree\n");
293 return; 133 return;
294 } 134 }
295 if (of_address_to_resource(np, 1, &r)) { 135
296 printk(KERN_INFO "No memory reg property [1] in devicetree\n"); 136 bcsr = of_iomap(np, 0);
137 if (!bcsr) {
138 printk(KERN_ERR "Cannot map BCSR registers\n");
297 return; 139 return;
298 } 140 }
299 of_node_put(np);
300 bcsr = ioremap(r.start + 4, sizeof(u32));
301 /* Enable the 2nd UART port */
302 clrbits32(bcsr, BCSR1_RS232_EN2);
303
304#ifdef CONFIG_SERIAL_CPM_SCC1
305 clrbits32((u32 *) & immap->im_scc[0].scc_sccm,
306 UART_SCCM_TX | UART_SCCM_RX);
307 clrbits32((u32 *) & immap->im_scc[0].scc_gsmrl,
308 SCC_GSMRL_ENR | SCC_GSMRL_ENT);
309#endif
310
311#ifdef CONFIG_SERIAL_CPM_SCC2
312 clrbits32((u32 *) & immap->im_scc[1].scc_sccm,
313 UART_SCCM_TX | UART_SCCM_RX);
314 clrbits32((u32 *) & immap->im_scc[1].scc_gsmrl,
315 SCC_GSMRL_ENR | SCC_GSMRL_ENT);
316#endif
317
318#ifdef CONFIG_SERIAL_CPM_SCC3
319 clrbits32((u32 *) & immap->im_scc[2].scc_sccm,
320 UART_SCCM_TX | UART_SCCM_RX);
321 clrbits32((u32 *) & immap->im_scc[2].scc_gsmrl,
322 SCC_GSMRL_ENR | SCC_GSMRL_ENT);
323#endif
324
325#ifdef CONFIG_SERIAL_CPM_SCC4
326 clrbits32((u32 *) & immap->im_scc[3].scc_sccm,
327 UART_SCCM_TX | UART_SCCM_RX);
328 clrbits32((u32 *) & immap->im_scc[3].scc_gsmrl,
329 SCC_GSMRL_ENR | SCC_GSMRL_ENT);
330#endif
331
332 iounmap(bcsr);
333 iounmap(immap);
334}
335
336#ifdef CONFIG_PCI
337static void m82xx_pci_mask_irq(unsigned int irq)
338{
339 int bit = irq - pci_int_base;
340 141
341 *pci_regs.pci_int_mask_reg |= (1 << (31 - bit)); 142 of_node_put(np);
342 return;
343}
344 143
345static void m82xx_pci_unmask_irq(unsigned int irq) 144 clrbits32(&bcsr[1], BCSR1_RS232_EN1 | BCSR1_RS232_EN2 | BCSR1_FETHIEN);
346{ 145 setbits32(&bcsr[1], BCSR1_FETH_RST);
347 int bit = irq - pci_int_base;
348 146
349 *pci_regs.pci_int_mask_reg &= ~(1 << (31 - bit)); 147 clrbits32(&bcsr[3], BCSR3_FETHIEN2);
350 return; 148 setbits32(&bcsr[3], BCSR3_FETH2_RST);
351}
352 149
353static void m82xx_pci_mask_and_ack(unsigned int irq) 150 iounmap(bcsr);
354{
355 int bit = irq - pci_int_base;
356
357 *pci_regs.pci_int_mask_reg |= (1 << (31 - bit));
358 return;
359}
360 151
361static void m82xx_pci_end_irq(unsigned int irq) 152 init_ioports();
362{ 153 pq2_init_pci();
363 int bit = irq - pci_int_base;
364 154
365 *pci_regs.pci_int_mask_reg &= ~(1 << (31 - bit)); 155 if (ppc_md.progress)
366 return; 156 ppc_md.progress("mpc8272_ads_setup_arch(), finish", 0);
367} 157}
368 158
369struct hw_interrupt_type m82xx_pci_ic = { 159static struct of_device_id __initdata of_bus_ids[] = {
370 .typename = "MPC82xx ADS PCI", 160 { .name = "soc", },
371 .name = "MPC82xx ADS PCI", 161 { .name = "cpm", },
372 .enable = m82xx_pci_unmask_irq, 162 { .name = "localbus", },
373 .disable = m82xx_pci_mask_irq, 163 {},
374 .ack = m82xx_pci_mask_and_ack,
375 .end = m82xx_pci_end_irq,
376 .mask = m82xx_pci_mask_irq,
377 .mask_ack = m82xx_pci_mask_and_ack,
378 .unmask = m82xx_pci_unmask_irq,
379 .eoi = m82xx_pci_end_irq,
380}; 164};
381 165
382static void 166static int __init declare_of_platform_devices(void)
383m82xx_pci_irq_demux(unsigned int irq, struct irq_desc *desc)
384{ 167{
385 unsigned long stat, mask, pend; 168 if (!machine_is(mpc8272_ads))
386 int bit; 169 return 0;
387
388 for (;;) {
389 stat = *pci_regs.pci_int_stat_reg;
390 mask = *pci_regs.pci_int_mask_reg;
391 pend = stat & ~mask & 0xf0000000;
392 if (!pend)
393 break;
394 for (bit = 0; pend != 0; ++bit, pend <<= 1) {
395 if (pend & 0x80000000)
396 __do_IRQ(pci_int_base + bit);
397 }
398 }
399}
400 170
401static int pci_pic_host_map(struct irq_host *h, unsigned int virq, 171 /* Publish the QE devices */
402 irq_hw_number_t hw) 172 of_platform_bus_probe(NULL, of_bus_ids, NULL);
403{
404 get_irq_desc(virq)->status |= IRQ_LEVEL;
405 set_irq_chip(virq, &m82xx_pci_ic);
406 return 0; 173 return 0;
407} 174}
408 175device_initcall(declare_of_platform_devices);
409static void pci_host_unmap(struct irq_host *h, unsigned int virq)
410{
411 /* remove chip and handler */
412 set_irq_chip(virq, NULL);
413}
414
415static struct irq_host_ops pci_pic_host_ops = {
416 .map = pci_pic_host_map,
417 .unmap = pci_host_unmap,
418};
419
420void m82xx_pci_init_irq(void)
421{
422 int irq;
423 cpm2_map_t *immap;
424 struct device_node *np;
425 struct resource r;
426 const u32 *regs;
427 unsigned int size;
428 const u32 *irq_map;
429 int i;
430 unsigned int irq_max, irq_min;
431
432 if ((np = of_find_node_by_type(NULL, "soc")) == NULL) {
433 printk(KERN_INFO "No SOC node in device tree\n");
434 return;
435 }
436 memset(&r, 0, sizeof(r));
437 if (of_address_to_resource(np, 0, &r)) {
438 printk(KERN_INFO "No SOC reg property in device tree\n");
439 return;
440 }
441 immap = ioremap(r.start, sizeof(*immap));
442 of_node_put(np);
443
444 /* install the demultiplexer for the PCI cascade interrupt */
445 np = of_find_node_by_type(NULL, "pci");
446 if (!np) {
447 printk(KERN_INFO "No pci node on device tree\n");
448 iounmap(immap);
449 return;
450 }
451 irq_map = of_get_property(np, "interrupt-map", &size);
452 if ((!irq_map) || (size <= 7)) {
453 printk(KERN_INFO "No interrupt-map property of pci node\n");
454 iounmap(immap);
455 return;
456 }
457 size /= sizeof(irq_map[0]);
458 for (i = 0, irq_max = 0, irq_min = 512; i < size; i += 7, irq_map += 7) {
459 if (irq_map[5] < irq_min)
460 irq_min = irq_map[5];
461 if (irq_map[5] > irq_max)
462 irq_max = irq_map[5];
463 }
464 pci_int_base = irq_min;
465 irq = irq_of_parse_and_map(np, 0);
466 set_irq_chained_handler(irq, m82xx_pci_irq_demux);
467 of_node_put(np);
468 np = of_find_node_by_type(NULL, "pci-pic");
469 if (!np) {
470 printk(KERN_INFO "No pci pic node on device tree\n");
471 iounmap(immap);
472 return;
473 }
474 /* PCI interrupt controller registers: status and mask */
475 regs = of_get_property(np, "reg", &size);
476 if ((!regs) || (size <= 2)) {
477 printk(KERN_INFO "No reg property in pci pic node\n");
478 iounmap(immap);
479 return;
480 }
481 pci_regs.pci_int_stat_reg =
482 ioremap(regs[0], sizeof(*pci_regs.pci_int_stat_reg));
483 pci_regs.pci_int_mask_reg =
484 ioremap(regs[1], sizeof(*pci_regs.pci_int_mask_reg));
485 /* configure chip select for PCI interrupt controller */
486 immap->im_memctl.memc_br3 = regs[0] | 0x00001801;
487 immap->im_memctl.memc_or3 = 0xffff8010;
488 /* make PCI IRQ level sensitive */
489 immap->im_intctl.ic_siexr &= ~(1 << (14 - (irq - SIU_INT_IRQ1)));
490
491 /* mask all PCI interrupts */
492 *pci_regs.pci_int_mask_reg |= 0xfff00000;
493 iounmap(immap);
494 pci_pic_host =
495 irq_alloc_host(np, IRQ_HOST_MAP_LINEAR, irq_max - irq_min + 1,
496 &pci_pic_host_ops, irq_max + 1);
497 return;
498}
499
500static int m82xx_pci_exclude_device(struct pci_controller *hose,
501 u_char bus, u_char devfn)
502{
503 if (bus == 0 && PCI_SLOT(devfn) == 0)
504 return PCIBIOS_DEVICE_NOT_FOUND;
505 else
506 return PCIBIOS_SUCCESSFUL;
507}
508
509static void __init mpc82xx_add_bridge(struct device_node *np)
510{
511 int len;
512 struct pci_controller *hose;
513 struct resource r;
514 const int *bus_range;
515 const uint *ptr;
516
517 memset(&r, 0, sizeof(r));
518 if (of_address_to_resource(np, 0, &r)) {
519 printk(KERN_INFO "No PCI reg property in device tree\n");
520 return;
521 }
522 if (!(ptr = of_get_property(np, "clock-frequency", NULL))) {
523 printk(KERN_INFO "No clock-frequency property in PCI node");
524 return;
525 }
526 pci_clk_frq = *ptr;
527 of_node_put(np);
528 bus_range = of_get_property(np, "bus-range", &len);
529 if (bus_range == NULL || len < 2 * sizeof(int)) {
530 printk(KERN_WARNING "Can't get bus-range for %s, assume"
531 " bus 0\n", np->full_name);
532 }
533
534 pci_assign_all_buses = 1;
535
536 hose = pcibios_alloc_controller(np);
537
538 if (!hose)
539 return;
540
541 hose->first_busno = bus_range ? bus_range[0] : 0;
542 hose->last_busno = bus_range ? bus_range[1] : 0xff;
543
544 setup_indirect_pci(hose,
545 r.start + offsetof(pci_cpm2_t, pci_cfg_addr),
546 r.start + offsetof(pci_cpm2_t, pci_cfg_data),
547 0);
548
549 pci_process_bridge_OF_ranges(hose, np, 1);
550}
551#endif
552
553/*
554 * Setup the architecture
555 */
556static void __init mpc8272_ads_setup_arch(void)
557{
558#ifdef CONFIG_PCI
559 struct device_node *np;
560#endif
561
562 if (ppc_md.progress)
563 ppc_md.progress("mpc8272_ads_setup_arch()", 0);
564 cpm2_reset();
565
566 /* Map I/O region to a 256MB BAT */
567
568 m82xx_board_setup();
569
570#ifdef CONFIG_PCI
571 ppc_md.pci_exclude_device = m82xx_pci_exclude_device;
572 for (np = NULL; (np = of_find_node_by_type(np, "pci")) != NULL;)
573 mpc82xx_add_bridge(np);
574
575 of_node_put(np);
576#endif
577
578#ifdef CONFIG_ROOT_NFS
579 ROOT_DEV = Root_NFS;
580#else
581 ROOT_DEV = Root_HDA1;
582#endif
583
584 if (ppc_md.progress)
585 ppc_md.progress("mpc8272_ads_setup_arch(), finish", 0);
586}
587 176
588/* 177/*
589 * Called very early, device-tree isn't unflattened 178 * Called very early, device-tree isn't unflattened
590 */ 179 */
591static int __init mpc8272_ads_probe(void) 180static int __init mpc8272_ads_probe(void)
592{ 181{
593 /* We always match for now, eventually we should look at 182 unsigned long root = of_get_flat_dt_root();
594 * the flat dev tree to ensure this is the board we are 183 return of_flat_dt_is_compatible(root, "fsl,mpc8272ads");
595 * supposed to run on
596 */
597 return 1;
598}
599
600#define RMR_CSRE 0x00000001
601static void m82xx_restart(char *cmd)
602{
603 __volatile__ unsigned char dummy;
604
605 local_irq_disable();
606 ((cpm2_map_t *) cpm2_immr)->im_clkrst.car_rmr |= RMR_CSRE;
607
608 /* Clear the ME,EE,IR & DR bits in MSR to cause checkstop */
609 mtmsr(mfmsr() & ~(MSR_ME | MSR_EE | MSR_IR | MSR_DR));
610 dummy = ((cpm2_map_t *) cpm2_immr)->im_clkrst.res[0];
611 printk("Restart failed\n");
612 while (1) ;
613} 184}
614 185
615define_machine(mpc8272_ads) 186define_machine(mpc8272_ads)
616{ 187{
617 .name = "MPC8272 ADS", 188 .name = "Freescale MPC8272 ADS",
618 .probe = mpc8272_ads_probe, 189 .probe = mpc8272_ads_probe,
619 .setup_arch = mpc8272_ads_setup_arch, 190 .setup_arch = mpc8272_ads_setup_arch,
620 .init_IRQ = mpc8272_ads_pic_init, 191 .init_IRQ = mpc8272_ads_pic_init,
621 .get_irq = cpm2_get_irq, 192 .get_irq = cpm2_get_irq,
622 .calibrate_decr = generic_calibrate_decr, 193 .calibrate_decr = generic_calibrate_decr,
623 .restart = m82xx_restart, 194 .restart = pq2_restart,
195 .progress = udbg_progress,
624}; 196};
diff --git a/arch/powerpc/platforms/82xx/pq2.c b/arch/powerpc/platforms/82xx/pq2.c
new file mode 100644
index 000000000000..a497cbaa1ac5
--- /dev/null
+++ b/arch/powerpc/platforms/82xx/pq2.c
@@ -0,0 +1,82 @@
1/*
2 * Common PowerQUICC II code.
3 *
4 * Author: Scott Wood <scottwood@freescale.com>
5 * Copyright (c) 2007 Freescale Semiconductor
6 *
7 * Based on code by Vitaly Bordug <vbordug@ru.mvista.com>
8 * pq2_restart fix by Wade Farnsworth <wfarnsworth@mvista.com>
9 * Copyright (c) 2006 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#include <asm/cpm2.h>
18#include <asm/io.h>
19#include <asm/pci-bridge.h>
20#include <asm/system.h>
21
22#include <platforms/82xx/pq2.h>
23
24#define RMR_CSRE 0x00000001
25
26void pq2_restart(char *cmd)
27{
28 local_irq_disable();
29 setbits32(&cpm2_immr->im_clkrst.car_rmr, RMR_CSRE);
30
31 /* Clear the ME,EE,IR & DR bits in MSR to cause checkstop */
32 mtmsr(mfmsr() & ~(MSR_ME | MSR_EE | MSR_IR | MSR_DR));
33 in_8(&cpm2_immr->im_clkrst.res[0]);
34
35 panic("Restart failed\n");
36}
37
38#ifdef CONFIG_PCI
39static int pq2_pci_exclude_device(struct pci_controller *hose,
40 u_char bus, u8 devfn)
41{
42 if (bus == 0 && PCI_SLOT(devfn) == 0)
43 return PCIBIOS_DEVICE_NOT_FOUND;
44 else
45 return PCIBIOS_SUCCESSFUL;
46}
47
48static void __init pq2_pci_add_bridge(struct device_node *np)
49{
50 struct pci_controller *hose;
51 struct resource r;
52
53 if (of_address_to_resource(np, 0, &r) || r.end - r.start < 0x10b)
54 goto err;
55
56 pci_assign_all_buses = 1;
57
58 hose = pcibios_alloc_controller(np);
59 if (!hose)
60 return;
61
62 hose->arch_data = np;
63
64 setup_indirect_pci(hose, r.start + 0x100, r.start + 0x104, 0);
65 pci_process_bridge_OF_ranges(hose, np, 1);
66
67 return;
68
69err:
70 printk(KERN_ERR "No valid PCI reg property in device tree\n");
71}
72
73void __init pq2_init_pci(void)
74{
75 struct device_node *np = NULL;
76
77 ppc_md.pci_exclude_device = pq2_pci_exclude_device;
78
79 while ((np = of_find_compatible_node(np, NULL, "fsl,pq2-pci")))
80 pq2_pci_add_bridge(np);
81}
82#endif
diff --git a/arch/powerpc/platforms/82xx/pq2.h b/arch/powerpc/platforms/82xx/pq2.h
new file mode 100644
index 000000000000..a41f84ae2325
--- /dev/null
+++ b/arch/powerpc/platforms/82xx/pq2.h
@@ -0,0 +1,20 @@
1#ifndef _PQ2_H
2#define _PQ2_H
3
4void pq2_restart(char *cmd);
5
6#ifdef CONFIG_PCI
7int pq2ads_pci_init_irq(void);
8void pq2_init_pci(void);
9#else
10static inline int pq2ads_pci_init_irq(void)
11{
12 return 0;
13}
14
15static inline void pq2_init_pci(void)
16{
17}
18#endif
19
20#endif
diff --git a/arch/powerpc/platforms/82xx/pq2ads-pci-pic.c b/arch/powerpc/platforms/82xx/pq2ads-pci-pic.c
new file mode 100644
index 000000000000..a8013816125c
--- /dev/null
+++ b/arch/powerpc/platforms/82xx/pq2ads-pci-pic.c
@@ -0,0 +1,195 @@
1/*
2 * PQ2 ADS-style PCI interrupt controller
3 *
4 * Copyright 2007 Freescale Semiconductor, Inc.
5 * Author: Scott Wood <scottwood@freescale.com>
6 *
7 * Loosely based on mpc82xx ADS support by Vitaly Bordug <vbordug@ru.mvista.com>
8 * Copyright (c) 2006 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 version 2 as published
12 * by the Free Software Foundation.
13 */
14
15#include <linux/init.h>
16#include <linux/spinlock.h>
17#include <linux/irq.h>
18#include <linux/types.h>
19#include <linux/bootmem.h>
20
21#include <asm/io.h>
22#include <asm/prom.h>
23#include <asm/cpm2.h>
24
25#include "pq2.h"
26
27static DEFINE_SPINLOCK(pci_pic_lock);
28
29struct pq2ads_pci_pic {
30 struct device_node *node;
31 struct irq_host *host;
32
33 struct {
34 u32 stat;
35 u32 mask;
36 } __iomem *regs;
37};
38
39#define NUM_IRQS 32
40
41static void pq2ads_pci_mask_irq(unsigned int virq)
42{
43 struct pq2ads_pci_pic *priv = get_irq_chip_data(virq);
44 int irq = NUM_IRQS - virq_to_hw(virq) - 1;
45
46 if (irq != -1) {
47 unsigned long flags;
48 spin_lock_irqsave(&pci_pic_lock, flags);
49
50 setbits32(&priv->regs->mask, 1 << irq);
51 mb();
52
53 spin_unlock_irqrestore(&pci_pic_lock, flags);
54 }
55}
56
57static void pq2ads_pci_unmask_irq(unsigned int virq)
58{
59 struct pq2ads_pci_pic *priv = get_irq_chip_data(virq);
60 int irq = NUM_IRQS - virq_to_hw(virq) - 1;
61
62 if (irq != -1) {
63 unsigned long flags;
64
65 spin_lock_irqsave(&pci_pic_lock, flags);
66 clrbits32(&priv->regs->mask, 1 << irq);
67 spin_unlock_irqrestore(&pci_pic_lock, flags);
68 }
69}
70
71static struct irq_chip pq2ads_pci_ic = {
72 .typename = "PQ2 ADS PCI",
73 .name = "PQ2 ADS PCI",
74 .end = pq2ads_pci_unmask_irq,
75 .mask = pq2ads_pci_mask_irq,
76 .mask_ack = pq2ads_pci_mask_irq,
77 .ack = pq2ads_pci_mask_irq,
78 .unmask = pq2ads_pci_unmask_irq,
79 .enable = pq2ads_pci_unmask_irq,
80 .disable = pq2ads_pci_mask_irq
81};
82
83static void pq2ads_pci_irq_demux(unsigned int irq, struct irq_desc *desc)
84{
85 struct pq2ads_pci_pic *priv = desc->handler_data;
86 u32 stat, mask, pend;
87 int bit;
88
89 for (;;) {
90 stat = in_be32(&priv->regs->stat);
91 mask = in_be32(&priv->regs->mask);
92
93 pend = stat & ~mask;
94
95 if (!pend)
96 break;
97
98 for (bit = 0; pend != 0; ++bit, pend <<= 1) {
99 if (pend & 0x80000000) {
100 int virq = irq_linear_revmap(priv->host, bit);
101 generic_handle_irq(virq);
102 }
103 }
104 }
105}
106
107static int pci_pic_host_map(struct irq_host *h, unsigned int virq,
108 irq_hw_number_t hw)
109{
110 get_irq_desc(virq)->status |= IRQ_LEVEL;
111 set_irq_chip_data(virq, h->host_data);
112 set_irq_chip(virq, &pq2ads_pci_ic);
113 return 0;
114}
115
116static void pci_host_unmap(struct irq_host *h, unsigned int virq)
117{
118 /* remove chip and handler */
119 set_irq_chip_data(virq, NULL);
120 set_irq_chip(virq, NULL);
121}
122
123static struct irq_host_ops pci_pic_host_ops = {
124 .map = pci_pic_host_map,
125 .unmap = pci_host_unmap,
126};
127
128int __init pq2ads_pci_init_irq(void)
129{
130 struct pq2ads_pci_pic *priv;
131 struct irq_host *host;
132 struct device_node *np;
133 int ret = -ENODEV;
134 int irq;
135
136 np = of_find_compatible_node(NULL, NULL, "fsl,pq2ads-pci-pic");
137 if (!np) {
138 printk(KERN_ERR "No pci pic node in device tree.\n");
139 of_node_put(np);
140 goto out;
141 }
142
143 irq = irq_of_parse_and_map(np, 0);
144 if (irq == NO_IRQ) {
145 printk(KERN_ERR "No interrupt in pci pic node.\n");
146 of_node_put(np);
147 goto out;
148 }
149
150 priv = alloc_bootmem(sizeof(struct pq2ads_pci_pic));
151 if (!priv) {
152 of_node_put(np);
153 ret = -ENOMEM;
154 goto out_unmap_irq;
155 }
156
157 /* PCI interrupt controller registers: status and mask */
158 priv->regs = of_iomap(np, 0);
159 if (!priv->regs) {
160 printk(KERN_ERR "Cannot map PCI PIC registers.\n");
161 goto out_free_bootmem;
162 }
163
164 /* mask all PCI interrupts */
165 out_be32(&priv->regs->mask, ~0);
166 mb();
167
168 host = irq_alloc_host(np, IRQ_HOST_MAP_LINEAR, NUM_IRQS,
169 &pci_pic_host_ops, NUM_IRQS);
170 if (!host) {
171 ret = -ENOMEM;
172 goto out_unmap_regs;
173 }
174
175 host->host_data = priv;
176
177 priv->host = host;
178 host->host_data = priv;
179 set_irq_data(irq, priv);
180 set_irq_chained_handler(irq, pq2ads_pci_irq_demux);
181
182 of_node_put(np);
183 return 0;
184
185out_unmap_regs:
186 iounmap(priv->regs);
187out_free_bootmem:
188 free_bootmem((unsigned long)priv,
189 sizeof(sizeof(struct pq2ads_pci_pic)));
190 of_node_put(np);
191out_unmap_irq:
192 irq_dispose_mapping(irq);
193out:
194 return ret;
195}
diff --git a/arch/powerpc/platforms/82xx/pq2ads.h b/arch/powerpc/platforms/82xx/pq2ads.h
index 8b67048e6f22..984db42cc8e7 100644
--- a/arch/powerpc/platforms/82xx/pq2ads.h
+++ b/arch/powerpc/platforms/82xx/pq2ads.h
@@ -53,7 +53,5 @@
53#define SIU_INT_SCC3 ((uint)0x2a+CPM_IRQ_OFFSET) 53#define SIU_INT_SCC3 ((uint)0x2a+CPM_IRQ_OFFSET)
54#define SIU_INT_SCC4 ((uint)0x2b+CPM_IRQ_OFFSET) 54#define SIU_INT_SCC4 ((uint)0x2b+CPM_IRQ_OFFSET)
55 55
56void m82xx_pci_init_irq(void);
57
58#endif /* __MACH_ADS8260_DEFS */ 56#endif /* __MACH_ADS8260_DEFS */
59#endif /* __KERNEL__ */ 57#endif /* __KERNEL__ */