drivers: uart_pl011: Implemented runtime configure
Implemented runtime configure functions for the driver. Signed-off-by: Lukas Gehreke <lk.gehreke@gmail.com>
This commit is contained in:
parent
95bf346b3b
commit
9e06a8a1e6
1 changed files with 123 additions and 15 deletions
|
@ -9,6 +9,7 @@
|
||||||
#define DT_DRV_COMPAT arm_pl011
|
#define DT_DRV_COMPAT arm_pl011
|
||||||
#define SBSA_COMPAT arm_sbsa_uart
|
#define SBSA_COMPAT arm_sbsa_uart
|
||||||
|
|
||||||
|
#include <string.h>
|
||||||
#include <zephyr/kernel.h>
|
#include <zephyr/kernel.h>
|
||||||
#include <zephyr/arch/cpu.h>
|
#include <zephyr/arch/cpu.h>
|
||||||
#include <zephyr/init.h>
|
#include <zephyr/init.h>
|
||||||
|
@ -44,7 +45,7 @@ struct pl011_config {
|
||||||
/* Device data structure */
|
/* Device data structure */
|
||||||
struct pl011_data {
|
struct pl011_data {
|
||||||
DEVICE_MMIO_RAM;
|
DEVICE_MMIO_RAM;
|
||||||
uint32_t baud_rate; /* Baud rate */
|
struct uart_config uart_cfg;
|
||||||
bool sbsa; /* SBSA mode */
|
bool sbsa; /* SBSA mode */
|
||||||
#ifdef CONFIG_UART_INTERRUPT_DRIVEN
|
#ifdef CONFIG_UART_INTERRUPT_DRIVEN
|
||||||
volatile bool sw_call_txdrdy;
|
volatile bool sw_call_txdrdy;
|
||||||
|
@ -139,6 +140,115 @@ static void pl011_poll_out(const struct device *dev,
|
||||||
get_uart(dev)->dr = (uint32_t)c;
|
get_uart(dev)->dr = (uint32_t)c;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
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;
|
||||||
|
|
||||||
|
if (data->sbsa) {
|
||||||
|
goto out;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (disable) {
|
||||||
|
pl011_disable(dev);
|
||||||
|
pl011_disable_fifo(dev);
|
||||||
|
}
|
||||||
|
|
||||||
|
lcrh = get_uart(dev)->lcr_h & ~(PL011_LCRH_FORMAT_MASK | PL011_LCRH_STP2);
|
||||||
|
|
||||||
|
switch (cfg->parity) {
|
||||||
|
case UART_CFG_PARITY_NONE:
|
||||||
|
lcrh &= ~(BIT(1) | BIT(2));
|
||||||
|
break;
|
||||||
|
case UART_CFG_PARITY_ODD:
|
||||||
|
lcrh |= PL011_LCRH_PARITY_ODD;
|
||||||
|
break;
|
||||||
|
case UART_CFG_PARITY_EVEN:
|
||||||
|
lcrh |= PL011_LCRH_PARTIY_EVEN;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
goto enable;
|
||||||
|
}
|
||||||
|
|
||||||
|
switch (cfg->stop_bits) {
|
||||||
|
case UART_CFG_STOP_BITS_1:
|
||||||
|
lcrh &= ~(PL011_LCRH_STP2);
|
||||||
|
break;
|
||||||
|
case UART_CFG_STOP_BITS_2:
|
||||||
|
lcrh |= PL011_LCRH_STP2;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
goto enable;
|
||||||
|
}
|
||||||
|
|
||||||
|
switch (cfg->data_bits) {
|
||||||
|
case UART_CFG_DATA_BITS_5:
|
||||||
|
lcrh |= PL011_LCRH_WLEN_SIZE(5) << PL011_LCRH_WLEN_SHIFT;
|
||||||
|
break;
|
||||||
|
case UART_CFG_DATA_BITS_6:
|
||||||
|
lcrh |= PL011_LCRH_WLEN_SIZE(6) << PL011_LCRH_WLEN_SHIFT;
|
||||||
|
break;
|
||||||
|
case UART_CFG_DATA_BITS_7:
|
||||||
|
lcrh |= PL011_LCRH_WLEN_SIZE(7) << PL011_LCRH_WLEN_SHIFT;
|
||||||
|
break;
|
||||||
|
case UART_CFG_DATA_BITS_8:
|
||||||
|
lcrh |= PL011_LCRH_WLEN_SIZE(8) << PL011_LCRH_WLEN_SHIFT;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
goto enable;
|
||||||
|
}
|
||||||
|
|
||||||
|
switch (cfg->flow_ctrl) {
|
||||||
|
case UART_CFG_FLOW_CTRL_NONE:
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
goto enable;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Set baud rate */
|
||||||
|
ret = pl011_set_baudrate(dev, config->sys_clk_freq, cfg->baudrate);
|
||||||
|
if (ret != 0) {
|
||||||
|
goto enable;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Update settings */
|
||||||
|
get_uart(dev)->lcr_h = lcrh;
|
||||||
|
|
||||||
|
memcpy(&data->uart_cfg, cfg, sizeof(data->uart_cfg));
|
||||||
|
|
||||||
|
enable:
|
||||||
|
if (disable) {
|
||||||
|
pl011_enable_fifo(dev);
|
||||||
|
pl011_enable(dev);
|
||||||
|
}
|
||||||
|
|
||||||
|
out:
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
#ifdef CONFIG_UART_USE_RUNTIME_CONFIGURE
|
||||||
|
|
||||||
|
static int pl011_runtime_configure(const struct device *dev,
|
||||||
|
const struct uart_config *cfg)
|
||||||
|
{
|
||||||
|
return pl011_runtime_configure_internal(dev, cfg, true);
|
||||||
|
}
|
||||||
|
|
||||||
|
static int pl011_runtime_config_get(const struct device *dev,
|
||||||
|
struct uart_config *cfg)
|
||||||
|
{
|
||||||
|
struct pl011_data *data = dev->data;
|
||||||
|
|
||||||
|
*cfg = data->uart_cfg;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif /* CONFIG_UART_USE_RUNTIME_CONFIGURE */
|
||||||
|
|
||||||
#ifdef CONFIG_UART_INTERRUPT_DRIVEN
|
#ifdef CONFIG_UART_INTERRUPT_DRIVEN
|
||||||
static int pl011_fifo_fill(const struct device *dev,
|
static int pl011_fifo_fill(const struct device *dev,
|
||||||
const uint8_t *tx_data, int len)
|
const uint8_t *tx_data, int len)
|
||||||
|
@ -268,6 +378,10 @@ static void pl011_irq_callback_set(const struct device *dev,
|
||||||
static const struct uart_driver_api pl011_driver_api = {
|
static const struct uart_driver_api pl011_driver_api = {
|
||||||
.poll_in = pl011_poll_in,
|
.poll_in = pl011_poll_in,
|
||||||
.poll_out = pl011_poll_out,
|
.poll_out = pl011_poll_out,
|
||||||
|
#ifdef CONFIG_UART_USE_RUNTIME_CONFIGURE
|
||||||
|
.configure = pl011_runtime_configure,
|
||||||
|
.config_get = pl011_runtime_config_get,
|
||||||
|
#endif
|
||||||
#ifdef CONFIG_UART_INTERRUPT_DRIVEN
|
#ifdef CONFIG_UART_INTERRUPT_DRIVEN
|
||||||
.fifo_fill = pl011_fifo_fill,
|
.fifo_fill = pl011_fifo_fill,
|
||||||
.fifo_read = pl011_fifo_read,
|
.fifo_read = pl011_fifo_read,
|
||||||
|
@ -291,7 +405,6 @@ static int pl011_init(const struct device *dev)
|
||||||
const struct pl011_config *config = dev->config;
|
const struct pl011_config *config = dev->config;
|
||||||
struct pl011_data *data = dev->data;
|
struct pl011_data *data = dev->data;
|
||||||
int ret;
|
int ret;
|
||||||
uint32_t lcrh;
|
|
||||||
|
|
||||||
DEVICE_MMIO_MAP(dev, K_MEM_CACHE_NONE);
|
DEVICE_MMIO_MAP(dev, K_MEM_CACHE_NONE);
|
||||||
|
|
||||||
|
@ -324,18 +437,7 @@ static int pl011_init(const struct device *dev)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Set baud rate */
|
pl011_runtime_configure_internal(dev, &data->uart_cfg, false);
|
||||||
ret = pl011_set_baudrate(dev, config->sys_clk_freq,
|
|
||||||
data->baud_rate);
|
|
||||||
if (ret != 0) {
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Setting the default character format */
|
|
||||||
lcrh = get_uart(dev)->lcr_h & ~(PL011_LCRH_FORMAT_MASK);
|
|
||||||
lcrh &= ~(BIT(0) | BIT(7));
|
|
||||||
lcrh |= PL011_LCRH_WLEN_SIZE(8) << PL011_LCRH_WLEN_SHIFT;
|
|
||||||
get_uart(dev)->lcr_h = lcrh;
|
|
||||||
|
|
||||||
/* Setting transmit and receive interrupt FIFO level */
|
/* Setting transmit and receive interrupt FIFO level */
|
||||||
get_uart(dev)->ifls = FIELD_PREP(PL011_IFLS_TXIFLSEL_M, TXIFLSEL_1_8_FULL)
|
get_uart(dev)->ifls = FIELD_PREP(PL011_IFLS_TXIFLSEL_M, TXIFLSEL_1_8_FULL)
|
||||||
|
@ -439,7 +541,13 @@ void pl011_isr(const struct device *dev)
|
||||||
PL011_CONFIG_PORT(n) \
|
PL011_CONFIG_PORT(n) \
|
||||||
\
|
\
|
||||||
static struct pl011_data pl011_data_port_##n = { \
|
static struct pl011_data pl011_data_port_##n = { \
|
||||||
.baud_rate = DT_INST_PROP(n, current_speed), \
|
.uart_cfg = { \
|
||||||
|
.baudrate = DT_INST_PROP(n, current_speed), \
|
||||||
|
.parity = UART_CFG_PARITY_NONE, \
|
||||||
|
.stop_bits = UART_CFG_STOP_BITS_1, \
|
||||||
|
.data_bits = UART_CFG_DATA_BITS_8, \
|
||||||
|
.flow_ctrl = UART_CFG_FLOW_CTRL_NONE, \
|
||||||
|
}, \
|
||||||
}; \
|
}; \
|
||||||
\
|
\
|
||||||
DEVICE_DT_INST_DEFINE(n, &pl011_init, \
|
DEVICE_DT_INST_DEFINE(n, &pl011_init, \
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue