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