driver: uart: ns16550: implement configure API

The UART configure API was added to uart.h and this commit
implements the initial framework for the configure API for
the ns16550 uart. This includes the configure() and config_get()
functions and uart device configuration structures of the uart
configure API for the ns16550.

Note this commit does not resolve the pre-existing hard-coded
8-n-1 implementation.

Signed-off-by: Jennifer Williams <jennifer.m.williams@intel.com>
This commit is contained in:
Jennifer Williams 2020-01-03 15:22:47 -08:00 committed by Anas Nashif
commit 3a34db8501
2 changed files with 61 additions and 42 deletions

View file

@ -2,6 +2,7 @@
/*
* Copyright (c) 2010, 2012-2015 Wind River Systems, Inc.
* Copyright (c) 2020 Intel Corp.
*
* SPDX-License-Identifier: Apache-2.0
*/
@ -203,19 +204,21 @@ BUILD_ASSERT_MSG(IS_ENABLED(CONFIG_PCIE), "NS16550(s) in DT need CONFIG_PCIE");
#define DEV_DATA(dev) \
((struct uart_ns16550_dev_data_t *)(dev)->driver_data)
#define THR(dev) (DEV_DATA(dev)->port + REG_THR * UART_REG_ADDR_INTERVAL)
#define RDR(dev) (DEV_DATA(dev)->port + REG_RDR * UART_REG_ADDR_INTERVAL)
#define BRDL(dev) (DEV_DATA(dev)->port + REG_BRDL * UART_REG_ADDR_INTERVAL)
#define BRDH(dev) (DEV_DATA(dev)->port + REG_BRDH * UART_REG_ADDR_INTERVAL)
#define IER(dev) (DEV_DATA(dev)->port + REG_IER * UART_REG_ADDR_INTERVAL)
#define IIR(dev) (DEV_DATA(dev)->port + REG_IIR * UART_REG_ADDR_INTERVAL)
#define FCR(dev) (DEV_DATA(dev)->port + REG_FCR * UART_REG_ADDR_INTERVAL)
#define LCR(dev) (DEV_DATA(dev)->port + REG_LCR * UART_REG_ADDR_INTERVAL)
#define MDC(dev) (DEV_DATA(dev)->port + REG_MDC * UART_REG_ADDR_INTERVAL)
#define LSR(dev) (DEV_DATA(dev)->port + REG_LSR * UART_REG_ADDR_INTERVAL)
#define MSR(dev) (DEV_DATA(dev)->port + REG_MSR * UART_REG_ADDR_INTERVAL)
#define DLF(dev) (DEV_DATA(dev)->port + REG_DLF)
#define PCP(dev) (DEV_DATA(dev)->port + REG_PCP)
#define THR(dev) (DEV_CFG(dev)->devconf.port + REG_THR * UART_REG_ADDR_INTERVAL)
#define RDR(dev) (DEV_CFG(dev)->devconf.port + REG_RDR * UART_REG_ADDR_INTERVAL)
#define BRDL(dev) \
(DEV_CFG(dev)->devconf.port + REG_BRDL * UART_REG_ADDR_INTERVAL)
#define BRDH(dev) \
(DEV_CFG(dev)->devconf.port + REG_BRDH * UART_REG_ADDR_INTERVAL)
#define IER(dev) (DEV_CFG(dev)->devconf.port + REG_IER * UART_REG_ADDR_INTERVAL)
#define IIR(dev) (DEV_CFG(dev)->devconf.port + REG_IIR * UART_REG_ADDR_INTERVAL)
#define FCR(dev) (DEV_CFG(dev)->devconf.port + REG_FCR * UART_REG_ADDR_INTERVAL)
#define LCR(dev) (DEV_CFG(dev)->devconf.port + REG_LCR * UART_REG_ADDR_INTERVAL)
#define MDC(dev) (DEV_CFG(dev)->devconf.port + REG_MDC * UART_REG_ADDR_INTERVAL)
#define LSR(dev) (DEV_CFG(dev)->devconf.port + REG_LSR * UART_REG_ADDR_INTERVAL)
#define MSR(dev) (DEV_CFG(dev)->devconf.port + REG_MSR * UART_REG_ADDR_INTERVAL)
#define DLF(dev) (DEV_CFG(dev)->devconf.port + REG_DLF)
#define PCP(dev) (DEV_CFG(dev)->devconf.port + REG_PCP)
#define IIRC(dev) (DEV_DATA(dev)->iir_cache)
@ -248,14 +251,9 @@ BUILD_ASSERT_MSG(IS_ENABLED(CONFIG_PCIE), "NS16550(s) in DT need CONFIG_PCIE");
#define OUTBYTE(x, d) OUTWORD(x, d)
#endif
/* device config */
struct uart_ns16550_device_config {
u32_t sys_clk_freq;
#ifdef CONFIG_UART_INTERRUPT_DRIVEN
uart_irq_config_func_t irq_config_func;
#endif
struct uart_device_config devconf;
#ifdef UART_NS16550_PCP_ENABLED
u32_t pcp;
#endif
@ -269,8 +267,7 @@ struct uart_ns16550_device_config {
/** Device data structure */
struct uart_ns16550_dev_data_t {
u32_t port;
u32_t baud_rate; /**< Baud rate */
struct uart_config uart_config;
u8_t options; /**< Serial port options */
#ifdef CONFIG_UART_INTERRUPT_DRIVEN
@ -293,12 +290,12 @@ static void set_baud_rate(struct device *dev, u32_t baud_rate)
u32_t divisor; /* baud rate divisor */
u8_t lcr_cache;
if ((baud_rate != 0U) && (dev_cfg->sys_clk_freq != 0U)) {
if ((baud_rate != 0U) && (dev_cfg->devconf.sys_clk_freq != 0U)) {
/*
* calculate baud rate divisor. a variant of
* (u32_t)(dev_cfg->sys_clk_freq / (16.0 * baud_rate) + 0.5)
*/
divisor = ((dev_cfg->sys_clk_freq + (baud_rate << 3))
divisor = ((dev_cfg->devconf.sys_clk_freq + (baud_rate << 3))
/ baud_rate) >> 4;
/* set the DLAB to access the baud rate divisor registers */
@ -310,20 +307,12 @@ static void set_baud_rate(struct device *dev, u32_t baud_rate)
/* restore the DLAB to access the baud rate divisor registers */
OUTBYTE(LCR(dev), lcr_cache);
dev_data->baud_rate = baud_rate;
dev_data->uart_config.baudrate = baud_rate;
}
}
/**
* @brief Initialize individual UART port
*
* This routine is called to reset the chip in a quiescent state.
*
* @param dev UART device struct
*
* @return 0 if successful, failed otherwise
*/
static int uart_ns16550_init(struct device *dev)
static int uart_ns16550_configure(struct device *dev,
const struct uart_config *cfg)
{
struct uart_ns16550_dev_data_t * const dev_data = DEV_DATA(dev);
const struct uart_ns16550_device_config * const dev_cfg = DEV_CFG(dev);
@ -364,7 +353,7 @@ static int uart_ns16550_init(struct device *dev)
}
#endif
set_baud_rate(dev, dev_data->baud_rate);
set_baud_rate(dev, dev_data->uart_config.baudrate);
/* 8 data bits, 1 stop bit, no parity, clear DLAB */
OUTBYTE(LCR(dev), LCR_CS8 | LCR_1_STB | LCR_PDIS);
@ -396,8 +385,36 @@ static int uart_ns16550_init(struct device *dev)
irq_unlock(old_level);
return 0;
};
static int uart_ns16550_config_get(struct device *dev, struct uart_config *cfg)
{
struct uart_ns16550_dev_data_t *data = DEV_DATA(dev);
cfg->baudrate = data->uart_config.baudrate;
cfg->parity = UART_CFG_PARITY_NONE; /* use uart_config_parity */
cfg->stop_bits = UART_CFG_STOP_BITS_1; /* use uart_config_stop_bits */
cfg->data_bits = UART_CFG_DATA_BITS_8; /* use uart_config_data_bits */
cfg->flow_ctrl = UART_CFG_FLOW_CTRL_NONE;/* use uart_config_flow_control */
return 0;
}
/**
* @brief Initialize individual UART port
*
* This routine is called to reset the chip in a quiescent state.
*
* @param dev UART device struct
*
* @return 0 if successful, failed otherwise
*/
static int uart_ns16550_init(struct device *dev)
{
uart_ns16550_configure(dev, &DEV_DATA(dev)->uart_config);
#ifdef CONFIG_UART_INTERRUPT_DRIVEN
DEV_CFG(dev)->irq_config_func(dev);
DEV_CFG(dev)->devconf.irq_config_func(dev);
#endif
return 0;
@ -757,6 +774,8 @@ static const struct uart_driver_api uart_ns16550_driver_api = {
.poll_in = uart_ns16550_poll_in,
.poll_out = uart_ns16550_poll_out,
.err_check = uart_ns16550_err_check,
.configure = uart_ns16550_configure,
.config_get = uart_ns16550_config_get,
#ifdef CONFIG_UART_INTERRUPT_DRIVEN
.fifo_fill = uart_ns16550_fifo_fill,

View file

@ -1,6 +1,6 @@
/*
* Copyright (c) 2010, 2012-2015 Wind River Systems, Inc.
* Copyright (c) 2019 Intel Corp.
* Copyright (c) 2019-2020 Intel Corp.
*
* SPDX-License-Identifier: Apache-2.0
*
@ -12,10 +12,11 @@ static void irq_config_func_@NUM@(struct device *port);
#endif
static const struct uart_ns16550_device_config uart_ns16550_dev_cfg_@NUM@ = {
.sys_clk_freq = DT_UART_NS16550_PORT_@NUM@_CLK_FREQ,
.devconf.port = DT_UART_NS16550_PORT_@NUM@_BASE_ADDR,
.devconf.sys_clk_freq = DT_UART_NS16550_PORT_@NUM@_CLK_FREQ,
#ifdef CONFIG_UART_INTERRUPT_DRIVEN
.irq_config_func = irq_config_func_@NUM@,
.devconf.irq_config_func = irq_config_func_@NUM@,
#endif
#ifdef DT_UART_NS16550_PORT_@NUM@_PCP
@ -30,8 +31,7 @@ static const struct uart_ns16550_device_config uart_ns16550_dev_cfg_@NUM@ = {
};
static struct uart_ns16550_dev_data_t uart_ns16550_dev_data_@NUM@ = {
.port = DT_UART_NS16550_PORT_@NUM@_BASE_ADDR,
.baud_rate = DT_UART_NS16550_PORT_@NUM@_BAUD_RATE,
.uart_config.baudrate = DT_UART_NS16550_PORT_@NUM@_BAUD_RATE,
.options = CONFIG_UART_NS16550_PORT_@NUM@_OPTIONS,
#ifdef DT_UART_NS16550_PORT_@NUM@_DLF