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-03 01:06:07 +08:00
|
|
|
/*
|
|
|
|
* Copyright (c) 2019 Intel Corporation
|
|
|
|
*
|
|
|
|
* SPDX-License-Identifier: Apache-2.0
|
|
|
|
*/
|
|
|
|
|
2019-04-21 03:18:43 +08:00
|
|
|
#include <kernel.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-03 01:06:07 +08:00
|
|
|
#include <stdbool.h>
|
|
|
|
#include <drivers/pcie/pcie.h>
|
|
|
|
|
2019-04-21 03:18:43 +08:00
|
|
|
#if CONFIG_PCIE_MSI
|
|
|
|
#include <drivers/pcie/msi.h>
|
|
|
|
#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-03 01:06:07 +08:00
|
|
|
/* functions documented in drivers/pcie/pcie.h */
|
|
|
|
|
|
|
|
bool pcie_probe(pcie_bdf_t bdf, pcie_id_t id)
|
|
|
|
{
|
|
|
|
u32_t data;
|
|
|
|
|
|
|
|
data = pcie_conf_read(bdf, PCIE_CONF_ID);
|
|
|
|
|
|
|
|
if (data == PCIE_ID_NONE) {
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (id == PCIE_ID_NONE) {
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
return (id == data);
|
|
|
|
}
|
|
|
|
|
|
|
|
void pcie_set_cmd(pcie_bdf_t bdf, u32_t bits, bool on)
|
|
|
|
{
|
|
|
|
u32_t cmdstat;
|
|
|
|
|
|
|
|
cmdstat = pcie_conf_read(bdf, PCIE_CONF_CMDSTAT);
|
|
|
|
|
|
|
|
if (on) {
|
|
|
|
cmdstat |= bits;
|
|
|
|
} else {
|
|
|
|
cmdstat &= ~bits;
|
|
|
|
}
|
|
|
|
|
|
|
|
pcie_conf_write(bdf, PCIE_CONF_CMDSTAT, cmdstat);
|
|
|
|
}
|
|
|
|
|
|
|
|
static u32_t pcie_get_bar(pcie_bdf_t bdf, unsigned int index, bool io)
|
|
|
|
{
|
|
|
|
int bar;
|
|
|
|
u32_t data;
|
|
|
|
|
|
|
|
for (bar = PCIE_CONF_BAR0; bar <= PCIE_CONF_BAR5; ++bar) {
|
|
|
|
data = pcie_conf_read(bdf, bar);
|
|
|
|
if (data == PCIE_CONF_BAR_NONE) {
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
|
|
|
|
if ((PCIE_CONF_BAR_IO(data) && io) ||
|
|
|
|
(PCIE_CONF_BAR_MEM(data) && !io)) {
|
|
|
|
if (index == 0) {
|
|
|
|
return PCIE_CONF_BAR_ADDR(data);
|
|
|
|
}
|
|
|
|
|
|
|
|
--index;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (PCIE_CONF_BAR_64(data)) {
|
|
|
|
++bar;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return PCIE_CONF_BAR_NONE;
|
|
|
|
}
|
|
|
|
|
|
|
|
u32_t pcie_get_mbar(pcie_bdf_t bdf, unsigned int index)
|
|
|
|
{
|
|
|
|
return pcie_get_bar(bdf, index, false);
|
|
|
|
}
|
|
|
|
|
2019-05-02 02:21:32 +08:00
|
|
|
unsigned int pcie_wired_irq(pcie_bdf_t bdf)
|
|
|
|
{
|
|
|
|
u32_t data = pcie_conf_read(bdf, PCIE_CONF_INTR);
|
|
|
|
|
|
|
|
return PCIE_CONF_INTR_IRQ(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-03 01:06:07 +08:00
|
|
|
u32_t pcie_get_iobar(pcie_bdf_t bdf, unsigned int index)
|
|
|
|
{
|
|
|
|
return pcie_get_bar(bdf, index, true);
|
|
|
|
}
|
2019-04-21 03:18:43 +08:00
|
|
|
|
2019-05-23 03:31:38 +08:00
|
|
|
void pcie_irq_enable(pcie_bdf_t bdf, unsigned int irq)
|
2019-04-21 03:18:43 +08:00
|
|
|
{
|
|
|
|
#if CONFIG_PCIE_MSI
|
2019-05-23 03:31:38 +08:00
|
|
|
if (pcie_set_msi(bdf, irq)) {
|
|
|
|
return;
|
2019-04-21 03:18:43 +08:00
|
|
|
}
|
2019-05-23 03:31:38 +08:00
|
|
|
#endif
|
|
|
|
irq_enable(irq);
|
2019-04-21 03:18:43 +08:00
|
|
|
}
|