From f0ac2347daeda7b1f1bf5ae64b3016549ad60029 Mon Sep 17 00:00:00 2001 From: Girisha Dengi Date: Thu, 6 Jul 2023 14:47:06 +0000 Subject: [PATCH] drivers: serial: Add optional reset line for uart_ns16550 If the optional hardware reset line is available, this change will use that reset line to assert the uart module and bring it out of reset state to use. Signed-off-by: Girisha Dengi --- drivers/serial/uart_ns16550.c | 58 +++++++++++++++++++++++++++++++- dts/bindings/serial/ns16550.yaml | 2 +- 2 files changed, 58 insertions(+), 2 deletions(-) diff --git a/drivers/serial/uart_ns16550.c b/drivers/serial/uart_ns16550.c index da5bd79fa53..c7357d076f1 100644 --- a/drivers/serial/uart_ns16550.c +++ b/drivers/serial/uart_ns16550.c @@ -4,7 +4,7 @@ /* * Copyright (c) 2010, 2012-2015 Wind River Systems, Inc. - * Copyright (c) 2020-2022 Intel Corp. + * Copyright (c) 2020-2023 Intel Corp. * * SPDX-License-Identifier: Apache-2.0 */ @@ -39,6 +39,9 @@ #endif #include +#include + +LOG_MODULE_REGISTER(uart_ns16550, CONFIG_UART_LOG_LEVEL); #define INST_HAS_PCP_HELPER(inst) DT_INST_NODE_HAS_PROP(inst, pcp) || #define INST_HAS_DLF_HELPER(inst) DT_INST_NODE_HAS_PROP(inst, dlf) || @@ -53,6 +56,13 @@ BUILD_ASSERT(IS_ENABLED(CONFIG_PCIE), "NS16550(s) in DT need CONFIG_PCIE"); #include #endif +/* Is UART module 'resets' line property defined */ +#define UART_NS16550_RESET_ENABLED DT_ANY_INST_HAS_PROP_STATUS_OKAY(resets) + +#if UART_NS16550_RESET_ENABLED +#include +#endif + /* register definitions */ #define REG_THR 0x00 /* Transmitter holding reg. */ @@ -247,6 +257,9 @@ struct uart_ns16550_device_config { #if defined(CONFIG_UART_NS16550_ACCESS_IOPORT) || defined(CONFIG_UART_NS16550_SIMULT_ACCESS) bool io_map; #endif +#if UART_NS16550_RESET_ENABLED + struct reset_dt_spec reset_spec; +#endif }; /** Device data structure */ @@ -580,6 +593,35 @@ static int uart_ns16550_config_get(const struct device *dev, } #endif /* CONFIG_UART_USE_RUNTIME_CONFIGURE */ +#if UART_NS16550_RESET_ENABLED +/** + * @brief Toggle the reset UART line + * + * This routine is called to bring UART IP out of reset state. + * + * @param reset_spec Reset controller device configuration struct + * + * @return 0 if successful, failed otherwise + */ +static int uart_reset_config(const struct reset_dt_spec *reset_spec) +{ + int ret; + + if (!device_is_ready(reset_spec->dev)) { + LOG_ERR("Reset controller device is not ready"); + return -ENODEV; + } + + ret = reset_line_toggle(reset_spec->dev, reset_spec->id); + if (ret != 0) { + LOG_ERR("UART toggle reset line failed"); + return ret; + } + + return 0; +} +#endif /* UART_NS16550_RESET_ENABLED */ + /** * @brief Initialize individual UART port * @@ -597,6 +639,16 @@ static int uart_ns16550_init(const struct device *dev) ARG_UNUSED(dev_cfg); +#if UART_NS16550_RESET_ENABLED + /* Assert the UART reset line if it is defined. */ + if (dev_cfg->reset_spec.dev != NULL) { + ret = uart_reset_config(&(dev_cfg->reset_spec)); + if (ret != 0) { + return ret; + } + } +#endif + #if DT_ANY_INST_ON_BUS_STATUS_OKAY(pcie) if (dev_cfg->pcie) { struct pcie_bar mbar; @@ -1285,6 +1337,8 @@ static const struct uart_driver_api uart_ns16550_driver_api = { #else #define BOOT_LEVEL(n) PRE_KERNEL_1 #endif +#define UART_RESET_FUNC_INIT(n) \ + .reset_spec = RESET_DT_SPEC_INST_GET(n), #define UART_NS16550_DEVICE_INIT(n) \ UART_NS16550_IRQ_FUNC_DECLARE(n); \ @@ -1310,6 +1364,8 @@ static const struct uart_driver_api uart_ns16550_driver_api = { DEV_CONFIG_PCIE_INIT(n) \ IF_ENABLED(DT_INST_NODE_HAS_PROP(n, pinctrl_0), \ (.pincfg = PINCTRL_DT_DEV_CONFIG_GET(DT_DRV_INST(n)),)) \ + IF_ENABLED(DT_INST_NODE_HAS_PROP(n, resets), \ + (UART_RESET_FUNC_INIT(n))) \ }; \ static struct uart_ns16550_dev_data uart_ns16550_dev_data_##n = { \ .uart_config.baudrate = DT_INST_PROP_OR(n, current_speed, 0), \ diff --git a/dts/bindings/serial/ns16550.yaml b/dts/bindings/serial/ns16550.yaml index 04766ea117b..da315af4271 100644 --- a/dts/bindings/serial/ns16550.yaml +++ b/dts/bindings/serial/ns16550.yaml @@ -2,7 +2,7 @@ description: ns16550 UART compatible: "ns16550" -include: [uart-controller.yaml, pcie-device.yaml, pinctrl-device.yaml] +include: [uart-controller.yaml, pcie-device.yaml, pinctrl-device.yaml, reset-device.yaml] properties: reg-shift: