drivers/serial: Add ITE UART wrapper to enable serial driver of ns16550
Add ITE UART wrapper to enable serial driver of ns16550. Signed-off-by: Tim Lin <tim2.lin@ite.corp-partner.google.com>
This commit is contained in:
parent
df56c85e94
commit
d64d87f655
6 changed files with 242 additions and 0 deletions
|
@ -35,6 +35,7 @@ zephyr_library_sources_ifdef(CONFIG_UART_HOSTLINK uart_hostlink.c)
|
|||
zephyr_library_sources_ifdef(CONFIG_UART_IMX uart_imx.c)
|
||||
zephyr_library_sources_ifdef(CONFIG_UART_INFINEON_CAT1 uart_ifx_cat1.c)
|
||||
zephyr_library_sources_ifdef(CONFIG_UART_INTEL_LW uart_intel_lw.c)
|
||||
zephyr_library_sources_ifdef(CONFIG_UART_ITE_IT51XXX uart_ite_it51xxx.c)
|
||||
zephyr_library_sources_ifdef(CONFIG_UART_ITE_IT8XXX2 uart_ite_it8xxx2.c)
|
||||
zephyr_library_sources_ifdef(CONFIG_UART_LITEX uart_litex.c)
|
||||
zephyr_library_sources_ifdef(CONFIG_UART_LPC11U6X uart_lpc11u6x.c)
|
||||
|
|
|
@ -178,6 +178,7 @@ rsource "Kconfig.hostlink"
|
|||
rsource "Kconfig.ifx_cat1"
|
||||
rsource "Kconfig.imx"
|
||||
rsource "Kconfig.intel_lw"
|
||||
rsource "Kconfig.it51xxx"
|
||||
rsource "Kconfig.it8xxx2"
|
||||
rsource "Kconfig.leuart_gecko"
|
||||
rsource "Kconfig.litex"
|
||||
|
|
13
drivers/serial/Kconfig.it51xxx
Normal file
13
drivers/serial/Kconfig.it51xxx
Normal file
|
@ -0,0 +1,13 @@
|
|||
# Copyright (c) 2025 ITE Corporation. All Rights Reserved.
|
||||
# SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
config UART_ITE_IT51XXX
|
||||
bool "ITE IT51XXX UART driver"
|
||||
default y
|
||||
select UART_NS16550_ITE_HIGH_SPEED_BAUDRATE
|
||||
depends on DT_HAS_ITE_IT51XXX_UART_ENABLED
|
||||
select PINCTRL
|
||||
help
|
||||
IT51XXX uses shared ns16550.c driver. This wrapper primarily
|
||||
registers an interrupt to wake up the EC from doze or deep
|
||||
doze mode back to active state.
|
163
drivers/serial/uart_ite_it51xxx.c
Normal file
163
drivers/serial/uart_ite_it51xxx.c
Normal file
|
@ -0,0 +1,163 @@
|
|||
/*
|
||||
* Copyright (c) 2025 ITE Corporation. All Rights Reserved.
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
#define DT_DRV_COMPAT ite_it51xxx_uart
|
||||
|
||||
#include <soc.h>
|
||||
#include <soc_dt.h>
|
||||
#include <zephyr/device.h>
|
||||
#include <zephyr/drivers/clock_control.h>
|
||||
#include <zephyr/drivers/interrupt_controller/wuc_ite_it51xxx.h>
|
||||
#include <zephyr/drivers/pinctrl.h>
|
||||
#include <zephyr/drivers/uart.h>
|
||||
#include <zephyr/kernel.h>
|
||||
#include <zephyr/logging/log.h>
|
||||
#include <zephyr/pm/device.h>
|
||||
#include <zephyr/pm/policy.h>
|
||||
|
||||
LOG_MODULE_REGISTER(uart_ite_it51xxx, CONFIG_UART_LOG_LEVEL);
|
||||
|
||||
struct it51xxx_uart_wuc_map_cfg {
|
||||
/* WUC control device structure */
|
||||
const struct device *wucs;
|
||||
/* WUC pin mask */
|
||||
uint8_t mask;
|
||||
};
|
||||
|
||||
struct uart_it51xxx_config {
|
||||
/* UART wake-up input source configuration list */
|
||||
const struct it51xxx_uart_wuc_map_cfg *wuc_map_list;
|
||||
const struct device *clk_dev;
|
||||
/* clock configuration */
|
||||
struct ite_clk_cfg clk_cfg;
|
||||
/* UART interrupt */
|
||||
uint8_t irq;
|
||||
};
|
||||
|
||||
struct uart_it51xxx_data {
|
||||
#ifdef CONFIG_UART_CONSOLE_INPUT_EXPIRED
|
||||
struct k_work_delayable rx_refresh_timeout_work;
|
||||
#endif
|
||||
};
|
||||
|
||||
static void it51xxx_uart_wui_isr(const void *arg)
|
||||
{
|
||||
const struct device *dev = arg;
|
||||
const struct uart_it51xxx_config *const config = dev->config;
|
||||
|
||||
/* Disable interrupts on UART RX pin to avoid repeated interrupts. */
|
||||
irq_disable(config->irq);
|
||||
/* W/C wakeup interrupt status of UART pin */
|
||||
it51xxx_wuc_clear_status(config->wuc_map_list[0].wucs, config->wuc_map_list[0].mask);
|
||||
|
||||
/* Refresh console expired time if got UART Rx wake-up event */
|
||||
#ifdef CONFIG_UART_CONSOLE_INPUT_EXPIRED
|
||||
struct uart_it51xxx_data *data = dev->data;
|
||||
k_timeout_t delay = K_MSEC(CONFIG_UART_CONSOLE_INPUT_EXPIRED_TIMEOUT);
|
||||
|
||||
/*
|
||||
* The pm state of it51xxx chip only supports standby, so here we
|
||||
* can directly set the constraint for standby.
|
||||
*/
|
||||
pm_policy_state_lock_get(PM_STATE_STANDBY, PM_ALL_SUBSTATES);
|
||||
k_work_reschedule(&data->rx_refresh_timeout_work, delay);
|
||||
#endif
|
||||
}
|
||||
|
||||
static inline int uart_it51xxx_pm_action(const struct device *dev, enum pm_device_action action)
|
||||
{
|
||||
const struct uart_it51xxx_config *const config = dev->config;
|
||||
|
||||
switch (action) {
|
||||
/* Next device power state is in active. */
|
||||
case PM_DEVICE_ACTION_RESUME:
|
||||
/* Nothing to do. */
|
||||
break;
|
||||
/* Next device power state is deep doze mode */
|
||||
case PM_DEVICE_ACTION_SUSPEND:
|
||||
/* W/C wake-up interrupt status of UART pin */
|
||||
it51xxx_wuc_clear_status(config->wuc_map_list[0].wucs,
|
||||
config->wuc_map_list[0].mask);
|
||||
/* W/C interrupt status of UART pin */
|
||||
ite_intc_isr_clear(config->irq);
|
||||
/* Enable UART interrupt */
|
||||
irq_enable(config->irq);
|
||||
|
||||
break;
|
||||
default:
|
||||
return -ENOTSUP;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
#ifdef CONFIG_UART_CONSOLE_INPUT_EXPIRED
|
||||
static void uart_it51xxx_rx_refresh_timeout(struct k_work *work)
|
||||
{
|
||||
ARG_UNUSED(work);
|
||||
|
||||
pm_policy_state_lock_put(PM_STATE_STANDBY, PM_ALL_SUBSTATES);
|
||||
}
|
||||
#endif
|
||||
|
||||
static int uart_it51xxx_init(const struct device *dev)
|
||||
{
|
||||
const struct uart_it51xxx_config *const config = dev->config;
|
||||
int ret;
|
||||
|
||||
/* Enable clock to specified peripheral */
|
||||
ret = clock_control_on(config->clk_dev, (clock_control_subsys_t *)&config->clk_cfg);
|
||||
if (ret < 0) {
|
||||
LOG_ERR("Turn on clock fail %d", ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
/* Select wakeup interrupt falling-edge triggered of UART pin */
|
||||
it51xxx_wuc_set_polarity(config->wuc_map_list[0].wucs, config->wuc_map_list[0].mask,
|
||||
WUC_TYPE_EDGE_FALLING);
|
||||
/* W/C wakeup interrupt status of UART pin */
|
||||
it51xxx_wuc_clear_status(config->wuc_map_list[0].wucs, config->wuc_map_list[0].mask);
|
||||
/* Enable wakeup interrupt of UART pin */
|
||||
it51xxx_wuc_enable(config->wuc_map_list[0].wucs, config->wuc_map_list[0].mask);
|
||||
|
||||
/*
|
||||
* We need to configure UART Rx interrupt as wakeup source and initialize
|
||||
* a delayable work for console expired time.
|
||||
*/
|
||||
#ifdef CONFIG_UART_CONSOLE_INPUT_EXPIRED
|
||||
struct uart_it51xxx_data *data = dev->data;
|
||||
|
||||
k_work_init_delayable(&data->rx_refresh_timeout_work, uart_it51xxx_rx_refresh_timeout);
|
||||
#endif
|
||||
/*
|
||||
* When the system enters deep doze, all clocks are gated only the
|
||||
* 32.768k clock is active. We need to wakeup EC by configuring
|
||||
* UART Rx interrupt as a wakeup source. When the interrupt of UART
|
||||
* Rx falling, EC will be woken.
|
||||
*/
|
||||
irq_connect_dynamic(config->irq, 0, it51xxx_uart_wui_isr, dev, 0);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
#define UART_ITE_IT51XXX_INIT(inst) \
|
||||
static const struct it51xxx_uart_wuc_map_cfg \
|
||||
it51xxx_uart_wuc_##inst[IT8XXX2_DT_INST_WUCCTRL_LEN(inst)] = \
|
||||
IT8XXX2_DT_WUC_ITEMS_LIST(inst); \
|
||||
static struct uart_it51xxx_data uart_it51xxx_data_##inst; \
|
||||
static const struct uart_it51xxx_config uart_it51xxx_cfg_##inst = { \
|
||||
.wuc_map_list = it51xxx_uart_wuc_##inst, \
|
||||
.clk_dev = DEVICE_DT_GET(DT_INST_PHANDLE(inst, clocks)), \
|
||||
.clk_cfg = {.ctrl = DT_INST_CLOCKS_CELL(inst, ctrl), \
|
||||
.bits = DT_INST_CLOCKS_CELL(inst, bits)}, \
|
||||
.irq = DT_INST_IRQN(inst), \
|
||||
}; \
|
||||
PM_DEVICE_DT_INST_DEFINE(inst, uart_it51xxx_pm_action); \
|
||||
DEVICE_DT_INST_DEFINE(inst, uart_it51xxx_init, PM_DEVICE_DT_INST_GET(inst), \
|
||||
&uart_it51xxx_data_##inst, &uart_it51xxx_cfg_##inst, PRE_KERNEL_1, \
|
||||
CONFIG_SERIAL_INIT_PRIORITY, NULL);
|
||||
|
||||
DT_INST_FOREACH_STATUS_OKAY(UART_ITE_IT51XXX_INIT)
|
22
dts/bindings/serial/ite,it51xxx-uart.yaml
Normal file
22
dts/bindings/serial/ite,it51xxx-uart.yaml
Normal file
|
@ -0,0 +1,22 @@
|
|||
# Copyright (c) 2025 ITE Corporation. All Rights Reserved.
|
||||
# SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
description: ITE, IT51XXX-UART node
|
||||
|
||||
compatible: "ite,it51xxx-uart"
|
||||
|
||||
include: [uart-controller.yaml]
|
||||
|
||||
properties:
|
||||
reg:
|
||||
required: true
|
||||
|
||||
wucctrl:
|
||||
type: phandles
|
||||
description: |
|
||||
WUC groups internal and external inputs, and asserts wake-up
|
||||
signals to INTC that allows the CPU to exit a Doze/Deep
|
||||
Doze/Sleep mode.
|
||||
|
||||
clocks:
|
||||
required: true
|
|
@ -927,6 +927,48 @@
|
|||
reg = <0x00f02000 0x100>;
|
||||
};
|
||||
|
||||
uart1: uart@f02700 {
|
||||
compatible = "ns16550";
|
||||
reg = <0x00f02700 0x0020>;
|
||||
status = "disabled";
|
||||
current-speed = <115200>;
|
||||
clock-frequency = <1843200>;
|
||||
interrupts = <38 IRQ_TYPE_EDGE_RISING>;
|
||||
interrupt-parent = <&intc>;
|
||||
reg-shift = <0>;
|
||||
};
|
||||
|
||||
ite_uart1_wrapper: uartwrapper@f02720 {
|
||||
compatible = "ite,it51xxx-uart";
|
||||
reg = <0x00f02720 0x0020>;
|
||||
status = "disabled";
|
||||
wucctrl = <&wuc_wu86>; /* GPC7 */
|
||||
interrupts = <IT51XXX_IRQ_WU86 IRQ_TYPE_LEVEL_HIGH>;
|
||||
interrupt-parent = <&intc>;
|
||||
clocks = <&ecpm IT51XXX_ECPM_CGCTRL3R_OFF BIT(2)>;
|
||||
};
|
||||
|
||||
uart2: uart@f02800 {
|
||||
compatible = "ns16550";
|
||||
reg = <0x00f02800 0x0020>;
|
||||
status = "disabled";
|
||||
current-speed = <460800>;
|
||||
clock-frequency = <1843200>;
|
||||
interrupts = <39 IRQ_TYPE_EDGE_RISING>;
|
||||
interrupt-parent = <&intc>;
|
||||
reg-shift = <0>;
|
||||
};
|
||||
|
||||
ite_uart2_wrapper: uartwrapper@f02820 {
|
||||
compatible = "ite,it51xxx-uart";
|
||||
reg = <0x00f02820 0x0020>;
|
||||
status = "disabled";
|
||||
wucctrl = <&wuc_wu61>; /* GPH1 */
|
||||
interrupts = <IT51XXX_IRQ_WU61 IRQ_TYPE_LEVEL_HIGH>;
|
||||
interrupt-parent = <&intc>;
|
||||
clocks = <&ecpm IT51XXX_ECPM_CGCTRL3R_OFF BIT(2)>;
|
||||
};
|
||||
|
||||
intc: interrupt-controller@f04300 {
|
||||
compatible = "ite,it51xxx-intc";
|
||||
#address-cells = <0>;
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue