1/*
2 * MPC85xx DS Board Setup
3 *
4 * Author Xianghua Xiao (x.xiao@freescale.com)
5 * Roy Zang <tie-fei.zang@freescale.com>
6 * 	- Add PCI/PCI Exprees support
7 * Copyright 2007 Freescale Semiconductor 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/stddef.h>
16#include <linux/kernel.h>
17#include <linux/pci.h>
18#include <linux/kdev_t.h>
19#include <linux/delay.h>
20#include <linux/seq_file.h>
21#include <linux/interrupt.h>
22#include <linux/of_platform.h>
23
24#include <asm/time.h>
25#include <asm/machdep.h>
26#include <asm/pci-bridge.h>
27#include <mm/mmu_decl.h>
28#include <asm/prom.h>
29#include <asm/udbg.h>
30#include <asm/mpic.h>
31#include <asm/i8259.h>
32#include <asm/swiotlb.h>
33
34#include <sysdev/fsl_soc.h>
35#include <sysdev/fsl_pci.h>
36#include "smp.h"
37
38#include "mpc85xx.h"
39
40#undef DEBUG
41
42#ifdef DEBUG
43#define DBG(fmt, args...) printk(KERN_ERR "%s: " fmt, __func__, ## args)
44#else
45#define DBG(fmt, args...)
46#endif
47
48#ifdef CONFIG_PPC_I8259
49static void mpc85xx_8259_cascade(struct irq_desc *desc)
50{
51	struct irq_chip *chip = irq_desc_get_chip(desc);
52	unsigned int cascade_irq = i8259_irq();
53
54	if (cascade_irq != NO_IRQ) {
55		generic_handle_irq(cascade_irq);
56	}
57	chip->irq_eoi(&desc->irq_data);
58}
59#endif	/* CONFIG_PPC_I8259 */
60
61void __init mpc85xx_ds_pic_init(void)
62{
63	struct mpic *mpic;
64#ifdef CONFIG_PPC_I8259
65	struct device_node *np;
66	struct device_node *cascade_node = NULL;
67	int cascade_irq;
68#endif
69	unsigned long root = of_get_flat_dt_root();
70
71	if (of_flat_dt_is_compatible(root, "fsl,MPC8572DS-CAMP")) {
72		mpic = mpic_alloc(NULL, 0,
73			MPIC_NO_RESET |
74			MPIC_BIG_ENDIAN |
75			MPIC_SINGLE_DEST_CPU,
76			0, 256, " OpenPIC  ");
77	} else {
78		mpic = mpic_alloc(NULL, 0,
79			  MPIC_BIG_ENDIAN |
80			  MPIC_SINGLE_DEST_CPU,
81			0, 256, " OpenPIC  ");
82	}
83
84	BUG_ON(mpic == NULL);
85	mpic_init(mpic);
86
87#ifdef CONFIG_PPC_I8259
88	/* Initialize the i8259 controller */
89	for_each_node_by_type(np, "interrupt-controller")
90	    if (of_device_is_compatible(np, "chrp,iic")) {
91		cascade_node = np;
92		break;
93	}
94
95	if (cascade_node == NULL) {
96		printk(KERN_DEBUG "Could not find i8259 PIC\n");
97		return;
98	}
99
100	cascade_irq = irq_of_parse_and_map(cascade_node, 0);
101	if (cascade_irq == NO_IRQ) {
102		printk(KERN_ERR "Failed to map cascade interrupt\n");
103		return;
104	}
105
106	DBG("mpc85xxds: cascade mapped to irq %d\n", cascade_irq);
107
108	i8259_init(cascade_node, 0);
109	of_node_put(cascade_node);
110
111	irq_set_chained_handler(cascade_irq, mpc85xx_8259_cascade);
112#endif	/* CONFIG_PPC_I8259 */
113}
114
115#ifdef CONFIG_PCI
116extern int uli_exclude_device(struct pci_controller *hose,
117				u_char bus, u_char devfn);
118
119static struct device_node *pci_with_uli;
120
121static int mpc85xx_exclude_device(struct pci_controller *hose,
122				   u_char bus, u_char devfn)
123{
124	if (hose->dn == pci_with_uli)
125		return uli_exclude_device(hose, bus, devfn);
126
127	return PCIBIOS_SUCCESSFUL;
128}
129#endif	/* CONFIG_PCI */
130
131static void __init mpc85xx_ds_uli_init(void)
132{
133#ifdef CONFIG_PCI
134	struct device_node *node;
135
136	/* See if we have a ULI under the primary */
137
138	node = of_find_node_by_name(NULL, "uli1575");
139	while ((pci_with_uli = of_get_parent(node))) {
140		of_node_put(node);
141		node = pci_with_uli;
142
143		if (pci_with_uli == fsl_pci_primary) {
144			ppc_md.pci_exclude_device = mpc85xx_exclude_device;
145			break;
146		}
147	}
148#endif
149}
150
151/*
152 * Setup the architecture
153 */
154static void __init mpc85xx_ds_setup_arch(void)
155{
156	if (ppc_md.progress)
157		ppc_md.progress("mpc85xx_ds_setup_arch()", 0);
158
159	swiotlb_detect_4g();
160	fsl_pci_assign_primary();
161	mpc85xx_ds_uli_init();
162	mpc85xx_smp_init();
163
164	printk("MPC85xx DS board from Freescale Semiconductor\n");
165}
166
167/*
168 * Called very early, device-tree isn't unflattened
169 */
170static int __init mpc8544_ds_probe(void)
171{
172	unsigned long root = of_get_flat_dt_root();
173
174	return !!of_flat_dt_is_compatible(root, "MPC8544DS");
175}
176
177machine_arch_initcall(mpc8544_ds, mpc85xx_common_publish_devices);
178machine_arch_initcall(mpc8572_ds, mpc85xx_common_publish_devices);
179machine_arch_initcall(p2020_ds, mpc85xx_common_publish_devices);
180
181machine_arch_initcall(mpc8544_ds, swiotlb_setup_bus_notifier);
182machine_arch_initcall(mpc8572_ds, swiotlb_setup_bus_notifier);
183machine_arch_initcall(p2020_ds, swiotlb_setup_bus_notifier);
184
185/*
186 * Called very early, device-tree isn't unflattened
187 */
188static int __init mpc8572_ds_probe(void)
189{
190	unsigned long root = of_get_flat_dt_root();
191
192	return !!of_flat_dt_is_compatible(root, "fsl,MPC8572DS");
193}
194
195/*
196 * Called very early, device-tree isn't unflattened
197 */
198static int __init p2020_ds_probe(void)
199{
200	unsigned long root = of_get_flat_dt_root();
201
202	return !!of_flat_dt_is_compatible(root, "fsl,P2020DS");
203}
204
205define_machine(mpc8544_ds) {
206	.name			= "MPC8544 DS",
207	.probe			= mpc8544_ds_probe,
208	.setup_arch		= mpc85xx_ds_setup_arch,
209	.init_IRQ		= mpc85xx_ds_pic_init,
210#ifdef CONFIG_PCI
211	.pcibios_fixup_bus	= fsl_pcibios_fixup_bus,
212	.pcibios_fixup_phb      = fsl_pcibios_fixup_phb,
213#endif
214	.get_irq		= mpic_get_irq,
215	.restart		= fsl_rstcr_restart,
216	.calibrate_decr		= generic_calibrate_decr,
217	.progress		= udbg_progress,
218};
219
220define_machine(mpc8572_ds) {
221	.name			= "MPC8572 DS",
222	.probe			= mpc8572_ds_probe,
223	.setup_arch		= mpc85xx_ds_setup_arch,
224	.init_IRQ		= mpc85xx_ds_pic_init,
225#ifdef CONFIG_PCI
226	.pcibios_fixup_bus	= fsl_pcibios_fixup_bus,
227	.pcibios_fixup_phb      = fsl_pcibios_fixup_phb,
228#endif
229	.get_irq		= mpic_get_irq,
230	.restart		= fsl_rstcr_restart,
231	.calibrate_decr		= generic_calibrate_decr,
232	.progress		= udbg_progress,
233};
234
235define_machine(p2020_ds) {
236	.name			= "P2020 DS",
237	.probe			= p2020_ds_probe,
238	.setup_arch		= mpc85xx_ds_setup_arch,
239	.init_IRQ		= mpc85xx_ds_pic_init,
240#ifdef CONFIG_PCI
241	.pcibios_fixup_bus	= fsl_pcibios_fixup_bus,
242	.pcibios_fixup_phb      = fsl_pcibios_fixup_phb,
243#endif
244	.get_irq		= mpic_get_irq,
245	.restart		= fsl_rstcr_restart,
246	.calibrate_decr		= generic_calibrate_decr,
247	.progress		= udbg_progress,
248};
249