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