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 <asm/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
38void __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 */
65void __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
86static 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	{
121		.compatible    = "fsl,fman",
122	},
123	/* The following two are for the Freescale hypervisor */
124	{
125		.name		= "hypervisor",
126	},
127	{
128		.name		= "handles",
129	},
130	{}
131};
132
133int __init corenet_gen_publish_devices(void)
134{
135	return of_platform_bus_probe(NULL, of_device_ids, NULL);
136}
137
138static const char * const boards[] __initconst = {
139	"fsl,P2041RDB",
140	"fsl,P3041DS",
141	"fsl,OCA4080",
142	"fsl,P4080DS",
143	"fsl,P5020DS",
144	"fsl,P5040DS",
145	"fsl,T2080QDS",
146	"fsl,T2080RDB",
147	"fsl,T2081QDS",
148	"fsl,T4240QDS",
149	"fsl,T4240RDB",
150	"fsl,B4860QDS",
151	"fsl,B4420QDS",
152	"fsl,B4220QDS",
153	"fsl,T1040QDS",
154	"fsl,T1042QDS",
155	"fsl,T1040RDB",
156	"fsl,T1042RDB",
157	"fsl,T1042RDB_PI",
158	"keymile,kmcoge4",
159	NULL
160};
161
162/*
163 * Called very early, device-tree isn't unflattened
164 */
165static int __init corenet_generic_probe(void)
166{
167	unsigned long root = of_get_flat_dt_root();
168	char hv_compat[24];
169	int i;
170#ifdef CONFIG_SMP
171	extern struct smp_ops_t smp_85xx_ops;
172#endif
173
174	if (of_flat_dt_match(root, boards))
175		return 1;
176
177	/* Check if we're running under the Freescale hypervisor */
178	for (i = 0; boards[i]; i++) {
179		snprintf(hv_compat, sizeof(hv_compat), "%s-hv", boards[i]);
180		if (of_flat_dt_is_compatible(root, hv_compat)) {
181			ppc_md.init_IRQ = ehv_pic_init;
182
183			ppc_md.get_irq = ehv_pic_get_irq;
184			ppc_md.restart = fsl_hv_restart;
185			pm_power_off = fsl_hv_halt;
186			ppc_md.halt = fsl_hv_halt;
187#ifdef CONFIG_SMP
188			/*
189			 * Disable the timebase sync operations because we
190			 * can't write to the timebase registers under the
191			 * hypervisor.
192			 */
193			smp_85xx_ops.give_timebase = NULL;
194			smp_85xx_ops.take_timebase = NULL;
195#endif
196			return 1;
197		}
198	}
199
200	return 0;
201}
202
203define_machine(corenet_generic) {
204	.name			= "CoreNet Generic",
205	.probe			= corenet_generic_probe,
206	.setup_arch		= corenet_gen_setup_arch,
207	.init_IRQ		= corenet_gen_pic_init,
208#ifdef CONFIG_PCI
209	.pcibios_fixup_bus	= fsl_pcibios_fixup_bus,
210	.pcibios_fixup_phb      = fsl_pcibios_fixup_phb,
211#endif
212	.get_irq		= mpic_get_coreint_irq,
213	.restart		= fsl_rstcr_restart,
214	.calibrate_decr		= generic_calibrate_decr,
215	.progress		= udbg_progress,
216#ifdef CONFIG_PPC64
217	.power_save		= book3e_idle,
218#else
219	.power_save		= e500_idle,
220#endif
221};
222
223machine_arch_initcall(corenet_generic, corenet_gen_publish_devices);
224
225#ifdef CONFIG_SWIOTLB
226machine_arch_initcall(corenet_generic, swiotlb_setup_bus_notifier);
227#endif
228