From dd84e8db26dfd7c08cad381f12794679abad3d94 Mon Sep 17 00:00:00 2001 From: TOKITA Hiroshi Date: Thu, 4 Apr 2024 07:10:48 +0900 Subject: [PATCH] drivers: serial: pl011: Use clock control to determine frequency If a clock control device is set in the `clocks` property, it is used to determine the frequency. If `fixed-clock` is set for the clocks, we use that value as is. Signed-off-by: TOKITA Hiroshi --- drivers/serial/uart_pl011.c | 40 +++++++++++++++++++++++++++++-------- 1 file changed, 32 insertions(+), 8 deletions(-) diff --git a/drivers/serial/uart_pl011.c b/drivers/serial/uart_pl011.c index cd8e24fb12f..6b496923536 100644 --- a/drivers/serial/uart_pl011.c +++ b/drivers/serial/uart_pl011.c @@ -24,6 +24,9 @@ #if IS_ENABLED(CONFIG_RESET) #include #endif +#if IS_ENABLED(CONFIG_CLOCK_CONTROL) +#include +#endif #ifdef CONFIG_CPU_CORTEX_M #include @@ -34,13 +37,16 @@ struct pl011_config { DEVICE_MMIO_ROM; - uint32_t sys_clk_freq; #if defined(CONFIG_PINCTRL) const struct pinctrl_dev_config *pincfg; #endif #if IS_ENABLED(CONFIG_RESET) const struct reset_dt_spec reset; #endif +#if IS_ENABLED(CONFIG_CLOCK_CONTROL) + const struct device *clock_dev; + clock_control_subsys_t clock_id; +#endif #ifdef CONFIG_UART_INTERRUPT_DRIVEN uart_irq_config_func_t irq_config_func; #endif @@ -53,6 +59,7 @@ struct pl011_data { DEVICE_MMIO_RAM; struct uart_config uart_cfg; bool sbsa; /* SBSA mode */ + uint32_t clk_freq; #ifdef CONFIG_UART_INTERRUPT_DRIVEN volatile bool sw_call_txdrdy; uart_irq_callback_user_data_t irq_cb; @@ -150,7 +157,6 @@ static int pl011_runtime_configure_internal(const struct device *dev, const struct uart_config *cfg, bool disable) { - const struct pl011_config *config = dev->config; struct pl011_data *data = dev->data; uint32_t lcrh; int ret = -ENOTSUP; @@ -216,7 +222,7 @@ static int pl011_runtime_configure_internal(const struct device *dev, } /* Set baud rate */ - ret = pl011_set_baudrate(dev, config->sys_clk_freq, cfg->baudrate); + ret = pl011_set_baudrate(dev, data->clk_freq, cfg->baudrate); if (ret != 0) { goto enable; } @@ -423,6 +429,13 @@ static int pl011_init(const struct device *dev) } #endif +#if IS_ENABLED(CONFIG_CLOCK_CONTROL) + if (config->clock_dev) { + clock_control_on(config->clock_dev, config->clock_id); + clock_control_get_rate(config->clock_dev, config->clock_id, &data->clk_freq); + } +#endif + /* * If working in SBSA mode, we assume that UART is already configured, * or does not require configuration at all (if UART is emulated by @@ -446,7 +459,7 @@ static int pl011_init(const struct device *dev) /* Call vendor-specific function to enable clock for the peripheral */ if (config->clk_enable_func != NULL) { - ret = config->clk_enable_func(dev, config->sys_clk_freq); + ret = config->clk_enable_func(dev, data->clk_freq); if (ret) { return ret; } @@ -511,6 +524,8 @@ static int pl011_init(const struct device *dev) #define COMPAT_SPECIFIC_DEFINE(n) \ _CONCAT(DT_INST_STRING_UPPER_TOKEN_BY_IDX(n, compatible, 0), _DEFINE)(n) +#define COMPAT_SPECIFIC_CLOCK_CTLR_SUBSYS_CELL(n) \ + _CONCAT(DT_INST_STRING_UPPER_TOKEN_BY_IDX(n, compatible, 0), _CLOCK_CTLR_SUBSYS_CELL) #if defined(CONFIG_PINCTRL) #define PINCTRL_DEFINE(n) PINCTRL_DT_INST_DEFINE(n); @@ -527,6 +542,12 @@ static int pl011_init(const struct device *dev) #define RESET_INIT(n) #endif +#define CLOCK_INIT(n) \ + COND_CODE_1(DT_NODE_HAS_COMPAT(DT_INST_CLOCKS_CTLR(n), fixed_clock), (), \ + (.clock_dev = DEVICE_DT_GET(DT_INST_CLOCKS_CTLR(n)), \ + .clock_id = (clock_control_subsys_t)DT_INST_CLOCKS_CELL(n, \ + COMPAT_SPECIFIC_CLOCK_CTLR_SUBSYS_CELL(n)),)) + #define ARM_PL011_DEFINE(n) \ static inline int pwr_on_arm_pl011_##n(void) \ { \ @@ -569,8 +590,8 @@ void pl011_isr(const struct device *dev) \ static struct pl011_config pl011_cfg_port_##n = { \ DEVICE_MMIO_ROM_INIT(DT_DRV_INST(n)), \ - .sys_clk_freq = DT_INST_PROP_BY_PHANDLE(n, clocks, clock_frequency), \ - PINCTRL_INIT(n) \ + CLOCK_INIT(n) \ + PINCTRL_INIT(n) \ .irq_config_func = pl011_irq_config_func_##n, \ .clk_enable_func = COMPAT_SPECIFIC_CLK_ENABLE_FUNC(n), \ .pwr_on_func = COMPAT_SPECIFIC_PWR_ON_FUNC(n), \ @@ -579,8 +600,8 @@ void pl011_isr(const struct device *dev) #define PL011_CONFIG_PORT(n) \ static struct pl011_config pl011_cfg_port_##n = { \ DEVICE_MMIO_ROM_INIT(DT_DRV_INST(n)), \ - .sys_clk_freq = DT_INST_PROP_BY_PHANDLE(n, clocks, clock_frequency), \ - PINCTRL_INIT(n) \ + CLOCK_INIT(n) \ + PINCTRL_INIT(n) \ }; #endif /* CONFIG_UART_INTERRUPT_DRIVEN */ @@ -597,6 +618,9 @@ void pl011_isr(const struct device *dev) .data_bits = UART_CFG_DATA_BITS_8, \ .flow_ctrl = UART_CFG_FLOW_CTRL_NONE, \ }, \ + .clk_freq = COND_CODE_1( \ + DT_NODE_HAS_COMPAT(DT_INST_CLOCKS_CTLR(n), fixed_clock), \ + (DT_INST_PROP_BY_PHANDLE(n, clocks, clock_frequency)), (0)), \ }; \ \ DEVICE_DT_INST_DEFINE(n, &pl011_init, \