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