drivers: serial: Add Intel SEDI driver
Adds a new serial shim driver for Intel SoCs. Builds upon the SEDI bare metal UART driver in the hal-intel module. Signed-off-by: Nachiketa Kumar <nachiketa.kumar@intel.com> Signed-off-by: Dong Wang <dong.d.wang@intel.com>
This commit is contained in:
parent
4e3ec6207d
commit
9f6d6a0fa7
|
@ -63,6 +63,7 @@ zephyr_library_sources_ifdef(CONFIG_UART_HOSTLINK uart_hostlink.c)
|
|||
zephyr_library_sources_ifdef(CONFIG_UART_EMUL uart_emul.c)
|
||||
zephyr_library_sources_ifdef(CONFIG_UART_NUMAKER uart_numaker.c)
|
||||
zephyr_library_sources_ifdef(CONFIG_UART_EFINIX_SAPPIHIRE uart_efinix_sapphire.c)
|
||||
zephyr_library_sources_ifdef(CONFIG_UART_SEDI uart_sedi.c)
|
||||
|
||||
zephyr_library_sources_ifdef(CONFIG_USERSPACE uart_handlers.c)
|
||||
|
||||
|
|
|
@ -239,4 +239,6 @@ source "drivers/serial/Kconfig.numaker"
|
|||
|
||||
source "drivers/serial/Kconfig.efinix_sapphire"
|
||||
|
||||
source "drivers/serial/Kconfig.sedi"
|
||||
|
||||
endif # SERIAL
|
||||
|
|
15
drivers/serial/Kconfig.sedi
Normal file
15
drivers/serial/Kconfig.sedi
Normal file
|
@ -0,0 +1,15 @@
|
|||
# Copyright (c) 2023 Intel Corporation
|
||||
#
|
||||
# SPDX-License-Identifier: Apache-2.0
|
||||
#
|
||||
|
||||
config UART_SEDI
|
||||
bool "Intel SEDI UART driver"
|
||||
default y
|
||||
depends on DT_HAS_INTEL_SEDI_UART_ENABLED
|
||||
select SERIAL_HAS_DRIVER
|
||||
select SERIAL_SUPPORT_INTERRUPT
|
||||
help
|
||||
This option enables the Intel SEDI UART driver.
|
||||
This driver is simply a shim driver built upon the SEDI
|
||||
bare metal UART driver in the hal-intel module
|
597
drivers/serial/uart_sedi.c
Normal file
597
drivers/serial/uart_sedi.c
Normal file
|
@ -0,0 +1,597 @@
|
|||
/*
|
||||
* Copyright (c) 2023 Intel Corporation.
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
#include <errno.h>
|
||||
#include <zephyr/device.h>
|
||||
#include <zephyr/drivers/uart.h>
|
||||
#include <zephyr/pm/device.h>
|
||||
#include "sedi_driver_uart.h"
|
||||
|
||||
#ifdef CONFIG_UART_INTERRUPT_DRIVEN
|
||||
static void uart_sedi_isr(void *arg);
|
||||
static void uart_sedi_cb(struct device *port);
|
||||
#endif
|
||||
|
||||
#define DT_DRV_COMPAT intel_sedi_uart
|
||||
|
||||
/* Helper macro to set flow control. */
|
||||
#define UART_CONFIG_FLOW_CTRL_SET(n) \
|
||||
.hw_fc = DT_INST_PROP(n, hw_flow_control)
|
||||
|
||||
/* Helper macro to set line control. */
|
||||
#define UART_CONFIG_LINE_CTRL_SET \
|
||||
.line_ctrl = SEDI_UART_LC_8N1
|
||||
|
||||
#ifdef CONFIG_UART_INTERRUPT_DRIVEN
|
||||
/* UART IRQ handler declaration. */
|
||||
#define UART_IRQ_HANDLER_DECL(n) \
|
||||
static void irq_config_uart_##n(const struct device *dev)
|
||||
|
||||
/* Setting configuration function. */
|
||||
#define UART_CONFIG_IRQ_HANDLER_SET(n) \
|
||||
.uart_irq_config_func = irq_config_uart_##n
|
||||
#define UART_IRQ_HANDLER_DEFINE(n) \
|
||||
static void irq_config_uart_##n(const struct device *dev) \
|
||||
{ \
|
||||
ARG_UNUSED(dev); \
|
||||
IRQ_CONNECT(DT_INST_IRQN(n), \
|
||||
DT_INST_IRQ(n, priority), uart_sedi_isr, \
|
||||
DEVICE_DT_GET(DT_NODELABEL(uart##n)), \
|
||||
DT_INST_IRQ(n, sense)); \
|
||||
irq_enable(DT_INST_IRQN(n)); \
|
||||
}
|
||||
#else /*CONFIG_UART_INTERRUPT_DRIVEN */
|
||||
#define UART_IRQ_HANDLER_DECL(n)
|
||||
#define UART_CONFIG_IRQ_HANDLER_SET(n) (0)
|
||||
|
||||
#define UART_IRQ_HANDLER_DEFINE(n)
|
||||
#endif /* !CONFIG_UART_INTERRUPT_DRIVEN */
|
||||
|
||||
/* Device init macro for UART instance. As multiple uart instances follow a
|
||||
* similar definition of data structures differing only in the instance
|
||||
* number.This macro makes adding instances simpler.
|
||||
*/
|
||||
#define UART_SEDI_DEVICE_INIT(n) \
|
||||
UART_IRQ_HANDLER_DECL(n); \
|
||||
static K_MUTEX_DEFINE(uart_##n##_mutex); \
|
||||
static K_SEM_DEFINE(uart_##n##_tx_sem, 1, 1); \
|
||||
static K_SEM_DEFINE(uart_##n##_rx_sem, 1, 1); \
|
||||
static K_SEM_DEFINE(uart_##n##_sync_read_sem, 0, 1); \
|
||||
static const struct uart_sedi_config_info config_info_##n = { \
|
||||
DEVICE_MMIO_ROM_INIT(DT_DRV_INST(n)), \
|
||||
.instance = SEDI_UART_##n, \
|
||||
.baud_rate = DT_INST_PROP(n, current_speed), \
|
||||
UART_CONFIG_FLOW_CTRL_SET(n), \
|
||||
UART_CONFIG_LINE_CTRL_SET, \
|
||||
.mutex = &uart_##n##_mutex, \
|
||||
.tx_sem = &uart_##n##_tx_sem, \
|
||||
.rx_sem = &uart_##n##_rx_sem, \
|
||||
.sync_read_sem = &uart_##n##_sync_read_sem, \
|
||||
UART_CONFIG_IRQ_HANDLER_SET(n) \
|
||||
}; \
|
||||
\
|
||||
static struct uart_sedi_drv_data drv_data_##n; \
|
||||
PM_DEVICE_DT_DEFINE(DT_NODELABEL(uart##n), \
|
||||
uart_sedi_pm_action); \
|
||||
DEVICE_DT_DEFINE(DT_NODELABEL(uart##n), \
|
||||
&uart_sedi_init, \
|
||||
PM_DEVICE_DT_GET(DT_NODELABEL(uart##n)), \
|
||||
&drv_data_##n, &config_info_##n, \
|
||||
PRE_KERNEL_1, \
|
||||
CONFIG_SERIAL_INIT_PRIORITY, &api); \
|
||||
UART_IRQ_HANDLER_DEFINE(n)
|
||||
|
||||
|
||||
|
||||
/* Convenient macro to get the controller instance. */
|
||||
#define GET_CONTROLLER_INSTANCE(dev) \
|
||||
(((const struct uart_sedi_config_info *) \
|
||||
dev->config)->instance)
|
||||
|
||||
/* Convenient macro to get tx semamphore */
|
||||
#define GET_TX_SEM(dev) \
|
||||
(((const struct uart_sedi_config_info *) \
|
||||
dev->config)->tx_sem)
|
||||
|
||||
|
||||
/* Convenient macro to get rx sempahore */
|
||||
#define GET_RX_SEM(dev) \
|
||||
(((const struct uart_sedi_config_info *) \
|
||||
dev->config)->rx_sem)
|
||||
|
||||
/* Convenient macro to get sync_read sempahore */
|
||||
#define GET_SYNC_READ_SEM(dev) \
|
||||
(((const struct uart_sedi_config_info *) \
|
||||
dev->config)->sync_read_sem)
|
||||
|
||||
#define GET_MUTEX(dev) \
|
||||
(((const struct uart_sedi_config_info *) \
|
||||
dev->config)->mutex)
|
||||
|
||||
struct uart_sedi_config_info {
|
||||
DEVICE_MMIO_ROM;
|
||||
/* Specifies the uart instance for configuration. */
|
||||
sedi_uart_t instance;
|
||||
|
||||
/* Specifies the baudrate for the uart instance. */
|
||||
uint32_t baud_rate;
|
||||
|
||||
/* Specifies the port line contorl settings */
|
||||
sedi_uart_lc_t line_ctrl;
|
||||
|
||||
struct k_mutex *mutex;
|
||||
struct k_sem *tx_sem;
|
||||
struct k_sem *rx_sem;
|
||||
struct k_sem *sync_read_sem;
|
||||
/* Enable / disable hardware flow control for UART. */
|
||||
|
||||
bool hw_fc;
|
||||
|
||||
/* UART irq configuration function when supporting interrupt
|
||||
* mode.
|
||||
*/
|
||||
uart_irq_config_func_t uart_irq_config_func;
|
||||
};
|
||||
|
||||
|
||||
static int uart_sedi_init(const struct device *dev);
|
||||
|
||||
struct uart_sedi_drv_data {
|
||||
DEVICE_MMIO_RAM;
|
||||
uart_irq_callback_user_data_t user_cb;
|
||||
void *unsol_rx_usr_cb_param;
|
||||
uint32_t sync_rx_len;
|
||||
uint32_t sync_rx_status;
|
||||
void *user_data;
|
||||
void *usr_rx_buff;
|
||||
uint32_t usr_rx_size;
|
||||
uint8_t iir_cache;
|
||||
uint8_t busy_count;
|
||||
};
|
||||
|
||||
#ifdef CONFIG_UART_INTERRUPT_DRIVEN
|
||||
static void uart_busy_set(const struct device *dev)
|
||||
{
|
||||
|
||||
struct uart_sedi_drv_data *context = dev->data;
|
||||
|
||||
context->busy_count++;
|
||||
|
||||
if (context->busy_count == 1) {
|
||||
pm_device_busy_set(dev);
|
||||
}
|
||||
}
|
||||
|
||||
static void uart_busy_clear(const struct device *dev)
|
||||
{
|
||||
|
||||
struct uart_sedi_drv_data *context = dev->data;
|
||||
|
||||
context->busy_count--;
|
||||
|
||||
if (context->busy_count == 0) {
|
||||
pm_device_busy_clear(dev);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_PM_DEVICE
|
||||
|
||||
#ifndef CONFIG_UART_CONSOLE
|
||||
|
||||
static int uart_suspend_device(const struct device *dev)
|
||||
{
|
||||
const struct uart_sedi_config_info *config = dev->config;
|
||||
|
||||
if (pm_device_is_busy(dev)) {
|
||||
return -EBUSY;
|
||||
}
|
||||
|
||||
int ret = sedi_uart_set_power(config->instance, SEDI_POWER_SUSPEND);
|
||||
|
||||
if (ret != SEDI_DRIVER_OK) {
|
||||
return -EIO;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int uart_resume_device_from_suspend(const struct device *dev)
|
||||
{
|
||||
const struct uart_sedi_config_info *config = dev->config;
|
||||
int ret;
|
||||
|
||||
ret = sedi_uart_set_power(config->instance, SEDI_POWER_FULL);
|
||||
if (ret != SEDI_DRIVER_OK) {
|
||||
return -EIO;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int uart_sedi_pm_action(const struct device *dev,
|
||||
enum pm_device_action action)
|
||||
{
|
||||
int ret = 0;
|
||||
|
||||
switch (action) {
|
||||
case PM_DEVICE_ACTION_SUSPEND:
|
||||
ret = uart_suspend_device(dev);
|
||||
break;
|
||||
case PM_DEVICE_ACTION_RESUME:
|
||||
ret = uart_resume_device_from_suspend(dev);
|
||||
break;
|
||||
|
||||
default:
|
||||
ret = -ENOTSUP;
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
#else
|
||||
|
||||
static int uart_sedi_pm_action(const struct device *dev,
|
||||
enum pm_device_action action)
|
||||
{
|
||||
/* do nothing if using UART print log to avoid clock gating
|
||||
* pm driver already handled power management for uart.
|
||||
*/
|
||||
return 0;
|
||||
}
|
||||
|
||||
#endif /* CONFIG_UART_CONSOLE */
|
||||
|
||||
#endif /* CONFIG_PM_DEVICE */
|
||||
|
||||
static int uart_sedi_poll_in(const struct device *dev, unsigned char *data)
|
||||
{
|
||||
sedi_uart_t instance = GET_CONTROLLER_INSTANCE(dev);
|
||||
uint32_t status;
|
||||
int ret = 0;
|
||||
|
||||
sedi_uart_get_status(instance, (uint32_t *) &status);
|
||||
|
||||
/* In order to check if there is any data to read from UART
|
||||
* controller we should check if the SEDI_UART_RX_BUSY bit from
|
||||
* 'status' is not set. This bit is set only if there is any
|
||||
* pending character to read.
|
||||
*/
|
||||
if (!(status & SEDI_UART_RX_BUSY)) {
|
||||
ret = -1;
|
||||
} else {
|
||||
if (sedi_uart_read(instance, data, (uint32_t *)&status)) {
|
||||
ret = -1;
|
||||
}
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
static void uart_sedi_poll_out(const struct device *dev,
|
||||
unsigned char data)
|
||||
{
|
||||
sedi_uart_t instance = GET_CONTROLLER_INSTANCE(dev);
|
||||
|
||||
sedi_uart_write(instance, data);
|
||||
}
|
||||
|
||||
#ifdef CONFIG_UART_LINE_CTRL
|
||||
static int get_xfer_error(int bsp_err)
|
||||
{
|
||||
int err;
|
||||
|
||||
switch (bsp_err) {
|
||||
case SEDI_DRIVER_OK:
|
||||
err = 0;
|
||||
break;
|
||||
case SEDI_USART_ERROR_CANCELED:
|
||||
err = -ECANCELED;
|
||||
break;
|
||||
case SEDI_DRIVER_ERROR:
|
||||
err = -EIO;
|
||||
break;
|
||||
case SEDI_DRIVER_ERROR_PARAMETER:
|
||||
err = -EINVAL;
|
||||
break;
|
||||
case SEDI_DRIVER_ERROR_UNSUPPORTED:
|
||||
err = -ENOTSUP;
|
||||
break;
|
||||
default:
|
||||
err = -EFAULT;
|
||||
}
|
||||
return err;
|
||||
}
|
||||
#endif /* CONFIG_UART_LINE_CTRL */
|
||||
|
||||
static int uart_sedi_err_check(const struct device *dev)
|
||||
{
|
||||
sedi_uart_t instance = GET_CONTROLLER_INSTANCE(dev);
|
||||
uint32_t status;
|
||||
int ret_status = 0;
|
||||
|
||||
sedi_uart_get_status(instance, (uint32_t *const)&status);
|
||||
if (status & SEDI_UART_RX_OE) {
|
||||
ret_status = UART_ERROR_OVERRUN;
|
||||
}
|
||||
|
||||
if (status & SEDI_UART_RX_PE) {
|
||||
ret_status = UART_ERROR_PARITY;
|
||||
}
|
||||
|
||||
if (status & SEDI_UART_RX_FE) {
|
||||
ret_status = UART_ERROR_FRAMING;
|
||||
}
|
||||
|
||||
if (status & SEDI_UART_RX_BI) {
|
||||
ret_status = UART_BREAK;
|
||||
}
|
||||
|
||||
return ret_status;
|
||||
}
|
||||
|
||||
|
||||
#ifdef CONFIG_UART_INTERRUPT_DRIVEN
|
||||
|
||||
static int uart_sedi_fifo_fill(const struct device *dev, const uint8_t *tx_data,
|
||||
int size)
|
||||
{
|
||||
sedi_uart_t instance = GET_CONTROLLER_INSTANCE(dev);
|
||||
|
||||
return sedi_uart_fifo_fill(instance, tx_data, size);
|
||||
}
|
||||
|
||||
static int uart_sedi_fifo_read(const struct device *dev, uint8_t *rx_data,
|
||||
const int size)
|
||||
{
|
||||
sedi_uart_t instance = GET_CONTROLLER_INSTANCE(dev);
|
||||
|
||||
return sedi_uart_fifo_read(instance, rx_data, size);
|
||||
}
|
||||
|
||||
static void uart_sedi_irq_tx_enable(const struct device *dev)
|
||||
{
|
||||
sedi_uart_t instance = GET_CONTROLLER_INSTANCE(dev);
|
||||
|
||||
sedi_uart_irq_tx_enable(instance);
|
||||
}
|
||||
|
||||
static void uart_sedi_irq_tx_disable(const struct device *dev)
|
||||
{
|
||||
sedi_uart_t instance = GET_CONTROLLER_INSTANCE(dev);
|
||||
|
||||
sedi_uart_irq_tx_disable(instance);
|
||||
}
|
||||
|
||||
static int uart_sedi_irq_tx_ready(const struct device *dev)
|
||||
{
|
||||
sedi_uart_t instance = GET_CONTROLLER_INSTANCE(dev);
|
||||
|
||||
return sedi_uart_irq_tx_ready(instance);
|
||||
}
|
||||
|
||||
static int uart_sedi_irq_tx_complete(const struct device *dev)
|
||||
{
|
||||
sedi_uart_t instance = GET_CONTROLLER_INSTANCE(dev);
|
||||
|
||||
return sedi_uart_is_tx_complete(instance);
|
||||
}
|
||||
|
||||
static void uart_sedi_irq_rx_enable(const struct device *dev)
|
||||
{
|
||||
sedi_uart_t instance = GET_CONTROLLER_INSTANCE(dev);
|
||||
|
||||
uart_busy_set(dev);
|
||||
sedi_uart_irq_rx_enable(instance);
|
||||
}
|
||||
|
||||
static void uart_sedi_irq_rx_disable(const struct device *dev)
|
||||
{
|
||||
sedi_uart_t instance = GET_CONTROLLER_INSTANCE(dev);
|
||||
|
||||
sedi_uart_irq_rx_disable(instance);
|
||||
uart_busy_clear(dev);
|
||||
}
|
||||
|
||||
static int uart_sedi_irq_rx_ready(const struct device *dev)
|
||||
{
|
||||
sedi_uart_t instance = GET_CONTROLLER_INSTANCE(dev);
|
||||
|
||||
return sedi_uart_is_irq_rx_ready(instance);
|
||||
}
|
||||
|
||||
static void uart_sedi_irq_err_enable(const struct device *dev)
|
||||
{
|
||||
sedi_uart_t instance = GET_CONTROLLER_INSTANCE(dev);
|
||||
|
||||
sedi_uart_irq_err_enable(instance);
|
||||
}
|
||||
|
||||
static void uart_sedi_irq_err_disable(const struct device *dev)
|
||||
{
|
||||
sedi_uart_t instance = GET_CONTROLLER_INSTANCE(dev);
|
||||
|
||||
sedi_uart_irq_err_disable(instance);
|
||||
}
|
||||
|
||||
static int uart_sedi_irq_is_pending(const struct device *dev)
|
||||
{
|
||||
|
||||
sedi_uart_t instance = GET_CONTROLLER_INSTANCE(dev);
|
||||
|
||||
return sedi_uart_is_irq_pending(instance);
|
||||
}
|
||||
|
||||
static int uart_sedi_irq_update(const struct device *dev)
|
||||
{
|
||||
sedi_uart_t instance = GET_CONTROLLER_INSTANCE(dev);
|
||||
|
||||
sedi_uart_update_irq_cache(instance);
|
||||
return 1;
|
||||
}
|
||||
|
||||
static void uart_sedi_irq_callback_set(const struct device *dev,
|
||||
uart_irq_callback_user_data_t cb,
|
||||
void *user_data)
|
||||
{
|
||||
struct uart_sedi_drv_data *drv_data = dev->data;
|
||||
|
||||
drv_data->user_cb = cb;
|
||||
drv_data->user_data = user_data;
|
||||
|
||||
}
|
||||
|
||||
static void uart_sedi_isr(void *arg)
|
||||
{
|
||||
struct device *dev = arg;
|
||||
struct uart_sedi_drv_data *drv_data = dev->data;
|
||||
|
||||
if (drv_data->user_cb) {
|
||||
drv_data->user_cb(dev, drv_data->user_data);
|
||||
} else {
|
||||
uart_sedi_cb(dev);
|
||||
}
|
||||
}
|
||||
|
||||
/* Called from generic callback of zephyr , set by set_cb. */
|
||||
static void uart_sedi_cb(struct device *port)
|
||||
{
|
||||
sedi_uart_t instance = GET_CONTROLLER_INSTANCE(port);
|
||||
|
||||
sedi_uart_isr_handler(instance);
|
||||
}
|
||||
|
||||
#endif /* CONFIG_UART_INTERRUPT_DRIVEN */
|
||||
|
||||
#ifdef CONFIG_UART_LINE_CTRL
|
||||
static int uart_sedi_line_ctrl_set(struct device *dev,
|
||||
uint32_t ctrl, uint32_t val)
|
||||
{
|
||||
sedi_uart_t instance = GET_CONTROLLER_INSTANCE(dev);
|
||||
sedi_uart_config_t cfg;
|
||||
uint32_t mask;
|
||||
int ret;
|
||||
|
||||
k_mutex_lock(GET_MUTEX(dev), K_FOREVER);
|
||||
switch (ctrl) {
|
||||
case UART_LINE_CTRL_BAUD_RATE:
|
||||
sedi_uart_get_config(instance, &cfg);
|
||||
cfg.baud_rate = val;
|
||||
ret = sedi_uart_set_config(instance, &cfg);
|
||||
break;
|
||||
|
||||
default:
|
||||
ret = -ENODEV;
|
||||
}
|
||||
k_mutex_unlock(GET_MUTEX(dev));
|
||||
ret = get_xfer_error(ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int uart_sedi_line_ctrl_get(struct device *dev,
|
||||
uint32_t ctrl, uint32_t *val)
|
||||
{
|
||||
sedi_uart_t instance = GET_CONTROLLER_INSTANCE(dev);
|
||||
sedi_uart_config_t cfg;
|
||||
uint32_t mask;
|
||||
int ret;
|
||||
|
||||
k_mutex_lock(GET_MUTEX(dev), K_FOREVER);
|
||||
switch (ctrl) {
|
||||
case UART_LINE_CTRL_BAUD_RATE:
|
||||
ret = sedi_uart_get_config(instance, &cfg);
|
||||
*val = cfg.baud_rate;
|
||||
break;
|
||||
|
||||
case UART_LINE_CTRL_LOOPBACK:
|
||||
ret = sedi_uart_get_loopback_mode(instance, (uint32_t *)val);
|
||||
break;
|
||||
|
||||
case UART_LINE_CTRL_AFCE:
|
||||
ret = sedi_uart_get_config(instance, &cfg);
|
||||
*val = cfg.hw_fc;
|
||||
break;
|
||||
|
||||
case UART_LINE_CTRL_LINE_STATUS_REPORT_MASK:
|
||||
mask = 0;
|
||||
*val = 0;
|
||||
ret = sedi_get_ln_status_report_mask(instance,
|
||||
(uint32_t *)&mask);
|
||||
*val |= ((mask & SEDI_UART_RX_OE) ? UART_ERROR_OVERRUN : 0);
|
||||
*val |= ((mask & SEDI_UART_RX_PE) ? UART_ERROR_PARITY : 0);
|
||||
*val |= ((mask & SEDI_UART_RX_FE) ? UART_ERROR_FRAMING : 0);
|
||||
*val |= ((mask & SEDI_UART_RX_BI) ? UART_BREAK : 0);
|
||||
break;
|
||||
|
||||
case UART_LINE_CTRL_RTS:
|
||||
ret = sedi_uart_read_rts(instance, (uint32_t *)val);
|
||||
break;
|
||||
|
||||
case UART_LINE_CTRL_CTS:
|
||||
ret = sedi_uart_read_cts(instance, (uint32_t *)val);
|
||||
break;
|
||||
|
||||
|
||||
default:
|
||||
ret = -ENODEV;
|
||||
}
|
||||
k_mutex_unlock(GET_MUTEX(dev));
|
||||
ret = get_xfer_error(ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
#endif /* CONFIG_UART_LINE_CTRL */
|
||||
|
||||
static const struct uart_driver_api api = {
|
||||
.poll_in = uart_sedi_poll_in,
|
||||
.poll_out = uart_sedi_poll_out,
|
||||
.err_check = uart_sedi_err_check,
|
||||
#ifdef CONFIG_UART_INTERRUPT_DRIVEN
|
||||
.fifo_fill = uart_sedi_fifo_fill,
|
||||
.fifo_read = uart_sedi_fifo_read,
|
||||
.irq_tx_enable = uart_sedi_irq_tx_enable,
|
||||
.irq_tx_disable = uart_sedi_irq_tx_disable,
|
||||
.irq_tx_ready = uart_sedi_irq_tx_ready,
|
||||
.irq_tx_complete = uart_sedi_irq_tx_complete,
|
||||
.irq_rx_enable = uart_sedi_irq_rx_enable,
|
||||
.irq_rx_disable = uart_sedi_irq_rx_disable,
|
||||
.irq_rx_ready = uart_sedi_irq_rx_ready,
|
||||
.irq_err_enable = uart_sedi_irq_err_enable,
|
||||
.irq_err_disable = uart_sedi_irq_err_disable,
|
||||
.irq_is_pending = uart_sedi_irq_is_pending,
|
||||
.irq_update = uart_sedi_irq_update,
|
||||
.irq_callback_set = uart_sedi_irq_callback_set,
|
||||
#endif /* CONFIG_UART_INTERRUPT_DRIVEN */
|
||||
#ifdef CONFIG_UART_LINE_CTRL
|
||||
.line_ctrl_set = uart_sedi_line_ctrl_set,
|
||||
.line_ctrl_get = uart_sedi_line_ctrl_get,
|
||||
#endif /* CONFIG_UART_LINE_CTRL */
|
||||
|
||||
};
|
||||
|
||||
static int uart_sedi_init(const struct device *dev)
|
||||
{
|
||||
|
||||
const struct uart_sedi_config_info *config = dev->config;
|
||||
sedi_uart_config_t cfg;
|
||||
|
||||
DEVICE_MMIO_MAP(dev, K_MEM_CACHE_NONE);
|
||||
sedi_uart_init(config->instance, (void *)DEVICE_MMIO_GET(dev));
|
||||
|
||||
cfg.line_control = config->line_ctrl;
|
||||
cfg.baud_rate = config->baud_rate;
|
||||
cfg.hw_fc = config->hw_fc;
|
||||
|
||||
/* Setting to full power and enabling clk. */
|
||||
sedi_uart_set_power(config->instance, SEDI_POWER_FULL);
|
||||
|
||||
sedi_uart_set_config(config->instance, &cfg);
|
||||
|
||||
#ifdef CONFIG_UART_INTERRUPT_DRIVEN
|
||||
config->uart_irq_config_func(dev);
|
||||
#endif /* CONFIG_UART_INTERRUPT_DRIVEN */
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
DT_INST_FOREACH_STATUS_OKAY(UART_SEDI_DEVICE_INIT)
|
16
dts/bindings/serial/intel,sedi-uart.yaml
Normal file
16
dts/bindings/serial/intel,sedi-uart.yaml
Normal file
|
@ -0,0 +1,16 @@
|
|||
# Copyright (c) 2023 Intel Corporation
|
||||
#
|
||||
# SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
description: INTEL SEDI UART
|
||||
|
||||
compatible: "intel,sedi-uart"
|
||||
|
||||
include: uart-controller.yaml
|
||||
|
||||
properties:
|
||||
reg:
|
||||
required: true
|
||||
|
||||
interrupts:
|
||||
required: true
|
Loading…
Reference in a new issue