drivers: serial: Uart ns16550 get clock frequency from clock manager
This patch is to enhance the uart ns16550 driver to get clock frequency from clock manager or devicetree if clock_frequency is defined. Signed-off-by: Teik Heng Chong <teik.heng.chong@intel.com>
This commit is contained in:
parent
89075f42bb
commit
f551c29576
2 changed files with 40 additions and 10 deletions
|
@ -4,7 +4,7 @@
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 2010, 2012-2015 Wind River Systems, Inc.
|
* 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
|
* SPDX-License-Identifier: Apache-2.0
|
||||||
*/
|
*/
|
||||||
|
@ -28,6 +28,7 @@
|
||||||
#include <zephyr/toolchain.h>
|
#include <zephyr/toolchain.h>
|
||||||
#include <zephyr/linker/sections.h>
|
#include <zephyr/linker/sections.h>
|
||||||
#include <zephyr/drivers/uart.h>
|
#include <zephyr/drivers/uart.h>
|
||||||
|
#include <zephyr/drivers/clock_control.h>
|
||||||
#include <zephyr/pm/policy.h>
|
#include <zephyr/pm/policy.h>
|
||||||
#include <zephyr/sys/sys_io.h>
|
#include <zephyr/sys/sys_io.h>
|
||||||
#include <zephyr/spinlock.h>
|
#include <zephyr/spinlock.h>
|
||||||
|
@ -225,6 +226,8 @@ struct uart_ns16550_device_config {
|
||||||
uint32_t port;
|
uint32_t port;
|
||||||
#endif
|
#endif
|
||||||
uint32_t sys_clk_freq;
|
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)
|
#if defined(CONFIG_UART_INTERRUPT_DRIVEN) || defined(CONFIG_UART_ASYNC_API)
|
||||||
uart_irq_config_func_t irq_config_func;
|
uart_irq_config_func_t irq_config_func;
|
||||||
#endif
|
#endif
|
||||||
|
@ -283,19 +286,18 @@ static inline uintptr_t get_port(const struct device *dev)
|
||||||
#endif
|
#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;
|
struct uart_ns16550_dev_data * const dev_data = dev->data;
|
||||||
uint32_t divisor; /* baud rate divisor */
|
uint32_t divisor; /* baud rate divisor */
|
||||||
uint8_t lcr_cache;
|
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
|
* 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;
|
/ baud_rate) >> 4;
|
||||||
|
|
||||||
/* set the DLAB to access the baud rate divisor registers */
|
/* 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;
|
struct uart_ns16550_dev_data * const dev_data = dev->data;
|
||||||
const struct uart_ns16550_device_config * const dev_cfg = dev->config;
|
const struct uart_ns16550_device_config * const dev_cfg = dev->config;
|
||||||
uint8_t mdc = 0U;
|
uint8_t mdc = 0U;
|
||||||
|
uint32_t pclk = 0U;
|
||||||
|
|
||||||
/* temp for return value if error occurs in this locked region */
|
/* temp for return value if error occurs in this locked region */
|
||||||
int ret = 0;
|
int ret = 0;
|
||||||
|
@ -367,7 +370,23 @@ static int uart_ns16550_configure(const struct device *dev,
|
||||||
}
|
}
|
||||||
#endif
|
#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() */
|
/* Local structure to hold temporary values to pass to OUTBYTE() */
|
||||||
struct uart_config uart_cfg;
|
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); \
|
UART_NS16550_IRQ_FUNC_DECLARE(n); \
|
||||||
static const struct uart_ns16550_device_config uart_ns16550_dev_cfg_##n = { \
|
static const struct uart_ns16550_device_config uart_ns16550_dev_cfg_##n = { \
|
||||||
DEV_CONFIG_REG_INIT(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_IRQ_FUNC_INIT(n) \
|
||||||
DEV_CONFIG_PCP_INIT(n) \
|
DEV_CONFIG_PCP_INIT(n) \
|
||||||
.reg_interval = (1 << DT_INST_PROP(n, reg_shift)), \
|
.reg_interval = (1 << DT_INST_PROP(n, reg_shift)), \
|
||||||
|
|
|
@ -1,12 +1,13 @@
|
||||||
/*
|
/*
|
||||||
* SPDX-License-Identifier: Apache-2.0
|
* SPDX-License-Identifier: Apache-2.0
|
||||||
*
|
*
|
||||||
* Copyright (C) 2021, Intel Corporation
|
* Copyright (C) 2021-2022, Intel Corporation
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include <arm64/armv8-a.dtsi>
|
#include <arm64/armv8-a.dtsi>
|
||||||
#include <zephyr/dt-bindings/interrupt-controller/arm-gic.h>
|
#include <zephyr/dt-bindings/interrupt-controller/arm-gic.h>
|
||||||
|
#include <zephyr/dt-bindings/clock/intel_socfpga_clock.h>
|
||||||
|
|
||||||
/ {
|
/ {
|
||||||
cpus {
|
cpus {
|
||||||
|
@ -70,7 +71,7 @@
|
||||||
interrupts = <GIC_SPI 108 IRQ_TYPE_LEVEL
|
interrupts = <GIC_SPI 108 IRQ_TYPE_LEVEL
|
||||||
IRQ_DEFAULT_PRIORITY>;
|
IRQ_DEFAULT_PRIORITY>;
|
||||||
interrupt-names = "irq_0";
|
interrupt-names = "irq_0";
|
||||||
clock-frequency = <100000000>;
|
clocks = <&clock INTEL_SOCFPGA_CLOCK_UART>;
|
||||||
label = "uart_0";
|
label = "uart_0";
|
||||||
status = "disabled";
|
status = "disabled";
|
||||||
};
|
};
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue