diff --git a/drivers/serial/uart_ns16550.c b/drivers/serial/uart_ns16550.c index e4a11077c8d..843c0265441 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 Intel Corp. + * Copyright (c) 2020-2022 Intel Corp. * * SPDX-License-Identifier: Apache-2.0 */ @@ -28,6 +28,7 @@ #include #include #include +#include #include #include #include @@ -225,6 +226,8 @@ struct uart_ns16550_device_config { uint32_t port; #endif uint32_t sys_clk_freq; + const struct device *clock_dev; + clock_control_subsys_t clock_subsys; #if defined(CONFIG_UART_INTERRUPT_DRIVEN) || defined(CONFIG_UART_ASYNC_API) uart_irq_config_func_t irq_config_func; #endif @@ -283,19 +286,18 @@ static inline uintptr_t get_port(const struct device *dev) #endif } -static void set_baud_rate(const struct device *dev, uint32_t baud_rate) +static void set_baud_rate(const struct device *dev, uint32_t baud_rate, uint32_t pclk) { - const struct uart_ns16550_device_config * const dev_cfg = dev->config; struct uart_ns16550_dev_data * const dev_data = dev->data; uint32_t divisor; /* baud rate divisor */ uint8_t lcr_cache; - if ((baud_rate != 0U) && (dev_cfg->sys_clk_freq != 0U)) { + if ((baud_rate != 0U) && (pclk != 0U)) { /* * calculate baud rate divisor. a variant of - * (uint32_t)(dev_cfg->sys_clk_freq / (16.0 * baud_rate) + 0.5) + * (uint32_t)(pclk / (16.0 * baud_rate) + 0.5) */ - divisor = ((dev_cfg->sys_clk_freq + (baud_rate << 3)) + divisor = ((pclk + (baud_rate << 3)) / baud_rate) >> 4; /* set the DLAB to access the baud rate divisor registers */ @@ -317,6 +319,7 @@ static int uart_ns16550_configure(const struct device *dev, struct uart_ns16550_dev_data * const dev_data = dev->data; const struct uart_ns16550_device_config * const dev_cfg = dev->config; uint8_t mdc = 0U; + uint32_t pclk = 0U; /* temp for return value if error occurs in this locked region */ int ret = 0; @@ -367,7 +370,23 @@ static int uart_ns16550_configure(const struct device *dev, } #endif - set_baud_rate(dev, cfg->baudrate); + /* + * set clock frequency from clock_frequency property if valid, + * otherwise, get clock frequency from clock manager + */ + if (dev_cfg->sys_clk_freq != 0U) { + pclk = dev_cfg->sys_clk_freq; + } else { + if (dev_cfg->clock_dev == NULL) { + ret = -EINVAL; + goto out; + } + + clock_control_get_rate(dev_cfg->clock_dev, dev_cfg->clock_subsys, + &pclk); + } + + set_baud_rate(dev, cfg->baudrate, pclk); /* Local structure to hold temporary values to pass to OUTBYTE() */ struct uart_config uart_cfg; @@ -1111,7 +1130,17 @@ static const struct uart_driver_api uart_ns16550_driver_api = { UART_NS16550_IRQ_FUNC_DECLARE(n); \ static const struct uart_ns16550_device_config uart_ns16550_dev_cfg_##n = { \ DEV_CONFIG_REG_INIT(n) \ - .sys_clk_freq = DT_INST_PROP(n, clock_frequency), \ + COND_CODE_1(DT_INST_NODE_HAS_PROP(n, clock_frequency), ( \ + .sys_clk_freq = DT_INST_PROP(n, clock_frequency), \ + .clock_dev = NULL, \ + .clock_subsys = NULL, \ + ), ( \ + .sys_clk_freq = 0, \ + .clock_dev = DEVICE_DT_GET(DT_INST_CLOCKS_CTLR(n)), \ + .clock_subsys = (clock_control_subsys_t) DT_INST_PHA(\ + 0, clocks, clkid), \ + ) \ + ) \ DEV_CONFIG_IRQ_FUNC_INIT(n) \ DEV_CONFIG_PCP_INIT(n) \ .reg_interval = (1 << DT_INST_PROP(n, reg_shift)), \ diff --git a/dts/arm64/intel/intel_socfpga_agilex.dtsi b/dts/arm64/intel/intel_socfpga_agilex.dtsi index 1b0323ae75c..6a40282696c 100644 --- a/dts/arm64/intel/intel_socfpga_agilex.dtsi +++ b/dts/arm64/intel/intel_socfpga_agilex.dtsi @@ -1,12 +1,13 @@ /* * SPDX-License-Identifier: Apache-2.0 * - * Copyright (C) 2021, Intel Corporation + * Copyright (C) 2021-2022, Intel Corporation * */ #include #include +#include / { cpus { @@ -70,7 +71,7 @@ interrupts = ; interrupt-names = "irq_0"; - clock-frequency = <100000000>; + clocks = <&clock INTEL_SOCFPGA_CLOCK_UART>; label = "uart_0"; status = "disabled"; };