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