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 	pr_info("%s board\n", ppc_md.name);
72 
73 	mpc85xx_qe_init();
74 }
75 
76 static const struct of_device_id of_device_ids[] = {
77 	{
78 		.compatible	= "simple-bus"
79 	},
80 	{
81 		.compatible	= "mdio-mux-gpio"
82 	},
83 	{
84 		.compatible	= "fsl,fpga-ngpixis"
85 	},
86 	{
87 		.compatible	= "fsl,fpga-qixis"
88 	},
89 	{
90 		.compatible	= "fsl,srio",
91 	},
92 	{
93 		.compatible	= "fsl,p4080-pcie",
94 	},
95 	{
96 		.compatible	= "fsl,qoriq-pcie-v2.2",
97 	},
98 	{
99 		.compatible	= "fsl,qoriq-pcie-v2.3",
100 	},
101 	{
102 		.compatible	= "fsl,qoriq-pcie-v2.4",
103 	},
104 	{
105 		.compatible	= "fsl,qoriq-pcie-v3.0",
106 	},
107 	{
108 		.compatible	= "fsl,qe",
109 	},
110 	/* The following two are for the Freescale hypervisor */
111 	{
112 		.name		= "hypervisor",
113 	},
114 	{
115 		.name		= "handles",
116 	},
117 	{}
118 };
119 
120 int __init corenet_gen_publish_devices(void)
121 {
122 	return of_platform_bus_probe(NULL, of_device_ids, NULL);
123 }
124 
125 static const char * const boards[] __initconst = {
126 	"fsl,P2041RDB",
127 	"fsl,P3041DS",
128 	"fsl,OCA4080",
129 	"fsl,P4080DS",
130 	"fsl,P5020DS",
131 	"fsl,P5040DS",
132 	"fsl,T2080QDS",
133 	"fsl,T2080RDB",
134 	"fsl,T2081QDS",
135 	"fsl,T4240QDS",
136 	"fsl,T4240RDB",
137 	"fsl,B4860QDS",
138 	"fsl,B4420QDS",
139 	"fsl,B4220QDS",
140 	"fsl,T1023RDB",
141 	"fsl,T1024QDS",
142 	"fsl,T1024RDB",
143 	"fsl,T1040D4RDB",
144 	"fsl,T1042D4RDB",
145 	"fsl,T1040QDS",
146 	"fsl,T1042QDS",
147 	"fsl,T1040RDB",
148 	"fsl,T1042RDB",
149 	"fsl,T1042RDB_PI",
150 	"keymile,kmcent2",
151 	"keymile,kmcoge4",
152 	"varisys,CYRUS",
153 	NULL
154 };
155 
156 /*
157  * Called very early, device-tree isn't unflattened
158  */
159 static int __init corenet_generic_probe(void)
160 {
161 	char hv_compat[24];
162 	int i;
163 #ifdef CONFIG_SMP
164 	extern struct smp_ops_t smp_85xx_ops;
165 #endif
166 
167 	if (of_device_compatible_match(of_root, boards))
168 		return 1;
169 
170 	/* Check if we're running under the Freescale hypervisor */
171 	for (i = 0; boards[i]; i++) {
172 		snprintf(hv_compat, sizeof(hv_compat), "%s-hv", boards[i]);
173 		if (of_machine_is_compatible(hv_compat)) {
174 			ppc_md.init_IRQ = ehv_pic_init;
175 
176 			ppc_md.get_irq = ehv_pic_get_irq;
177 			ppc_md.restart = fsl_hv_restart;
178 			pm_power_off = fsl_hv_halt;
179 			ppc_md.halt = fsl_hv_halt;
180 #ifdef CONFIG_SMP
181 			/*
182 			 * Disable the timebase sync operations because we
183 			 * can't write to the timebase registers under the
184 			 * hypervisor.
185 			 */
186 			smp_85xx_ops.give_timebase = NULL;
187 			smp_85xx_ops.take_timebase = NULL;
188 #endif
189 			return 1;
190 		}
191 	}
192 
193 	return 0;
194 }
195 
196 define_machine(corenet_generic) {
197 	.name			= "CoreNet Generic",
198 	.probe			= corenet_generic_probe,
199 	.setup_arch		= corenet_gen_setup_arch,
200 	.init_IRQ		= corenet_gen_pic_init,
201 #ifdef CONFIG_PCI
202 	.pcibios_fixup_bus	= fsl_pcibios_fixup_bus,
203 	.pcibios_fixup_phb      = fsl_pcibios_fixup_phb,
204 #endif
205 /*
206  * Core reset may cause issues if using the proxy mode of MPIC.
207  * So, use the mixed mode of MPIC if enabling CPU hotplug.
208  *
209  * Likewise, problems have been seen with kexec when coreint is enabled.
210  */
211 #if defined(CONFIG_HOTPLUG_CPU) || defined(CONFIG_KEXEC_CORE)
212 	.get_irq		= mpic_get_irq,
213 #else
214 	.get_irq		= mpic_get_coreint_irq,
215 #endif
216 	.calibrate_decr		= generic_calibrate_decr,
217 	.progress		= udbg_progress,
218 #ifdef CONFIG_PPC64
219 	.power_save		= book3e_idle,
220 #else
221 	.power_save		= e500_idle,
222 #endif
223 };
224 
225 machine_arch_initcall(corenet_generic, corenet_gen_publish_devices);
226 
227 #ifdef CONFIG_SWIOTLB
228 machine_arch_initcall(corenet_generic, swiotlb_setup_bus_notifier);
229 #endif
230