blob: be452a05b60d43c8547972729de5bd00ea2cf218 [file] [log] [blame]
Jonathan Zhang8f895492020-01-16 11:16:45 -08001/*
2 * This file is part of the coreboot project.
3 *
Jonathan Zhang8f895492020-01-16 11:16:45 -08004 *
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation; either version 2 of the License, or
8 * (at your option) any later version.
9 *
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
14 */
15
16#include <cbfs.h>
17#include <assert.h>
18#include <device/pci.h>
19#include <soc/acpi.h>
20#include <soc/ramstage.h>
21#include <soc/soc_util.h>
22
23struct pci_resource {
24 struct device *dev;
25 struct resource *res;
26 struct pci_resource *next;
27};
28
29struct stack_dev_resource {
30 uint8_t align;
31 struct pci_resource *children;
32 struct stack_dev_resource *next;
33};
34
35static void assign_stack_resources(struct iiostack_resource *stack_list,
36 struct device *dev, struct resource *bridge);
37
38static void xeonsp_pci_domain_scan_bus(struct device *dev)
39{
40 DEV_FUNC_ENTER(dev);
41 struct bus *link = dev->link_list;
42
43 printk(BIOS_SPEW, "%s:%s scanning buses under device %s\n",
44 __FILE__, __func__, dev_path(dev));
45 while (link != NULL) {
46 if (link->secondary == 0) { // scan only PSTACK buses
47 struct device *d;
48 for (d = link->children; d; d = d->sibling)
49 pci_probe_dev(d, link, d->path.pci.devfn);
50 scan_bridges(link);
51 } else {
52 pci_scan_bus(link, PCI_DEVFN(0, 0), 0xff);
53 }
54 link = link->next;
55 }
56 DEV_FUNC_EXIT(dev);
57}
58
59static void xeonsp_pci_dev_iterator(struct bus *bus,
60 void (*dev_iterator)(struct device *, void *),
61 void (*res_iterator)(struct device *, struct resource *, void *),
62 void *data)
63{
64 struct device *curdev;
65 struct resource *res;
66
67 /* Walk through all devices and find which resources they need. */
68 for (curdev = bus->children; curdev; curdev = curdev->sibling) {
69 struct bus *link;
70
71 if (!curdev->enabled)
72 continue;
73
74 if (!curdev->ops || !curdev->ops->read_resources) {
75 if (curdev->path.type != DEVICE_PATH_APIC)
76 printk(BIOS_ERR, "%s missing read_resources\n",
77 dev_path(curdev));
78 continue;
79 }
80
81 if (dev_iterator)
82 dev_iterator(curdev, data);
83
84 if (res_iterator) {
85 for (res = curdev->resource_list; res; res = res->next)
86 res_iterator(curdev, res, data);
87 }
88
89 /* Read in the resources behind the current device's links. */
90 for (link = curdev->link_list; link; link = link->next)
91 xeonsp_pci_dev_iterator(link, dev_iterator, res_iterator, data);
92 }
93}
94
95static void xeonsp_pci_dev_read_resources(struct device *dev, void *data)
96{
97 post_log_path(dev);
98 dev->ops->read_resources(dev);
99}
100
101static void xeonsp_pci_dev_dummy_func(struct device *dev)
102{
103}
104
105static void xeonsp_reset_pci_op(struct device *dev, void *data)
106{
107 if (dev->ops)
108 dev->ops->read_resources = xeonsp_pci_dev_dummy_func;
109}
110
111static STACK_RES *find_stack_for_bus(struct iiostack_resource *info, uint8_t bus)
112{
113 for (int i = 0; i < info->no_of_stacks; ++i) {
114 if (bus >= info->res[i].BusBase && bus <= info->res[i].BusLimit)
115 return &info->res[i];
116 }
117 return NULL;
118}
119
120static void add_res_to_stack(struct stack_dev_resource **root,
121 struct device *dev, struct resource *res)
122{
123 struct stack_dev_resource *cur = *root;
124 while (cur) {
125 if (cur->align == res->align || cur->next == NULL) /* equal or last record */
126 break;
127 else if (cur->align > res->align) {
128 if (cur->next->align < res->align) /* need to insert new record here */
129 break;
130 cur = cur->next;
131 } else {
132 break;
133 }
134 }
135
136 struct stack_dev_resource *nr;
137 if (!cur || cur->align != res->align) { /* need to add new record */
138 nr = malloc(sizeof(struct stack_dev_resource));
139 if (nr == 0)
140 die("assign_resource_to_stack(): out of memory.\n");
141 memset(nr, 0, sizeof(struct stack_dev_resource));
142 nr->align = res->align;
143 if (!cur) {
144 *root = nr; /* head node */
145 } else if (cur->align > nr->align) {
146 if (cur->next == NULL) {
147 cur->next = nr;
148 } else {
149 nr->next = cur->next;
150 cur->next = nr;
151 }
152 } else { /* insert in the beginning */
153 nr->next = cur;
154 *root = nr;
155 }
156 } else {
157 nr = cur;
158 }
159
160 assert(nr != NULL && nr->align == res->align);
161
162 struct pci_resource *npr = malloc(sizeof(struct pci_resource));
163 if (npr == NULL)
164 die("%s: out of memory.\n", __func__);
165 npr->res = res;
166 npr->dev = dev;
167 npr->next = NULL;
168
169 if (nr->children == NULL) {
170 nr->children = npr;
171 } else {
172 struct pci_resource *pr = nr->children;
173 while (pr->next != NULL)
174 pr = pr->next;
175 pr->next = npr;
176 }
177}
178
179static void reserve_dev_resources(STACK_RES *stack, unsigned long res_type,
180 struct stack_dev_resource *res_root, struct resource *bridge)
181{
182 uint8_t align;
183 uint64_t orig_base, base;
184
185 if (res_type & IORESOURCE_IO)
186 orig_base = stack->PciResourceIoBase;
187 else if ((res_type & IORESOURCE_MEM) && ((res_type & IORESOURCE_PCI64) ||
188 (!res_root && bridge && (bridge->flags & IORESOURCE_PREFETCH))))
189 orig_base = stack->PciResourceMem64Base;
190 else
191 orig_base = stack->PciResourceMem32Base;
192
193 align = 0;
194 base = orig_base;
195 int first = 1;
196 while (res_root) { /* loop through all devices grouped by alignment requirements */
197 struct pci_resource *pr = res_root->children;
198 while (pr) {
199 if (first) {
200 if (bridge) { /* takes highest alignment */
201 if (bridge->align < pr->res->align)
202 bridge->align = pr->res->align;
203 orig_base = ALIGN_UP(orig_base, 1 << bridge->align);
204 } else {
205 orig_base = ALIGN_UP(orig_base, 1 << pr->res->align);
206 }
207 base = orig_base;
208
209 if (bridge)
210 bridge->base = base;
211 pr->res->base = base;
212 first = 0;
213 } else {
214 pr->res->base = ALIGN_UP(base, 1 << pr->res->align);
215 }
216 pr->res->limit = pr->res->base + pr->res->size - 1;
217 base = pr->res->limit + 1;
218 pr->res->flags |= (IORESOURCE_ASSIGNED);
219 pr = pr->next;
220 }
221 res_root = res_root->next;
222 }
223
224 if (bridge) {
225 /* this bridge doesn't have any resources, will set it to default window */
226 if (first) {
227 orig_base = ALIGN_UP(orig_base, 1 << bridge->align);
228 bridge->base = orig_base;
229 base = orig_base + (1ULL << bridge->gran);
230 }
231
232 bridge->size = ALIGN_UP(base, 1 << bridge->align) - bridge->base;
233
234 bridge->limit = bridge->base + bridge->size - 1;
235 bridge->flags |= (IORESOURCE_ASSIGNED);
236 base = bridge->limit + 1;
237 }
238
239 /* update new limits */
240 if (res_type & IORESOURCE_IO)
241 stack->PciResourceIoBase = base;
242 else if ((res_type & IORESOURCE_MEM) && ((res_type & IORESOURCE_PCI64) ||
243 (!res_root && bridge && (bridge->flags & IORESOURCE_PREFETCH))))
244 stack->PciResourceMem64Base = base;
245 else
246 stack->PciResourceMem32Base = base;
247}
248
249static void reclaim_resource_mem(struct stack_dev_resource *res_root)
250{
251 while (res_root) { /* loop through all devices grouped by alignment requirements */
252 /* free pci_resource */
253 struct pci_resource *pr = res_root->children;
254 while (pr) {
255 struct pci_resource *dpr = pr;
256 pr = pr->next;
257 free(dpr);
258 }
259
260 /* free stack_dev_resource */
261 struct stack_dev_resource *ddr = res_root;
262 res_root = res_root->next;
263 free(ddr);
264 }
265}
266
267static void assign_bridge_resources(struct iiostack_resource *stack_list,
268 struct device *dev, struct resource *bridge)
269{
270 struct resource *res;
271 if (!dev->enabled)
272 return;
273
274 for (res = dev->resource_list; res; res = res->next) {
275 if (!(res->flags & IORESOURCE_BRIDGE) ||
276 (bridge && ((bridge->flags & (IORESOURCE_IO | IORESOURCE_MEM |
277 IORESOURCE_PREFETCH | IORESOURCE_PCI64)) !=
278 (res->flags & (IORESOURCE_IO | IORESOURCE_MEM |
279 IORESOURCE_PREFETCH | IORESOURCE_PCI64)))))
280 continue;
281
282 assign_stack_resources(stack_list, dev, res);
283 if (!bridge)
284 continue;
285 /* for 1st time update, overlading IORESOURCE_ASSIGNED */
286 if (!(bridge->flags & IORESOURCE_ASSIGNED)) {
287 bridge->base = res->base;
288 bridge->limit = res->limit;
289 bridge->flags |= (IORESOURCE_ASSIGNED);
290 } else {
291 /* update bridge range from child bridge range */
292 if (res->base < bridge->base)
293 bridge->base = res->base;
294 if (res->limit > bridge->limit)
295 bridge->limit = res->limit;
296 }
297 bridge->size = (bridge->limit - bridge->base + 1);
298 }
299}
300
301static void assign_stack_resources(struct iiostack_resource *stack_list,
302 struct device *dev, struct resource *bridge)
303{
304 struct bus *bus;
305
306 /* Read in the resources behind the current device's links. */
307 for (bus = dev->link_list; bus; bus = bus->next) {
308 struct device *curdev;
309 STACK_RES *stack;
310
311 /* get IIO stack for this bus */
312 stack = find_stack_for_bus(stack_list, bus->secondary);
313 assert(stack != NULL);
314
315 /* Assign resources to bridge */
316 for (curdev = bus->children; curdev; curdev = curdev->sibling)
317 assign_bridge_resources(stack_list, curdev, bridge);
318
319 /* Pick non-bridged resources for resource allocation for each resource type */
320 unsigned long flags[5] = {IORESOURCE_IO, IORESOURCE_MEM,
321 (IORESOURCE_PCI64|IORESOURCE_MEM), (IORESOURCE_MEM|IORESOURCE_PREFETCH),
322 (IORESOURCE_PCI64|IORESOURCE_MEM|IORESOURCE_PREFETCH)};
323 uint8_t no_res_types = 5;
324 if (bridge) {
325 flags[0] = bridge->flags &
326 (IORESOURCE_IO | IORESOURCE_MEM | IORESOURCE_PREFETCH);
327 if ((bridge->flags & IORESOURCE_MEM) &&
328 (bridge->flags & IORESOURCE_PREFETCH))
329 flags[0] |= IORESOURCE_PCI64;
330 no_res_types = 1;
331 }
332
333 /* Process each resource type */
334 for (int rt = 0; rt < no_res_types; ++rt) {
335 struct stack_dev_resource *res_root = NULL;
336
337 for (curdev = bus->children; curdev; curdev = curdev->sibling) {
338 struct resource *res;
339 if (!curdev->enabled)
340 continue;
341
342 for (res = curdev->resource_list; res; res = res->next) {
343 if ((res->flags & IORESOURCE_BRIDGE) || (res->flags &
344 (IORESOURCE_STORED | IORESOURCE_RESERVE |
345 IORESOURCE_FIXED | IORESOURCE_ASSIGNED)
346 ) || ((res->flags & (IORESOURCE_IO |
347 IORESOURCE_MEM | IORESOURCE_PCI64
348 | IORESOURCE_PREFETCH))
349 != flags[rt]) || res->size == 0)
350 continue;
351 else
352 add_res_to_stack(&res_root, curdev, res);
353 }
354 }
355
356 /* Allocate resources and update bridge range */
357 if (res_root || (bridge && !(bridge->flags & IORESOURCE_ASSIGNED))) {
358 reserve_dev_resources(stack, flags[rt], res_root, bridge);
359 reclaim_resource_mem(res_root);
360 }
361 }
362 }
363}
364
365static void xeonsp_constrain_pci_resources(struct device *dev, struct resource *res, void *data)
366{
367 STACK_RES *stack = (STACK_RES *) data;
368 if (!(res->flags & IORESOURCE_FIXED))
369 return;
370
371 uint64_t base, limit;
372 if (res->flags & IORESOURCE_IO) {
373 base = stack->PciResourceIoBase;
374 limit = stack->PciResourceIoLimit;
375 } else if ((res->flags & IORESOURCE_MEM) && (res->flags & IORESOURCE_PCI64)) {
376 base = stack->PciResourceMem64Base;
377 limit = stack->PciResourceMem64Limit;
378 } else {
379 base = stack->PciResourceMem32Base;
380 limit = stack->PciResourceMem32Limit;
381 }
382
383 if (((res->base + res->size - 1) < base) || (res->base > limit)) /* outside window */
384 return;
385
386 if (res->limit > limit) /* resource end is out of limit */
387 limit = res->base - 1;
388 else
389 base = res->base + res->size;
390
391 if (res->flags & IORESOURCE_IO) {
392 stack->PciResourceIoBase = base;
393 stack->PciResourceIoLimit = limit;
394 } else if ((res->flags & IORESOURCE_MEM) && (res->flags & IORESOURCE_PCI64)) {
395 stack->PciResourceMem64Base = base;
396 stack->PciResourceMem64Limit = limit;
397 } else {
398 stack->PciResourceMem32Base = base;
399 stack->PciResourceMem32Limit = limit;
400 }
401}
402
403static void xeonsp_pci_domain_read_resources(struct device *dev)
404{
405 struct bus *link;
406
407 DEV_FUNC_ENTER(dev);
408
409 pci_domain_read_resources(dev);
410
411 /*
412 * Walk through all devices in this domain and read resources.
413 * Since there is no callback when read resource operation is
414 * complete for all devices, domain read resource function initiates
415 * read resources for all devices and swaps read resource operation
416 * with dummy function to avoid warning.
417 */
418 for (link = dev->link_list; link; link = link->next)
419 xeonsp_pci_dev_iterator(link, xeonsp_pci_dev_read_resources, NULL, NULL);
420
421 for (link = dev->link_list; link; link = link->next)
422 xeonsp_pci_dev_iterator(link, xeonsp_reset_pci_op, NULL, NULL);
423
424 /*
425 * 1. group devices, resources for each stack
426 * 2. order resources in descending order of requested resource allocation sizes
427 */
428 struct iiostack_resource stack_info = {0};
429 get_iiostack_info(&stack_info);
430
431 /* constrain stack window */
432 for (link = dev->link_list; link; link = link->next) {
433 STACK_RES *stack = find_stack_for_bus(&stack_info, link->secondary);
434 assert(stack != 0);
435 xeonsp_pci_dev_iterator(link, NULL, xeonsp_constrain_pci_resources, stack);
436 }
437
438 /* assign resources */
439 assign_stack_resources(&stack_info, dev, NULL);
440
441 DEV_FUNC_EXIT(dev);
442}
443
444static void reset_resource_to_unassigned(struct device *dev, struct resource *res, void *data)
445{
446 if ((res->flags & (IORESOURCE_IO | IORESOURCE_MEM)) &&
447 !(res->flags & (IORESOURCE_FIXED | IORESOURCE_RESERVE))) {
448 res->flags &= ~IORESOURCE_ASSIGNED;
449 }
450}
451
452static void xeonsp_pci_domain_set_resources(struct device *dev)
453{
454 DEV_FUNC_ENTER(dev);
455
456 print_resource_tree(dev, BIOS_SPEW, "Before xeonsp pci domain set resource");
457
458 /* reset bus 0 dev resource assignment - need to change them to FSP IIOStack window */
459 xeonsp_pci_dev_iterator(dev->link_list, NULL, reset_resource_to_unassigned, NULL);
460
461 /* update dev resources based on IIOStack IO/Mem32/Mem64 windows */
462 xeonsp_pci_domain_read_resources(dev);
463
464 struct bus *link = dev->link_list;
465 while (link != NULL) {
466 assign_resources(link);
467 link = link->next;
468 }
469
470 print_resource_tree(dev, BIOS_SPEW, "After xeonsp pci domain set resource");
471
472 DEV_FUNC_EXIT(dev);
473}
474
475static struct device_operations pci_domain_ops = {
476 .read_resources = &pci_domain_read_resources,
477 .set_resources = &xeonsp_pci_domain_set_resources,
478 .scan_bus = &xeonsp_pci_domain_scan_bus,
479#if CONFIG(HAVE_ACPI_TABLES)
480 .write_acpi_tables = &northbridge_write_acpi_tables,
481#endif
482};
483
484static struct device_operations cpu_bus_ops = {
Nico Huber2f8ba692020-04-05 14:05:24 +0200485 .read_resources = noop_read_resources,
486 .set_resources = noop_set_resources,
Jonathan Zhang8f895492020-01-16 11:16:45 -0800487 .init = xeon_sp_init_cpus,
Jonathan Zhang8f895492020-01-16 11:16:45 -0800488#if CONFIG(HAVE_ACPI_TABLES)
489 /* defined in src/soc/intel/common/block/acpi/acpi.c */
Nico Huber68680dd2020-03-31 17:34:52 +0200490 .acpi_fill_ssdt = generate_cpu_entries,
Jonathan Zhang8f895492020-01-16 11:16:45 -0800491#endif
492};
493
494/* Attach IIO stack bus numbers with dummy device to PCI DOMAIN 0000 device */
495static void attach_iio_stacks(struct device *dev)
496{
497 struct bus *iiostack_bus;
498 struct device dummy;
499 struct iiostack_resource stack_info = {0};
500
501 DEV_FUNC_ENTER(dev);
502
503 get_iiostack_info(&stack_info);
504 for (int s = 0; s < stack_info.no_of_stacks; ++s) {
505 /* only non zero bus no. needs to be enumerated */
506 if (stack_info.res[s].BusBase == 0)
507 continue;
508
509 iiostack_bus = malloc(sizeof(struct bus));
510 if (iiostack_bus == NULL)
511 die("%s: out of memory.\n", __func__);
512 memset(iiostack_bus, 0, sizeof(*iiostack_bus));
513 memcpy(iiostack_bus, dev->bus, sizeof(*iiostack_bus));
514 iiostack_bus->secondary = stack_info.res[s].BusBase;
515 iiostack_bus->subordinate = stack_info.res[s].BusBase;
516 iiostack_bus->dev = NULL;
517 iiostack_bus->children = NULL;
518 iiostack_bus->next = NULL;
519 iiostack_bus->link_num = 1;
520
521 dummy.bus = iiostack_bus;
522 dummy.path.type = DEVICE_PATH_PCI;
523 dummy.path.pci.devfn = 0;
524 uint32_t id = pci_read_config32(&dummy, PCI_VENDOR_ID);
525 if (id == 0xffffffff)
526 printk(BIOS_WARNING, "IIO Stack device %s not visible\n",
527 dev_path(&dummy));
528
529 if (dev->link_list == NULL) {
530 dev->link_list = iiostack_bus;
531 } else {
532 struct bus *nlink = dev->link_list;
533 while (nlink->next != NULL)
534 nlink = nlink->next;
535 nlink->next = iiostack_bus;
536 }
537 }
538
539 DEV_FUNC_EXIT(dev);
540}
541
542static void soc_enable_dev(struct device *dev)
543{
544 /* Set the operations if it is a special bus type */
545 if (dev->path.type == DEVICE_PATH_DOMAIN) {
546 dev->ops = &pci_domain_ops;
547 attach_iio_stacks(dev);
548 } else if (dev->path.type == DEVICE_PATH_CPU_CLUSTER) {
549 dev->ops = &cpu_bus_ops;
550 }
551}
552
553static void soc_init(void *data)
554{
555 printk(BIOS_DEBUG, "coreboot: calling fsp_silicon_init\n");
556 fsp_silicon_init(false);
557}
558
559static void soc_final(void *data)
560{
561 // Temp Fix - should be done by FSP, in 2S bios completion
562 // is not carried out on socket 2
563 set_bios_init_completion();
564}
565
566static void soc_silicon_init_params(FSPS_UPD *silupd)
567{
568}
569
570void platform_fsp_silicon_init_params_cb(FSPS_UPD *silupd)
571{
572 const struct microcode *microcode_file;
573 size_t microcode_len;
574
575 microcode_file = cbfs_boot_map_with_leak("cpu_microcode_blob.bin",
576 CBFS_TYPE_MICROCODE, &microcode_len);
577
578 if ((microcode_file != NULL) && (microcode_len != 0)) {
579 /* Update CPU Microcode patch base address/size */
580 silupd->FspsConfig.PcdCpuMicrocodePatchBase =
581 (uint32_t)microcode_file;
582 silupd->FspsConfig.PcdCpuMicrocodePatchSize =
583 (uint32_t)microcode_len;
584 }
585
586 soc_silicon_init_params(silupd);
587 mainboard_silicon_init_params(silupd);
588}
589
Andrey Petrov662da6c2020-03-16 22:46:57 -0700590struct chip_operations soc_intel_xeon_sp_skx_ops = {
591 CHIP_NAME("Intel Skylake-SP")
Jonathan Zhang8f895492020-01-16 11:16:45 -0800592 .enable_dev = soc_enable_dev,
593 .init = soc_init,
594 .final = soc_final
595};
596
597struct pci_operations soc_pci_ops = {
598 .set_subsystem = pci_dev_set_subsystem,
599};