1 // SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later
2 /* Copyright 2013-2019 IBM Corp. */
3 
4 #include <skiboot.h>
5 #include <device.h>
6 #include <console.h>
7 #include <chip.h>
8 #include <ipmi.h>
9 #include <psi.h>
10 #include <npu-regs.h>
11 
12 #include "astbmc.h"
13 
14 static const struct slot_table_entry garrison_phb0_0_slot[] = {
15 	{
16 		.etype = st_pluggable_slot,
17 		.location = ST_LOC_DEVFN(0,0),
18 		.name = "Slot3",
19 	},
20 	{ .etype = st_end },
21 };
22 
23 static const struct slot_table_entry garrison_phb0_1_slot[] = {
24 	{
25 		.etype = st_pluggable_slot,
26 		.location = ST_LOC_DEVFN(0,0),
27 		.name = "Slot2",
28 	},
29 	{ .etype = st_end },
30 };
31 
32 static const struct slot_table_entry garrison_phb0_2_slot[] = {
33 	{
34 		.etype = st_pluggable_slot,
35 		.location = ST_LOC_DEVFN(0,0),
36 		.name = "GPU1",
37 	},
38 	{ .etype = st_end },
39 };
40 
41 static const struct slot_table_entry garrison_phb0_3_slot[] = {
42 	{
43 		.etype = st_pluggable_slot,
44 		.location = ST_LOC_DEVFN(0,0),
45 		.name = "GPU2",
46 	},
47 	{ .etype = st_end },
48 };
49 
50 static const struct slot_table_entry garrison_npu0_slots[] = {
51 	{
52 		.etype = st_npu_slot,
53 		.location = ST_LOC_NPU_GROUP(0),
54 		.name = "GPU2",
55 	},
56 	{
57 		.etype = st_npu_slot,
58 		.location = ST_LOC_NPU_GROUP(1),
59 		.name = "GPU1",
60 	},
61 	{ .etype = st_end },
62 };
63 
64 static const struct slot_table_entry garrison_phb1_0_slot[] = {
65 	{
66 		.etype = st_pluggable_slot,
67 		.location = ST_LOC_DEVFN(0,0),
68 		.name = "Slot1",
69 	},
70 	{ .etype = st_end },
71 };
72 
73 static const struct slot_table_entry garrison_plx_slots[] = {
74 	{
75 		.etype = st_builtin_dev,
76 		.location = ST_LOC_DEVFN(1,0),
77 		.name = "Backplane USB",
78 	},
79 	{
80 		.etype = st_builtin_dev,
81 		.location = ST_LOC_DEVFN(2,0),
82 		.name = "Backplane SATA",
83 	},
84 	{
85 		.etype = st_builtin_dev,
86 		.location = ST_LOC_DEVFN(3,0),
87 		.name = "Backplane BMC",
88 	},
89 	{ .etype = st_end },
90 };
91 
92 static const struct slot_table_entry garrison_plx_up[] = {
93 	{
94 		.etype = st_builtin_dev,
95 		.location = ST_LOC_DEVFN(0,0),
96 		.children = garrison_plx_slots,
97 	},
98 	{ .etype = st_end },
99 };
100 
101 static const struct slot_table_entry garrison_phb1_1_slot[] = {
102 	{
103 		.etype = st_builtin_dev,
104 		.location = ST_LOC_DEVFN(0,0),
105 		.name = "Backplane PLX",
106 		.children = garrison_plx_up,
107 	},
108 	{ .etype = st_end },
109 };
110 
111 static const struct slot_table_entry garrison_phb1_2_slot[] = {
112 	{
113 		.etype = st_pluggable_slot,
114 		.location = ST_LOC_DEVFN(0,0),
115 		.name = "GPU3",
116 	},
117 	{ .etype = st_end },
118 };
119 
120 static const struct slot_table_entry garrison_phb1_3_slot[] = {
121 	{
122 		.etype = st_pluggable_slot,
123 		.location = ST_LOC_DEVFN(0,0),
124 		.name = "GPU4",
125 	},
126 	{ .etype = st_end },
127 };
128 
129 static const struct slot_table_entry garrison_npu1_slots[] = {
130 	{
131 		.etype = st_npu_slot,
132 		.location = ST_LOC_NPU_GROUP(0),
133 		.name = "GPU4",
134 	},
135 	{
136 		.etype = st_npu_slot,
137 		.location = ST_LOC_NPU_GROUP(1),
138 		.name = "GPU3",
139 	},
140 	{ .etype = st_end },
141 };
142 
143 static const struct slot_table_entry garrison_phb_table[] = {
144 	{
145 		.etype = st_phb,
146 		.location = ST_LOC_PHB(0,0),
147 		.children = garrison_phb0_0_slot,
148 	},
149 	{
150 		.etype = st_phb,
151 		.location = ST_LOC_PHB(0,1),
152 		.children = garrison_phb0_1_slot,
153 	},
154 	{
155 		.etype = st_phb,
156 		.location = ST_LOC_PHB(0,2),
157 		.children = garrison_phb0_2_slot,
158 	},
159 	{
160 		.etype = st_phb,
161 		.location = ST_LOC_PHB(0,3),
162 		.children = garrison_phb0_3_slot,
163 	},
164 	{
165 		.etype = st_phb,
166 		.location = ST_LOC_PHB(0,4),
167 		.children = garrison_npu0_slots,
168 	},
169 	{
170 		.etype = st_phb,
171 		.location = ST_LOC_PHB(1,0),
172 		.children = garrison_phb1_0_slot,
173 	},
174 	{
175 		.etype = st_phb,
176 		.location = ST_LOC_PHB(1,1),
177 		.children = garrison_phb1_1_slot,
178 	},
179 	{
180 		.etype = st_phb,
181 		.location = ST_LOC_PHB(1,2),
182 		.children = garrison_phb1_2_slot,
183 	},
184 	{
185 		.etype = st_phb,
186 		.location = ST_LOC_PHB(1,3),
187 		.children = garrison_phb1_3_slot,
188 	},
189 	{
190 		.etype = st_phb,
191 		.location = ST_LOC_PHB(1,4),
192 		.children = garrison_npu1_slots,
193 	},
194 	{ .etype = st_end },
195 };
196 
197 #define NPU_BASE 0x8013c00
198 #define NPU_SIZE 0x2c
199 #define NPU_INDIRECT0	0x8000000008010c3fUL
200 #define NPU_INDIRECT1	0x8000000008010c7fUL
201 
create_link(struct dt_node * npu,int group,int index)202 static void create_link(struct dt_node *npu, int group, int index)
203 {
204 	struct dt_node *link;
205 	uint32_t lane_mask;
206 	uint64_t phy;
207 	char namebuf[32];
208 
209 	snprintf(namebuf, sizeof(namebuf), "link@%x", index);
210 	link = dt_new(npu, namebuf);
211 
212 	dt_add_property_string(link, "compatible", "ibm,npu-link");
213 	dt_add_property_cells(link, "ibm,npu-link-index", index);
214 
215 	if (index < 4) {
216 		phy = NPU_INDIRECT0;
217 		lane_mask = 0xff << (index * 8);
218 	} else {
219 		phy = NPU_INDIRECT1;
220 		lane_mask = 0xff0000 >> (index - 3) * 8;
221 	}
222 	dt_add_property_u64s(link, "ibm,npu-phy", phy);
223 	dt_add_property_cells(link, "ibm,npu-lane-mask", lane_mask);
224 	dt_add_property_cells(link, "ibm,npu-group-id", group);
225 }
226 
dt_create_npu(void)227 static void dt_create_npu(void)
228 {
229         struct dt_node *xscom, *npu;
230         char namebuf[32];
231 
232 	dt_for_each_compatible(dt_root, xscom, "ibm,xscom") {
233 		snprintf(namebuf, sizeof(namebuf), "npu@%x", NPU_BASE);
234 		npu = dt_new(xscom, namebuf);
235 		dt_add_property_cells(npu, "reg", NPU_BASE, NPU_SIZE);
236 		dt_add_property_strings(npu, "compatible", "ibm,power8-npu");
237 
238 		/* Use the first available PHB index which is 4 given
239 		 * there are three normal PHBs. */
240 		dt_add_property_cells(npu, "ibm,phb-index", 4);
241 		dt_add_property_cells(npu, "ibm,npu-index", 0);
242 		dt_add_property_cells(npu, "ibm,npu-links", 4);
243 
244 		/* On Garrison we have 2 links per GPU device.  These are
245 		 * grouped together as per the slot tables above. */
246 		create_link(npu, 0, 0);
247 		create_link(npu, 0, 1);
248 		create_link(npu, 1, 4);
249 		create_link(npu, 1, 5);
250 	}
251 }
252 
garrison_probe(void)253 static bool garrison_probe(void)
254 {
255 	if (!dt_node_is_compatible(dt_root, "ibm,garrison"))
256 		return false;
257 
258 	/* Lot of common early inits here */
259 	astbmc_early_init();
260 
261 	/* Fixups until HB get the NPU bindings */
262 	dt_create_npu();
263 
264 	slot_table_init(garrison_phb_table);
265 
266 	return true;
267 }
268 
269 DECLARE_PLATFORM(garrison) = {
270 	.name			= "Garrison",
271 	.bmc			= &bmc_plat_ast2400_ami,
272 	.probe			= garrison_probe,
273 	.init			= astbmc_init,
274 	.pci_get_slot_info	= slot_table_get_slot_info,
275 	.pci_probe_complete	= check_all_slot_table,
276 	.cec_power_down         = astbmc_ipmi_power_down,
277 	.cec_reboot             = astbmc_ipmi_reboot,
278 	.elog_commit		= ipmi_elog_commit,
279 	.start_preload_resource	= flash_start_preload_resource,
280 	.resource_loaded	= flash_resource_loaded,
281 	.exit			= ipmi_wdt_final_reset,
282 	.terminate		= ipmi_terminate,
283 	.seeprom_update		= astbmc_seeprom_update,
284 	.op_display		= op_display_lpc,
285 };
286