drivers: serial: add support for Nuvoton series UART
Add Nuvoton numicro series UART support, currently supports only poll mode. UART0 clock and pincontrol are directly configured, will be replace when clock and gpio support is added. Signed-off-by: Saravanan Sekar <saravanan@linumiz.com>
This commit is contained in:
parent
4a5a165e0c
commit
bda358a64f
|
@ -218,6 +218,7 @@
|
|||
/drivers/serial/Kconfig.xlnx @wjliang
|
||||
/drivers/serial/uart_xlnx_ps.c @wjliang
|
||||
/drivers/serial/*xmc4xxx* @parthitce
|
||||
/drivers/serial/*nuvoton* @ssekar15
|
||||
/drivers/net/ @jukkar @tbursztyka
|
||||
/drivers/ptp_clock/ @jukkar
|
||||
/drivers/pwm/*rv32m1* @henrikbrixandersen
|
||||
|
|
|
@ -19,6 +19,7 @@ zephyr_library_sources_if_kconfig(uart_msp432p4xx.c)
|
|||
zephyr_library_sources_ifdef(CONFIG_NRF_UART_PERIPHERAL uart_nrfx_uart.c)
|
||||
zephyr_library_sources_ifdef(CONFIG_NRF_UARTE_PERIPHERAL uart_nrfx_uarte.c)
|
||||
zephyr_library_sources_if_kconfig(uart_nsim.c)
|
||||
zephyr_library_sources_if_kconfig(uart_nuvoton.c)
|
||||
zephyr_library_sources_if_kconfig(uart_sam.c)
|
||||
zephyr_library_sources_if_kconfig(usart_sam.c)
|
||||
zephyr_library_sources_if_kconfig(uart_stellaris.c)
|
||||
|
|
|
@ -110,6 +110,8 @@ source "drivers/serial/Kconfig.leuart_gecko"
|
|||
|
||||
source "drivers/serial/Kconfig.msp432p4xx"
|
||||
|
||||
source "drivers/serial/Kconfig.nuvoton"
|
||||
|
||||
source "drivers/serial/Kconfig.sam0"
|
||||
|
||||
source "drivers/serial/Kconfig.psoc6"
|
||||
|
|
16
drivers/serial/Kconfig.nuvoton
Normal file
16
drivers/serial/Kconfig.nuvoton
Normal file
|
@ -0,0 +1,16 @@
|
|||
# SPDX-License-Identifier: Apache-2.0
|
||||
#
|
||||
# NUVOTON UART configuration
|
||||
#
|
||||
# Copyright (c) 2020 Linumiz
|
||||
# Author: Saravanan Sekar <saravanan@linumiz.com>
|
||||
|
||||
config UART_NUVOTON
|
||||
bool "NUVOTON MCU serial driver"
|
||||
select SERIAL_HAS_DRIVER
|
||||
select HAS_NUMICRO_UART
|
||||
depends on SOC_FAMILY_NUMICRO
|
||||
help
|
||||
This option enables the UART driver for Nuvoton Numicro
|
||||
family of processors.
|
||||
Say y to use serial port on Nuvoton MCU.
|
207
drivers/serial/uart_nuvoton.c
Normal file
207
drivers/serial/uart_nuvoton.c
Normal file
|
@ -0,0 +1,207 @@
|
|||
/*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*
|
||||
* Copyright (c) 2020 Linumiz
|
||||
* Author: Saravanan Sekar <saravanan@linumiz.com>
|
||||
*/
|
||||
|
||||
#include <drivers/uart.h>
|
||||
#include <NuMicro.h>
|
||||
#include <string.h>
|
||||
|
||||
#define DT_DRV_COMPAT nuvoton_numicro_uart
|
||||
|
||||
/* Device data structure */
|
||||
#define DEV_CFG(dev) \
|
||||
((const struct uart_numicro_config * const)(dev)->config_info)
|
||||
|
||||
#define DRV_DATA(dev) \
|
||||
((struct uart_numicro_data * const)(dev)->driver_data)
|
||||
|
||||
#define UART_STRUCT(dev) \
|
||||
((UART_T *)(DEV_CFG(dev))->devcfg.base)
|
||||
|
||||
struct uart_numicro_config {
|
||||
struct uart_device_config devcfg;
|
||||
uint32_t id_rst;
|
||||
uint32_t id_clk;
|
||||
};
|
||||
|
||||
struct uart_numicro_data {
|
||||
struct device *clock;
|
||||
struct uart_config ucfg;
|
||||
};
|
||||
|
||||
static int uart_numicro_poll_in(struct device *dev, unsigned char *c)
|
||||
{
|
||||
uint32_t count;
|
||||
|
||||
count = UART_Read(UART_STRUCT(dev), c, 1);
|
||||
if (!count) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void uart_numicro_poll_out(struct device *dev, unsigned char c)
|
||||
{
|
||||
UART_Write(UART_STRUCT(dev), &c, 1);
|
||||
}
|
||||
|
||||
static int uart_numicro_err_check(struct device *dev)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
static inline int32_t uart_numicro_convert_stopbit(enum uart_config_stop_bits sb)
|
||||
{
|
||||
switch (sb) {
|
||||
case UART_CFG_STOP_BITS_1:
|
||||
return UART_STOP_BIT_1;
|
||||
case UART_CFG_STOP_BITS_1_5:
|
||||
return UART_STOP_BIT_1_5;
|
||||
case UART_CFG_STOP_BITS_2:
|
||||
return UART_STOP_BIT_2;
|
||||
default:
|
||||
return -ENOTSUP;
|
||||
}
|
||||
};
|
||||
|
||||
static inline int32_t uart_numicro_convert_datalen(enum uart_config_data_bits db)
|
||||
{
|
||||
switch (db) {
|
||||
case UART_CFG_DATA_BITS_5:
|
||||
return UART_WORD_LEN_5;
|
||||
case UART_CFG_DATA_BITS_6:
|
||||
return UART_WORD_LEN_6;
|
||||
case UART_CFG_DATA_BITS_7:
|
||||
return UART_WORD_LEN_7;
|
||||
case UART_CFG_DATA_BITS_8:
|
||||
return UART_WORD_LEN_8;
|
||||
default:
|
||||
return -ENOTSUP;
|
||||
}
|
||||
}
|
||||
|
||||
static inline uint32_t uart_numicro_convert_parity(enum uart_config_parity parity)
|
||||
{
|
||||
switch (parity) {
|
||||
case UART_CFG_PARITY_ODD:
|
||||
return UART_PARITY_ODD;
|
||||
case UART_CFG_PARITY_EVEN:
|
||||
return UART_PARITY_EVEN;
|
||||
case UART_CFG_PARITY_MARK:
|
||||
return UART_PARITY_MARK;
|
||||
case UART_CFG_PARITY_SPACE:
|
||||
return UART_PARITY_SPACE;
|
||||
case UART_CFG_PARITY_NONE:
|
||||
default:
|
||||
return UART_PARITY_NONE;
|
||||
}
|
||||
}
|
||||
|
||||
static int uart_numicro_configure(struct device *dev,
|
||||
const struct uart_config *cfg)
|
||||
{
|
||||
struct uart_numicro_data *ddata = DRV_DATA(dev);
|
||||
int32_t databits, stopbits;
|
||||
uint32_t parity;
|
||||
|
||||
databits = uart_numicro_convert_datalen(cfg->data_bits);
|
||||
if (databits < 0) {
|
||||
return databits;
|
||||
}
|
||||
|
||||
stopbits = uart_numicro_convert_stopbit(cfg->stop_bits);
|
||||
if (stopbits < 0) {
|
||||
return stopbits;
|
||||
}
|
||||
|
||||
if (cfg->flow_ctrl == UART_CFG_FLOW_CTRL_NONE) {
|
||||
UART_DisableFlowCtrl(UART_STRUCT(dev));
|
||||
} else if (cfg->flow_ctrl == UART_CFG_FLOW_CTRL_RTS_CTS) {
|
||||
UART_EnableFlowCtrl(UART_STRUCT(dev));
|
||||
} else {
|
||||
return -ENOTSUP;
|
||||
}
|
||||
|
||||
parity = uart_numicro_convert_parity(cfg->parity);
|
||||
|
||||
UART_SetLineConfig(UART_STRUCT(dev), cfg->baudrate, databits,
|
||||
parity, stopbits);
|
||||
|
||||
memcpy(&ddata->ucfg, cfg, sizeof(*cfg));
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int uart_numicro_config_get(struct device *dev, struct uart_config *cfg)
|
||||
{
|
||||
struct uart_numicro_data *ddata = DRV_DATA(dev);
|
||||
|
||||
memcpy(cfg, &ddata->ucfg, sizeof(*cfg));
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int uart_numicro_init(struct device *dev)
|
||||
{
|
||||
const struct uart_numicro_config *config = DEV_CFG(dev);
|
||||
struct uart_numicro_data *ddata = DRV_DATA(dev);
|
||||
|
||||
SYS_ResetModule(config->id_rst);
|
||||
|
||||
SYS_UnlockReg();
|
||||
|
||||
/* Enable UART module clock */
|
||||
CLK_EnableModuleClock(config->id_clk);
|
||||
|
||||
/* Select UART0 clock source is PLL */
|
||||
CLK_SetModuleClock(config->id_clk, CLK_CLKSEL1_UART0SEL_PLL,
|
||||
CLK_CLKDIV0_UART0(0));
|
||||
|
||||
/* Set pinctrl for UART0 RXD and TXD */
|
||||
SYS->GPB_MFPH &= ~(SYS_GPB_MFPH_PB12MFP_Msk | SYS_GPB_MFPH_PB13MFP_Msk);
|
||||
SYS->GPB_MFPH |= (SYS_GPB_MFPH_PB12MFP_UART0_RXD |
|
||||
SYS_GPB_MFPH_PB13MFP_UART0_TXD);
|
||||
|
||||
SYS_LockReg();
|
||||
|
||||
UART_Open(UART_STRUCT(dev), ddata->ucfg.baudrate);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static const struct uart_driver_api uart_numicro_driver_api = {
|
||||
.poll_in = uart_numicro_poll_in,
|
||||
.poll_out = uart_numicro_poll_out,
|
||||
.err_check = uart_numicro_err_check,
|
||||
.configure = uart_numicro_configure,
|
||||
.config_get = uart_numicro_config_get,
|
||||
};
|
||||
|
||||
#define NUMICRO_INIT(index) \
|
||||
\
|
||||
static const struct uart_numicro_config uart_numicro_cfg_##index = { \
|
||||
.devcfg = { \
|
||||
.base = (uint8_t *)DT_INST_REG_ADDR(index), \
|
||||
}, \
|
||||
.id_rst = UART##index##_RST, \
|
||||
.id_clk = UART##index##_MODULE, \
|
||||
}; \
|
||||
\
|
||||
static struct uart_numicro_data uart_numicro_data_##index = { \
|
||||
.ucfg = { \
|
||||
.baudrate = DT_INST_PROP(index, current_speed), \
|
||||
}, \
|
||||
}; \
|
||||
\
|
||||
DEVICE_AND_API_INIT(uart_numicro_##index, DT_INST_LABEL(index), \
|
||||
&uart_numicro_init, \
|
||||
&uart_numicro_data_##index, \
|
||||
&uart_numicro_cfg_##index, \
|
||||
PRE_KERNEL_1, CONFIG_KERNEL_INIT_PRIORITY_DEVICE, \
|
||||
&uart_numicro_driver_api);
|
||||
|
||||
DT_INST_FOREACH_STATUS_OKAY(NUMICRO_INIT)
|
9
dts/bindings/serial/nuvoton,numicro-uart.yaml
Normal file
9
dts/bindings/serial/nuvoton,numicro-uart.yaml
Normal file
|
@ -0,0 +1,9 @@
|
|||
description: NUVOTON NUMICRO FAMILY UART
|
||||
|
||||
compatible: "nuvoton,numicro-uart"
|
||||
|
||||
include: uart-controller.yaml
|
||||
|
||||
properties:
|
||||
reg:
|
||||
required: true
|
Loading…
Reference in a new issue