From 9f9b4a8afa98e05d0478f5f2c318b665f445bd67 Mon Sep 17 00:00:00 2001 From: Daniel Leung Date: Thu, 21 Sep 2023 17:17:13 -0700 Subject: [PATCH] uart: ns16550: use io-mapped DT property for IO port access The old CONFIG_UART_NS16550_ACCESS_IOPORT has been used to indicate whether to access the NS16550 UART via IO port before device tree is used to describe hardware. Now we have device tree, and we can specify whether a particular UART needs to be accessed via IO port using property io-mapped. Therefore, CONFIG_UART_NS16550_ACCESS_IOPORT is no longer needed (and thus also CONFIG_UART_NS16550_SIMULT_ACCESS). Remove these two kconfigs and modify code to use device tree to figure out how to access the UART hardware. Signed-off-by: Daniel Leung --- arch/x86/core/early_serial.c | 7 ++- boards/x86/intel_adl/Kconfig.defconfig | 7 --- boards/x86/qemu_x86/Kconfig.defconfig | 3 -- boards/x86/qemu_x86/qemu_x86_lakemont.dts | 1 + drivers/serial/Kconfig.ns16550 | 12 ----- drivers/serial/uart_ns16550.c | 61 +++++++++++------------ dts/arc/synopsys/arc_iot.dtsi | 4 ++ dts/x86/intel/alder_lake.dtsi | 1 + dts/x86/intel/atom.dtsi | 2 + dts/x86/intel/ia32.dtsi | 2 + dts/x86/intel/raptor_lake.dtsi | 1 + soc/arc/snps_arc_iot/Kconfig.defconfig | 3 -- soc/x86/atom/Kconfig.defconfig | 3 -- soc/x86/ia32/Kconfig.defconfig | 3 -- soc/x86/raptor_lake/Kconfig.defconfig | 3 -- 15 files changed, 45 insertions(+), 68 deletions(-) diff --git a/arch/x86/core/early_serial.c b/arch/x86/core/early_serial.c index 0c102300a51..572b71cf5a0 100644 --- a/arch/x86/core/early_serial.c +++ b/arch/x86/core/early_serial.c @@ -11,7 +11,10 @@ #include -#ifdef CONFIG_UART_NS16550_ACCESS_IOPORT +#define UART_IS_IOPORT_ACCESS \ + DT_NODE_HAS_PROP(DT_CHOSEN(zephyr_console), io_mapped) + +#if UART_IS_IOPORT_ACCESS /* Legacy I/O Port Access to a NS16550 UART */ #define IN(reg) sys_in8(reg + DT_REG_ADDR(DT_CHOSEN(zephyr_console))) #define OUT(reg, val) sys_out8(val, reg + DT_REG_ADDR(DT_CHOSEN(zephyr_console))) @@ -86,7 +89,7 @@ int arch_printk_char_out(int c) void z_x86_early_serial_init(void) { -#if defined(DEVICE_MMIO_IS_IN_RAM) && !defined(CONFIG_UART_NS16550_ACCESS_IOPORT) +#if defined(DEVICE_MMIO_IS_IN_RAM) && !UART_IS_IOPORT_ACCESS #ifdef X86_SOC_EARLY_SERIAL_PCIDEV struct pcie_bar mbar; pcie_get_mbar(X86_SOC_EARLY_SERIAL_PCIDEV, 0, &mbar); diff --git a/boards/x86/intel_adl/Kconfig.defconfig b/boards/x86/intel_adl/Kconfig.defconfig index 0bc114e4693..9e2255a7471 100644 --- a/boards/x86/intel_adl/Kconfig.defconfig +++ b/boards/x86/intel_adl/Kconfig.defconfig @@ -44,10 +44,3 @@ endif # SHELL endif # ACPI endif # BOARD_INTEL_ADL_CRB || BOARD_INTEL_ADL_RVP - -if BOARD_INTEL_ADL_RVP - -config UART_NS16550_ACCESS_IOPORT - default y if UART_NS16550 - -endif # BOARD_INTEL_ADL_RVP diff --git a/boards/x86/qemu_x86/Kconfig.defconfig b/boards/x86/qemu_x86/Kconfig.defconfig index 1ea60480f64..4ed71964aa3 100644 --- a/boards/x86/qemu_x86/Kconfig.defconfig +++ b/boards/x86/qemu_x86/Kconfig.defconfig @@ -81,9 +81,6 @@ config QEMU_ICOUNT config QEMU_ICOUNT_SHIFT default 5 -config UART_NS16550_ACCESS_IOPORT - default y if UART_NS16550 - endif # BOARD_QEMU_X86_LAKEMONT if BOARD_QEMU_X86_TINY diff --git a/boards/x86/qemu_x86/qemu_x86_lakemont.dts b/boards/x86/qemu_x86/qemu_x86_lakemont.dts index 9c6a6da82ec..87056f9cf65 100644 --- a/boards/x86/qemu_x86/qemu_x86_lakemont.dts +++ b/boards/x86/qemu_x86/qemu_x86_lakemont.dts @@ -40,6 +40,7 @@ uart0: uart@3f8 { compatible = "ns16550"; reg = <0x000003f8 0x100>; + io-mapped; clock-frequency = <1843200>; interrupts = <4 IRQ_TYPE_LOWEST_EDGE_RISING 3>; interrupt-parent = <&intc>; diff --git a/drivers/serial/Kconfig.ns16550 b/drivers/serial/Kconfig.ns16550 index 22988f5f699..90c29046044 100644 --- a/drivers/serial/Kconfig.ns16550 +++ b/drivers/serial/Kconfig.ns16550 @@ -60,18 +60,6 @@ config UART_NS16550_ACCESS_WORD_ONLY 16550 (DesignWare UART) only allows word access, byte access will raise exception. -config UART_NS16550_ACCESS_IOPORT - bool - help - When enabled, NS16550 will not be a memory mapped device. This option - must be selected at SoC/board level if needed. - -config UART_NS16550_SIMULT_ACCESS - bool - help - When enabled, NS16550 supports IO, MMIO, PCIe UART devices simultaneously. - For io-mapped instances, io-mapped DTS property need to be added in dtsi. - config UART_NS16550_PARENT_INIT_LEVEL bool "Boot level based on parent node" default y if ACPI diff --git a/drivers/serial/uart_ns16550.c b/drivers/serial/uart_ns16550.c index 08bcd4a38c1..b0b7f4e1a26 100644 --- a/drivers/serial/uart_ns16550.c +++ b/drivers/serial/uart_ns16550.c @@ -58,6 +58,21 @@ BUILD_ASSERT(IS_ENABLED(CONFIG_PCIE), "NS16550(s) in DT need CONFIG_PCIE"); #include #endif +/* If any node has property io-mapped set, we need to support IO port + * access in the code and device config struct. + * + * Note that DT_ANY_INST_HAS_PROP_STATUS_OKAY() always returns true + * as io-mapped property is considered always exists and present, + * even if its value is zero. Therefore we cannot use it, and has to + * resort to the follow helper to see if any okay nodes have io-mapped + * as 1. + */ +#define UART_NS16550_DT_PROP_IOMAPPED_HELPER(inst, prop, def) \ + DT_INST_PROP_OR(inst, prop, def) || + +#define UART_NS16550_IOPORT_ENABLED \ + (DT_INST_FOREACH_STATUS_OKAY_VARGS(UART_NS16550_DT_PROP_IOMAPPED_HELPER, io_mapped, 0) 0) + /* register definitions */ #define REG_THR 0x00 /* Transmitter holding reg. */ @@ -249,7 +264,7 @@ struct uart_ns16550_device_config { #if defined(CONFIG_PINCTRL) const struct pinctrl_dev_config *pincfg; #endif -#if defined(CONFIG_UART_NS16550_ACCESS_IOPORT) || defined(CONFIG_UART_NS16550_SIMULT_ACCESS) +#if UART_NS16550_IOPORT_ENABLED bool io_map; #endif #if UART_NS16550_RESET_ENABLED @@ -282,7 +297,7 @@ struct uart_ns16550_dev_data { static void ns16550_outbyte(const struct uart_ns16550_device_config *cfg, uintptr_t port, uint8_t val) { -#if defined(CONFIG_UART_NS16550_ACCESS_IOPORT) || defined(CONFIG_UART_NS16550_SIMULT_ACCESS) +#if UART_NS16550_IOPORT_ENABLED if (cfg->io_map) { if (IS_ENABLED(CONFIG_UART_NS16550_ACCESS_WORD_ONLY)) { sys_out32(val, port); @@ -305,7 +320,7 @@ static void ns16550_outbyte(const struct uart_ns16550_device_config *cfg, static uint8_t ns16550_inbyte(const struct uart_ns16550_device_config *cfg, uintptr_t port) { -#if defined(CONFIG_UART_NS16550_ACCESS_IOPORT) || defined(CONFIG_UART_NS16550_SIMULT_ACCESS) +#if UART_NS16550_IOPORT_ENABLED if (cfg->io_map) { if (IS_ENABLED(CONFIG_UART_NS16550_ACCESS_WORD_ONLY)) { return sys_in32(port); @@ -330,7 +345,7 @@ static uint8_t ns16550_inbyte(const struct uart_ns16550_device_config *cfg, static void ns16550_outword(const struct uart_ns16550_device_config *cfg, uintptr_t port, uint32_t val) { -#if defined(CONFIG_UART_NS16550_ACCESS_IOPORT) || defined(CONFIG_UART_NS16550_SIMULT_ACCESS) +#if UART_NS16550_IOPORT_ENABLED if (cfg->io_map) { sys_out32(val, port); } else { @@ -345,7 +360,7 @@ static void ns16550_outword(const struct uart_ns16550_device_config *cfg, static uint32_t ns16550_inword(const struct uart_ns16550_device_config *cfg, uintptr_t port) { -#if defined(CONFIG_UART_NS16550_ACCESS_IOPORT) || defined(CONFIG_UART_NS16550_SIMULT_ACCESS) +#if UART_NS16550_IOPORT_ENABLED if (cfg->io_map) { return sys_in32(port); } @@ -365,7 +380,7 @@ static inline uint8_t reg_interval(const struct device *dev) static inline uintptr_t get_port(const struct device *dev) { uintptr_t port; -#if defined(CONFIG_UART_NS16550_ACCESS_IOPORT) || defined(CONFIG_UART_NS16550_SIMULT_ACCESS) +#if UART_NS16550_IOPORT_ENABLED const struct uart_ns16550_device_config *config = dev->config; if (config->io_map) { @@ -658,7 +673,7 @@ static int uart_ns16550_init(const struct device *dev) } else #endif /* DT_ANY_INST_ON_BUS_STATUS_OKAY(pcie) */ { -#if defined(CONFIG_UART_NS16550_ACCESS_IOPORT) || defined(CONFIG_UART_NS16550_SIMULT_ACCESS) +#if UART_NS16550_IOPORT_ENABLED /* Map directly from DTS */ if (!dev_cfg->io_map) { #else @@ -1257,30 +1272,6 @@ static const struct uart_driver_api uart_ns16550_driver_api = { pcie_irq_enable(dev_cfg->pcie->bdf, irq); \ } -#ifdef CONFIG_UART_NS16550_ACCESS_IOPORT -#define REG_INIT(n) \ - .port = DT_INST_REG_ADDR(n), \ - .io_map = true, -#else -#define REG_INIT_PCIE1(n) -#define REG_INIT_PCIE0(n) DEVICE_MMIO_ROM_INIT(DT_DRV_INST(n)), - -#define DEV_REG_PORT_IO_1(n) \ - .port = DT_INST_REG_ADDR(n), -#define DEV_REG_PORT_IO_0(n) \ - _CONCAT(REG_INIT_PCIE, DT_INST_ON_BUS(n, pcie))(n) -#ifdef CONFIG_UART_NS16550_SIMULT_ACCESS -#define DEV_IO_INIT(n) \ - .io_map = DT_INST_PROP(n, io_mapped), -#else -#define DEV_IO_INIT(n) -#endif - -#define REG_INIT(n) \ - _CONCAT(DEV_REG_PORT_IO_, DT_INST_PROP(n, io_mapped))(n) \ - DEV_IO_INIT(n) -#endif - #ifdef CONFIG_UART_INTERRUPT_DRIVEN #define DEV_CONFIG_IRQ_FUNC_INIT(n) \ .irq_config_func = irq_config_func##n, @@ -1316,7 +1307,13 @@ static const struct uart_driver_api uart_ns16550_driver_api = { IF_ENABLED(DT_INST_NODE_HAS_PROP(n, pinctrl_0), \ (PINCTRL_DT_INST_DEFINE(n))); \ static const struct uart_ns16550_device_config uart_ns16550_dev_cfg_##n = { \ - REG_INIT(n) \ + COND_CODE_0(DT_INST_ON_BUS(n, pcie), \ + (COND_CODE_1(DT_INST_PROP_OR(n, io_mapped, 0), \ + (.port = DT_INST_REG_ADDR(n),), \ + (DEVICE_MMIO_ROM_INIT(DT_DRV_INST(n)),))), \ + ()) \ + IF_ENABLED(DT_INST_PROP_OR(n, io_mapped, 0), \ + (.io_map = true,)) \ COND_CODE_1(DT_INST_NODE_HAS_PROP(n, clock_frequency), ( \ .sys_clk_freq = DT_INST_PROP(n, clock_frequency), \ .clock_dev = NULL, \ diff --git a/dts/arc/synopsys/arc_iot.dtsi b/dts/arc/synopsys/arc_iot.dtsi index 1e8a67d443e..7d04321e0ee 100644 --- a/dts/arc/synopsys/arc_iot.dtsi +++ b/dts/arc/synopsys/arc_iot.dtsi @@ -76,6 +76,7 @@ compatible = "ns16550"; clock-frequency = <16000000>; reg = <0x80014000 0x100>; + io-mapped; interrupts = <86 0>; interrupt-parent = <&intc>; dlf = <0x01>; @@ -86,6 +87,7 @@ compatible = "ns16550"; clock-frequency = <16000000>; reg = <0x80014100 0x100>; + io-mapped; interrupts = <87 0>; interrupt-parent = <&intc>; reg-shift = <2>; @@ -96,6 +98,7 @@ compatible = "ns16550"; clock-frequency = <16000000>; reg = <0x80014200 0x1000>; + io-mapped; interrupts = <88 0>; interrupt-parent = <&intc>; reg-shift = <2>; @@ -106,6 +109,7 @@ compatible = "ns16550"; clock-frequency = <144000000>; reg = <0x80014300 0x100>; + io-mapped; interrupts = <89 0>; interrupt-parent = <&intc>; reg-shift = <2>; diff --git a/dts/x86/intel/alder_lake.dtsi b/dts/x86/intel/alder_lake.dtsi index b0cca7e5200..43f552609a4 100644 --- a/dts/x86/intel/alder_lake.dtsi +++ b/dts/x86/intel/alder_lake.dtsi @@ -239,6 +239,7 @@ uart0_legacy: uart@3f8 { compatible = "ns16550"; reg = <0x000003f8 0x100>; + io-mapped; clock-frequency = <1843200>; interrupts = <4 IRQ_TYPE_LOWEST_EDGE_RISING 3>; interrupt-parent = <&intc>; diff --git a/dts/x86/intel/atom.dtsi b/dts/x86/intel/atom.dtsi index fe8340163ba..f1aee1502df 100644 --- a/dts/x86/intel/atom.dtsi +++ b/dts/x86/intel/atom.dtsi @@ -49,6 +49,7 @@ uart0: uart@3f8 { compatible = "ns16550"; reg = <0x000003f8 0x100>; + io-mapped; clock-frequency = <1843200>; interrupts = <4 IRQ_TYPE_LOWEST_EDGE_RISING 3>; interrupt-parent = <&intc>; @@ -59,6 +60,7 @@ uart1: uart@2f8 { compatible = "ns16550"; reg = <0x000002f8 0x100>; + io-mapped; clock-frequency = <1843200>; interrupts = <3 IRQ_TYPE_LOWEST_EDGE_RISING 3>; interrupt-parent = <&intc>; diff --git a/dts/x86/intel/ia32.dtsi b/dts/x86/intel/ia32.dtsi index 6058fff6123..9d1715aa840 100644 --- a/dts/x86/intel/ia32.dtsi +++ b/dts/x86/intel/ia32.dtsi @@ -51,6 +51,7 @@ uart0: uart@3f8 { compatible = "ns16550"; reg = <0x000003f8 0x100>; + io-mapped; clock-frequency = <1843200>; interrupts = <4 IRQ_TYPE_LOWEST_EDGE_RISING 3>; interrupt-parent = <&intc>; @@ -61,6 +62,7 @@ uart1: uart@2f8 { compatible = "ns16550"; reg = <0x000002f8 0x100>; + io-mapped; clock-frequency = <1843200>; interrupts = <3 IRQ_TYPE_LOWEST_EDGE_RISING 3>; interrupt-parent = <&intc>; diff --git a/dts/x86/intel/raptor_lake.dtsi b/dts/x86/intel/raptor_lake.dtsi index 91a6d933260..bc3c59c2159 100644 --- a/dts/x86/intel/raptor_lake.dtsi +++ b/dts/x86/intel/raptor_lake.dtsi @@ -373,6 +373,7 @@ uart_ec_0: uart@3f8 { compatible = "ns16550"; reg = <0x000003f8 0x100>; + io-mapped; clock-frequency = <1843200>; interrupts = <4 IRQ_TYPE_LOWEST_EDGE_RISING 3>; interrupt-parent = <&intc>; diff --git a/soc/arc/snps_arc_iot/Kconfig.defconfig b/soc/arc/snps_arc_iot/Kconfig.defconfig index 8abaa3382d5..202697a7cf9 100644 --- a/soc/arc/snps_arc_iot/Kconfig.defconfig +++ b/soc/arc/snps_arc_iot/Kconfig.defconfig @@ -34,7 +34,4 @@ config HARVARD config ARC_FIRQ default y -config UART_NS16550_ACCESS_IOPORT - default y - endif # ARC_IOT diff --git a/soc/x86/atom/Kconfig.defconfig b/soc/x86/atom/Kconfig.defconfig index 2658fa7220b..743b43465f4 100644 --- a/soc/x86/atom/Kconfig.defconfig +++ b/soc/x86/atom/Kconfig.defconfig @@ -11,7 +11,4 @@ config SOC config SYS_CLOCK_HW_CYCLES_PER_SEC default 25000000 if HPET_TIMER -config UART_NS16550_ACCESS_IOPORT - default y if UART_NS16550 - endif diff --git a/soc/x86/ia32/Kconfig.defconfig b/soc/x86/ia32/Kconfig.defconfig index cd6f6f20790..87600183a20 100644 --- a/soc/x86/ia32/Kconfig.defconfig +++ b/soc/x86/ia32/Kconfig.defconfig @@ -11,7 +11,4 @@ config SOC config SYS_CLOCK_HW_CYCLES_PER_SEC default 25000000 if HPET_TIMER -config UART_NS16550_ACCESS_IOPORT - default y if UART_NS16550 - endif diff --git a/soc/x86/raptor_lake/Kconfig.defconfig b/soc/x86/raptor_lake/Kconfig.defconfig index 70abc51438b..f9b14da95d0 100644 --- a/soc/x86/raptor_lake/Kconfig.defconfig +++ b/soc/x86/raptor_lake/Kconfig.defconfig @@ -15,7 +15,4 @@ config X86_DYNAMIC_IRQ_STUBS default 16 depends on DYNAMIC_INTERRUPTS -config UART_NS16550_SIMULT_ACCESS - default y if UART_NS16550 - endif # SOC_RAPTOR_LAKE