1 /* SPDX-License-Identifier: GPL-2.0-only */
3 #include <acpi/acpi_ivrs.h>
4 #include <amdblocks/acpi.h>
5 #include <amdblocks/cpu.h>
6 #include <amdblocks/ioapic.h>
7 #include <amdblocks/iommu.h>
8 #include <arch/ioapic.h>
9 #include <console/console.h>
10 #include <cpu/amd/cpuid.h>
11 #include <device/device.h>
12 #include <device/mmio.h>
13 #include <device/pci_def.h>
14 #include <device/pci_ops.h>
15 #include <soc/data_fabric.h>
16 #include <soc/iomap.h>
17 #include <soc/pci_devs.h>
19 static unsigned long acpi_fill_ivrs_ioapic(unsigned long current
, uintptr_t ioapic_base
,
20 uint16_t src_devid
, uint8_t dte_setting
)
22 ivrs_ivhd_special_t
*ivhd_ioapic
= (ivrs_ivhd_special_t
*)current
;
23 memset(ivhd_ioapic
, 0, sizeof(*ivhd_ioapic
));
25 ivhd_ioapic
->type
= IVHD_DEV_8_BYTE_EXT_SPECIAL_DEV
;
26 ivhd_ioapic
->dte_setting
= dte_setting
;
27 ivhd_ioapic
->handle
= get_ioapic_id(ioapic_base
);
28 ivhd_ioapic
->source_dev_id
= src_devid
;
29 ivhd_ioapic
->variety
= IVHD_SPECIAL_DEV_IOAPIC
;
30 current
+= sizeof(ivrs_ivhd_special_t
);
35 static unsigned long ivhd_describe_hpet(unsigned long current
, uint8_t hndl
, uint16_t src_devid
)
37 ivrs_ivhd_special_t
*ivhd_hpet
= (ivrs_ivhd_special_t
*)current
;
38 memset(ivhd_hpet
, 0, sizeof(*ivhd_hpet
));
40 ivhd_hpet
->type
= IVHD_DEV_8_BYTE_EXT_SPECIAL_DEV
;
41 ivhd_hpet
->handle
= hndl
;
42 ivhd_hpet
->source_dev_id
= src_devid
; /* function 0 of FCH PCI device */
43 ivhd_hpet
->variety
= IVHD_SPECIAL_DEV_HPET
;
44 current
+= sizeof(ivrs_ivhd_special_t
);
49 static unsigned long ivhd_describe_f0_device(unsigned long current
, uint16_t dev_id
,
50 const char acpi_hid
[8], uint8_t datasetting
)
52 ivrs_ivhd_f0_entry_t
*ivhd_f0
= (ivrs_ivhd_f0_entry_t
*)current
;
53 memset(ivhd_f0
, 0, sizeof(*ivhd_f0
));
55 ivhd_f0
->type
= IVHD_DEV_VARIABLE
;
56 ivhd_f0
->dev_id
= dev_id
;
57 ivhd_f0
->dte_setting
= datasetting
;
59 memcpy(ivhd_f0
->hardware_id
, acpi_hid
, sizeof(ivhd_f0
->hardware_id
));
61 current
+= sizeof(ivrs_ivhd_f0_entry_t
);
65 static unsigned long ivhd_dev_range(unsigned long current
, uint16_t start_devid
,
66 uint16_t end_devid
, uint8_t setting
)
68 /* 4-byte IVHD structures must be aligned to the 4-byte boundary. */
69 current
= ALIGN_UP(current
, 4);
70 ivrs_ivhd_generic_t
*ivhd_range
= (ivrs_ivhd_generic_t
*)current
;
71 memset(ivhd_range
, 0, sizeof(*ivhd_range
));
73 /* Create the start range IVHD entry */
74 ivhd_range
->type
= IVHD_DEV_4_BYTE_START_RANGE
;
75 ivhd_range
->dev_id
= start_devid
;
76 ivhd_range
->dte_setting
= setting
;
77 current
+= sizeof(ivrs_ivhd_generic_t
);
79 /* Create the end range IVHD entry */
80 ivhd_range
= (ivrs_ivhd_generic_t
*)current
;
81 ivhd_range
->type
= IVHD_DEV_4_BYTE_END_RANGE
;
82 ivhd_range
->dev_id
= end_devid
;
83 ivhd_range
->dte_setting
= setting
;
84 current
+= sizeof(ivrs_ivhd_generic_t
);
89 static unsigned long add_ivhd_dev_entry(struct device
*parent
, struct device
*dev
,
90 unsigned long *current
, uint8_t type
, uint8_t data
)
92 if (type
== IVHD_DEV_4_BYTE_SELECT
) {
93 /* 4-byte IVHD structures must be aligned to the 4-byte boundary. */
94 *current
= ALIGN_UP(*current
, 4);
95 ivrs_ivhd_generic_t
*ivhd_entry
= (ivrs_ivhd_generic_t
*)*current
;
96 memset(ivhd_entry
, 0, sizeof(*ivhd_entry
));
98 ivhd_entry
->type
= type
;
99 ivhd_entry
->dev_id
= dev
->path
.pci
.devfn
| (dev
->upstream
->secondary
<< 8);
100 ivhd_entry
->dte_setting
= data
;
101 *current
+= sizeof(ivrs_ivhd_generic_t
);
102 } else if (type
== IVHD_DEV_8_BYTE_ALIAS_SELECT
) {
103 ivrs_ivhd_alias_t
*ivhd_entry
= (ivrs_ivhd_alias_t
*)*current
;
104 memset(ivhd_entry
, 0, sizeof(*ivhd_entry
));
106 ivhd_entry
->type
= type
;
107 ivhd_entry
->dev_id
= dev
->path
.pci
.devfn
| (dev
->upstream
->secondary
<< 8);
108 ivhd_entry
->dte_setting
= data
;
109 ivhd_entry
->reserved1
= 0;
110 ivhd_entry
->reserved2
= 0;
111 ivhd_entry
->source_dev_id
= parent
->path
.pci
.devfn
|
112 (parent
->upstream
->secondary
<< 8);
113 *current
+= sizeof(ivrs_ivhd_alias_t
);
119 static void ivrs_add_device_or_bridge(struct device
*parent
, struct device
*dev
,
120 unsigned long *current
)
122 unsigned int header_type
, is_pcie
;
124 header_type
= dev
->hdr_type
& 0x7f;
125 is_pcie
= pci_find_capability(dev
, PCI_CAP_ID_PCIE
);
127 if (((header_type
== PCI_HEADER_TYPE_NORMAL
) ||
128 (header_type
== PCI_HEADER_TYPE_BRIDGE
)) && is_pcie
) {
129 /* Device or Bridge is PCIe */
130 add_ivhd_dev_entry(parent
, dev
, current
, IVHD_DEV_4_BYTE_SELECT
, 0x0);
131 } else if ((header_type
== PCI_HEADER_TYPE_NORMAL
) && !is_pcie
) {
132 /* Device is legacy PCI or PCI-X */
133 add_ivhd_dev_entry(parent
, dev
, current
, IVHD_DEV_8_BYTE_ALIAS_SELECT
, 0x0);
137 static void add_ivhd_device_entries(struct device
*parent
, struct device
*dev
,
138 unsigned int depth
, int linknum
, int8_t *root_level
,
139 unsigned long *current
, uint16_t nb_bus
)
141 struct device
*sibling
;
146 if (dev
->path
.type
== DEVICE_PATH_PCI
) {
147 if ((dev
->upstream
->secondary
== nb_bus
) &&
148 (dev
->path
.pci
.devfn
== 0x0))
151 if ((*root_level
!= -1) && (dev
->enabled
))
152 if (depth
!= *root_level
)
153 ivrs_add_device_or_bridge(parent
, dev
, current
);
156 if (!dev
->downstream
)
158 for (sibling
= dev
->downstream
->children
; sibling
; sibling
= sibling
->sibling
)
159 add_ivhd_device_entries(dev
, sibling
, depth
+ 1, depth
, root_level
, current
,
163 static unsigned long acpi_ivhd_misc(unsigned long current
, struct device
*dev
)
165 u8 dte_setting
= IVHD_DTE_LINT_1_PASS
| IVHD_DTE_LINT_0_PASS
|
166 IVHD_DTE_SYS_MGT_NO_TRANS
| IVHD_DTE_NMI_PASS
|
167 IVHD_DTE_EXT_INT_PASS
| IVHD_DTE_INIT_PASS
;
168 int8_t root_level
= -1;
169 struct resource
*res
;
172 * Add all possible PCI devices in the domain that can generate transactions
173 * processed by IOMMU. Start with device <bus>:01.0
175 current
= ivhd_dev_range(current
, PCI_DEVFN(0, 3) | (dev
->downstream
->secondary
<< 8),
176 0xff | (dev
->downstream
->subordinate
<< 8), 0);
178 add_ivhd_device_entries(NULL
, dev
, 0, -1, &root_level
,
179 ¤t
, dev
->downstream
->secondary
);
181 res
= probe_resource(dev
, IOMMU_IOAPIC_IDX
);
183 /* Describe IOAPIC associated with the IOMMU */
184 current
= acpi_fill_ivrs_ioapic(current
, (uintptr_t)res
->base
,
185 PCI_DEVFN(0, 1) | (dev
->downstream
->secondary
<< 8), 0);
188 /* If the domain has secondary bus as zero then associate HPET & FCH IOAPIC */
189 if (dev
->downstream
->secondary
== 0) {
191 current
= ivhd_describe_hpet(current
, 0x00, SMBUS_DEVFN
);
192 /* Describe FCH IOAPICs */
193 current
= acpi_fill_ivrs_ioapic(current
, IO_APIC_ADDR
,
194 SMBUS_DEVFN
, dte_setting
);
200 static unsigned long acpi_fill_ivrs40(unsigned long current
, acpi_ivrs_ivhd_t
*ivhd
,
201 struct device
*nb_dev
, struct device
*iommu_dev
)
203 acpi_ivrs_ivhd40_t
*ivhd_40
= (acpi_ivrs_ivhd40_t
*)current
;
204 unsigned long current_backup
;
206 memset(ivhd_40
, 0, sizeof(*ivhd_40
));
209 ivhd_40
->type
= IVHD_BLOCK_TYPE_FULL__ACPI_HID
;
210 /* For type 40h bits 6 and 7 are reserved */
211 ivhd_40
->flags
= ivhd
->flags
& 0x3f;
212 ivhd_40
->length
= sizeof(struct acpi_ivrs_ivhd_40
);
214 ivhd_40
->device_id
= 0x02 | (nb_dev
->upstream
->secondary
<< 8);
215 ivhd_40
->capability_offset
= pci_find_capability(iommu_dev
, IOMMU_CAP_ID
);
216 ivhd_40
->iommu_base_low
= ivhd
->iommu_base_low
;
217 ivhd_40
->iommu_base_high
= ivhd
->iommu_base_high
;
218 ivhd_40
->pci_segment_group
= nb_dev
->upstream
->segment_group
;
219 ivhd_40
->iommu_info
= ivhd
->iommu_info
;
220 /* For type 40h bits 31:28 and 12:0 are reserved */
221 ivhd_40
->iommu_attributes
= ivhd
->iommu_feature_info
& 0xfffe000;
223 if (pci_read_config32(iommu_dev
, ivhd_40
->capability_offset
) & EFR_FEATURE_SUP
) {
224 ivhd_40
->efr_reg_image_low
= read32p(ivhd_40
->iommu_base_low
+ 0x30);
225 ivhd_40
->efr_reg_image_high
= read32p(ivhd_40
->iommu_base_low
+ 0x34);
228 current
+= sizeof(acpi_ivrs_ivhd40_t
);
230 /* Now repeat all the device entries from type 10h */
231 current_backup
= current
;
232 current
= acpi_ivhd_misc(current
, nb_dev
->upstream
->dev
);
234 if (nb_dev
->upstream
->secondary
== 0) {
236 if (CONFIG(SOC_AMD_COMMON_BLOCK_EMMC
)) {
237 /* PCI_DEVFN(0x13, 1) doesn't exist in the hardware, but it's what the
238 * reference code uses. Maybe to have a unique PCI device to put into
239 * the field that doesn't collide with any existing device? */
240 current
= ivhd_describe_f0_device(current
, PCI_DEVFN(0x13, 1),
242 IVHD_DTE_LINT_1_PASS
| IVHD_DTE_LINT_0_PASS
|
243 IVHD_DTE_SYS_MGT_TRANS
| IVHD_DTE_NMI_PASS
|
244 IVHD_DTE_EXT_INT_PASS
| IVHD_DTE_INIT_PASS
);
247 ivhd_40
->length
+= (current
- current_backup
);
252 static unsigned long acpi_fill_ivrs11(unsigned long current
, acpi_ivrs_ivhd_t
*ivhd
,
253 struct device
*nb_dev
, struct device
*iommu_dev
)
255 acpi_ivrs_ivhd11_t
*ivhd_11
= (acpi_ivrs_ivhd11_t
*)current
;
256 ivhd11_iommu_attr_t
*ivhd11_attr_ptr
;
257 unsigned long current_backup
;
260 * In order to utilize all features, firmware should expose type 11h
261 * IVHD which supersedes the type 10h.
263 memset(ivhd_11
, 0, sizeof(*ivhd_11
));
266 ivhd_11
->type
= IVHD_BLOCK_TYPE_FULL__FIXED
;
267 /* For type 11h bits 6 and 7 are reserved */
268 ivhd_11
->flags
= ivhd
->flags
& 0x3f;
269 ivhd_11
->length
= sizeof(struct acpi_ivrs_ivhd_11
);
271 ivhd_11
->device_id
= 0x02 | (nb_dev
->upstream
->secondary
<< 8);
272 ivhd_11
->capability_offset
= pci_find_capability(iommu_dev
, IOMMU_CAP_ID
);
273 ivhd_11
->iommu_base_low
= ivhd
->iommu_base_low
;
274 ivhd_11
->iommu_base_high
= ivhd
->iommu_base_high
;
275 ivhd_11
->pci_segment_group
= nb_dev
->upstream
->segment_group
;
276 ivhd_11
->iommu_info
= ivhd
->iommu_info
;
277 ivhd11_attr_ptr
= (ivhd11_iommu_attr_t
*)&ivhd
->iommu_feature_info
;
278 ivhd_11
->iommu_attributes
.perf_counters
= ivhd11_attr_ptr
->perf_counters
;
279 ivhd_11
->iommu_attributes
.perf_counter_banks
= ivhd11_attr_ptr
->perf_counter_banks
;
280 ivhd_11
->iommu_attributes
.msi_num_ppr
= ivhd11_attr_ptr
->msi_num_ppr
;
282 if (pci_read_config32(iommu_dev
, ivhd_11
->capability_offset
) & EFR_FEATURE_SUP
) {
283 ivhd_11
->efr_reg_image_low
= read32p(ivhd_11
->iommu_base_low
+ 0x30);
284 ivhd_11
->efr_reg_image_high
= read32p(ivhd_11
->iommu_base_low
+ 0x34);
287 current
+= sizeof(acpi_ivrs_ivhd11_t
);
289 /* Now repeat all the device entries from type 10h */
290 current_backup
= current
;
291 current
= acpi_ivhd_misc(current
, nb_dev
->upstream
->dev
);
292 ivhd_11
->length
+= (current
- current_backup
);
294 return acpi_fill_ivrs40(current
, ivhd
, nb_dev
, iommu_dev
);
297 static unsigned long acpi_fill_ivrs(acpi_ivrs_t
*ivrs
, unsigned long current
)
299 unsigned long current_backup
;
300 uint64_t mmio_x30_value
;
301 uint64_t mmio_x18_value
;
302 uint64_t mmio_x4000_value
;
303 uint32_t cap_offset_0
;
304 uint32_t cap_offset_10
;
305 struct acpi_ivrs_ivhd
*ivhd
;
306 struct device
*iommu_dev
;
307 struct device
*nb_dev
;
308 struct device
*dev
= NULL
;
311 printk(BIOS_WARNING
, "%s: ivrs is NULL\n", __func__
);
317 while ((dev
= dev_find_path(dev
, DEVICE_PATH_DOMAIN
)) != NULL
) {
318 nb_dev
= pcidev_path_behind(dev
->downstream
, PCI_DEVFN(0, 0));
319 iommu_dev
= pcidev_path_behind(dev
->downstream
, PCI_DEVFN(0, 2));
321 printk(BIOS_WARNING
, "%s: Northbridge device not present!\n", __func__
);
322 printk(BIOS_WARNING
, "%s: IVRS table not generated...\n", __func__
);
323 return (unsigned long)ivrs
;
327 printk(BIOS_WARNING
, "%s: IOMMU device not found\n", __func__
);
328 return (unsigned long)ivrs
;
331 ivhd
->type
= IVHD_BLOCK_TYPE_LEGACY__FIXED
;
332 ivhd
->length
= sizeof(struct acpi_ivrs_ivhd
);
335 ivhd
->device_id
= PCI_DEVFN(0, 2) | (nb_dev
->upstream
->secondary
<< 8);
336 ivhd
->capability_offset
= pci_find_capability(iommu_dev
, IOMMU_CAP_ID
);
337 ivhd
->iommu_base_low
= pci_read_config32(iommu_dev
, IOMMU_CAP_BASE_LO
) & 0xffffc000;
338 ivhd
->iommu_base_high
= pci_read_config32(iommu_dev
, IOMMU_CAP_BASE_HI
);
340 cap_offset_0
= pci_read_config32(iommu_dev
, ivhd
->capability_offset
);
341 cap_offset_10
= pci_read_config32(iommu_dev
,
342 ivhd
->capability_offset
+ 0x10);
343 mmio_x18_value
= read64p(ivhd
->iommu_base_low
+ 0x18);
344 mmio_x30_value
= read64p(ivhd
->iommu_base_low
+ 0x30);
345 mmio_x4000_value
= read64p(ivhd
->iommu_base_low
+ 0x4000);
347 ivhd
->flags
|= ((mmio_x30_value
& MMIO_EXT_FEATURE_PPR_SUP
) ?
348 IVHD_FLAG_PPE_SUP
: 0);
349 ivhd
->flags
|= ((mmio_x30_value
& MMIO_EXT_FEATURE_PRE_F_SUP
) ?
350 IVHD_FLAG_PREF_SUP
: 0);
351 ivhd
->flags
|= ((mmio_x18_value
& MMIO_CTRL_COHERENT
) ?
352 IVHD_FLAG_COHERENT
: 0);
353 ivhd
->flags
|= ((cap_offset_0
& CAP_OFFSET_0_IOTLB_SP
) ?
354 IVHD_FLAG_IOTLB_SUP
: 0);
355 ivhd
->flags
|= ((mmio_x18_value
& MMIO_CTRL_ISOC
) ?
357 ivhd
->flags
|= ((mmio_x18_value
& MMIO_CTRL_RES_PASS_PW
) ?
358 IVHD_FLAG_RES_PASS_PW
: 0);
359 ivhd
->flags
|= ((mmio_x18_value
& MMIO_CTRL_PASS_PW
) ?
360 IVHD_FLAG_PASS_PW
: 0);
361 ivhd
->flags
|= ((mmio_x18_value
& MMIO_CTRL_HT_TUN_EN
) ?
362 IVHD_FLAG_HT_TUN_EN
: 0);
364 ivhd
->pci_segment_group
= nb_dev
->upstream
->segment_group
;
366 ivhd
->iommu_info
= pci_read_config16(iommu_dev
,
367 ivhd
->capability_offset
+ 0x10) & 0x1F;
368 ivhd
->iommu_info
|= (pci_read_config16(iommu_dev
,
369 ivhd
->capability_offset
+ 0xC) & 0x1F) << IOMMU_INFO_UNIT_ID_SHIFT
;
371 ivhd
->iommu_feature_info
= 0;
372 ivhd
->iommu_feature_info
|= (mmio_x30_value
& MMIO_EXT_FEATURE_HATS_MASK
)
373 << (IOMMU_FEATURE_HATS_SHIFT
- MMIO_EXT_FEATURE_HATS_SHIFT
);
375 ivhd
->iommu_feature_info
|= (mmio_x30_value
& MMIO_EXT_FEATURE_GATS_MASK
)
376 << (IOMMU_FEATURE_GATS_SHIFT
- MMIO_EXT_FEATURE_GATS_SHIFT
);
378 ivhd
->iommu_feature_info
|= (cap_offset_10
& CAP_OFFSET_10_MSI_NUM_PPR
)
379 >> (CAP_OFFSET_10_MSI_NUM_PPR_SHIFT
380 - IOMMU_FEATURE_MSI_NUM_PPR_SHIFT
);
382 ivhd
->iommu_feature_info
|= (mmio_x4000_value
&
383 MMIO_CNT_CFG_N_COUNTER_BANKS
)
384 << (IOMMU_FEATURE_PN_BANKS_SHIFT
- MMIO_CNT_CFG_N_CNT_BANKS_SHIFT
);
386 ivhd
->iommu_feature_info
|= (mmio_x4000_value
& MMIO_CNT_CFG_N_COUNTER
)
387 << (IOMMU_FEATURE_PN_COUNTERS_SHIFT
- MMIO_CNT_CFG_N_COUNTER_SHIFT
);
388 ivhd
->iommu_feature_info
|= (mmio_x30_value
&
389 MMIO_EXT_FEATURE_PAS_MAX_MASK
)
390 >> (MMIO_EXT_FEATURE_PAS_MAX_SHIFT
- IOMMU_FEATURE_PA_SMAX_SHIFT
);
391 ivhd
->iommu_feature_info
|= ((mmio_x30_value
& MMIO_EXT_FEATURE_HE_SUP
)
392 ? IOMMU_FEATURE_HE_SUP
: 0);
393 ivhd
->iommu_feature_info
|= ((mmio_x30_value
& MMIO_EXT_FEATURE_GA_SUP
)
394 ? IOMMU_FEATURE_GA_SUP
: 0);
395 ivhd
->iommu_feature_info
|= ((mmio_x30_value
& MMIO_EXT_FEATURE_IA_SUP
)
396 ? IOMMU_FEATURE_IA_SUP
: 0);
397 ivhd
->iommu_feature_info
|= (mmio_x30_value
&
398 MMIO_EXT_FEATURE_GLX_SUP_MASK
)
399 >> (MMIO_EXT_FEATURE_GLX_SHIFT
- IOMMU_FEATURE_GLX_SHIFT
);
400 ivhd
->iommu_feature_info
|= ((mmio_x30_value
& MMIO_EXT_FEATURE_GT_SUP
)
401 ? IOMMU_FEATURE_GT_SUP
: 0);
402 ivhd
->iommu_feature_info
|= ((mmio_x30_value
& MMIO_EXT_FEATURE_NX_SUP
)
403 ? IOMMU_FEATURE_NX_SUP
: 0);
404 ivhd
->iommu_feature_info
|= ((mmio_x30_value
& MMIO_EXT_FEATURE_XT_SUP
)
405 ? IOMMU_FEATURE_XT_SUP
: 0);
407 /* Enable EFR if supported */
408 ivrs
->iv_info
= pci_read_config32(iommu_dev
,
409 ivhd
->capability_offset
+ 0x10) & 0x007fffe0;
410 if (pci_read_config32(iommu_dev
,
411 ivhd
->capability_offset
) & EFR_FEATURE_SUP
)
412 ivrs
->iv_info
|= IVINFO_EFR_SUPPORTED
;
415 current_backup
= current
;
416 current
= acpi_ivhd_misc(current
, dev
);
417 ivhd
->length
+= (current
- current_backup
);
419 /* If EFR is not supported, IVHD type 11h is reserved */
420 if (!(ivrs
->iv_info
& IVINFO_EFR_SUPPORTED
))
423 current
= acpi_fill_ivrs11(current
, ivhd
, nb_dev
, iommu_dev
);
425 ivhd
= (struct acpi_ivrs_ivhd
*)current
;
426 current
+= sizeof(struct acpi_ivrs_ivhd
);
428 current
-= sizeof(struct acpi_ivrs_ivhd
);
433 unsigned long acpi_add_ivrs_table(unsigned long current
, acpi_rsdp_t
*rsdp
)
437 current
= acpi_align_current(current
);
438 ivrs
= (acpi_ivrs_t
*)current
;
439 acpi_create_ivrs(ivrs
, acpi_fill_ivrs
);
440 current
+= ivrs
->header
.length
;
441 acpi_add_table(rsdp
, ivrs
);