• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /* SPDX-License-Identifier: GPL-2.0-only */
2 
3 /* TODO: Update for Phoenix */
4 
5 #include <acpi/acpigen.h>
6 #include <amdblocks/alib.h>
7 #include <amdblocks/data_fabric.h>
8 #include <amdblocks/ioapic.h>
9 #include <amdblocks/root_complex.h>
10 #include <arch/ioapic.h>
11 #include <device/device.h>
12 #include <device/pci.h>
13 #include <soc/iomap.h>
14 #include <stdint.h>
15 #include "chip.h"
16 
17 #define DPTC_TOTAL_UPDATE_PARAMS	7
18 
19 struct 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 
acipgen_dptci(void)60 static void acipgen_dptci(void)
61 {
62 	const struct soc_amd_phoenix_config *config = config_of_soc();
63 
64 	/* Normal mode DPTC values. */
65 	struct dptc_input default_input = DPTC_INPUTS(config->thermctl_limit_degreeC,
66 		config->sustained_power_limit_mW,
67 		config->fast_ppt_limit_mW,
68 		config->slow_ppt_limit_mW,
69 		config->vrm_current_limit_mA,
70 		config->vrm_maximum_current_limit_mA,
71 		config->vrm_soc_current_limit_mA);
72 	acpigen_write_alib_dptc_default((uint8_t *)&default_input, sizeof(default_input));
73 
74 	/* Low/No Battery */
75 	struct dptc_input no_battery_input = DPTC_INPUTS(
76 		config->thermctl_limit_degreeC,
77 		config->sustained_power_limit_mW,
78 		config->fast_ppt_limit_mW,
79 		config->slow_ppt_limit_mW,
80 		config->vrm_current_limit_throttle_mA,
81 		config->vrm_maximum_current_limit_throttle_mA,
82 		config->vrm_soc_current_limit_throttle_mA);
83 	acpigen_write_alib_dptc_no_battery((uint8_t *)&no_battery_input,
84 		sizeof(no_battery_input));
85 }
86 
root_complex_fill_ssdt(const struct device * device)87 static void root_complex_fill_ssdt(const struct device *device)
88 {
89 	if (CONFIG(SOC_AMD_COMMON_BLOCK_ACPI_DPTC))
90 		acipgen_dptci();
91 }
92 
gnb_acpi_name(const struct device * dev)93 static const char *gnb_acpi_name(const struct device *dev)
94 {
95 	return "GNB";
96 }
97 
98 struct device_operations phoenix_root_complex_operations = {
99 	/* The root complex has no PCI BARs implemented, so there's no need to call
100 	   pci_dev_read_resources for it */
101 	.read_resources		= noop_read_resources,
102 	.set_resources		= noop_set_resources,
103 	.enable_resources	= pci_dev_enable_resources,
104 	.acpi_name		= gnb_acpi_name,
105 	.acpi_fill_ssdt		= root_complex_fill_ssdt,
106 };
107 
get_iohc_misc_smn_base(struct device * domain)108 uint32_t get_iohc_misc_smn_base(struct device *domain)
109 {
110 	return SMN_IOHC_MISC_BASE_13B1;
111 }
112 
113 static const struct non_pci_mmio_reg non_pci_mmio[] = {
114 	{ 0x2d0, 0xfffffff00000ull,   1 * MiB, NON_PCI_RES_IDX_AUTO },
115 	{ 0x2d8, 0xfffffff00000ull,   1 * MiB, NON_PCI_RES_IDX_AUTO },
116 	{ 0x2e0, 0xfffffff00000ull,   1 * MiB, NON_PCI_RES_IDX_AUTO },
117 	{ 0x2e8, 0xfffffff00000ull,   1 * MiB, NON_PCI_RES_IDX_AUTO },
118 	/* The hardware has a 256 byte alignment requirement for the IOAPIC MMIO base, but we
119 	   tell the FSP to configure a 4k-aligned base address and this is reported as 4 KiB
120 	   resource. */
121 	{ 0x2f0, 0xffffffffff00ull,   4 * KiB, IOMMU_IOAPIC_IDX },
122 	{ 0x2f8, 0xfffffff00000ull,   1 * MiB, NON_PCI_RES_IDX_AUTO },
123 	{ 0x300, 0xfffffff00000ull,   1 * MiB, NON_PCI_RES_IDX_AUTO },
124 	{ 0x308, 0xfffffffff000ull,   4 * KiB, NON_PCI_RES_IDX_AUTO },
125 	{ 0x310, 0xfffffff00000ull,   1 * MiB, NON_PCI_RES_IDX_AUTO },
126 	{ 0x318, 0xfffffff80000ull, 512 * KiB, NON_PCI_RES_IDX_AUTO },
127 	{ 0x320, 0xfffffff00000ull,   1 * MiB, NON_PCI_RES_IDX_AUTO },
128 };
129 
get_iohc_non_pci_mmio_regs(size_t * count)130 const struct non_pci_mmio_reg *get_iohc_non_pci_mmio_regs(size_t *count)
131 {
132 	*count = ARRAY_SIZE(non_pci_mmio);
133 	return non_pci_mmio;
134 }
135 
get_iohc_fabric_id(struct device * domain)136 signed int get_iohc_fabric_id(struct device *domain)
137 {
138 	switch (domain->path.domain.domain) {
139 	case 0:
140 		return IOMS0_FABRIC_ID;
141 	default:
142 		return -1;
143 	}
144 }
145