1 /*
2  * Corenet based SoC DS Setup
3  *
4  * Maintained by Kumar Gala (see MAINTAINERS for contact information)
5  *
6  * Copyright 2009-2011 Freescale Semiconductor 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 #include <linux/kernel.h>
15 #include <linux/pci.h>
16 #include <linux/kdev_t.h>
17 #include <linux/delay.h>
18 #include <linux/interrupt.h>
19 
20 #include <asm/time.h>
21 #include <asm/machdep.h>
22 #include <asm/pci-bridge.h>
23 #include <asm/pgtable.h>
24 #include <asm/ppc-pci.h>
25 #include <mm/mmu_decl.h>
26 #include <asm/prom.h>
27 #include <asm/udbg.h>
28 #include <asm/mpic.h>
29 #include <asm/ehv_pic.h>
30 #include <soc/fsl/qe/qe_ic.h>
31 
32 #include <linux/of_platform.h>
33 #include <sysdev/fsl_soc.h>
34 #include <sysdev/fsl_pci.h>
35 #include "smp.h"
36 #include "mpc85xx.h"
37 
38 void __init corenet_gen_pic_init(void)
39 {
40 	struct mpic *mpic;
41 	unsigned int flags = MPIC_BIG_ENDIAN | MPIC_SINGLE_DEST_CPU |
42 		MPIC_NO_RESET;
43 
44 	struct device_node *np;
45 
46 	if (ppc_md.get_irq == mpic_get_coreint_irq)
47 		flags |= MPIC_ENABLE_COREINT;
48 
49 	mpic = mpic_alloc(NULL, 0, flags, 0, 512, " OpenPIC  ");
50 	BUG_ON(mpic == NULL);
51 
52 	mpic_init(mpic);
53 
54 	np = of_find_compatible_node(NULL, NULL, "fsl,qe-ic");
55 	if (np) {
56 		qe_ic_init(np, 0, qe_ic_cascade_low_mpic,
57 				qe_ic_cascade_high_mpic);
58 		of_node_put(np);
59 	}
60 }
61 
62 /*
63  * Setup the architecture
64  */
65 void __init corenet_gen_setup_arch(void)
66 {
67 	mpc85xx_smp_init();
68 
69 	swiotlb_detect_4g();
70 
71 #if defined(CONFIG_FSL_PCI) && defined(CONFIG_ZONE_DMA32)
72 	/*
73 	 * Inbound windows don't cover the full lower 4 GiB
74 	 * due to conflicts with PCICSRBAR and outbound windows,
75 	 * so limit the DMA32 zone to 2 GiB, to allow consistent
76 	 * allocations to succeed.
77 	 */
78 	limit_zone_pfn(ZONE_DMA32, 1UL << (31 - PAGE_SHIFT));
79 #endif
80 
81 	pr_info("%s board\n", ppc_md.name);
82 
83 	mpc85xx_qe_init();
84 }
85 
86 static const struct of_device_id of_device_ids[] = {
87 	{
88 		.compatible	= "simple-bus"
89 	},
90 	{
91 		.compatible	= "mdio-mux-gpio"
92 	},
93 	{
94 		.compatible	= "fsl,fpga-ngpixis"
95 	},
96 	{
97 		.compatible	= "fsl,fpga-qixis"
98 	},
99 	{
100 		.compatible	= "fsl,srio",
101 	},
102 	{
103 		.compatible	= "fsl,p4080-pcie",
104 	},
105 	{
106 		.compatible	= "fsl,qoriq-pcie-v2.2",
107 	},
108 	{
109 		.compatible	= "fsl,qoriq-pcie-v2.3",
110 	},
111 	{
112 		.compatible	= "fsl,qoriq-pcie-v2.4",
113 	},
114 	{
115 		.compatible	= "fsl,qoriq-pcie-v3.0",
116 	},
117 	{
118 		.compatible	= "fsl,qe",
119 	},
120 	/* The following two are for the Freescale hypervisor */
121 	{
122 		.name		= "hypervisor",
123 	},
124 	{
125 		.name		= "handles",
126 	},
127 	{}
128 };
129 
130 int __init corenet_gen_publish_devices(void)
131 {
132 	return of_platform_bus_probe(NULL, of_device_ids, NULL);
133 }
134 
135 static const char * const boards[] __initconst = {
136 	"fsl,P2041RDB",
137 	"fsl,P3041DS",
138 	"fsl,OCA4080",
139 	"fsl,P4080DS",
140 	"fsl,P5020DS",
141 	"fsl,P5040DS",
142 	"fsl,T2080QDS",
143 	"fsl,T2080RDB",
144 	"fsl,T2081QDS",
145 	"fsl,T4240QDS",
146 	"fsl,T4240RDB",
147 	"fsl,B4860QDS",
148 	"fsl,B4420QDS",
149 	"fsl,B4220QDS",
150 	"fsl,T1023RDB",
151 	"fsl,T1024QDS",
152 	"fsl,T1024RDB",
153 	"fsl,T1040D4RDB",
154 	"fsl,T1042D4RDB",
155 	"fsl,T1040QDS",
156 	"fsl,T1042QDS",
157 	"fsl,T1040RDB",
158 	"fsl,T1042RDB",
159 	"fsl,T1042RDB_PI",
160 	"keymile,kmcent2",
161 	"keymile,kmcoge4",
162 	"varisys,CYRUS",
163 	NULL
164 };
165 
166 /*
167  * Called very early, device-tree isn't unflattened
168  */
169 static int __init corenet_generic_probe(void)
170 {
171 	char hv_compat[24];
172 	int i;
173 #ifdef CONFIG_SMP
174 	extern struct smp_ops_t smp_85xx_ops;
175 #endif
176 
177 	if (of_device_compatible_match(of_root, boards))
178 		return 1;
179 
180 	/* Check if we're running under the Freescale hypervisor */
181 	for (i = 0; boards[i]; i++) {
182 		snprintf(hv_compat, sizeof(hv_compat), "%s-hv", boards[i]);
183 		if (of_machine_is_compatible(hv_compat)) {
184 			ppc_md.init_IRQ = ehv_pic_init;
185 
186 			ppc_md.get_irq = ehv_pic_get_irq;
187 			ppc_md.restart = fsl_hv_restart;
188 			pm_power_off = fsl_hv_halt;
189 			ppc_md.halt = fsl_hv_halt;
190 #ifdef CONFIG_SMP
191 			/*
192 			 * Disable the timebase sync operations because we
193 			 * can't write to the timebase registers under the
194 			 * hypervisor.
195 			 */
196 			smp_85xx_ops.give_timebase = NULL;
197 			smp_85xx_ops.take_timebase = NULL;
198 #endif
199 			return 1;
200 		}
201 	}
202 
203 	return 0;
204 }
205 
206 define_machine(corenet_generic) {
207 	.name			= "CoreNet Generic",
208 	.probe			= corenet_generic_probe,
209 	.setup_arch		= corenet_gen_setup_arch,
210 	.init_IRQ		= corenet_gen_pic_init,
211 #ifdef CONFIG_PCI
212 	.pcibios_fixup_bus	= fsl_pcibios_fixup_bus,
213 	.pcibios_fixup_phb      = fsl_pcibios_fixup_phb,
214 #endif
215 /*
216  * Core reset may cause issues if using the proxy mode of MPIC.
217  * So, use the mixed mode of MPIC if enabling CPU hotplug.
218  *
219  * Likewise, problems have been seen with kexec when coreint is enabled.
220  */
221 #if defined(CONFIG_HOTPLUG_CPU) || defined(CONFIG_KEXEC_CORE)
222 	.get_irq		= mpic_get_irq,
223 #else
224 	.get_irq		= mpic_get_coreint_irq,
225 #endif
226 	.calibrate_decr		= generic_calibrate_decr,
227 	.progress		= udbg_progress,
228 #ifdef CONFIG_PPC64
229 	.power_save		= book3e_idle,
230 #else
231 	.power_save		= e500_idle,
232 #endif
233 };
234 
235 machine_arch_initcall(corenet_generic, corenet_gen_publish_devices);
236 
237 #ifdef CONFIG_SWIOTLB
238 machine_arch_initcall(corenet_generic, swiotlb_setup_bus_notifier);
239 #endif
240