From e03905354671129de41a415b3b34e35a924a1c5b Mon Sep 17 00:00:00 2001 From: "Charles E. Youse" Date: Tue, 2 Apr 2019 10:06:07 -0700 Subject: [PATCH] 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 --- CODEOWNERS | 7 + arch/x86/core/CMakeLists.txt | 1 + arch/x86/core/pcie.c | 90 ++++++ boards/x86/galileo/galileo_defconfig | 1 + boards/x86/up_squared/dts_fixup.h | 56 ++-- boards/x86/up_squared/up_squared.dts | 18 +- boards/x86/up_squared/up_squared_defconfig | 1 + drivers/CMakeLists.txt | 1 + drivers/Kconfig | 2 + drivers/pcie/CMakeLists.txt | 3 + drivers/pcie/Kconfig | 34 +++ drivers/pcie/msi.c | 67 +++++ drivers/pcie/pcie.c | 80 ++++++ drivers/pcie/shell.c | 111 ++++++++ drivers/serial/Kconfig.ns16550 | 120 -------- drivers/serial/uart_ns16550.c | 266 +++++++++--------- dts/arc/arc_iot.dtsi | 1 + dts/bindings/serial/ns16550.yaml | 18 ++ dts/x86/quark_x1000.dtsi | 9 +- include/drivers/pcie/msi.h | 106 +++++++ include/drivers/pcie/pcie.h | 168 +++++++++++ include/dt-bindings/pcie/pcie.h | 59 ++++ soc/arc/snps_arc_iot/Kconfig.defconfig | 6 - soc/arc/snps_arc_iot/dts_fixup.h | 14 + soc/nios2/nios2f-zephyr/Kconfig.defconfig | 3 - soc/x86/apollo_lake/Kconfig.defconfig | 15 - soc/x86/apollo_lake/soc.h | 54 ---- soc/x86/atom/Kconfig.defconfig | 3 - soc/x86/ia32/Kconfig.defconfig | 3 - .../quark_x1000/Kconfig.defconfig.series | 9 - soc/x86/intel_quark/quark_x1000/dts_fixup.h | 56 ++-- soc/x86/intel_quark/quark_x1000/soc.h | 19 -- 32 files changed, 968 insertions(+), 433 deletions(-) create mode 100644 arch/x86/core/pcie.c create mode 100644 drivers/pcie/CMakeLists.txt create mode 100644 drivers/pcie/Kconfig create mode 100644 drivers/pcie/msi.c create mode 100644 drivers/pcie/pcie.c create mode 100644 drivers/pcie/shell.c create mode 100644 include/drivers/pcie/msi.h create mode 100644 include/drivers/pcie/pcie.h create mode 100644 include/dt-bindings/pcie/pcie.h diff --git a/CODEOWNERS b/CODEOWNERS index 4964755613..27a8ae8070 100644 --- a/CODEOWNERS +++ b/CODEOWNERS @@ -29,6 +29,7 @@ /arch/x86/ @andrewboie @ramakrishnapallala /arch/x86/core/ @andrewboie /arch/x86/core/crt0.S @ramakrishnapallala @nashif +/arch/x86/core/pcie.c @gnuless /soc/x86/ @andrewboie @ramakrishnapallala /soc/x86/intel_quark/quark_d2000/ @nashif /soc/x86/intel_quark/quark_se/ @nashif @@ -119,6 +120,7 @@ /drivers/led_strip/ @mbolivar /drivers/modem/ @mike-scott /drivers/pci/ @gnuless +/drivers/pcie/ @gnuless /drivers/pinmux/stm32/ @rsalveti @idlethread /drivers/sensor/ @bogdan-davidoaia @MaureenHelm /drivers/sensor/hts*/ @avisconti @@ -126,6 +128,7 @@ /drivers/sensor/lps*/ @avisconti /drivers/sensor/lsm*/ @avisconti /drivers/serial/uart_altera_jtag_hal.c @ramakrishnapallala +/drivers/serial/*ns16550* @gnuless /drivers/net/slip.c @jukkar @tbursztyka /drivers/spi/ @tbursztyka /drivers/spi/spi_ll_stm32.* @superna9999 @@ -142,6 +145,7 @@ /dts/arm/nxp/ @MaureenHelm /dts/bindings/ @galak /dts/bindings/can/ @alexanderwachter +/dts/bindings/serial/ns16550.yaml @gnuless /dts/bindings/*/nordic* @anangl /dts/bindings/*/nxp* @MaureenHelm /ext/fs/ @nashif @ramakrishnapallala @@ -181,6 +185,9 @@ /include/drivers/ioapic.h @andrewboie /include/drivers/loapic.h @andrewboie /include/drivers/mvic.h @andrewboie +/include/drivers/pcie/ @gnuless +/include/drivers/serial/uart_ns16550.h @gnuless +/include/dt-bindings/pcie/ @gnuless /include/fs.h @nashif @ramakrishnapallala /include/fs/ @nashif @ramakrishnapallala /include/hwinfo.h @alexanderwachter diff --git a/arch/x86/core/CMakeLists.txt b/arch/x86/core/CMakeLists.txt index 876ca4bff0..3c4a9f1563 100644 --- a/arch/x86/core/CMakeLists.txt +++ b/arch/x86/core/CMakeLists.txt @@ -32,6 +32,7 @@ zephyr_library_sources( zephyr_library_sources_if_kconfig( irq_offload.c) zephyr_library_sources_if_kconfig( x86_mmu.c) zephyr_library_sources_if_kconfig( reboot_rst_cnt.c) +zephyr_library_sources_if_kconfig( pcie.c) zephyr_library_sources_ifdef(CONFIG_LAZY_FP_SHARING float.c) zephyr_library_sources_ifdef(CONFIG_X86_USERSPACE userspace.S) diff --git a/arch/x86/core/pcie.c b/arch/x86/core/pcie.c new file mode 100644 index 0000000000..7be9b8e1a1 --- /dev/null +++ b/arch/x86/core/pcie.c @@ -0,0 +1,90 @@ +/* + * Copyright (c) 2019 Intel Corporation + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include +#include +#include + +#ifdef CONFIG_PCIE_MSI +#include +#endif + +/* + * The Configuration Mechanism (previously, Configuration Mechanism #1) + * uses two 32-bit ports in the I/O space, here called CAP and CDP. + * + * N.B.: this code relies on the fact that the PCIE_BDF() format (as + * defined in dt-bindings/pcie/pcie.h) and the CAP agree on the bus/dev/func + * bitfield positions and sizes. + */ + +#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 + * ain't atomic, so spinlock to keep drivers from clobbering each other. + */ +static void pcie_conf(pcie_bdf_t bdf, unsigned int reg, bool write, u32_t *data) +{ + 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); +} + +/* these functions are explained in include/drivers/pcie/pcie.h */ + +u32_t pcie_conf_read(pcie_bdf_t bdf, unsigned int reg) +{ + u32_t data; + + pcie_conf(bdf, reg, false, &data); + return data; +} + +void pcie_conf_write(pcie_bdf_t bdf, unsigned int reg, u32_t data) +{ + pcie_conf(bdf, reg, true, &data); +} + +#ifdef CONFIG_PCIE_MSI + +/* these functions are explained in include/drivers/pcie/msi.h */ + +u32_t pcie_msi_map(unsigned int irq) +{ + ARG_UNUSED(irq); + return 0xFEE00000U; /* standard delivery to BSP local APIC */ +} + +u16_t pcie_msi_mdr(unsigned int irq) +{ + unsigned char vector = _irq_to_interrupt_vector[irq]; + + return 0x4000U | vector; /* edge triggered */ +} + +#endif diff --git a/boards/x86/galileo/galileo_defconfig b/boards/x86/galileo/galileo_defconfig index e150a5c7ac..b4d3526315 100644 --- a/boards/x86/galileo/galileo_defconfig +++ b/boards/x86/galileo/galileo_defconfig @@ -1,6 +1,7 @@ # SPDX-License-Identifier: Apache-2.0 CONFIG_X86=y +CONFIG_PCIE=y CONFIG_SOC_QUARK_X1000=y CONFIG_SOC_SERIES_QUARK_X1000=y CONFIG_BOARD_GALILEO=y diff --git a/boards/x86/up_squared/dts_fixup.h b/boards/x86/up_squared/dts_fixup.h index 126353a582..6a76124f8e 100644 --- a/boards/x86/up_squared/dts_fixup.h +++ b/boards/x86/up_squared/dts_fixup.h @@ -6,42 +6,32 @@ /* Board level DTS fixup file */ -#ifdef CONFIG_SBL_FIXUP +#define DT_UART_NS16550_PORT_0_BASE_ADDR DT_NS16550_0_BASE_ADDRESS +#define DT_UART_NS16550_PORT_0_SIZE DT_NS16550_0_SIZE +#define DT_UART_NS16550_PORT_0_BAUD_RATE DT_NS16550_0_CURRENT_SPEED +#define DT_UART_NS16550_PORT_0_NAME DT_NS16550_0_LABEL +#define DT_UART_NS16550_PORT_0_IRQ DT_NS16550_0_IRQ_0 +#define DT_UART_NS16550_PORT_0_IRQ_PRI DT_NS16550_0_IRQ_0_PRIORITY +#define DT_UART_NS16550_PORT_0_IRQ_FLAGS DT_NS16550_0_IRQ_0_SENSE +#define DT_UART_NS16550_PORT_0_CLK_FREQ DT_NS16550_0_CLOCK_FREQUENCY +#define DT_UART_NS16550_PORT_0_PCIE DT_NS16550_0_PCIE -#define DT_UART_NS16550_PORT_0_BASE_ADDR DT_NS16550_81434000_BASE_ADDRESS -#define DT_UART_NS16550_PORT_0_BAUD_RATE DT_NS16550_81434000_CURRENT_SPEED -#define DT_UART_NS16550_PORT_0_NAME DT_NS16550_81434000_LABEL -#define DT_UART_NS16550_PORT_0_IRQ DT_NS16550_81434000_IRQ_0 -#define DT_UART_NS16550_PORT_0_IRQ_PRI DT_NS16550_81434000_IRQ_0_PRIORITY -#define DT_UART_NS16550_PORT_0_IRQ_FLAGS DT_NS16550_81434000_IRQ_0_SENSE -#define DT_UART_NS16550_PORT_0_CLK_FREQ DT_NS16550_81434000_CLOCK_FREQUENCY +#ifdef DT_NS16550_0_PCP +#define DT_UART_NS16550_PORT_0_PCP DT_NS16550_0_PCP +#endif -#define DT_UART_NS16550_PORT_1_BASE_ADDR DT_NS16550_81432000_BASE_ADDRESS -#define DT_UART_NS16550_PORT_1_BAUD_RATE DT_NS16550_81432000_CURRENT_SPEED -#define DT_UART_NS16550_PORT_1_NAME DT_NS16550_81432000_LABEL -#define DT_UART_NS16550_PORT_1_IRQ DT_NS16550_81432000_IRQ_0 -#define DT_UART_NS16550_PORT_1_IRQ_PRI DT_NS16550_81432000_IRQ_0_PRIORITY -#define DT_UART_NS16550_PORT_1_IRQ_FLAGS DT_NS16550_81432000_IRQ_0_SENSE -#define DT_UART_NS16550_PORT_1_CLK_FREQ DT_NS16550_81432000_CLOCK_FREQUENCY - -#else - -#define DT_UART_NS16550_PORT_0_BASE_ADDR DT_NS16550_91524000_BASE_ADDRESS -#define DT_UART_NS16550_PORT_0_BAUD_RATE DT_NS16550_91524000_CURRENT_SPEED -#define DT_UART_NS16550_PORT_0_NAME DT_NS16550_91524000_LABEL -#define DT_UART_NS16550_PORT_0_IRQ DT_NS16550_91524000_IRQ_0 -#define DT_UART_NS16550_PORT_0_IRQ_PRI DT_NS16550_91524000_IRQ_0_PRIORITY -#define DT_UART_NS16550_PORT_0_IRQ_FLAGS DT_NS16550_91524000_IRQ_0_SENSE -#define DT_UART_NS16550_PORT_0_CLK_FREQ DT_NS16550_91524000_CLOCK_FREQUENCY - -#define DT_UART_NS16550_PORT_1_BASE_ADDR DT_NS16550_91522000_BASE_ADDRESS -#define DT_UART_NS16550_PORT_1_BAUD_RATE DT_NS16550_91522000_CURRENT_SPEED -#define DT_UART_NS16550_PORT_1_NAME DT_NS16550_91522000_LABEL -#define DT_UART_NS16550_PORT_1_IRQ DT_NS16550_91522000_IRQ_0 -#define DT_UART_NS16550_PORT_1_IRQ_PRI DT_NS16550_91522000_IRQ_0_PRIORITY -#define DT_UART_NS16550_PORT_1_IRQ_FLAGS DT_NS16550_91522000_IRQ_0_SENSE -#define DT_UART_NS16550_PORT_1_CLK_FREQ DT_NS16550_91522000_CLOCK_FREQUENCY +#define DT_UART_NS16550_PORT_1_BASE_ADDR DT_NS16550_1_BASE_ADDRESS +#define DT_UART_NS16550_PORT_1_SIZE DT_NS16550_1_SIZE +#define DT_UART_NS16550_PORT_1_BAUD_RATE DT_NS16550_1_CURRENT_SPEED +#define DT_UART_NS16550_PORT_1_NAME DT_NS16550_1_LABEL +#define DT_UART_NS16550_PORT_1_IRQ DT_NS16550_1_IRQ_0 +#define DT_UART_NS16550_PORT_1_IRQ_PRI DT_NS16550_1_IRQ_0_PRIORITY +#define DT_UART_NS16550_PORT_1_IRQ_FLAGS DT_NS16550_1_IRQ_0_SENSE +#define DT_UART_NS16550_PORT_1_CLK_FREQ DT_NS16550_1_CLOCK_FREQUENCY +#define DT_UART_NS16550_PORT_1_PCIE DT_NS16550_1_PCIE +#ifdef DT_NS16550_1_PCP +#define DT_UART_NS16550_PORT_1_PCP DT_NS16550_1_PCP #endif /* End of Board Level DTS fixup file */ diff --git a/boards/x86/up_squared/up_squared.dts b/boards/x86/up_squared/up_squared.dts index 2e86b269e1..0842d919e9 100644 --- a/boards/x86/up_squared/up_squared.dts +++ b/boards/x86/up_squared/up_squared.dts @@ -13,6 +13,7 @@ #include #include +#include / { model = "up_squared"; @@ -29,24 +30,29 @@ }; soc { - uart0: uart@91524000 { + uart0: uart@0 { compatible = "ns16550"; - reg = <0x91524000 0x1000>; + + pcie; + reg = ; + label = "UART_0"; clock-frequency = <1843200>; interrupts = <4 IRQ_TYPE_LEVEL_LOW 3>; interrupt-parent = <&intc>; - status = "ok"; current-speed = <115200>; }; - uart1: uart@91522000 { + uart1: uart@1 { compatible = "ns16550"; - reg = <0x91522000 0x1000>; + + pcie; + reg = ; + label = "UART_1"; clock-frequency = <1843200>; - interrupts = <5 IRQ_TYPE_LEVEL_LOW 3>; + interrupts = <3 IRQ_TYPE_LEVEL_LOW 3>; interrupt-parent = <&intc>; status = "ok"; diff --git a/boards/x86/up_squared/up_squared_defconfig b/boards/x86/up_squared/up_squared_defconfig index a55170494d..7d4b33cf90 100644 --- a/boards/x86/up_squared/up_squared_defconfig +++ b/boards/x86/up_squared/up_squared_defconfig @@ -13,4 +13,5 @@ CONFIG_UART_NS16550=y CONFIG_UART_CONSOLE=y CONFIG_I2C=y CONFIG_PCI=y +CONFIG_PCIE=y CONFIG_PCI_ENUMERATION=y diff --git a/drivers/CMakeLists.txt b/drivers/CMakeLists.txt index 3da125b8de..aa770c1049 100644 --- a/drivers/CMakeLists.txt +++ b/drivers/CMakeLists.txt @@ -21,6 +21,7 @@ add_subdirectory_if_kconfig(led) add_subdirectory_if_kconfig(led_strip) add_subdirectory_if_kconfig(modem) add_subdirectory_if_kconfig(pci) +add_subdirectory_if_kconfig(pcie) add_subdirectory_if_kconfig(pinmux) add_subdirectory_if_kconfig(pwm) add_subdirectory_if_kconfig(rtc) diff --git a/drivers/Kconfig b/drivers/Kconfig index 94b898722b..662c02f7ba 100644 --- a/drivers/Kconfig +++ b/drivers/Kconfig @@ -29,6 +29,8 @@ source "drivers/entropy/Kconfig" source "drivers/pci/Kconfig" +source "drivers/pcie/Kconfig" + source "drivers/gpio/Kconfig" source "drivers/interrupt_controller/Kconfig.shared_irq" diff --git a/drivers/pcie/CMakeLists.txt b/drivers/pcie/CMakeLists.txt new file mode 100644 index 0000000000..c6443fcb6a --- /dev/null +++ b/drivers/pcie/CMakeLists.txt @@ -0,0 +1,3 @@ +zephyr_sources(pcie.c) +zephyr_sources_ifdef(CONFIG_PCIE_MSI msi.c) +zephyr_sources_ifdef(CONFIG_PCIE_SHELL shell.c) diff --git a/drivers/pcie/Kconfig b/drivers/pcie/Kconfig new file mode 100644 index 0000000000..12af0fb204 --- /dev/null +++ b/drivers/pcie/Kconfig @@ -0,0 +1,34 @@ +# Kconfig - PCIe/new PCI configuration options + +# +# Copyright (c) 2019 Intel Corporation +# +# SPDX-License-Identifier: Apache-2.0 +# + +menuconfig PCIE + bool "Enable new PCI/PCIe support" + depends on X86 + help + This option enables support for new PCI(e) drivers. + +if PCIE + +config PCIE_MSI + bool "Enable support for PCI(e) MSI" + default n + help + Use Message-Signaled Interrupts where possible. With this option + enabled, PCI(e) devices which support MSI will be configured (at + runtime) to use them. This is typically required for PCIe devices + to generate interrupts at all. + +config PCIE_SHELL + bool "Enable PCIe/new PCI Shell" + default n + depends on SHELL + help + Enable commands for debugging PCI(e) using the built-in shell. + +endif # PCIE + diff --git a/drivers/pcie/msi.c b/drivers/pcie/msi.c new file mode 100644 index 0000000000..a6a855f4e4 --- /dev/null +++ b/drivers/pcie/msi.c @@ -0,0 +1,67 @@ +/* + * Copyright (c) 2019 Intel Corporation + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include +#include +#include + +/* functions documented in include/drivers/pcie/msi.h */ + +u32_t pcie_get_cap(pcie_bdf_t bdf, u32_t cap_id) +{ + u32_t reg = 0U; + u32_t data; + + data = pcie_conf_read(bdf, PCIE_CONF_CMDSTAT); + if (data & PCIE_CONF_CMDSTAT_CAPS) { + data = pcie_conf_read(bdf, PCIE_CONF_CAPPTR); + reg = PCIE_CONF_CAPPTR_FIRST(data); + } + + while (reg) { + data = pcie_conf_read(bdf, reg); + + if (PCIE_CONF_CAP_ID(data) == cap_id) + break; + + reg = PCIE_CONF_CAP_NEXT(data); + } + + return reg; +} + +bool pcie_set_msi(pcie_bdf_t bdf, unsigned int irq) +{ + bool success = false; /* keepin' the MISRA peeps employed */ + u32_t base; + u32_t mcr; + u32_t map; + u32_t mdr; + + map = pcie_msi_map(irq); + mdr = pcie_msi_mdr(irq); + base = pcie_get_cap(bdf, PCIE_MSI_CAP_ID); + + if (base != 0U) { + mcr = pcie_conf_read(bdf, base + PCIE_MSI_MCR); + pcie_conf_write(bdf, base + PCIE_MSI_MAP0, map); + + if (mcr & PCIE_MSI_MCR_64) { + pcie_conf_write(bdf, base + PCIE_MSI_MAP1_64, 0U); + pcie_conf_write(bdf, base + PCIE_MSI_MDR_64, mdr); + } else { + pcie_conf_write(bdf, base + PCIE_MSI_MDR_32, mdr); + } + + mcr |= PCIE_MSI_MCR_EN; + mcr &= ~PCIE_MSI_MCR_MME; /* only 1 IRQ please */ + pcie_conf_write(bdf, base + PCIE_MSI_MCR, mcr); + pcie_set_cmd(bdf, PCIE_CONF_CMDSTAT_MASTER, true); + success = true; + } + + return success; +} diff --git a/drivers/pcie/pcie.c b/drivers/pcie/pcie.c new file mode 100644 index 0000000000..928708471f --- /dev/null +++ b/drivers/pcie/pcie.c @@ -0,0 +1,80 @@ +/* + * Copyright (c) 2019 Intel Corporation + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include +#include + +/* 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); +} + +u32_t pcie_get_iobar(pcie_bdf_t bdf, unsigned int index) +{ + return pcie_get_bar(bdf, index, true); +} diff --git a/drivers/pcie/shell.c b/drivers/pcie/shell.c new file mode 100644 index 0000000000..ce6b08fc2b --- /dev/null +++ b/drivers/pcie/shell.c @@ -0,0 +1,111 @@ +/* + * Copyright (c) 2019 Intel Corporation + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include +#include + +#ifdef CONFIG_PCIE_MSI +#include +#endif + +#define MAX_BUS (0xFFFFFFFF & PCIE_BDF_BUS_MASK) +#define MAX_DEV (0xFFFFFFFF & PCIE_BDF_DEV_MASK) +#define MAX_FUNC (0xFFFFFFFF & PCIE_BDF_FUNC_MASK) + +static void show_msi(const struct shell *shell, pcie_bdf_t bdf) +{ +#ifdef CONFIG_PCIE_MSI + u32_t msi; + u32_t data; + + msi = pcie_get_cap(bdf, PCIE_MSI_CAP_ID); + + if (msi) { + data = pcie_conf_read(bdf, msi + PCIE_MSI_MCR); + shell_fprintf(shell, SHELL_NORMAL, " MSI support%s%s\n", + (data & PCIE_MSI_MCR_64) ? ", 64-bit" : "", + (data & PCIE_MSI_MCR_EN) ? ", enabled" : ""); + } +#endif +} + +static void show_bars(const struct shell *shell, pcie_bdf_t bdf) +{ + u32_t data; + int bar; + + for (bar = PCIE_CONF_BAR0; bar <= PCIE_CONF_BAR5; ++bar) { + data = pcie_conf_read(bdf, bar); + if (data == PCIE_CONF_BAR_NONE) { + continue; + } + + shell_fprintf(shell, SHELL_NORMAL, " bar %d: %s%s %x\n", + bar - PCIE_CONF_BAR0, + PCIE_CONF_BAR_IO(data) ? "I/O" : "MEM", + PCIE_CONF_BAR_64(data) ? ", 64-bit" : "", + PCIE_CONF_BAR_ADDR(data)); + + if (PCIE_CONF_BAR_64(data)) { + ++bar; + } + } +} + +static void show(const struct shell *shell, pcie_bdf_t bdf) +{ + u32_t data; + + data = pcie_conf_read(bdf, PCIE_CONF_ID); + + if (data == PCIE_ID_NONE) { + return; + } + + shell_fprintf(shell, SHELL_NORMAL, "%d:%x.%d ID %x:%x ", + PCIE_BDF_TO_BUS(bdf), + PCIE_BDF_TO_DEV(bdf), + PCIE_BDF_TO_FUNC(bdf), + PCIE_ID_TO_VEND(data), + PCIE_ID_TO_DEV(data)); + + data = pcie_conf_read(bdf, PCIE_CONF_CLASSREV); + shell_fprintf(shell, SHELL_NORMAL, + "class %x subclass %x prog i/f %x rev %x", + PCIE_CONF_CLASSREV_CLASS(data), + PCIE_CONF_CLASSREV_SUBCLASS(data), + PCIE_CONF_CLASSREV_PROGIF(data), + PCIE_CONF_CLASSREV_REV(data)); + + data = pcie_conf_read(bdf, PCIE_CONF_TYPE); + + if (PCIE_CONF_TYPE_BRIDGE(data)) { + shell_fprintf(shell, SHELL_NORMAL, " [bridge]\n"); + } else { + shell_fprintf(shell, SHELL_NORMAL, "\n"); + show_bars(shell, bdf); + show_msi(shell, bdf); + } +} + +static int cmd_lspcie(const struct shell *shell, size_t argc, char **argv) +{ + int bus; + int dev; + int func; + + for (bus = 0; bus <= MAX_BUS; ++bus) { + for (dev = 0; dev <= MAX_DEV; ++dev) { + for (func = 0; func <= MAX_FUNC; ++func) { + show(shell, PCIE_BDF(bus, dev, func)); + } + } + } + + return 0; +} + +SHELL_CMD_REGISTER(lspcie, NULL, "List PCI(e) devices", cmd_lspcie); diff --git a/drivers/serial/Kconfig.ns16550 b/drivers/serial/Kconfig.ns16550 index 07d6714216..9cd88d08a1 100644 --- a/drivers/serial/Kconfig.ns16550 +++ b/drivers/serial/Kconfig.ns16550 @@ -9,34 +9,6 @@ menuconfig UART_NS16550 This driver can be used for the serial hardware available on x86 boards. -config UART_NS16550_PCI - bool "Enable PCI Support" - depends on PCI && UART_NS16550 - help - This enables NS16550 to probe for PCI-based serial devices. - - This option enables the driver to auto-detect the device - configuration required to access those ports. - -config UART_NS16550_DLF - bool "Enable Divisor Latch Fraction (DLF) support" - depends on UART_NS16550 - help - This enables support for divisor latch fraction (DLF). - It is used to limit frequency error. - - Says n if you are not sure if hardware supports this. - -config UART_NS16550_PCP - bool "Enable Apollo Lake PRV_CLOCK_PARAMS (PCP) support" - depends on SOC_APOLLO_LAKE && UART_NS16550 - help - This enables configuration of the clock blocks that feed - the UARTs on Apollo Lake SoCs, allowing the generation of - custom baud rates. - - Say n unless you know you need this feature. - config UART_NS16550_LINE_CTRL bool "Enable Serial Line Control for Apps" depends on UART_LINE_CTRL && UART_NS16550 @@ -76,29 +48,6 @@ config UART_NS16550_PORT_0_OPTIONS help Options used for port initialization. -config UART_NS16550_PORT_0_DLF - hex "Port 0 DLF value" - default 0x0 - depends on UART_NS16550_PORT_0 && UART_NS16550_DLF - help - Value for DLF register. - -config UART_NS16550_PORT_0_PCP - hex "Port 0 PCP value" - default 0 - depends on UART_NS16550_PORT_0 && UART_NS16550_PCP - help - Value for PRV_CLOCK_PARAMS register. If left at its default - value (0), then the kernel will not attempt to set the PCP - for this UART; otherwise be sure the device tree for this - port has sys_clk_freq set accordingly. - -config UART_NS16550_PORT_0_PCI - bool "Port 0 is PCI-based" - depends on UART_NS16550_PCI && UART_NS16550_PORT_0 - help - Obtain port information from PCI. - # ---------- Port 1 ---------- menuconfig UART_NS16550_PORT_1 @@ -115,29 +64,6 @@ config UART_NS16550_PORT_1_OPTIONS help Options used for port initialization. -config UART_NS16550_PORT_1_DLF - hex "Port 1 DLF value" - default 0x0 - depends on UART_NS16550_PORT_1 && UART_NS16550_DLF - help - Value for DLF register. - -config UART_NS16550_PORT_1_PCP - hex "Port 1 PCP value" - default 0 - depends on UART_NS16550_PORT_1 && UART_NS16550_PCP - help - Value for PRV_CLOCK_PARAMS register. If left at its default - value (0), then the kernel will not attempt to set the PCP - for this UART; otherwise be sure the device tree for this - port has sys_clk_freq set accordingly. - -config UART_NS16550_PORT_1_PCI - bool "Port 1 is PCI-based" - depends on UART_NS16550_PCI && UART_NS16550_PORT_1 - help - Obtain port information from PCI. - # ---------- Port 2 ---------- menuconfig UART_NS16550_PORT_2 @@ -155,29 +81,6 @@ config UART_NS16550_PORT_2_OPTIONS help Options used for port initialization. -config UART_NS16550_PORT_2_DLF - hex "Port 2 DLF value" - default 0x0 - depends on UART_NS16550_PORT_2 && UART_NS16550_DLF - help - Value for DLF register. - -config UART_NS16550_PORT_2_PCP - hex "Port 2 PCP value" - default 0 - depends on UART_NS16550_PORT_2 && UART_NS16550_PCP - help - Value for PRV_CLOCK_PARAMS register. If left at its default - value (0), then the kernel will not attempt to set the PCP - for this UART; otherwise be sure the device tree for this - port has sys_clk_freq set accordingly. - -config UART_NS16550_PORT_2_PCI - bool "Port 2 is PCI-based" - depends on UART_NS16550_PCI && UART_NS16550_PORT_2 - help - Obtain port information from PCI. - # ---------- Port 3 ---------- menuconfig UART_NS16550_PORT_3 @@ -193,26 +96,3 @@ config UART_NS16550_PORT_3_OPTIONS depends on UART_NS16550_PORT_3 help Options used for port initialization. - -config UART_NS16550_PORT_3_DLF - hex "Port 3 DLF value" - default 0x0 - depends on UART_NS16550_PORT_3 && UART_NS16550_DLF - help - Value for DLF register. - -config UART_NS16550_PORT_3_PCP - hex "Port 3 PCP value" - default 0 - depends on UART_NS16550_PORT_3 && UART_NS16550_PCP - help - Value for PRV_CLOCK_PARAMS register. If left at its default - value (0), then the kernel will not attempt to set the PCP - for this UART; otherwise be sure the device tree for this - port has sys_clk_freq set accordingly. - -config UART_NS16550_PORT_3_PCI - bool "Port 3 is PCI-based" - depends on UART_NS16550_PCI && UART_NS16550_PORT_3 - help - Obtain port information from PCI. diff --git a/drivers/serial/uart_ns16550.c b/drivers/serial/uart_ns16550.c index 224e13177f..60ba9b50d4 100644 --- a/drivers/serial/uart_ns16550.c +++ b/drivers/serial/uart_ns16550.c @@ -20,7 +20,6 @@ * UART_REG_ADDR_INTERVAL */ - #include #include #include @@ -33,13 +32,39 @@ #include #include -#ifdef CONFIG_PCI -#include -#include -#endif /* CONFIG_PCI */ - #include +/* + * If PCP is set for any of the ports, enable support. + * Ditto for DLF and PCI(e). + */ + +#if defined(DT_UART_NS16550_PORT_0_PCP) || \ + defined(DT_UART_NS16550_PORT_1_PCP) || \ + defined(DT_UART_NS16550_PORT_2_PCP) || \ + defined(DT_UART_NS16550_PORT_3_PCP) +#define UART_NS16550_PCP_ENABLED +#endif + +#if defined(DT_UART_NS16550_PORT_0_DLF) || \ + defined(DT_UART_NS16550_PORT_1_DLF) || \ + defined(DT_UART_NS16550_PORT_2_DLF) || \ + defined(DT_UART_NS16550_PORT_3_DLF) +#define UART_NS16550_DLF_ENABLED +#endif + +#if DT_UART_NS16550_PORT_0_PCIE || \ + DT_UART_NS16550_PORT_1_PCIE || \ + DT_UART_NS16550_PORT_2_PCIE || \ + DT_UART_NS16550_PORT_3_PCIE +BUILD_ASSERT_MSG(IS_ENABLED(CONFIG_PCIE), "NS16550(s) in DT need CONFIG_PCIE"); +#define UART_NS16550_PCIE_ENABLED +#include +#ifdef CONFIG_PCIE_MSI +#include +#endif +#endif + /* register definitions */ #define REG_THR 0x00 /* Transmitter holding reg. */ @@ -227,9 +252,15 @@ struct uart_ns16550_device_config { uart_irq_config_func_t irq_config_func; #endif -#ifdef CONFIG_UART_NS16550_PCP +#ifdef UART_NS16550_PCP_ENABLED u32_t pcp; #endif + +#ifdef UART_NS16550_PCIE_ENABLED + bool pcie; + pcie_bdf_t pcie_bdf; + pcie_id_t pcie_id; +#endif }; /** Device data structure */ @@ -238,47 +269,19 @@ struct uart_ns16550_dev_data_t { u32_t baud_rate; /**< Baud rate */ u8_t options; /**< Serial port options */ -#ifdef CONFIG_PCI - struct pci_dev_info pci_dev; -#endif /* CONFIG_PCI */ - #ifdef CONFIG_UART_INTERRUPT_DRIVEN u8_t iir_cache; /**< cache of IIR since it clears when read */ - uart_irq_callback_user_data_t cb; /**< Callback function pointer */ + uart_irq_callback_user_data_t cb; /**< Callback function pointer */ void *cb_data; /**< Callback function arg */ #endif -#ifdef CONFIG_UART_NS16550_DLF +#ifdef UART_NS16550_DLF_ENABLED u8_t dlf; /**< DLF value */ #endif }; static const struct uart_driver_api uart_ns16550_driver_api; -#ifdef CONFIG_UART_NS16550_DLF -static inline void set_dlf(struct device *dev, u32_t val) -{ - struct uart_ns16550_dev_data_t * const dev_data = DEV_DATA(dev); - - OUTBYTE(DLF(dev), val); - dev_data->dlf = val; -} -#endif - -#ifdef CONFIG_UART_NS16550_PCP -static inline void set_pcp(struct device *dev) -{ - const struct uart_ns16550_device_config * const dev_cfg = DEV_CFG(dev); - u32_t pcp = dev_cfg->pcp; - - if (pcp) { - pcp |= PCP_EN; - OUTWORD(PCP(dev), pcp & ~PCP_UPDATE); - OUTWORD(PCP(dev), pcp | PCP_UPDATE); - } -} -#endif - static void set_baud_rate(struct device *dev, u32_t baud_rate) { const struct uart_ns16550_device_config * const dev_cfg = DEV_CFG(dev); @@ -307,36 +310,6 @@ static void set_baud_rate(struct device *dev, u32_t baud_rate) } } -#if defined(CONFIG_UART_NS16550_PCI) -static inline int ns16550_pci_uart_scan(struct device *dev) -{ - struct uart_ns16550_dev_data_t * const dev_data = DEV_DATA(dev); - - if (dev_data->pci_dev.vendor_id == 0x0000) { - return -EINVAL; - } - - pci_bus_scan_init(); - - if (!pci_bus_scan(&dev_data->pci_dev)) { - return 0; - } - -#ifdef CONFIG_PCI_ENUMERATION - dev_data->port = dev_data->pci_dev.addr; -#endif - - pci_enable_regs(&dev_data->pci_dev); - - return 1; -} - -#else - -#define ns16550_pci_uart_scan(_unused_) (1) - -#endif /* CONFIG_UART_NS16550_PCI */ - /** * @brief Initialize individual UART port * @@ -349,14 +322,23 @@ static inline int ns16550_pci_uart_scan(struct device *dev) static int uart_ns16550_init(struct device *dev) { struct uart_ns16550_dev_data_t * const dev_data = DEV_DATA(dev); + const struct uart_ns16550_device_config * const dev_cfg = DEV_CFG(dev); unsigned int old_level; /* old interrupt lock level */ u8_t mdc = 0U; - if (!ns16550_pci_uart_scan(dev)) { - dev->driver_api = NULL; - return -ENOTSUP; + ARG_UNUSED(dev_cfg); + +#ifdef UART_NS16550_PCIE_ENABLED + if (dev_cfg->pcie) { + if (!pcie_probe(dev_cfg->pcie_bdf, dev_cfg->pcie_id)) { + return -EINVAL; + } + + dev_data->port = pcie_get_mbar(dev_cfg->pcie_bdf, 0); + pcie_set_cmd(dev_cfg->pcie_bdf, PCIE_CONF_CMDSTAT_MEM, true); } +#endif #ifdef CONFIG_UART_INTERRUPT_DRIVEN dev_data->iir_cache = 0U; @@ -364,12 +346,18 @@ static int uart_ns16550_init(struct device *dev) old_level = irq_lock(); -#ifdef CONFIG_UART_NS16550_DLF - set_dlf(dev, dev_data->dlf); +#ifdef UART_NS16550_DLF_ENABLED + OUTBYTE(DLF(dev), dev_data->dlf); #endif -#ifdef CONFIG_UART_NS16550_PCP - set_pcp(dev); +#ifdef UART_NS16550_PCP_ENABLED + u32_t pcp = dev_cfg->pcp; + + if (pcp) { + pcp |= PCP_EN; + OUTWORD(PCP(dev), pcp & ~PCP_UPDATE); + OUTWORD(PCP(dev), pcp | PCP_UPDATE); + } #endif set_baud_rate(dev, dev_data->baud_rate); @@ -738,11 +726,16 @@ static int uart_ns16550_line_ctrl_set(struct device *dev, */ static int uart_ns16550_drv_cmd(struct device *dev, u32_t cmd, u32_t p) { + struct uart_ns16550_dev_data_t * const dev_data = DEV_DATA(dev); + + ARG_UNUSED(dev_data); + switch (cmd) { -#ifdef CONFIG_UART_NS16550_DLF +#ifdef UART_NS16550_DLF_ENABLED case CMD_SET_DLF: - set_dlf(dev, p); + dev_data->dlf = p; + OUTBYTE(DLF(dev), dev_data->dlf); return 0; #endif @@ -799,28 +792,24 @@ static const struct uart_ns16550_device_config uart_ns16550_dev_cfg_0 = { .irq_config_func = irq_config_func_0, #endif -#ifdef CONFIG_UART_NS16550_PORT_0_PCP - .pcp = CONFIG_UART_NS16550_PORT_0_PCP +#ifdef DT_UART_NS16550_PORT_0_PCP + .pcp = DT_UART_NS16550_PORT_0_PCP, +#endif + +#if DT_UART_NS16550_PORT_0_PCIE + .pcie = true, + .pcie_bdf = DT_UART_NS16550_PORT_0_BASE_ADDR, + .pcie_id = DT_UART_NS16550_PORT_0_SIZE, #endif }; static struct uart_ns16550_dev_data_t uart_ns16550_dev_data_0 = { -#ifdef CONFIG_UART_NS16550_PORT_0_PCI - .pci_dev.class_type = UART_NS16550_PORT_0_PCI_CLASS, - .pci_dev.bus = UART_NS16550_PORT_0_PCI_BUS, - .pci_dev.dev = UART_NS16550_PORT_0_PCI_DEV, - .pci_dev.vendor_id = UART_NS16550_PORT_0_PCI_VENDOR_ID, - .pci_dev.device_id = UART_NS16550_PORT_0_PCI_DEVICE_ID, - .pci_dev.function = UART_NS16550_PORT_0_PCI_FUNC, - .pci_dev.bar = UART_NS16550_PORT_0_PCI_BAR, -#endif /* CONFIG_UART_NS16550_PORT_0_PCI */ - .port = DT_UART_NS16550_PORT_0_BASE_ADDR, .baud_rate = DT_UART_NS16550_PORT_0_BAUD_RATE, .options = CONFIG_UART_NS16550_PORT_0_OPTIONS, -#ifdef CONFIG_UART_NS16550_PORT_0_DLF - .dlf = CONFIG_UART_NS16550_PORT_0_DLF, +#ifdef DT_UART_NS16550_PORT_0_DLF + .dlf = DT_UART_NS16550_PORT_0_DLF, #endif }; @@ -839,6 +828,12 @@ static void irq_config_func_0(struct device *dev) uart_ns16550_isr, DEVICE_GET(uart_ns16550_0), DT_UART_NS16550_PORT_0_IRQ_FLAGS); irq_enable(DT_UART_NS16550_PORT_0_IRQ); +#if defined(UART_NS16550_PCIE_ENABLED) && CONFIG_PCIE_MSI + if (DEV_CFG(dev)->pcie) { + pcie_set_msi(DT_UART_NS16550_PORT_0_BASE_ADDR, + DT_UART_NS16550_PORT_0_IRQ); + } +#endif } #endif @@ -857,28 +852,24 @@ static const struct uart_ns16550_device_config uart_ns16550_dev_cfg_1 = { .irq_config_func = irq_config_func_1, #endif -#ifdef CONFIG_UART_NS16550_PORT_1_PCP - .pcp = CONFIG_UART_NS16550_PORT_1_PCP +#ifdef DT_UART_NS16550_PORT_1_PCP + .pcp = DT_UART_NS16550_PORT_1_PCP, +#endif + +#if DT_UART_NS16550_PORT_1_PCIE + .pcie = true, + .pcie_bdf = DT_UART_NS16550_PORT_1_BASE_ADDR, + .pcie_id = DT_UART_NS16550_PORT_1_SIZE, #endif }; static struct uart_ns16550_dev_data_t uart_ns16550_dev_data_1 = { -#ifdef CONFIG_UART_NS16550_PORT_1_PCI - .pci_dev.class_type = UART_NS16550_PORT_1_PCI_CLASS, - .pci_dev.bus = UART_NS16550_PORT_1_PCI_BUS, - .pci_dev.dev = UART_NS16550_PORT_1_PCI_DEV, - .pci_dev.vendor_id = UART_NS16550_PORT_1_PCI_VENDOR_ID, - .pci_dev.device_id = UART_NS16550_PORT_1_PCI_DEVICE_ID, - .pci_dev.function = UART_NS16550_PORT_1_PCI_FUNC, - .pci_dev.bar = UART_NS16550_PORT_1_PCI_BAR, -#endif /* CONFIG_UART_NS16550_PORT_1_PCI */ - .port = DT_UART_NS16550_PORT_1_BASE_ADDR, .baud_rate = DT_UART_NS16550_PORT_1_BAUD_RATE, .options = CONFIG_UART_NS16550_PORT_1_OPTIONS, -#ifdef CONFIG_UART_NS16550_PORT_1_DLF - .dlf = CONFIG_UART_NS16550_PORT_1_DLF, +#ifdef DT_UART_NS16550_PORT_1_DLF + .dlf = DT_UART_NS16550_PORT_1_DLF, #endif }; @@ -897,6 +888,12 @@ static void irq_config_func_1(struct device *dev) uart_ns16550_isr, DEVICE_GET(uart_ns16550_1), DT_UART_NS16550_PORT_1_IRQ_FLAGS); irq_enable(DT_UART_NS16550_PORT_1_IRQ); +#if defined(UART_NS16550_PCIE_ENABLED) && CONFIG_PCIE_MSI + if (DEV_CFG(dev)->pcie) { + pcie_set_msi(DT_UART_NS16550_PORT_1_BASE_ADDR, + DT_UART_NS16550_PORT_1_IRQ); + } +#endif } #endif @@ -915,28 +912,24 @@ static const struct uart_ns16550_device_config uart_ns16550_dev_cfg_2 = { .irq_config_func = irq_config_func_2, #endif -#ifdef CONFIG_UART_NS16550_PORT_2_PCP - .pcp = CONFIG_UART_NS16550_PORT_2_PCP +#ifdef DT_UART_NS16550_PORT_2_PCP + .pcp = DT_UART_NS16550_PORT_2_PCP, +#endif + +#if DT_UART_NS16550_PORT_2_PCIE + .pcie = true, + .pcie_bdf = DT_UART_NS16550_PORT_2_BASE_ADDR, + .pcie_id = DT_UART_NS16550_PORT_2_SIZE, #endif }; static struct uart_ns16550_dev_data_t uart_ns16550_dev_data_2 = { -#ifdef CONFIG_UART_NS16550_PORT_2_PCI - .pci_dev.class_type = UART_NS16550_PORT_2_PCI_CLASS, - .pci_dev.bus = UART_NS16550_PORT_2_PCI_BUS, - .pci_dev.dev = UART_NS16550_PORT_2_PCI_DEV, - .pci_dev.vendor_id = UART_NS16550_PORT_2_PCI_VENDOR_ID, - .pci_dev.device_id = UART_NS16550_PORT_2_PCI_DEVICE_ID, - .pci_dev.function = UART_NS16550_PORT_2_PCI_FUNC, - .pci_dev.bar = UART_NS16550_PORT_2_PCI_BAR, -#endif /* CONFIG_UART_NS16550_PORT_2_PCI */ - .port = DT_UART_NS16550_PORT_2_BASE_ADDR, .baud_rate = DT_UART_NS16550_PORT_2_BAUD_RATE, .options = CONFIG_UART_NS16550_PORT_2_OPTIONS, -#ifdef CONFIG_UART_NS16550_PORT_2_DLF - .dlf = CONFIG_UART_NS16550_PORT_2_DLF, +#ifdef DT_UART_NS16550_PORT_2_DLF + .dlf = DT_UART_NS16550_PORT_2_DLF, #endif }; @@ -954,7 +947,14 @@ static void irq_config_func_2(struct device *dev) DT_UART_NS16550_PORT_2_IRQ_PRI, uart_ns16550_isr, DEVICE_GET(uart_ns16550_2), DT_UART_NS16550_PORT_2_IRQ_FLAGS); + irq_enable(DT_UART_NS16550_PORT_2_IRQ); +#if defined(UART_NS16550_PCIE_ENABLED) && CONFIG_PCIE_MSI + if (DEV_CFG(dev)->pcie) { + pcie_set_msi(DT_UART_NS16550_PORT_2_BASE_ADDR, + DT_UART_NS16550_PORT_2_IRQ); + } +#endif } #endif @@ -973,28 +973,24 @@ static const struct uart_ns16550_device_config uart_ns16550_dev_cfg_3 = { .irq_config_func = irq_config_func_3, #endif -#ifdef CONFIG_UART_NS16550_PORT_3_PCP - .pcp = CONFIG_UART_NS16550_PORT_3_PCP +#ifdef DT_UART_NS16550_PORT_3_PCP + .pcp = DT_UART_NS16550_PORT_3_PCP, +#endif + +#if DT_UART_NS16550_PORT_3_PCIE + .pcie = true, + .pcie_bdf = DT_UART_NS16550_PORT_3_BASE_ADDR, + .pcie_id = DT_UART_NS16550_PORT_3_SIZE, #endif }; static struct uart_ns16550_dev_data_t uart_ns16550_dev_data_3 = { -#ifdef CONFIG_UART_NS16550_PORT_3_PCI - .pci_dev.class_type = UART_NS16550_PORT_3_PCI_CLASS, - .pci_dev.bus = UART_NS16550_PORT_3_PCI_BUS, - .pci_dev.dev = UART_NS16550_PORT_3_PCI_DEV, - .pci_dev.vendor_id = UART_NS16550_PORT_3_PCI_VENDOR_ID, - .pci_dev.device_id = UART_NS16550_PORT_3_PCI_DEVICE_ID, - .pci_dev.function = UART_NS16550_PORT_3_PCI_FUNC, - .pci_dev.bar = UART_NS16550_PORT_3_PCI_BAR, -#endif /* CONFIG_UART_NS16550_PORT_3_PCI */ - .port = DT_UART_NS16550_PORT_3_BASE_ADDR, .baud_rate = DT_UART_NS16550_PORT_3_BAUD_RATE, .options = CONFIG_UART_NS16550_PORT_3_OPTIONS, -#ifdef CONFIG_UART_NS16550_PORT_3_DLF - .dlf = CONFIG_UART_NS16550_PORT_3_DLF, +#ifdef DT_UART_NS16550_PORT_3_DLF + .dlf = DT_UART_NS16550_PORT_3_DLF, #endif }; @@ -1013,6 +1009,12 @@ static void irq_config_func_3(struct device *dev) uart_ns16550_isr, DEVICE_GET(uart_ns16550_3), DT_UART_NS16550_PORT_3_IRQ_FLAGS); irq_enable(DT_UART_NS16550_PORT_3_IRQ); +#if defined(UART_NS16550_PCIE_ENABLED) && CONFIG_PCIE_MSI + if (DEV_CFG(dev)->pcie) { + pcie_set_msi(DT_UART_NS16550_PORT_3_BASE_ADDR, + DT_UART_NS16550_PORT_3_IRQ); + } +#endif } #endif diff --git a/dts/arc/arc_iot.dtsi b/dts/arc/arc_iot.dtsi index a891938b6b..b9390400ce 100644 --- a/dts/arc/arc_iot.dtsi +++ b/dts/arc/arc_iot.dtsi @@ -65,6 +65,7 @@ label = "UART_0"; interrupts = <86 0>; interrupt-parent = <&intc>; + dlf = <0x01>; }; uart1: uart@80014100 { diff --git a/dts/bindings/serial/ns16550.yaml b/dts/bindings/serial/ns16550.yaml index cce1bd3318..81dd39f2d4 100644 --- a/dts/bindings/serial/ns16550.yaml +++ b/dts/bindings/serial/ns16550.yaml @@ -29,4 +29,22 @@ properties: category: required description: required interrupts generation: define + + pcp: + type: int + category: optional + description: custom clock (PRV_CLOCK_PARAMS, if supported) + generation: define + + dlf: + type: int + category: optional + description: divisor latch fraction (DLF, if supported) + generation: define + + pcie: + type: boolean + category: optional + description: attached via PCI(e) bus + generation: define ... diff --git a/dts/x86/quark_x1000.dtsi b/dts/x86/quark_x1000.dtsi index 33ad72e3fd..acf6639de9 100644 --- a/dts/x86/quark_x1000.dtsi +++ b/dts/x86/quark_x1000.dtsi @@ -7,6 +7,7 @@ #include "skeleton.dtsi" #include #include +#include / { cpus { @@ -46,9 +47,9 @@ ranges; - uart0: uart@9000f000 { + uart0: uart@0 { compatible = "ns16550"; - reg = <0x9000f000 0x400>; + pcie; reg = ; label = "UART_0"; clock-frequency = <44236800>; interrupts = <0 IRQ_TYPE_LEVEL_LOW 0>; @@ -57,9 +58,9 @@ status = "disabled"; }; - uart1: uart@9000b000 { + uart1: uart@1 { compatible = "ns16550"; - reg = <0x9000b000 0x400>; + pcie; reg = ; label = "UART_1"; clock-frequency = <44236800>; interrupts = <17 IRQ_TYPE_LEVEL_LOW 3>; diff --git a/include/drivers/pcie/msi.h b/include/drivers/pcie/msi.h new file mode 100644 index 0000000000..4be2db081a --- /dev/null +++ b/include/drivers/pcie/msi.h @@ -0,0 +1,106 @@ +/* + * Copyright (c) 2019 Intel Corporation + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#ifndef ZEPHYR_INCLUDE_DRIVERS_PCIE_MSI_H_ +#define ZEPHYR_INCLUDE_DRIVERS_PCIE_MSI_H_ + +#include +#include +#include + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * @brief Find a PCI(e) capability in an endpoint's configuration space. + * + * @param bdf the PCI endpoint to examine + * @param cap_id the capability ID of interest + * @return the index of the configuration word, or 0 if no capability. + * + * Note: PCI(e) capabilities are only used in the MSI code, so for + * now, capabilities-related code is only included when MSI is. It + * can easily be separated out if/when its use spreads. + */ +extern u32_t pcie_get_cap(pcie_bdf_t bdf, u32_t cap_id); + +/* + * Configuration word 13 contains the head of the capabilities list. + */ + +#define PCIE_CONF_CAPPTR 13U /* capabilities pointer */ +#define PCIE_CONF_CAPPTR_FIRST(w) (((w) >> 2) & 0x3FU) + +/* + * The first word of every capability contains a capability identifier, + * and a link to the next capability (or 0) in configuration space. + */ + +#define PCIE_CONF_CAP_ID(w) ((w) & 0xFFU) +#define PCIE_CONF_CAP_NEXT(w) (((w) >> 10) & 0x3FU) + +/** + * @brief Compute the target address for an MSI posted write. + * + * This function is exported by the arch, board or SoC code. + * + * @param irq The IRQ we wish to trigger via MSI. + * @return A (32-bit) value for the MSI MAP register. + */ +extern u32_t pcie_msi_map(unsigned int irq); + +/** + * @brief Compute the data for an MSI posted write. + * + * This function is exported by the arch, board or SoC code. + * + * @param irq The IRQ we wish to trigger via MSI. + * @return A (16-bit) value for MSI MDR register. + */ +extern u16_t pcie_msi_mdr(unsigned int irq); + +/** + * @brief Configure the given PCI endpoint to generate MSIs. + * + * @param bdf the target PCI endpoint + * @param irq the IRQ which should be generated + * @return true if the endpoint supports MSI, false otherwise. + */ +extern bool pcie_set_msi(pcie_bdf_t bdf, unsigned int irq); + +/* + * MSI capability ID in the PCI configuration capability list. + */ + +#define PCIE_MSI_CAP_ID 05U + +/* + * The first word of the MSI capability is shared with the + * capability ID and list link. The high 16 bits are the MCR. + */ + +#define PCIE_MSI_MCR 0U + +#define PCIE_MSI_MCR_EN 0x00010000U /* enable MSI */ +#define PCIE_MSI_MCR_MME 0x00700000U /* mask of # of enabled IRQs */ +#define PCIE_MSI_MCR_64 0x00800000U /* 64-bit MSI */ + +/* + * The MAP follows the MCR. If PCIE_MSI_MCR_64, then the MAP + * is two words long. The MDR follows immediately after the MAP. + */ + +#define PCIE_MSI_MAP0 1U +#define PCIE_MSI_MAP1_64 2U +#define PCIE_MSI_MDR_32 2U +#define PCIE_MSI_MDR_64 3U + +#ifdef __cplusplus +} +#endif + +#endif /* ZEPHYR_INCLUDE_DRIVERS_PCIE_MSI_H_ */ diff --git a/include/drivers/pcie/pcie.h b/include/drivers/pcie/pcie.h new file mode 100644 index 0000000000..56a739fe57 --- /dev/null +++ b/include/drivers/pcie/pcie.h @@ -0,0 +1,168 @@ +/* + * Copyright (c) 2019 Intel Corporation + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#ifndef ZEPHYR_INCLUDE_DRIVERS_PCIE_PCIE_H_ +#define ZEPHYR_INCLUDE_DRIVERS_PCIE_PCIE_H_ + +#include +#include + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * @typedef pcie_bdf_t + * @brief A unique PCI(e) endpoint (bus, device, function). + * + * A PCI(e) endpoint is uniquely identified topologically using a + * (bus, device, function) tuple. The internal structure is documented + * in include/dt-bindings/pcie/pcie.h: see PCIE_BDF() and friends, since + * these tuples are referenced from devicetree. + */ +typedef u32_t pcie_bdf_t; + +/** + * @typedef pcie_id_t + * @brief A unique PCI(e) identifier (vendor ID, device ID). + * + * The PCIE_CONF_ID register for each endpoint is a (vendor ID, device ID) + * pair, which is meant to tell the system what the PCI(e) endpoint is. Again, + * look to PCIE_ID_* macros in include/dt-bindings/pcie/pcie.h for more. + */ +typedef u32_t pcie_id_t; + +/* + * These functions are arch-, board-, or SoC-specific. + */ + +/** + * @brief Read a 32-bit word from an endpoint's configuration space. + * + * This function is exported by the arch/SoC/board code. + * + * @param bdf PCI(e) endpoint + * @param reg the configuration word index (not address) + * @return the word read (0xFFFFFFFFU if nonexistent endpoint or word) + */ +extern u32_t pcie_conf_read(pcie_bdf_t bdf, unsigned int reg); + +/** + * @brief Write a 32-bit word to an endpoint's configuration space. + * + * This function is exported by the arch/SoC/board code. + * + * @param bdf PCI(e) endpoint + * @param reg the configuration word index (not address) + * @param data the value to write + */ +extern void pcie_conf_write(pcie_bdf_t bdf, unsigned int reg, u32_t data); + +/** + * @brief Probe for the presence of a PCI(e) endpoint. + * + * @param bdf the endpoint to probe + * @param id the endpoint ID to expect, or PCI_ID_ANY for "any device" + * @return true if the device is present, false otherwise + */ +extern bool pcie_probe(pcie_bdf_t bdf, pcie_id_t id); + +/** + * @brief Get the nth MMIO address assigned to an endpoint. + * @param bdf the PCI(e) endpoint + * @param index (0-based) index + * @return the (32-bit) address, or PCI_CONF_BAR_NONE if nonexistent. + * + * A PCI(e) endpoint has 0 or more memory-mapped regions. This function + * allows the caller to enumerate them by calling with index=0..n. If + * PCI_CONF_BAR_NONE is returned, there are no further regions. The indices + * are order-preserving with respect to the endpoint BARs: e.g., index 0 + * will return the lowest-numbered memory BAR on the endpoint. + */ +extern u32_t pcie_get_mbar(pcie_bdf_t bdf, unsigned int index); + +/** + * @brief Get the nth I/O address assigned to an endpoint. + * @param bdf the PCI(e) endpoint + * @param index (0-based) index + * @return the (32-bit) address, or PCI_CONF_BAR_NONE if nonexistent. + * + * Analogous to pcie_get_mbar(), except returns I/O region data. + */ +extern u32_t pcie_get_iobar(pcie_bdf_t bdf, unsigned int index); + +/** + * @brief Set or reset bits in the endpoint command/status register. + * + * @param bdf the PCI(e) endpoint + * @param bits the powerset of bits of interest + * @param on use true to set bits, false to reset them + */ +extern void pcie_set_cmd(pcie_bdf_t bdf, u32_t bits, bool on); + +/* + * Configuration word 0 aligns directly with pcie_id_t. + */ + +#define PCIE_CONF_ID 0U + +/* + * Configuration word 1 contains command and status bits. + */ + +#define PCIE_CONF_CMDSTAT 1U /* command/status register */ + +#define PCIE_CONF_CMDSTAT_IO 0x00000001U /* I/O access enable */ +#define PCIE_CONF_CMDSTAT_MEM 0x00000002U /* mem access enable */ +#define PCIE_CONF_CMDSTAT_MASTER 0x00000004U /* bus master enable */ +#define PCIE_CONF_CMDSTAT_CAPS 0x00100000U /* capabilities list */ + +/* + * Configuration word 2 has additional function identification that + * we only care about for debug output (PCIe shell commands). + */ + +#define PCIE_CONF_CLASSREV 2U /* class/revision register */ + +#define PCIE_CONF_CLASSREV_CLASS(w) (((w) >> 24) & 0xFFU) +#define PCIE_CONF_CLASSREV_SUBCLASS(w) (((w) >> 16) & 0xFFU) +#define PCIE_CONF_CLASSREV_PROGIF(w) (((w) >> 8) & 0xFFU) +#define PCIE_CONF_CLASSREV_REV(w) ((w) & 0xFFU) + +/* + * The only part of configuration word 3 that is of interest to us is + * the header type, as we use it to distinguish functional endpoints + * from bridges (which are, for our purposes, transparent). + */ + +#define PCIE_CONF_TYPE 3U + +#define PCIE_CONF_TYPE_BRIDGE(w) (((w) & 0x007F0000U) != 0U) + +/* + * Words 4-9 are BARs are I/O or memory decoders. Memory decoders may + * be 64-bit decoders, in which case the next configuration word holds + * the high-order bits (and is, thus, not a BAR itself). + */ + +#define PCIE_CONF_BAR0 4U +#define PCIE_CONF_BAR1 5U +#define PCIE_CONF_BAR2 6U +#define PCIE_CONF_BAR3 7U +#define PCIE_CONF_BAR4 8U +#define PCIE_CONF_BAR5 9U + +#define PCIE_CONF_BAR_IO(w) (((w) & 0x00000001U) == 0x00000001U) +#define PCIE_CONF_BAR_MEM(w) (((w) & 0x00000001U) != 0x00000001U) +#define PCIE_CONF_BAR_64(w) (((w) & 0x00000006U) == 0x00000004U) +#define PCIE_CONF_BAR_ADDR(w) ((w) & 0xFFFFFFF0U) +#define PCIE_CONF_BAR_NONE 0U + +#ifdef __cplusplus +} +#endif + +#endif /* ZEPHYR_INCLUDE_DRIVERS_PCIE_PCIE_H_ */ diff --git a/include/dt-bindings/pcie/pcie.h b/include/dt-bindings/pcie/pcie.h new file mode 100644 index 0000000000..0930469f74 --- /dev/null +++ b/include/dt-bindings/pcie/pcie.h @@ -0,0 +1,59 @@ +/* + * Copyright (c) 2019 Intel Corporation + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#ifndef ZEPHYR_INCLUDE_DT_BINDINGS_PCIE_PCIE_H_ +#define ZEPHYR_INCLUDE_DT_BINDINGS_PCIE_PCIE_H_ + +/* + * We represent a PCI device ID as [31:16] device ID, [15:0] vendor ID. Not + * coincidentally, this is same representation used in PCI configuration space. + */ + +#define PCIE_ID_VEND_SHIFT 0U +#define PCIE_ID_VEND_MASK 0xFFFFU +#define PCIE_ID_DEV_SHIFT 16U +#define PCIE_ID_DEV_MASK 0xFFFFU + +#define PCIE_ID(vend, dev) \ + ((((vend) & PCIE_ID_VEND_MASK) << PCIE_ID_VEND_SHIFT) | \ + (((dev) & PCIE_ID_DEV_MASK) << PCIE_ID_DEV_SHIFT)) + +#define PCIE_ID_TO_VEND(id) (((id) >> PCIE_ID_VEND_SHIFT) & PCIE_ID_VEND_MASK) +#define PCIE_ID_TO_DEV(id) (((id) >> PCIE_ID_DEV_SHIFT) & PCIE_ID_DEV_MASK) + +#define PCIE_ID_NONE PCIE_ID(0xFFFF, 0xFFFF) + +/* + * Since our internal representation of bus/device/function is arbitrary, + * we choose the same format employed in the x86 Configuration Address Port: + * + * [23:16] bus number, [15:11] device number, [10:8] function number + * + * All other bits must be zero. + * + * The x86 (the only arch, at present, that supports PCI) takes advantage + * of this shared format to avoid unnecessary layers of abstraction. + */ + +#define PCIE_BDF_BUS_SHIFT 16U +#define PCIE_BDF_BUS_MASK 0xFFU +#define PCIE_BDF_DEV_SHIFT 11U +#define PCIE_BDF_DEV_MASK 0x1FU +#define PCIE_BDF_FUNC_SHIFT 8U +#define PCIE_BDF_FUNC_MASK 0x7U + +#define PCIE_BDF(bus, dev, func) \ + ((((bus) & PCIE_BDF_BUS_MASK) << PCIE_BDF_BUS_SHIFT) | \ + (((dev) & PCIE_BDF_DEV_MASK) << PCIE_BDF_DEV_SHIFT) | \ + (((func) & PCIE_BDF_FUNC_MASK) << PCIE_BDF_FUNC_SHIFT)) + +#define PCIE_BDF_TO_BUS(bdf) (((bdf) >> PCIE_BDF_BUS_SHIFT) & PCIE_BDF_BUS_MASK) +#define PCIE_BDF_TO_DEV(bdf) (((bdf) >> PCIE_BDF_DEV_SHIFT) & PCIE_BDF_DEV_MASK) + +#define PCIE_BDF_TO_FUNC(bdf) \ + (((bdf) >> PCIE_BDF_FUNC_SHIFT) & PCIE_BDF_FUNC_MASK) + +#endif /* ZEPHYR_INCLUDE_DT_BINDINGS_PCIE_PCIE_H_ */ diff --git a/soc/arc/snps_arc_iot/Kconfig.defconfig b/soc/arc/snps_arc_iot/Kconfig.defconfig index ebbd9dabb6..8c657e681d 100644 --- a/soc/arc/snps_arc_iot/Kconfig.defconfig +++ b/soc/arc/snps_arc_iot/Kconfig.defconfig @@ -37,9 +37,6 @@ if SERIAL config UART_NS16550 def_bool y -config UART_NS16550_DLF - def_bool y - endif # SERIAL if UART_CONSOLE @@ -47,9 +44,6 @@ if UART_CONSOLE config UART_NS16550_PORT_0 def_bool y -config UART_NS16550_PORT_0_DLF - default 1 - endif # UART_CONSOLE endif #ARC_IOT diff --git a/soc/arc/snps_arc_iot/dts_fixup.h b/soc/arc/snps_arc_iot/dts_fixup.h index def132ed94..2b4f72ee3f 100644 --- a/soc/arc/snps_arc_iot/dts_fixup.h +++ b/soc/arc/snps_arc_iot/dts_fixup.h @@ -23,6 +23,10 @@ #define DT_UART_NS16550_PORT_0_NAME DT_NS16550_80014000_LABEL #define DT_UART_NS16550_PORT_0_IRQ_PRI DT_NS16550_80014000_IRQ_0_PRIORITY +#ifdef DT_NS16550_80014000_DLF +#define DT_UART_NS16550_PORT_0_DLF DT_NS16550_80014000_DLF +#endif + #define DT_UART_NS16550_PORT_1_BASE_ADDR DT_NS16550_80014100_BASE_ADDRESS #define DT_UART_NS16550_PORT_1_IRQ DT_NS16550_80014100_IRQ_0 #define DT_UART_NS16550_PORT_1_CLK_FREQ DT_NS16550_80014100_CLOCK_FREQUENCY @@ -30,6 +34,10 @@ #define DT_UART_NS16550_PORT_1_NAME DT_NS16550_80014100_LABEL #define DT_UART_NS16550_PORT_1_IRQ_PRI DT_NS16550_80014100_IRQ_0_PRIORITY +#ifdef DT_NS16550_80014100_DLF +#define DT_UART_NS16550_PORT_1_DLF DT_NS16550_80014100_DLF +#endif + #define DT_UART_NS16550_PORT_2_BASE_ADDR DT_NS16550_80014200_BASE_ADDRESS #define DT_UART_NS16550_PORT_2_IRQ DT_NS16550_80014200_IRQ_0 #define DT_UART_NS16550_PORT_2_CLK_FREQ DT_NS16550_80014200_CLOCK_FREQUENCY @@ -37,6 +45,9 @@ #define DT_UART_NS16550_PORT_2_NAME DT_NS16550_80014200_LABEL #define DT_UART_NS16550_PORT_2_IRQ_PRI DT_NS16550_80014200_IRQ_0_PRIORITY +#ifdef DT_NS16550_80014200_DLF +#define DT_UART_NS16550_PORT_2_DLF DT_NS16550_80014200_DLF +#endif #define DT_UART_NS16550_PORT_3_BASE_ADDR DT_NS16550_80014300_BASE_ADDRESS #define DT_UART_NS16550_PORT_3_IRQ DT_NS16550_80014300_IRQ_0 @@ -45,5 +56,8 @@ #define DT_UART_NS16550_PORT_3_NAME DT_NS16550_80014300_LABEL #define DT_UART_NS16550_PORT_3_IRQ_PRI DT_NS16550_80014300_IRQ_0_PRIORITY +#ifdef DT_NS16550_80014300_DLF +#define DT_UART_NS16550_PORT_3_DLF DT_NS16550_80014300_DLF +#endif /* End of SoC Level DTS fixup file */ diff --git a/soc/nios2/nios2f-zephyr/Kconfig.defconfig b/soc/nios2/nios2f-zephyr/Kconfig.defconfig index a729ac3c12..0e3cabb22b 100644 --- a/soc/nios2/nios2f-zephyr/Kconfig.defconfig +++ b/soc/nios2/nios2f-zephyr/Kconfig.defconfig @@ -43,9 +43,6 @@ endif # DMA_NIOS2_MSGDMA if UART_NS16550 -config UART_NS16550_PCI - default n - config UART_NS16550_PORT_0 default y diff --git a/soc/x86/apollo_lake/Kconfig.defconfig b/soc/x86/apollo_lake/Kconfig.defconfig index bf4c6502cd..c99b72651b 100644 --- a/soc/x86/apollo_lake/Kconfig.defconfig +++ b/soc/x86/apollo_lake/Kconfig.defconfig @@ -21,9 +21,6 @@ config CLFLUSH_DETECT if UART_NS16550 -config UART_NS16550_PCI - default y if PCI - config UART_NS16550_PORT_0 default y @@ -32,9 +29,6 @@ if UART_NS16550_PORT_0 config UART_NS16550_PORT_0_OPTIONS default 0 -config UART_NS16550_PORT_0_PCI - default y if PCI - endif # UART_NS16550_PORT_0 config UART_NS16550_PORT_1 @@ -45,9 +39,6 @@ if UART_NS16550_PORT_1 config UART_NS16550_PORT_1_OPTIONS default 0 -config UART_NS16550_PORT_1_PCI - default y if PCI - endif # UART_NS16550_PORT_1 if UART_NS16550_PORT_2 @@ -55,9 +46,6 @@ if UART_NS16550_PORT_2 config UART_NS16550_PORT_2_OPTIONS default 0 -config UART_NS16550_PORT_2_PCI - default y if PCI - endif # UART_NS16550_PORT_2 if UART_NS16550_PORT_3 @@ -65,9 +53,6 @@ if UART_NS16550_PORT_3 config UART_NS16550_PORT_3_OPTIONS default 0 -config UART_NS16550_PORT_3_PCI - default y if PCI - endif # UART_NS16550_PORT_3 endif # UART_NS16550 diff --git a/soc/x86/apollo_lake/soc.h b/soc/x86/apollo_lake/soc.h index 5efe6f33d0..b51656c481 100644 --- a/soc/x86/apollo_lake/soc.h +++ b/soc/x86/apollo_lake/soc.h @@ -45,60 +45,6 @@ */ #define pci_pin2irq(bus, dev, pin) (pin) - -/* UARTs */ -#ifdef CONFIG_UART_NS16550_PCI - -#ifdef CONFIG_UART_NS16550_PORT_0_PCI - -#define UART_NS16550_PORT_0_PCI_CLASS 0x11 -#define UART_NS16550_PORT_0_PCI_BUS 0 -#define UART_NS16550_PORT_0_PCI_DEV 18 -#define UART_NS16550_PORT_0_PCI_VENDOR_ID 0x8086 -#define UART_NS16550_PORT_0_PCI_DEVICE_ID 0x5abc -#define UART_NS16550_PORT_0_PCI_FUNC 0 -#define UART_NS16550_PORT_0_PCI_BAR 0 - -#endif /* CONFIG_UART_NS16550_PORT_0_PCI */ - -#ifdef CONFIG_UART_NS16550_PORT_1_PCI - -#define UART_NS16550_PORT_1_PCI_CLASS 0x11 -#define UART_NS16550_PORT_1_PCI_BUS 0 -#define UART_NS16550_PORT_1_PCI_DEV 18 -#define UART_NS16550_PORT_1_PCI_VENDOR_ID 0x8086 -#define UART_NS16550_PORT_1_PCI_DEVICE_ID 0x5abe -#define UART_NS16550_PORT_1_PCI_FUNC 1 -#define UART_NS16550_PORT_1_PCI_BAR 0 - -#endif /* CONFIG_UART_NS16550_PORT_1_PCI */ - -#ifdef CONFIG_UART_NS16550_PORT_2_PCI - -#define UART_NS16550_PORT_2_PCI_CLASS 0x11 -#define UART_NS16550_PORT_2_PCI_BUS 0 -#define UART_NS16550_PORT_2_PCI_DEV 18 -#define UART_NS16550_PORT_2_PCI_VENDOR_ID 0x8086 -#define UART_NS16550_PORT_2_PCI_DEVICE_ID 0x5ac0 -#define UART_NS16550_PORT_2_PCI_FUNC 2 -#define UART_NS16550_PORT_2_PCI_BAR 0 - -#endif /* CONFIG_UART_NS16550_PORT_2_PCI */ - -#ifdef CONFIG_UART_NS16550_PORT_3_PCI - -#define UART_NS16550_PORT_3_PCI_CLASS 0x11 -#define UART_NS16550_PORT_3_PCI_BUS 0 -#define UART_NS16550_PORT_3_PCI_DEV 18 -#define UART_NS16550_PORT_3_PCI_VENDOR_ID 0x8086 -#define UART_NS16550_PORT_3_PCI_DEVICE_ID 0x5aee -#define UART_NS16550_PORT_3_PCI_FUNC 3 -#define UART_NS16550_PORT_3_PCI_BAR 0 - -#endif /* CONFIG_UART_NS16550_PORT_3_PCI */ - -#endif /* CONFIG_UART_NS16550_PCI */ - /* I2C controllers */ #define I2C_DW_0_PCI_VENDOR_ID 0x8086 #define I2C_DW_0_PCI_DEVICE_ID 0x5aac diff --git a/soc/x86/atom/Kconfig.defconfig b/soc/x86/atom/Kconfig.defconfig index d604b8d0f9..0c3ab15f97 100644 --- a/soc/x86/atom/Kconfig.defconfig +++ b/soc/x86/atom/Kconfig.defconfig @@ -20,9 +20,6 @@ config CLFLUSH_DETECT if UART_NS16550 -config UART_NS16550_PCI - default n - config UART_NS16550_PORT_0 default y diff --git a/soc/x86/ia32/Kconfig.defconfig b/soc/x86/ia32/Kconfig.defconfig index 4856c24c2e..b97608e834 100644 --- a/soc/x86/ia32/Kconfig.defconfig +++ b/soc/x86/ia32/Kconfig.defconfig @@ -20,9 +20,6 @@ config CLFLUSH_DETECT if UART_NS16550 -config UART_NS16550_PCI - default n - config UART_NS16550_PORT_0 default y diff --git a/soc/x86/intel_quark/quark_x1000/Kconfig.defconfig.series b/soc/x86/intel_quark/quark_x1000/Kconfig.defconfig.series index a3484df78a..fa06e143b5 100644 --- a/soc/x86/intel_quark/quark_x1000/Kconfig.defconfig.series +++ b/soc/x86/intel_quark/quark_x1000/Kconfig.defconfig.series @@ -133,9 +133,6 @@ endif # SPI if UART_NS16550 -config UART_NS16550_PCI - default y if PCI - config UART_NS16550_PORT_0 default y @@ -144,9 +141,6 @@ if UART_NS16550_PORT_0 config UART_NS16550_PORT_0_OPTIONS default 0 -config UART_NS16550_PORT_0_PCI - default y if UART_NS16550_PCI - endif # UART_NS16550_PORT_0 config UART_NS16550_PORT_1 @@ -157,9 +151,6 @@ if UART_NS16550_PORT_1 config UART_NS16550_PORT_1_OPTIONS default 0 -config UART_NS16550_PORT_1_PCI - default y if UART_NS16550_PCI - endif # UART_NS16550_PORT_1 endif # UART_NS16550 diff --git a/soc/x86/intel_quark/quark_x1000/dts_fixup.h b/soc/x86/intel_quark/quark_x1000/dts_fixup.h index b6b153a117..dd6feeadb2 100644 --- a/soc/x86/intel_quark/quark_x1000/dts_fixup.h +++ b/soc/x86/intel_quark/quark_x1000/dts_fixup.h @@ -1,20 +1,24 @@ /* SPDX-License-Identifier: Apache-2.0 */ -#define DT_UART_NS16550_PORT_0_BASE_ADDR DT_NS16550_9000F000_BASE_ADDRESS -#define DT_UART_NS16550_PORT_0_BAUD_RATE DT_NS16550_9000F000_CURRENT_SPEED -#define DT_UART_NS16550_PORT_0_NAME DT_NS16550_9000F000_LABEL -#define DT_UART_NS16550_PORT_0_IRQ DT_NS16550_9000F000_IRQ_0 -#define DT_UART_NS16550_PORT_0_IRQ_PRI DT_NS16550_9000F000_IRQ_0_PRIORITY -#define DT_UART_NS16550_PORT_0_IRQ_FLAGS DT_NS16550_9000F000_IRQ_0_SENSE -#define DT_UART_NS16550_PORT_0_CLK_FREQ DT_NS16550_9000F000_CLOCK_FREQUENCY +#define DT_UART_NS16550_PORT_0_BASE_ADDR DT_NS16550_0_BASE_ADDRESS +#define DT_UART_NS16550_PORT_0_SIZE DT_NS16550_0_SIZE +#define DT_UART_NS16550_PORT_0_BAUD_RATE DT_NS16550_0_CURRENT_SPEED +#define DT_UART_NS16550_PORT_0_NAME DT_NS16550_0_LABEL +#define DT_UART_NS16550_PORT_0_IRQ DT_NS16550_0_IRQ_0 +#define DT_UART_NS16550_PORT_0_IRQ_PRI DT_NS16550_0_IRQ_0_PRIORITY +#define DT_UART_NS16550_PORT_0_IRQ_FLAGS DT_NS16550_0_IRQ_0_SENSE +#define DT_UART_NS16550_PORT_0_CLK_FREQ DT_NS16550_0_CLOCK_FREQUENCY +#define DT_UART_NS16550_PORT_0_PCIE DT_NS16550_0_PCIE -#define DT_UART_NS16550_PORT_1_BASE_ADDR DT_NS16550_9000B000_BASE_ADDRESS -#define DT_UART_NS16550_PORT_1_BAUD_RATE DT_NS16550_9000B000_CURRENT_SPEED -#define DT_UART_NS16550_PORT_1_NAME DT_NS16550_9000B000_LABEL -#define DT_UART_NS16550_PORT_1_IRQ DT_NS16550_9000B000_IRQ_0 -#define DT_UART_NS16550_PORT_1_IRQ_PRI DT_NS16550_9000B000_IRQ_0_PRIORITY -#define DT_UART_NS16550_PORT_1_IRQ_FLAGS DT_NS16550_9000B000_IRQ_0_SENSE -#define DT_UART_NS16550_PORT_1_CLK_FREQ DT_NS16550_9000B000_CLOCK_FREQUENCY +#define DT_UART_NS16550_PORT_1_BASE_ADDR DT_NS16550_1_BASE_ADDRESS +#define DT_UART_NS16550_PORT_1_SIZE DT_NS16550_1_SIZE +#define DT_UART_NS16550_PORT_1_BAUD_RATE DT_NS16550_1_CURRENT_SPEED +#define DT_UART_NS16550_PORT_1_NAME DT_NS16550_1_LABEL +#define DT_UART_NS16550_PORT_1_IRQ DT_NS16550_1_IRQ_0 +#define DT_UART_NS16550_PORT_1_IRQ_PRI DT_NS16550_1_IRQ_0_PRIORITY +#define DT_UART_NS16550_PORT_1_IRQ_FLAGS DT_NS16550_1_IRQ_0_SENSE +#define DT_UART_NS16550_PORT_1_CLK_FREQ DT_NS16550_1_CLOCK_FREQUENCY +#define DT_UART_NS16550_PORT_1_PCIE DT_NS16550_1_PCIE #define DT_PHYS_RAM_ADDR CONFIG_SRAM_BASE_ADDRESS @@ -24,22 +28,22 @@ #define DT_ROM_SIZE CONFIG_FLASH_SIZE -#define DT_IOAPIC_BASE_ADDRESS DT_INTEL_IOAPIC_FEC00000_BASE_ADDRESS +#define DT_IOAPIC_BASE_ADDRESS DT_INTEL_IOAPIC_FEC00000_BASE_ADDRESS -#define DT_SPI_0_BASE_ADDRESS DT_INTEL_INTEL_SPI_90009000_BASE_ADDRESS -#define DT_SPI_0_IRQ DT_INTEL_INTEL_SPI_90009000_IRQ_0 -#define DT_SPI_0_IRQ_FLAGS DT_INTEL_INTEL_SPI_90009000_IRQ_0_SENSE -#define DT_SPI_0_IRQ_PRI DT_INTEL_INTEL_SPI_90009000_IRQ_0_PRIORITY -#define DT_SPI_0_NAME DT_INTEL_INTEL_SPI_90009000_LABEL +#define DT_SPI_0_BASE_ADDRESS DT_INTEL_INTEL_SPI_90009000_BASE_ADDRESS +#define DT_SPI_0_IRQ DT_INTEL_INTEL_SPI_90009000_IRQ_0 +#define DT_SPI_0_IRQ_FLAGS DT_INTEL_INTEL_SPI_90009000_IRQ_0_SENSE +#define DT_SPI_0_IRQ_PRI DT_INTEL_INTEL_SPI_90009000_IRQ_0_PRIORITY +#define DT_SPI_0_NAME DT_INTEL_INTEL_SPI_90009000_LABEL -#define DT_SPI_1_BASE_ADDRESS DT_INTEL_INTEL_SPI_90008000_BASE_ADDRESS -#define DT_SPI_1_IRQ DT_INTEL_INTEL_SPI_90008000_IRQ_0 -#define DT_SPI_1_IRQ_FLAGS DT_INTEL_INTEL_SPI_90008000_IRQ_0_SENSE -#define DT_SPI_1_IRQ_PRI DT_INTEL_INTEL_SPI_90008000_IRQ_0_PRIORITY -#define DT_SPI_1_NAME DT_INTEL_INTEL_SPI_90008000_LABEL +#define DT_SPI_1_BASE_ADDRESS DT_INTEL_INTEL_SPI_90008000_BASE_ADDRESS +#define DT_SPI_1_IRQ DT_INTEL_INTEL_SPI_90008000_IRQ_0 +#define DT_SPI_1_IRQ_FLAGS DT_INTEL_INTEL_SPI_90008000_IRQ_0_SENSE +#define DT_SPI_1_IRQ_PRI DT_INTEL_INTEL_SPI_90008000_IRQ_0_PRIORITY +#define DT_SPI_1_NAME DT_INTEL_INTEL_SPI_90008000_LABEL #ifdef CONFIG_I2C_0 -#define DT_I2C_DW_0_IRQ_SHARED_NAME DT_SHARED_IRQ_SHAREDIRQ0_LABEL +#define DT_I2C_DW_0_IRQ_SHARED_NAME DT_SHARED_IRQ_SHAREDIRQ0_LABEL #endif #ifdef CONFIG_GPIO_DW_0 diff --git a/soc/x86/intel_quark/quark_x1000/soc.h b/soc/x86/intel_quark/quark_x1000/soc.h index 1d4a62bd33..ecf4ea1132 100644 --- a/soc/x86/intel_quark/quark_x1000/soc.h +++ b/soc/x86/intel_quark/quark_x1000/soc.h @@ -97,25 +97,6 @@ #define I2C_DW_0_PCI_FUNCTION 2 #define I2C_DW_0_PCI_BAR 0 -/* - * UART - */ -#define UART_NS16550_PORT_0_PCI_CLASS 0x07 -#define UART_NS16550_PORT_0_PCI_BUS 0 -#define UART_NS16550_PORT_0_PCI_DEV 20 -#define UART_NS16550_PORT_0_PCI_VENDOR_ID 0x8086 -#define UART_NS16550_PORT_0_PCI_DEVICE_ID 0x0936 -#define UART_NS16550_PORT_0_PCI_FUNC 1 -#define UART_NS16550_PORT_0_PCI_BAR 0 - -#define UART_NS16550_PORT_1_PCI_CLASS 0x07 -#define UART_NS16550_PORT_1_PCI_BUS 0 -#define UART_NS16550_PORT_1_PCI_DEV 20 -#define UART_NS16550_PORT_1_PCI_VENDOR_ID 0x8086 -#define UART_NS16550_PORT_1_PCI_DEVICE_ID 0x0936 -#define UART_NS16550_PORT_1_PCI_FUNC 5 -#define UART_NS16550_PORT_1_PCI_BAR 0 - #ifdef CONFIG_IOAPIC #define UART_IRQ_FLAGS (IOAPIC_LEVEL | IOAPIC_LOW) #endif /* CONFIG_IOAPIC */