uart/ns16550, drivers/pcie: add PCI(e) support
A parallel PCI implementation ("pcie") is added with features for PCIe.
In particular, message-signaled interrupts (MSI) are supported, which
are essential to the use of any non-trivial PCIe device.
The NS16550 UART driver is modified to use pcie.
pcie is a complete replacement for the old PCI support ("pci"). It is
smaller, by an order of magnitude, and cleaner. Both pci and pcie can
(and do) coexist in the same builds, but the intent is to rework any
existing drivers that depend on pci and ultimately remove pci entirely.
This patch is large, but things in mirror are smaller than they appear.
Most of the modified files are configuration-related, and are changed
only slightly to accommodate the modified UART driver.
Deficiencies:
64-bit support is minimal. The code works fine with 64-bit capable
devices, but will not cooperate with MMIO regions (or MSI targets) that
have high bits set. This is not needed on any current boards, and is
unlikely to be needed in the future. Only superficial changes would
be required if we change our minds.
The method specifying PCI endpoints in devicetree is somewhat kludgey.
The "right" way would be to hang PCI devices off a topological tree;
while this would be more aesthetically pleasing, I don't think it's
worth the effort, given our non-standard use of devicetree.
Signed-off-by: Charles E. Youse <charles.youse@intel.com>
2019-04-02 19:06:07 +02:00
|
|
|
/*
|
|
|
|
* Copyright (c) 2019 Intel Corporation
|
|
|
|
*
|
|
|
|
* SPDX-License-Identifier: Apache-2.0
|
|
|
|
*/
|
|
|
|
|
2022-05-06 10:49:15 +02:00
|
|
|
#include <zephyr/kernel.h>
|
|
|
|
#include <zephyr/sys/device_mmio.h>
|
|
|
|
#include <zephyr/drivers/pcie/pcie.h>
|
uart/ns16550, drivers/pcie: add PCI(e) support
A parallel PCI implementation ("pcie") is added with features for PCIe.
In particular, message-signaled interrupts (MSI) are supported, which
are essential to the use of any non-trivial PCIe device.
The NS16550 UART driver is modified to use pcie.
pcie is a complete replacement for the old PCI support ("pci"). It is
smaller, by an order of magnitude, and cleaner. Both pci and pcie can
(and do) coexist in the same builds, but the intent is to rework any
existing drivers that depend on pci and ultimately remove pci entirely.
This patch is large, but things in mirror are smaller than they appear.
Most of the modified files are configuration-related, and are changed
only slightly to accommodate the modified UART driver.
Deficiencies:
64-bit support is minimal. The code works fine with 64-bit capable
devices, but will not cooperate with MMIO regions (or MSI targets) that
have high bits set. This is not needed on any current boards, and is
unlikely to be needed in the future. Only superficial changes would
be required if we change our minds.
The method specifying PCI endpoints in devicetree is somewhat kludgey.
The "right" way would be to hang PCI devices off a topological tree;
while this would be more aesthetically pleasing, I don't think it's
worth the effort, given our non-standard use of devicetree.
Signed-off-by: Charles E. Youse <charles.youse@intel.com>
2019-04-02 19:06:07 +02:00
|
|
|
|
2023-07-02 11:57:24 +02:00
|
|
|
#ifdef CONFIG_ACPI
|
|
|
|
#include <zephyr/acpi/acpi.h>
|
2020-06-13 15:34:46 +02:00
|
|
|
#endif
|
|
|
|
|
uart/ns16550, drivers/pcie: add PCI(e) support
A parallel PCI implementation ("pcie") is added with features for PCIe.
In particular, message-signaled interrupts (MSI) are supported, which
are essential to the use of any non-trivial PCIe device.
The NS16550 UART driver is modified to use pcie.
pcie is a complete replacement for the old PCI support ("pci"). It is
smaller, by an order of magnitude, and cleaner. Both pci and pcie can
(and do) coexist in the same builds, but the intent is to rework any
existing drivers that depend on pci and ultimately remove pci entirely.
This patch is large, but things in mirror are smaller than they appear.
Most of the modified files are configuration-related, and are changed
only slightly to accommodate the modified UART driver.
Deficiencies:
64-bit support is minimal. The code works fine with 64-bit capable
devices, but will not cooperate with MMIO regions (or MSI targets) that
have high bits set. This is not needed on any current boards, and is
unlikely to be needed in the future. Only superficial changes would
be required if we change our minds.
The method specifying PCI endpoints in devicetree is somewhat kludgey.
The "right" way would be to hang PCI devices off a topological tree;
while this would be more aesthetically pleasing, I don't think it's
worth the effort, given our non-standard use of devicetree.
Signed-off-by: Charles E. Youse <charles.youse@intel.com>
2019-04-02 19:06:07 +02:00
|
|
|
#ifdef CONFIG_PCIE_MSI
|
2020-11-05 10:42:07 +01:00
|
|
|
#include <kernel_arch_func.h>
|
2022-05-06 10:49:15 +02:00
|
|
|
#include <zephyr/device.h>
|
|
|
|
#include <zephyr/drivers/pcie/msi.h>
|
|
|
|
#include <zephyr/drivers/interrupt_controller/sysapic.h>
|
|
|
|
#include <zephyr/arch/x86/cpuid.h>
|
uart/ns16550, drivers/pcie: add PCI(e) support
A parallel PCI implementation ("pcie") is added with features for PCIe.
In particular, message-signaled interrupts (MSI) are supported, which
are essential to the use of any non-trivial PCIe device.
The NS16550 UART driver is modified to use pcie.
pcie is a complete replacement for the old PCI support ("pci"). It is
smaller, by an order of magnitude, and cleaner. Both pci and pcie can
(and do) coexist in the same builds, but the intent is to rework any
existing drivers that depend on pci and ultimately remove pci entirely.
This patch is large, but things in mirror are smaller than they appear.
Most of the modified files are configuration-related, and are changed
only slightly to accommodate the modified UART driver.
Deficiencies:
64-bit support is minimal. The code works fine with 64-bit capable
devices, but will not cooperate with MMIO regions (or MSI targets) that
have high bits set. This is not needed on any current boards, and is
unlikely to be needed in the future. Only superficial changes would
be required if we change our minds.
The method specifying PCI endpoints in devicetree is somewhat kludgey.
The "right" way would be to hang PCI devices off a topological tree;
while this would be more aesthetically pleasing, I don't think it's
worth the effort, given our non-standard use of devicetree.
Signed-off-by: Charles E. Youse <charles.youse@intel.com>
2019-04-02 19:06:07 +02:00
|
|
|
#endif
|
|
|
|
|
2020-06-13 15:34:46 +02:00
|
|
|
/* PCI Express Extended Configuration Mechanism (MMIO) */
|
2020-09-15 21:53:20 +02:00
|
|
|
#ifdef CONFIG_PCIE_MMIO_CFG
|
2020-06-13 15:34:46 +02:00
|
|
|
|
|
|
|
#define MAX_PCI_BUS_SEGMENTS 4
|
|
|
|
|
|
|
|
static struct {
|
|
|
|
uint32_t start_bus;
|
|
|
|
uint32_t n_buses;
|
|
|
|
uint8_t *mmio;
|
|
|
|
} bus_segs[MAX_PCI_BUS_SEGMENTS];
|
|
|
|
|
2020-09-15 21:53:20 +02:00
|
|
|
static bool do_pcie_mmio_cfg;
|
|
|
|
|
2020-06-13 15:34:46 +02:00
|
|
|
static void pcie_mm_init(void)
|
|
|
|
{
|
2023-07-02 11:57:24 +02:00
|
|
|
#ifdef CONFIG_ACPI
|
|
|
|
struct acpi_mcfg *m = acpi_table_get("MCFG", 0);
|
2020-06-13 15:34:46 +02:00
|
|
|
|
|
|
|
if (m != NULL) {
|
2023-07-02 11:57:24 +02:00
|
|
|
int n = (m->header.Length - sizeof(*m)) / sizeof(m->pci_segs[0]);
|
2020-06-13 15:34:46 +02:00
|
|
|
|
|
|
|
for (int i = 0; i < n && i < MAX_PCI_BUS_SEGMENTS; i++) {
|
2020-07-07 22:42:01 +02:00
|
|
|
size_t size;
|
|
|
|
uintptr_t phys_addr;
|
|
|
|
|
2023-07-02 11:57:24 +02:00
|
|
|
bus_segs[i].start_bus = m->pci_segs[i].StartBusNumber;
|
|
|
|
bus_segs[i].n_buses =
|
|
|
|
1 + m->pci_segs[i].EndBusNumber - m->pci_segs[i].StartBusNumber;
|
2020-07-07 22:42:01 +02:00
|
|
|
|
2023-07-02 11:57:24 +02:00
|
|
|
phys_addr = m->pci_segs[i].Address;
|
2020-07-07 22:42:01 +02:00
|
|
|
/* 32 devices & 8 functions per bus, 4k per device */
|
|
|
|
size = bus_segs[i].n_buses * (32 * 8 * 4096);
|
|
|
|
|
2023-07-02 11:57:24 +02:00
|
|
|
device_map((mm_reg_t *)&bus_segs[i].mmio, phys_addr, size,
|
|
|
|
K_MEM_CACHE_NONE);
|
2020-06-13 15:34:46 +02:00
|
|
|
}
|
2020-09-15 21:53:20 +02:00
|
|
|
|
|
|
|
do_pcie_mmio_cfg = true;
|
2020-06-13 15:34:46 +02:00
|
|
|
}
|
|
|
|
#endif
|
|
|
|
}
|
|
|
|
|
|
|
|
static inline void pcie_mm_conf(pcie_bdf_t bdf, unsigned int reg,
|
|
|
|
bool write, uint32_t *data)
|
|
|
|
{
|
|
|
|
for (int i = 0; i < ARRAY_SIZE(bus_segs); i++) {
|
|
|
|
int off = PCIE_BDF_TO_BUS(bdf) - bus_segs[i].start_bus;
|
|
|
|
|
|
|
|
if (off >= 0 && off < bus_segs[i].n_buses) {
|
|
|
|
bdf = PCIE_BDF(off,
|
|
|
|
PCIE_BDF_TO_DEV(bdf),
|
|
|
|
PCIE_BDF_TO_FUNC(bdf));
|
|
|
|
|
|
|
|
volatile uint32_t *regs
|
2020-10-23 23:12:12 +02:00
|
|
|
= (void *)&bus_segs[i].mmio[bdf << 4];
|
2020-06-13 15:34:46 +02:00
|
|
|
|
|
|
|
if (write) {
|
|
|
|
regs[reg] = *data;
|
|
|
|
} else {
|
|
|
|
*data = regs[reg];
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2020-09-15 21:53:20 +02:00
|
|
|
#endif /* CONFIG_PCIE_MMIO_CFG */
|
|
|
|
|
2020-06-13 15:34:46 +02:00
|
|
|
/* Traditional Configuration Mechanism */
|
uart/ns16550, drivers/pcie: add PCI(e) support
A parallel PCI implementation ("pcie") is added with features for PCIe.
In particular, message-signaled interrupts (MSI) are supported, which
are essential to the use of any non-trivial PCIe device.
The NS16550 UART driver is modified to use pcie.
pcie is a complete replacement for the old PCI support ("pci"). It is
smaller, by an order of magnitude, and cleaner. Both pci and pcie can
(and do) coexist in the same builds, but the intent is to rework any
existing drivers that depend on pci and ultimately remove pci entirely.
This patch is large, but things in mirror are smaller than they appear.
Most of the modified files are configuration-related, and are changed
only slightly to accommodate the modified UART driver.
Deficiencies:
64-bit support is minimal. The code works fine with 64-bit capable
devices, but will not cooperate with MMIO regions (or MSI targets) that
have high bits set. This is not needed on any current boards, and is
unlikely to be needed in the future. Only superficial changes would
be required if we change our minds.
The method specifying PCI endpoints in devicetree is somewhat kludgey.
The "right" way would be to hang PCI devices off a topological tree;
while this would be more aesthetically pleasing, I don't think it's
worth the effort, given our non-standard use of devicetree.
Signed-off-by: Charles E. Youse <charles.youse@intel.com>
2019-04-02 19:06:07 +02:00
|
|
|
|
|
|
|
#define PCIE_X86_CAP 0xCF8U /* Configuration Address Port */
|
|
|
|
#define PCIE_X86_CAP_BDF_MASK 0x00FFFF00U /* b/d/f bits */
|
|
|
|
#define PCIE_X86_CAP_EN 0x80000000U /* enable bit */
|
|
|
|
#define PCIE_X86_CAP_WORD_MASK 0x3FU /* 6-bit word index .. */
|
|
|
|
#define PCIE_X86_CAP_WORD_SHIFT 2U /* .. is in CAP[7:2] */
|
|
|
|
|
|
|
|
#define PCIE_X86_CDP 0xCFCU /* Configuration Data Port */
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Helper function for exported configuration functions. Configuration access
|
2021-04-29 05:01:40 +02:00
|
|
|
* is not atomic, so spinlock to keep drivers from clobbering each other.
|
uart/ns16550, drivers/pcie: add PCI(e) support
A parallel PCI implementation ("pcie") is added with features for PCIe.
In particular, message-signaled interrupts (MSI) are supported, which
are essential to the use of any non-trivial PCIe device.
The NS16550 UART driver is modified to use pcie.
pcie is a complete replacement for the old PCI support ("pci"). It is
smaller, by an order of magnitude, and cleaner. Both pci and pcie can
(and do) coexist in the same builds, but the intent is to rework any
existing drivers that depend on pci and ultimately remove pci entirely.
This patch is large, but things in mirror are smaller than they appear.
Most of the modified files are configuration-related, and are changed
only slightly to accommodate the modified UART driver.
Deficiencies:
64-bit support is minimal. The code works fine with 64-bit capable
devices, but will not cooperate with MMIO regions (or MSI targets) that
have high bits set. This is not needed on any current boards, and is
unlikely to be needed in the future. Only superficial changes would
be required if we change our minds.
The method specifying PCI endpoints in devicetree is somewhat kludgey.
The "right" way would be to hang PCI devices off a topological tree;
while this would be more aesthetically pleasing, I don't think it's
worth the effort, given our non-standard use of devicetree.
Signed-off-by: Charles E. Youse <charles.youse@intel.com>
2019-04-02 19:06:07 +02:00
|
|
|
*/
|
2020-06-13 15:34:46 +02:00
|
|
|
static inline void pcie_io_conf(pcie_bdf_t bdf, unsigned int reg,
|
|
|
|
bool write, uint32_t *data)
|
uart/ns16550, drivers/pcie: add PCI(e) support
A parallel PCI implementation ("pcie") is added with features for PCIe.
In particular, message-signaled interrupts (MSI) are supported, which
are essential to the use of any non-trivial PCIe device.
The NS16550 UART driver is modified to use pcie.
pcie is a complete replacement for the old PCI support ("pci"). It is
smaller, by an order of magnitude, and cleaner. Both pci and pcie can
(and do) coexist in the same builds, but the intent is to rework any
existing drivers that depend on pci and ultimately remove pci entirely.
This patch is large, but things in mirror are smaller than they appear.
Most of the modified files are configuration-related, and are changed
only slightly to accommodate the modified UART driver.
Deficiencies:
64-bit support is minimal. The code works fine with 64-bit capable
devices, but will not cooperate with MMIO regions (or MSI targets) that
have high bits set. This is not needed on any current boards, and is
unlikely to be needed in the future. Only superficial changes would
be required if we change our minds.
The method specifying PCI endpoints in devicetree is somewhat kludgey.
The "right" way would be to hang PCI devices off a topological tree;
while this would be more aesthetically pleasing, I don't think it's
worth the effort, given our non-standard use of devicetree.
Signed-off-by: Charles E. Youse <charles.youse@intel.com>
2019-04-02 19:06:07 +02:00
|
|
|
{
|
|
|
|
static struct k_spinlock lock;
|
|
|
|
k_spinlock_key_t k;
|
|
|
|
|
|
|
|
bdf &= PCIE_X86_CAP_BDF_MASK;
|
|
|
|
bdf |= PCIE_X86_CAP_EN;
|
|
|
|
bdf |= (reg & PCIE_X86_CAP_WORD_MASK) << PCIE_X86_CAP_WORD_SHIFT;
|
|
|
|
|
|
|
|
k = k_spin_lock(&lock);
|
|
|
|
sys_out32(bdf, PCIE_X86_CAP);
|
|
|
|
|
|
|
|
if (write) {
|
|
|
|
sys_out32(*data, PCIE_X86_CDP);
|
|
|
|
} else {
|
|
|
|
*data = sys_in32(PCIE_X86_CDP);
|
|
|
|
}
|
|
|
|
|
|
|
|
sys_out32(0U, PCIE_X86_CAP);
|
|
|
|
k_spin_unlock(&lock, k);
|
|
|
|
}
|
|
|
|
|
2020-06-13 15:34:46 +02:00
|
|
|
static inline void pcie_conf(pcie_bdf_t bdf, unsigned int reg,
|
|
|
|
bool write, uint32_t *data)
|
|
|
|
|
|
|
|
{
|
|
|
|
#ifdef CONFIG_PCIE_MMIO_CFG
|
2020-09-22 16:04:25 +02:00
|
|
|
if (bus_segs[0].mmio == NULL) {
|
|
|
|
pcie_mm_init();
|
|
|
|
}
|
|
|
|
|
2020-09-15 21:53:20 +02:00
|
|
|
if (do_pcie_mmio_cfg) {
|
|
|
|
pcie_mm_conf(bdf, reg, write, data);
|
|
|
|
} else
|
2020-06-13 15:34:46 +02:00
|
|
|
#endif
|
2020-09-15 21:53:20 +02:00
|
|
|
{
|
|
|
|
pcie_io_conf(bdf, reg, write, data);
|
|
|
|
}
|
2020-06-13 15:34:46 +02:00
|
|
|
}
|
|
|
|
|
uart/ns16550, drivers/pcie: add PCI(e) support
A parallel PCI implementation ("pcie") is added with features for PCIe.
In particular, message-signaled interrupts (MSI) are supported, which
are essential to the use of any non-trivial PCIe device.
The NS16550 UART driver is modified to use pcie.
pcie is a complete replacement for the old PCI support ("pci"). It is
smaller, by an order of magnitude, and cleaner. Both pci and pcie can
(and do) coexist in the same builds, but the intent is to rework any
existing drivers that depend on pci and ultimately remove pci entirely.
This patch is large, but things in mirror are smaller than they appear.
Most of the modified files are configuration-related, and are changed
only slightly to accommodate the modified UART driver.
Deficiencies:
64-bit support is minimal. The code works fine with 64-bit capable
devices, but will not cooperate with MMIO regions (or MSI targets) that
have high bits set. This is not needed on any current boards, and is
unlikely to be needed in the future. Only superficial changes would
be required if we change our minds.
The method specifying PCI endpoints in devicetree is somewhat kludgey.
The "right" way would be to hang PCI devices off a topological tree;
while this would be more aesthetically pleasing, I don't think it's
worth the effort, given our non-standard use of devicetree.
Signed-off-by: Charles E. Youse <charles.youse@intel.com>
2019-04-02 19:06:07 +02:00
|
|
|
/* these functions are explained in include/drivers/pcie/pcie.h */
|
|
|
|
|
2020-05-27 18:26:57 +02:00
|
|
|
uint32_t pcie_conf_read(pcie_bdf_t bdf, unsigned int reg)
|
uart/ns16550, drivers/pcie: add PCI(e) support
A parallel PCI implementation ("pcie") is added with features for PCIe.
In particular, message-signaled interrupts (MSI) are supported, which
are essential to the use of any non-trivial PCIe device.
The NS16550 UART driver is modified to use pcie.
pcie is a complete replacement for the old PCI support ("pci"). It is
smaller, by an order of magnitude, and cleaner. Both pci and pcie can
(and do) coexist in the same builds, but the intent is to rework any
existing drivers that depend on pci and ultimately remove pci entirely.
This patch is large, but things in mirror are smaller than they appear.
Most of the modified files are configuration-related, and are changed
only slightly to accommodate the modified UART driver.
Deficiencies:
64-bit support is minimal. The code works fine with 64-bit capable
devices, but will not cooperate with MMIO regions (or MSI targets) that
have high bits set. This is not needed on any current boards, and is
unlikely to be needed in the future. Only superficial changes would
be required if we change our minds.
The method specifying PCI endpoints in devicetree is somewhat kludgey.
The "right" way would be to hang PCI devices off a topological tree;
while this would be more aesthetically pleasing, I don't think it's
worth the effort, given our non-standard use of devicetree.
Signed-off-by: Charles E. Youse <charles.youse@intel.com>
2019-04-02 19:06:07 +02:00
|
|
|
{
|
2021-04-03 07:44:10 +02:00
|
|
|
uint32_t data = 0U;
|
uart/ns16550, drivers/pcie: add PCI(e) support
A parallel PCI implementation ("pcie") is added with features for PCIe.
In particular, message-signaled interrupts (MSI) are supported, which
are essential to the use of any non-trivial PCIe device.
The NS16550 UART driver is modified to use pcie.
pcie is a complete replacement for the old PCI support ("pci"). It is
smaller, by an order of magnitude, and cleaner. Both pci and pcie can
(and do) coexist in the same builds, but the intent is to rework any
existing drivers that depend on pci and ultimately remove pci entirely.
This patch is large, but things in mirror are smaller than they appear.
Most of the modified files are configuration-related, and are changed
only slightly to accommodate the modified UART driver.
Deficiencies:
64-bit support is minimal. The code works fine with 64-bit capable
devices, but will not cooperate with MMIO regions (or MSI targets) that
have high bits set. This is not needed on any current boards, and is
unlikely to be needed in the future. Only superficial changes would
be required if we change our minds.
The method specifying PCI endpoints in devicetree is somewhat kludgey.
The "right" way would be to hang PCI devices off a topological tree;
while this would be more aesthetically pleasing, I don't think it's
worth the effort, given our non-standard use of devicetree.
Signed-off-by: Charles E. Youse <charles.youse@intel.com>
2019-04-02 19:06:07 +02:00
|
|
|
|
|
|
|
pcie_conf(bdf, reg, false, &data);
|
|
|
|
return data;
|
|
|
|
}
|
|
|
|
|
2020-05-27 18:26:57 +02:00
|
|
|
void pcie_conf_write(pcie_bdf_t bdf, unsigned int reg, uint32_t data)
|
uart/ns16550, drivers/pcie: add PCI(e) support
A parallel PCI implementation ("pcie") is added with features for PCIe.
In particular, message-signaled interrupts (MSI) are supported, which
are essential to the use of any non-trivial PCIe device.
The NS16550 UART driver is modified to use pcie.
pcie is a complete replacement for the old PCI support ("pci"). It is
smaller, by an order of magnitude, and cleaner. Both pci and pcie can
(and do) coexist in the same builds, but the intent is to rework any
existing drivers that depend on pci and ultimately remove pci entirely.
This patch is large, but things in mirror are smaller than they appear.
Most of the modified files are configuration-related, and are changed
only slightly to accommodate the modified UART driver.
Deficiencies:
64-bit support is minimal. The code works fine with 64-bit capable
devices, but will not cooperate with MMIO regions (or MSI targets) that
have high bits set. This is not needed on any current boards, and is
unlikely to be needed in the future. Only superficial changes would
be required if we change our minds.
The method specifying PCI endpoints in devicetree is somewhat kludgey.
The "right" way would be to hang PCI devices off a topological tree;
while this would be more aesthetically pleasing, I don't think it's
worth the effort, given our non-standard use of devicetree.
Signed-off-by: Charles E. Youse <charles.youse@intel.com>
2019-04-02 19:06:07 +02:00
|
|
|
{
|
|
|
|
pcie_conf(bdf, reg, true, &data);
|
|
|
|
}
|
|
|
|
|
|
|
|
#ifdef CONFIG_PCIE_MSI
|
|
|
|
|
2020-11-05 10:42:07 +01:00
|
|
|
#ifdef CONFIG_INTEL_VTD_ICTL
|
|
|
|
|
2022-05-06 10:49:15 +02:00
|
|
|
#include <zephyr/drivers/interrupt_controller/intel_vtd.h>
|
2020-11-05 10:42:07 +01:00
|
|
|
|
2022-08-17 15:37:22 +02:00
|
|
|
static const struct device *const vtd = DEVICE_DT_GET_ONE(intel_vt_d);
|
2020-11-05 10:42:07 +01:00
|
|
|
|
|
|
|
#endif /* CONFIG_INTEL_VTD_ICTL */
|
|
|
|
|
uart/ns16550, drivers/pcie: add PCI(e) support
A parallel PCI implementation ("pcie") is added with features for PCIe.
In particular, message-signaled interrupts (MSI) are supported, which
are essential to the use of any non-trivial PCIe device.
The NS16550 UART driver is modified to use pcie.
pcie is a complete replacement for the old PCI support ("pci"). It is
smaller, by an order of magnitude, and cleaner. Both pci and pcie can
(and do) coexist in the same builds, but the intent is to rework any
existing drivers that depend on pci and ultimately remove pci entirely.
This patch is large, but things in mirror are smaller than they appear.
Most of the modified files are configuration-related, and are changed
only slightly to accommodate the modified UART driver.
Deficiencies:
64-bit support is minimal. The code works fine with 64-bit capable
devices, but will not cooperate with MMIO regions (or MSI targets) that
have high bits set. This is not needed on any current boards, and is
unlikely to be needed in the future. Only superficial changes would
be required if we change our minds.
The method specifying PCI endpoints in devicetree is somewhat kludgey.
The "right" way would be to hang PCI devices off a topological tree;
while this would be more aesthetically pleasing, I don't think it's
worth the effort, given our non-standard use of devicetree.
Signed-off-by: Charles E. Youse <charles.youse@intel.com>
2019-04-02 19:06:07 +02:00
|
|
|
/* these functions are explained in include/drivers/pcie/msi.h */
|
|
|
|
|
2022-02-04 10:28:13 +01:00
|
|
|
#define MSI_MAP_DESTINATION_ID_SHIFT 12
|
|
|
|
#define MSI_RH BIT(3)
|
|
|
|
|
2020-11-05 10:42:07 +01:00
|
|
|
uint32_t pcie_msi_map(unsigned int irq,
|
2021-03-23 14:33:37 +01:00
|
|
|
msi_vector_t *vector,
|
|
|
|
uint8_t n_vector)
|
uart/ns16550, drivers/pcie: add PCI(e) support
A parallel PCI implementation ("pcie") is added with features for PCIe.
In particular, message-signaled interrupts (MSI) are supported, which
are essential to the use of any non-trivial PCIe device.
The NS16550 UART driver is modified to use pcie.
pcie is a complete replacement for the old PCI support ("pci"). It is
smaller, by an order of magnitude, and cleaner. Both pci and pcie can
(and do) coexist in the same builds, but the intent is to rework any
existing drivers that depend on pci and ultimately remove pci entirely.
This patch is large, but things in mirror are smaller than they appear.
Most of the modified files are configuration-related, and are changed
only slightly to accommodate the modified UART driver.
Deficiencies:
64-bit support is minimal. The code works fine with 64-bit capable
devices, but will not cooperate with MMIO regions (or MSI targets) that
have high bits set. This is not needed on any current boards, and is
unlikely to be needed in the future. Only superficial changes would
be required if we change our minds.
The method specifying PCI endpoints in devicetree is somewhat kludgey.
The "right" way would be to hang PCI devices off a topological tree;
while this would be more aesthetically pleasing, I don't think it's
worth the effort, given our non-standard use of devicetree.
Signed-off-by: Charles E. Youse <charles.youse@intel.com>
2019-04-02 19:06:07 +02:00
|
|
|
{
|
2022-02-04 10:28:13 +01:00
|
|
|
uint32_t dest_id;
|
|
|
|
|
uart/ns16550, drivers/pcie: add PCI(e) support
A parallel PCI implementation ("pcie") is added with features for PCIe.
In particular, message-signaled interrupts (MSI) are supported, which
are essential to the use of any non-trivial PCIe device.
The NS16550 UART driver is modified to use pcie.
pcie is a complete replacement for the old PCI support ("pci"). It is
smaller, by an order of magnitude, and cleaner. Both pci and pcie can
(and do) coexist in the same builds, but the intent is to rework any
existing drivers that depend on pci and ultimately remove pci entirely.
This patch is large, but things in mirror are smaller than they appear.
Most of the modified files are configuration-related, and are changed
only slightly to accommodate the modified UART driver.
Deficiencies:
64-bit support is minimal. The code works fine with 64-bit capable
devices, but will not cooperate with MMIO regions (or MSI targets) that
have high bits set. This is not needed on any current boards, and is
unlikely to be needed in the future. Only superficial changes would
be required if we change our minds.
The method specifying PCI endpoints in devicetree is somewhat kludgey.
The "right" way would be to hang PCI devices off a topological tree;
while this would be more aesthetically pleasing, I don't think it's
worth the effort, given our non-standard use of devicetree.
Signed-off-by: Charles E. Youse <charles.youse@intel.com>
2019-04-02 19:06:07 +02:00
|
|
|
ARG_UNUSED(irq);
|
2020-12-17 11:22:33 +01:00
|
|
|
|
2020-11-20 10:14:53 +01:00
|
|
|
#if defined(CONFIG_INTEL_VTD_ICTL)
|
2021-01-06 21:16:24 +01:00
|
|
|
if (vector != NULL && n_vector > 0) {
|
|
|
|
return vtd_remap_msi(vtd, vector, n_vector);
|
|
|
|
}
|
2020-11-20 10:14:53 +01:00
|
|
|
#endif
|
2022-02-04 10:28:13 +01:00
|
|
|
|
|
|
|
dest_id = z_x86_cpuid_get_current_physical_apic_id() <<
|
|
|
|
MSI_MAP_DESTINATION_ID_SHIFT;
|
|
|
|
|
|
|
|
/* Directing to current physical CPU (may not be BSP)
|
|
|
|
* Destination ID - RH 1 - DM 0
|
|
|
|
*/
|
|
|
|
return 0xFEE00000U | dest_id | MSI_RH;
|
uart/ns16550, drivers/pcie: add PCI(e) support
A parallel PCI implementation ("pcie") is added with features for PCIe.
In particular, message-signaled interrupts (MSI) are supported, which
are essential to the use of any non-trivial PCIe device.
The NS16550 UART driver is modified to use pcie.
pcie is a complete replacement for the old PCI support ("pci"). It is
smaller, by an order of magnitude, and cleaner. Both pci and pcie can
(and do) coexist in the same builds, but the intent is to rework any
existing drivers that depend on pci and ultimately remove pci entirely.
This patch is large, but things in mirror are smaller than they appear.
Most of the modified files are configuration-related, and are changed
only slightly to accommodate the modified UART driver.
Deficiencies:
64-bit support is minimal. The code works fine with 64-bit capable
devices, but will not cooperate with MMIO regions (or MSI targets) that
have high bits set. This is not needed on any current boards, and is
unlikely to be needed in the future. Only superficial changes would
be required if we change our minds.
The method specifying PCI endpoints in devicetree is somewhat kludgey.
The "right" way would be to hang PCI devices off a topological tree;
while this would be more aesthetically pleasing, I don't think it's
worth the effort, given our non-standard use of devicetree.
Signed-off-by: Charles E. Youse <charles.youse@intel.com>
2019-04-02 19:06:07 +02:00
|
|
|
}
|
|
|
|
|
2020-11-05 10:42:07 +01:00
|
|
|
uint16_t pcie_msi_mdr(unsigned int irq,
|
|
|
|
msi_vector_t *vector)
|
uart/ns16550, drivers/pcie: add PCI(e) support
A parallel PCI implementation ("pcie") is added with features for PCIe.
In particular, message-signaled interrupts (MSI) are supported, which
are essential to the use of any non-trivial PCIe device.
The NS16550 UART driver is modified to use pcie.
pcie is a complete replacement for the old PCI support ("pci"). It is
smaller, by an order of magnitude, and cleaner. Both pci and pcie can
(and do) coexist in the same builds, but the intent is to rework any
existing drivers that depend on pci and ultimately remove pci entirely.
This patch is large, but things in mirror are smaller than they appear.
Most of the modified files are configuration-related, and are changed
only slightly to accommodate the modified UART driver.
Deficiencies:
64-bit support is minimal. The code works fine with 64-bit capable
devices, but will not cooperate with MMIO regions (or MSI targets) that
have high bits set. This is not needed on any current boards, and is
unlikely to be needed in the future. Only superficial changes would
be required if we change our minds.
The method specifying PCI endpoints in devicetree is somewhat kludgey.
The "right" way would be to hang PCI devices off a topological tree;
while this would be more aesthetically pleasing, I don't think it's
worth the effort, given our non-standard use of devicetree.
Signed-off-by: Charles E. Youse <charles.youse@intel.com>
2019-04-02 19:06:07 +02:00
|
|
|
{
|
2021-01-06 21:16:24 +01:00
|
|
|
if (vector != NULL) {
|
|
|
|
if (IS_ENABLED(CONFIG_INTEL_VTD_ICTL)) {
|
|
|
|
return 0;
|
|
|
|
}
|
uart/ns16550, drivers/pcie: add PCI(e) support
A parallel PCI implementation ("pcie") is added with features for PCIe.
In particular, message-signaled interrupts (MSI) are supported, which
are essential to the use of any non-trivial PCIe device.
The NS16550 UART driver is modified to use pcie.
pcie is a complete replacement for the old PCI support ("pci"). It is
smaller, by an order of magnitude, and cleaner. Both pci and pcie can
(and do) coexist in the same builds, but the intent is to rework any
existing drivers that depend on pci and ultimately remove pci entirely.
This patch is large, but things in mirror are smaller than they appear.
Most of the modified files are configuration-related, and are changed
only slightly to accommodate the modified UART driver.
Deficiencies:
64-bit support is minimal. The code works fine with 64-bit capable
devices, but will not cooperate with MMIO regions (or MSI targets) that
have high bits set. This is not needed on any current boards, and is
unlikely to be needed in the future. Only superficial changes would
be required if we change our minds.
The method specifying PCI endpoints in devicetree is somewhat kludgey.
The "right" way would be to hang PCI devices off a topological tree;
while this would be more aesthetically pleasing, I don't think it's
worth the effort, given our non-standard use of devicetree.
Signed-off-by: Charles E. Youse <charles.youse@intel.com>
2019-04-02 19:06:07 +02:00
|
|
|
|
2020-12-17 11:22:33 +01:00
|
|
|
#if defined(CONFIG_PCIE_MSI_X)
|
2021-01-06 21:16:24 +01:00
|
|
|
if (vector->msix) {
|
|
|
|
return 0x4000U | vector->arch.vector;
|
|
|
|
}
|
2020-12-17 11:22:33 +01:00
|
|
|
#endif
|
2021-01-06 21:16:24 +01:00
|
|
|
}
|
|
|
|
|
2020-12-17 11:22:33 +01:00
|
|
|
return 0x4000U | Z_IRQ_TO_INTERRUPT_VECTOR(irq);
|
uart/ns16550, drivers/pcie: add PCI(e) support
A parallel PCI implementation ("pcie") is added with features for PCIe.
In particular, message-signaled interrupts (MSI) are supported, which
are essential to the use of any non-trivial PCIe device.
The NS16550 UART driver is modified to use pcie.
pcie is a complete replacement for the old PCI support ("pci"). It is
smaller, by an order of magnitude, and cleaner. Both pci and pcie can
(and do) coexist in the same builds, but the intent is to rework any
existing drivers that depend on pci and ultimately remove pci entirely.
This patch is large, but things in mirror are smaller than they appear.
Most of the modified files are configuration-related, and are changed
only slightly to accommodate the modified UART driver.
Deficiencies:
64-bit support is minimal. The code works fine with 64-bit capable
devices, but will not cooperate with MMIO regions (or MSI targets) that
have high bits set. This is not needed on any current boards, and is
unlikely to be needed in the future. Only superficial changes would
be required if we change our minds.
The method specifying PCI endpoints in devicetree is somewhat kludgey.
The "right" way would be to hang PCI devices off a topological tree;
while this would be more aesthetically pleasing, I don't think it's
worth the effort, given our non-standard use of devicetree.
Signed-off-by: Charles E. Youse <charles.youse@intel.com>
2019-04-02 19:06:07 +02:00
|
|
|
}
|
|
|
|
|
2020-11-20 10:14:53 +01:00
|
|
|
#if defined(CONFIG_INTEL_VTD_ICTL) || defined(CONFIG_PCIE_MSI_X)
|
2020-11-05 10:42:07 +01:00
|
|
|
|
|
|
|
uint8_t arch_pcie_msi_vectors_allocate(unsigned int priority,
|
|
|
|
msi_vector_t *vectors,
|
|
|
|
uint8_t n_vector)
|
|
|
|
{
|
2021-01-06 11:32:45 +01:00
|
|
|
int prev_vector = -1;
|
|
|
|
int i, irq, vector;
|
|
|
|
|
|
|
|
if (vectors == NULL || n_vector == 0) {
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2020-11-20 10:14:53 +01:00
|
|
|
#ifdef CONFIG_INTEL_VTD_ICTL
|
2021-01-06 11:32:45 +01:00
|
|
|
{
|
|
|
|
int irte;
|
2020-11-05 10:42:07 +01:00
|
|
|
|
2022-03-09 20:20:13 +01:00
|
|
|
if (!device_is_ready(vtd)) {
|
2021-01-06 11:32:45 +01:00
|
|
|
return 0;
|
|
|
|
}
|
2020-11-05 10:42:07 +01:00
|
|
|
|
2021-01-06 11:32:45 +01:00
|
|
|
irte = vtd_allocate_entries(vtd, n_vector);
|
|
|
|
if (irte < 0) {
|
|
|
|
return 0;
|
|
|
|
}
|
2020-11-05 10:42:07 +01:00
|
|
|
|
2021-01-06 11:32:45 +01:00
|
|
|
for (i = 0; i < n_vector; i++, irte++) {
|
|
|
|
vectors[i].arch.irte = irte;
|
|
|
|
vectors[i].arch.remap = true;
|
2020-11-05 10:42:07 +01:00
|
|
|
}
|
2021-01-06 11:32:45 +01:00
|
|
|
}
|
2020-11-20 10:14:53 +01:00
|
|
|
#endif /* CONFIG_INTEL_VTD_ICTL */
|
2020-11-05 10:42:07 +01:00
|
|
|
|
2021-01-06 11:32:45 +01:00
|
|
|
for (i = 0; i < n_vector; i++) {
|
|
|
|
if (n_vector == 1) {
|
|
|
|
/* This path is taken by PCIE device with fixed
|
|
|
|
* or single MSI: IRQ has been already allocated
|
|
|
|
* and/or set on the PCIe bus. Thus we only require
|
|
|
|
* to get it.
|
|
|
|
*/
|
|
|
|
irq = pcie_get_irq(vectors->bdf);
|
|
|
|
} else {
|
|
|
|
irq = arch_irq_allocate();
|
|
|
|
}
|
|
|
|
|
|
|
|
if ((irq == PCIE_CONF_INTR_IRQ_NONE) || (irq == -1)) {
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
|
|
|
vector = z_x86_allocate_vector(priority, prev_vector);
|
|
|
|
if (vector < 0) {
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
vectors[i].arch.irq = irq;
|
|
|
|
vectors[i].arch.vector = vector;
|
2020-11-05 10:42:07 +01:00
|
|
|
|
2021-01-06 10:55:19 +01:00
|
|
|
#ifdef CONFIG_INTEL_VTD_ICTL
|
2021-01-06 11:32:45 +01:00
|
|
|
vtd_set_irte_vector(vtd, vectors[i].arch.irte,
|
|
|
|
vectors[i].arch.vector);
|
|
|
|
vtd_set_irte_irq(vtd, vectors[i].arch.irte,
|
|
|
|
vectors[i].arch.irq);
|
|
|
|
vtd_set_irte_msi(vtd, vectors[i].arch.irte, true);
|
2021-01-06 10:55:19 +01:00
|
|
|
#endif
|
2021-01-06 11:32:45 +01:00
|
|
|
prev_vector = vectors[i].arch.vector;
|
2020-11-05 10:42:07 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
return n_vector;
|
|
|
|
}
|
|
|
|
|
|
|
|
bool arch_pcie_msi_vector_connect(msi_vector_t *vector,
|
|
|
|
void (*routine)(const void *parameter),
|
|
|
|
const void *parameter,
|
|
|
|
uint32_t flags)
|
|
|
|
{
|
2020-11-20 10:14:53 +01:00
|
|
|
#ifdef CONFIG_INTEL_VTD_ICTL
|
2020-11-05 10:42:07 +01:00
|
|
|
if (vector->arch.remap) {
|
2021-04-06 13:29:27 +02:00
|
|
|
union acpi_dmar_id id;
|
|
|
|
|
2022-03-09 20:20:13 +01:00
|
|
|
if (!device_is_ready(vtd)) {
|
2020-11-05 10:42:07 +01:00
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
2021-04-06 13:29:27 +02:00
|
|
|
id.bits.bus = PCIE_BDF_TO_BUS(vector->bdf);
|
|
|
|
id.bits.device = PCIE_BDF_TO_DEV(vector->bdf);
|
|
|
|
id.bits.function = PCIE_BDF_TO_FUNC(vector->bdf);
|
|
|
|
|
|
|
|
vtd_remap(vtd, vector->arch.irte, vector->arch.vector,
|
|
|
|
flags, id.raw);
|
2020-11-05 10:42:07 +01:00
|
|
|
}
|
2020-11-20 10:14:53 +01:00
|
|
|
#endif /* CONFIG_INTEL_VTD_ICTL */
|
2020-11-05 10:42:07 +01:00
|
|
|
|
|
|
|
z_x86_irq_connect_on_vector(vector->arch.irq, vector->arch.vector,
|
2021-03-18 14:29:40 +01:00
|
|
|
routine, parameter);
|
2020-11-05 10:42:07 +01:00
|
|
|
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
2020-11-20 10:14:53 +01:00
|
|
|
#endif /* CONFIG_INTEL_VTD_ICTL || CONFIG_PCIE_MSI_X */
|
2020-11-05 10:42:07 +01:00
|
|
|
#endif /* CONFIG_PCIE_MSI */
|