xref: /openbmc/linux/arch/powerpc/platforms/85xx/ge_imp3a.c (revision c900529f3d9161bfde5cca0754f83b4d3c3e0220)
12874c5fdSThomas Gleixner // SPDX-License-Identifier: GPL-2.0-or-later
2e041013aSMartyn Welch /*
3e041013aSMartyn Welch  * GE IMP3A Board Setup
4e041013aSMartyn Welch  *
5e041013aSMartyn Welch  * Author Martyn Welch <martyn.welch@ge.com>
6e041013aSMartyn Welch  *
7e041013aSMartyn Welch  * Copyright 2010 GE Intelligent Platforms Embedded Systems, Inc.
8e041013aSMartyn Welch  *
9e041013aSMartyn Welch  * Based on: mpc85xx_ds.c (MPC85xx DS Board Setup)
10e041013aSMartyn Welch  * Copyright 2007 Freescale Semiconductor Inc.
11e041013aSMartyn Welch  */
12e041013aSMartyn Welch 
13e041013aSMartyn Welch #include <linux/stddef.h>
14e041013aSMartyn Welch #include <linux/kernel.h>
15e041013aSMartyn Welch #include <linux/pci.h>
16e041013aSMartyn Welch #include <linux/kdev_t.h>
17e041013aSMartyn Welch #include <linux/delay.h>
18e041013aSMartyn Welch #include <linux/seq_file.h>
19e041013aSMartyn Welch #include <linux/interrupt.h>
20*81d7cac4SRob Herring #include <linux/of.h>
21e6f6390aSChristophe Leroy #include <linux/of_address.h>
22e041013aSMartyn Welch 
23e041013aSMartyn Welch #include <asm/time.h>
24e041013aSMartyn Welch #include <asm/machdep.h>
25e041013aSMartyn Welch #include <asm/pci-bridge.h>
26e041013aSMartyn Welch #include <mm/mmu_decl.h>
27e041013aSMartyn Welch #include <asm/udbg.h>
28e041013aSMartyn Welch #include <asm/mpic.h>
29e041013aSMartyn Welch #include <asm/swiotlb.h>
30e041013aSMartyn Welch #include <asm/nvram.h>
31e041013aSMartyn Welch 
32e041013aSMartyn Welch #include <sysdev/fsl_soc.h>
33e041013aSMartyn Welch #include <sysdev/fsl_pci.h>
34e041013aSMartyn Welch #include "smp.h"
35e041013aSMartyn Welch 
36e041013aSMartyn Welch #include "mpc85xx.h"
37e041013aSMartyn Welch #include <sysdev/ge/ge_pic.h>
38e041013aSMartyn Welch 
39e041013aSMartyn Welch void __iomem *imp3a_regs;
40e041013aSMartyn Welch 
ge_imp3a_pic_init(void)41e041013aSMartyn Welch void __init ge_imp3a_pic_init(void)
42e041013aSMartyn Welch {
43e041013aSMartyn Welch 	struct mpic *mpic;
44e041013aSMartyn Welch 	struct device_node *np;
45e041013aSMartyn Welch 	struct device_node *cascade_node = NULL;
46e041013aSMartyn Welch 
47b2827883SBenjamin Herrenschmidt 	if (of_machine_is_compatible("fsl,MPC8572DS-CAMP")) {
48e041013aSMartyn Welch 		mpic = mpic_alloc(NULL, 0,
49e041013aSMartyn Welch 			MPIC_NO_RESET |
50e041013aSMartyn Welch 			MPIC_BIG_ENDIAN |
51e041013aSMartyn Welch 			MPIC_SINGLE_DEST_CPU,
52e041013aSMartyn Welch 			0, 256, " OpenPIC  ");
53e041013aSMartyn Welch 	} else {
54e041013aSMartyn Welch 		mpic = mpic_alloc(NULL, 0,
55e041013aSMartyn Welch 			  MPIC_BIG_ENDIAN |
56e041013aSMartyn Welch 			  MPIC_SINGLE_DEST_CPU,
57e041013aSMartyn Welch 			0, 256, " OpenPIC  ");
58e041013aSMartyn Welch 	}
59e041013aSMartyn Welch 
60e041013aSMartyn Welch 	BUG_ON(mpic == NULL);
61e041013aSMartyn Welch 	mpic_init(mpic);
62e041013aSMartyn Welch 	/*
63e041013aSMartyn Welch 	 * There is a simple interrupt handler in the main FPGA, this needs
64e041013aSMartyn Welch 	 * to be cascaded into the MPIC
65e041013aSMartyn Welch 	 */
66e041013aSMartyn Welch 	for_each_node_by_type(np, "interrupt-controller")
67e041013aSMartyn Welch 		if (of_device_is_compatible(np, "gef,fpga-pic-1.00")) {
68e041013aSMartyn Welch 			cascade_node = np;
69e041013aSMartyn Welch 			break;
70e041013aSMartyn Welch 		}
71e041013aSMartyn Welch 
72e041013aSMartyn Welch 	if (cascade_node == NULL) {
73e041013aSMartyn Welch 		printk(KERN_WARNING "IMP3A: No FPGA PIC\n");
74e041013aSMartyn Welch 		return;
75e041013aSMartyn Welch 	}
76e041013aSMartyn Welch 
77e041013aSMartyn Welch 	gef_pic_init(cascade_node);
78e041013aSMartyn Welch 	of_node_put(cascade_node);
79e041013aSMartyn Welch }
80e041013aSMartyn Welch 
ge_imp3a_pci_assign_primary(void)81407454caSNick Child static void __init ge_imp3a_pci_assign_primary(void)
82905e75c4SJia Hongtao {
83e041013aSMartyn Welch #ifdef CONFIG_PCI
84905e75c4SJia Hongtao 	struct device_node *np;
85905e75c4SJia Hongtao 	struct resource rsrc;
86905e75c4SJia Hongtao 
87905e75c4SJia Hongtao 	for_each_node_by_type(np, "pci") {
88905e75c4SJia Hongtao 		if (of_device_is_compatible(np, "fsl,mpc8540-pci") ||
89905e75c4SJia Hongtao 		    of_device_is_compatible(np, "fsl,mpc8548-pcie") ||
90905e75c4SJia Hongtao 		    of_device_is_compatible(np, "fsl,p2020-pcie")) {
91905e75c4SJia Hongtao 			of_address_to_resource(np, 0, &rsrc);
92a8b89c10SLiang He 			if ((rsrc.start & 0xfffff) == 0x9000) {
93a8b89c10SLiang He 				of_node_put(fsl_pci_primary);
94a8b89c10SLiang He 				fsl_pci_primary = of_node_get(np);
95a8b89c10SLiang He 			}
96905e75c4SJia Hongtao 		}
97905e75c4SJia Hongtao 	}
98905e75c4SJia Hongtao #endif
99905e75c4SJia Hongtao }
100e041013aSMartyn Welch 
101e041013aSMartyn Welch /*
102e041013aSMartyn Welch  * Setup the architecture
103e041013aSMartyn Welch  */
ge_imp3a_setup_arch(void)104e041013aSMartyn Welch static void __init ge_imp3a_setup_arch(void)
105e041013aSMartyn Welch {
106e041013aSMartyn Welch 	struct device_node *regs;
107e041013aSMartyn Welch 
108e041013aSMartyn Welch 	if (ppc_md.progress)
109e041013aSMartyn Welch 		ppc_md.progress("ge_imp3a_setup_arch()", 0);
110e041013aSMartyn Welch 
111e041013aSMartyn Welch 	mpc85xx_smp_init();
112e041013aSMartyn Welch 
113905e75c4SJia Hongtao 	ge_imp3a_pci_assign_primary();
114905e75c4SJia Hongtao 
115905e75c4SJia Hongtao 	swiotlb_detect_4g();
116e041013aSMartyn Welch 
117e041013aSMartyn Welch 	/* Remap basic board registers */
118e041013aSMartyn Welch 	regs = of_find_compatible_node(NULL, NULL, "ge,imp3a-fpga-regs");
119e041013aSMartyn Welch 	if (regs) {
120e041013aSMartyn Welch 		imp3a_regs = of_iomap(regs, 0);
121e041013aSMartyn Welch 		if (imp3a_regs == NULL)
122e041013aSMartyn Welch 			printk(KERN_WARNING "Unable to map board registers\n");
123e041013aSMartyn Welch 		of_node_put(regs);
124e041013aSMartyn Welch 	}
125e041013aSMartyn Welch 
126e041013aSMartyn Welch #if defined(CONFIG_MMIO_NVRAM)
127e041013aSMartyn Welch 	mmio_nvram_init();
128e041013aSMartyn Welch #endif
129e041013aSMartyn Welch 
130e041013aSMartyn Welch 	printk(KERN_INFO "GE Intelligent Platforms IMP3A 3U cPCI SBC\n");
131e041013aSMartyn Welch }
132e041013aSMartyn Welch 
133e041013aSMartyn Welch /* Return the PCB revision */
ge_imp3a_get_pcb_rev(void)134e041013aSMartyn Welch static unsigned int ge_imp3a_get_pcb_rev(void)
135e041013aSMartyn Welch {
136e041013aSMartyn Welch 	unsigned int reg;
137e041013aSMartyn Welch 
138e041013aSMartyn Welch 	reg = ioread16(imp3a_regs);
139e041013aSMartyn Welch 	return (reg >> 8) & 0xff;
140e041013aSMartyn Welch }
141e041013aSMartyn Welch 
142e041013aSMartyn Welch /* Return the board (software) revision */
ge_imp3a_get_board_rev(void)143e041013aSMartyn Welch static unsigned int ge_imp3a_get_board_rev(void)
144e041013aSMartyn Welch {
145e041013aSMartyn Welch 	unsigned int reg;
146e041013aSMartyn Welch 
147e041013aSMartyn Welch 	reg = ioread16(imp3a_regs + 0x2);
148e041013aSMartyn Welch 	return reg & 0xff;
149e041013aSMartyn Welch }
150e041013aSMartyn Welch 
151e041013aSMartyn Welch /* Return the FPGA revision */
ge_imp3a_get_fpga_rev(void)152e041013aSMartyn Welch static unsigned int ge_imp3a_get_fpga_rev(void)
153e041013aSMartyn Welch {
154e041013aSMartyn Welch 	unsigned int reg;
155e041013aSMartyn Welch 
156e041013aSMartyn Welch 	reg = ioread16(imp3a_regs + 0x2);
157e041013aSMartyn Welch 	return (reg >> 8) & 0xff;
158e041013aSMartyn Welch }
159e041013aSMartyn Welch 
160e041013aSMartyn Welch /* Return compactPCI Geographical Address */
ge_imp3a_get_cpci_geo_addr(void)161e041013aSMartyn Welch static unsigned int ge_imp3a_get_cpci_geo_addr(void)
162e041013aSMartyn Welch {
163e041013aSMartyn Welch 	unsigned int reg;
164e041013aSMartyn Welch 
165e041013aSMartyn Welch 	reg = ioread16(imp3a_regs + 0x6);
166e041013aSMartyn Welch 	return (reg & 0x0f00) >> 8;
167e041013aSMartyn Welch }
168e041013aSMartyn Welch 
169e041013aSMartyn Welch /* Return compactPCI System Controller Status */
ge_imp3a_get_cpci_is_syscon(void)170e041013aSMartyn Welch static unsigned int ge_imp3a_get_cpci_is_syscon(void)
171e041013aSMartyn Welch {
172e041013aSMartyn Welch 	unsigned int reg;
173e041013aSMartyn Welch 
174e041013aSMartyn Welch 	reg = ioread16(imp3a_regs + 0x6);
175e041013aSMartyn Welch 	return reg & (1 << 12);
176e041013aSMartyn Welch }
177e041013aSMartyn Welch 
ge_imp3a_show_cpuinfo(struct seq_file * m)178e041013aSMartyn Welch static void ge_imp3a_show_cpuinfo(struct seq_file *m)
179e041013aSMartyn Welch {
180e041013aSMartyn Welch 	seq_printf(m, "Vendor\t\t: GE Intelligent Platforms\n");
181e041013aSMartyn Welch 
182e041013aSMartyn Welch 	seq_printf(m, "Revision\t: %u%c\n", ge_imp3a_get_pcb_rev(),
183e041013aSMartyn Welch 		('A' + ge_imp3a_get_board_rev() - 1));
184e041013aSMartyn Welch 
185e041013aSMartyn Welch 	seq_printf(m, "FPGA Revision\t: %u\n", ge_imp3a_get_fpga_rev());
186e041013aSMartyn Welch 
187e041013aSMartyn Welch 	seq_printf(m, "cPCI geo. addr\t: %u\n", ge_imp3a_get_cpci_geo_addr());
188e041013aSMartyn Welch 
189e041013aSMartyn Welch 	seq_printf(m, "cPCI syscon\t: %s\n",
190e041013aSMartyn Welch 		ge_imp3a_get_cpci_is_syscon() ? "yes" : "no");
191e041013aSMartyn Welch }
192e041013aSMartyn Welch 
193905e75c4SJia Hongtao machine_arch_initcall(ge_imp3a, mpc85xx_common_publish_devices);
194e041013aSMartyn Welch 
define_machine(ge_imp3a)195e041013aSMartyn Welch define_machine(ge_imp3a) {
196e041013aSMartyn Welch 	.name			= "GE_IMP3A",
1971c96fcdeSChristophe Leroy 	.compatible		= "ge,IMP3A",
198e041013aSMartyn Welch 	.setup_arch		= ge_imp3a_setup_arch,
199e041013aSMartyn Welch 	.init_IRQ		= ge_imp3a_pic_init,
200e041013aSMartyn Welch 	.show_cpuinfo		= ge_imp3a_show_cpuinfo,
201e041013aSMartyn Welch #ifdef CONFIG_PCI
202e041013aSMartyn Welch 	.pcibios_fixup_bus	= fsl_pcibios_fixup_bus,
20348b16180SWang Dongsheng 	.pcibios_fixup_phb      = fsl_pcibios_fixup_phb,
204e041013aSMartyn Welch #endif
205e041013aSMartyn Welch 	.get_irq		= mpic_get_irq,
206e041013aSMartyn Welch 	.progress		= udbg_progress,
207e041013aSMartyn Welch };
208