blob: 36942bf1f295c1a79aa1aef88c3159b70ec842d7 [file] [log] [blame]
Martin Rothf95a11e2022-10-21 16:43:08 -06001/* SPDX-License-Identifier: GPL-2.0-only */
2
3/* TODO: Update for Glinda */
4
5#include <acpi/acpigen.h>
Martin Rothf95a11e2022-10-21 16:43:08 -06006#include <amdblocks/alib.h>
Arthur Heymansce179722023-06-07 15:27:18 +02007#include <amdblocks/data_fabric.h>
Martin Rothf95a11e2022-10-21 16:43:08 -06008#include <amdblocks/ioapic.h>
Felix Heldc1be66e2023-07-18 20:38:01 +02009#include <amdblocks/root_complex.h>
Martin Rothf95a11e2022-10-21 16:43:08 -060010#include <arch/ioapic.h>
Martin Rothf95a11e2022-10-21 16:43:08 -060011#include <device/device.h>
12#include <device/pci.h>
Martin Rothf95a11e2022-10-21 16:43:08 -060013#include <soc/iomap.h>
14#include <stdint.h>
15#include "chip.h"
16
17#define DPTC_TOTAL_UPDATE_PARAMS 7
18
19struct dptc_input {
20 uint16_t size;
21 struct alib_dptc_param params[DPTC_TOTAL_UPDATE_PARAMS];
22} __packed;
23
24#define DPTC_INPUTS(_thermctllmit, _sustained, _fast, _slow, \
25 _vrmCurrentLimit, _vrmMaxCurrentLimit, _vrmSocCurrentLimit) \
26 { \
27 .size = sizeof(struct dptc_input), \
28 .params = { \
29 { \
30 .id = ALIB_DPTC_THERMAL_CONTROL_LIMIT_ID, \
31 .value = _thermctllmit, \
32 }, \
33 { \
34 .id = ALIB_DPTC_SUSTAINED_POWER_LIMIT_ID, \
35 .value = _sustained, \
36 }, \
37 { \
38 .id = ALIB_DPTC_FAST_PPT_LIMIT_ID, \
39 .value = _fast, \
40 }, \
41 { \
42 .id = ALIB_DPTC_SLOW_PPT_LIMIT_ID, \
43 .value = _slow, \
44 }, \
45 { \
46 .id = ALIB_DPTC_VRM_CURRENT_LIMIT_ID, \
47 .value = _vrmCurrentLimit, \
48 }, \
49 { \
50 .id = ALIB_DPTC_VRM_MAXIMUM_CURRENT_LIMIT, \
51 .value = _vrmMaxCurrentLimit, \
52 }, \
53 { \
54 .id = ALIB_DPTC_VRM_SOC_CURRENT_LIMIT_ID, \
55 .value = _vrmSocCurrentLimit, \
56 }, \
57 }, \
58 }
59
Martin Rothf95a11e2022-10-21 16:43:08 -060060static void root_complex_init(struct device *dev)
61{
Kyösti Mälkki2e65e9c2021-06-16 11:00:40 +030062 register_new_ioapic((u8 *)GNB_IO_APIC_ADDR);
Martin Rothf95a11e2022-10-21 16:43:08 -060063}
64
65static void acipgen_dptci(void)
66{
67 const struct soc_amd_glinda_config *config = config_of_soc();
68
69 /* Normal mode DPTC values. */
70 struct dptc_input default_input = DPTC_INPUTS(config->thermctl_limit_degreeC,
71 config->sustained_power_limit_mW,
72 config->fast_ppt_limit_mW,
73 config->slow_ppt_limit_mW,
74 config->vrm_current_limit_mA,
75 config->vrm_maximum_current_limit_mA,
76 config->vrm_soc_current_limit_mA);
77 acpigen_write_alib_dptc_default((uint8_t *)&default_input, sizeof(default_input));
78
79 /* Low/No Battery */
80 struct dptc_input no_battery_input = DPTC_INPUTS(
81 config->thermctl_limit_degreeC,
82 config->sustained_power_limit_mW,
83 config->fast_ppt_limit_mW,
84 config->slow_ppt_limit_mW,
85 config->vrm_current_limit_throttle_mA,
86 config->vrm_maximum_current_limit_throttle_mA,
87 config->vrm_soc_current_limit_throttle_mA);
88 acpigen_write_alib_dptc_no_battery((uint8_t *)&no_battery_input,
89 sizeof(no_battery_input));
90}
91
92static void root_complex_fill_ssdt(const struct device *device)
93{
Martin Rothf95a11e2022-10-21 16:43:08 -060094 if (CONFIG(SOC_AMD_COMMON_BLOCK_ACPI_DPTC))
95 acipgen_dptci();
96}
97
98static const char *gnb_acpi_name(const struct device *dev)
99{
100 return "GNB";
101}
102
103struct device_operations glinda_root_complex_operations = {
Felix Held30f36c32024-01-30 15:15:31 +0100104 /* The root complex has no PCI BARs implemented, so there's no need to call
105 pci_dev_read_resources for it */
106 .read_resources = noop_read_resources,
Martin Rothf95a11e2022-10-21 16:43:08 -0600107 .set_resources = noop_set_resources,
108 .enable_resources = pci_dev_enable_resources,
109 .init = root_complex_init,
110 .acpi_name = gnb_acpi_name,
111 .acpi_fill_ssdt = root_complex_fill_ssdt,
112};
Felix Heldc1be66e2023-07-18 20:38:01 +0200113
114uint32_t get_iohc_misc_smn_base(struct device *domain)
115{
Felix Held69ffebf2023-07-24 21:31:44 +0200116 return SMN_IOHC_MISC_BASE_13B1;
Felix Heldc1be66e2023-07-18 20:38:01 +0200117}
118
119static const struct non_pci_mmio_reg non_pci_mmio[] = {
120 { 0x2d0, 0xfffffff00000ull, 1 * MiB, NON_PCI_RES_IDX_AUTO },
121 { 0x2d8, 0xfffffff00000ull, 1 * MiB, NON_PCI_RES_IDX_AUTO },
122 { 0x2e0, 0xfffffff00000ull, 1 * MiB, NON_PCI_RES_IDX_AUTO },
123 { 0x2e8, 0xfffffff00000ull, 1 * MiB, NON_PCI_RES_IDX_AUTO },
124 /* The hardware has a 256 byte alignment requirement for the IOAPIC MMIO base, but we
125 tell the FSP to configure a 4k-aligned base address and this is reported as 4 KiB
126 resource. */
127 { 0x2f0, 0xffffffffff00ull, 4 * KiB, IOMMU_IOAPIC_IDX },
128 { 0x2f8, 0xfffffff00000ull, 1 * MiB, NON_PCI_RES_IDX_AUTO },
129 { 0x300, 0xfffffff00000ull, 1 * MiB, NON_PCI_RES_IDX_AUTO },
130 { 0x308, 0xfffffffff000ull, 4 * KiB, NON_PCI_RES_IDX_AUTO },
131 { 0x310, 0xfffffff00000ull, 1 * MiB, NON_PCI_RES_IDX_AUTO },
132 { 0x318, 0xfffffff80000ull, 512 * KiB, NON_PCI_RES_IDX_AUTO },
133 { 0x320, 0xfffffff00000ull, 1 * MiB, NON_PCI_RES_IDX_AUTO },
134};
135
136const struct non_pci_mmio_reg *get_iohc_non_pci_mmio_regs(size_t *count)
137{
138 *count = ARRAY_SIZE(non_pci_mmio);
139 return non_pci_mmio;
140}
Felix Heldb0ab5452023-08-11 22:24:00 +0200141
142signed int get_iohc_fabric_id(struct device *domain)
143{
144 switch (domain->path.domain.domain) {
145 case 0:
146 return IOMS0_FABRIC_ID;
147 default:
148 return -1;
149 }
150}