2025-10-16 10:44:21 +08:00
|
|
|
|
/*
|
|
|
|
|
|
* Copyright (c) 2025 Nuvoton Technology Corporation.
|
|
|
|
|
|
*
|
|
|
|
|
|
* SPDX-License-Identifier: Apache-2.0
|
|
|
|
|
|
*/
|
|
|
|
|
|
|
|
|
|
|
|
#include <zephyr/drivers/counter.h>
|
|
|
|
|
|
#include <zephyr/kernel.h>
|
2026-07-03 07:46:32 +02:00
|
|
|
|
#include <zephyr/sys/clock.h>
|
2025-10-16 10:44:21 +08:00
|
|
|
|
|
|
|
|
|
|
#include "soc_miwu.h"
|
|
|
|
|
|
|
|
|
|
|
|
#include <zephyr/logging/log.h>
|
|
|
|
|
|
LOG_MODULE_REGISTER(counter_npcx_lct, CONFIG_COUNTER_LOG_LEVEL);
|
|
|
|
|
|
|
|
|
|
|
|
#if DT_HAS_COMPAT_STATUS_OKAY(nuvoton_npcx_lct_v1)
|
|
|
|
|
|
#define DT_DRV_COMPAT nuvoton_npcx_lct_v1
|
|
|
|
|
|
#elif DT_HAS_COMPAT_STATUS_OKAY(nuvoton_npcx_lct_v2)
|
|
|
|
|
|
#define DT_DRV_COMPAT nuvoton_npcx_lct_v2
|
|
|
|
|
|
#elif DT_HAS_COMPAT_STATUS_OKAY(nuvoton_npck_lct)
|
|
|
|
|
|
#define DT_DRV_COMPAT nuvoton_npck_lct
|
|
|
|
|
|
#endif
|
|
|
|
|
|
BUILD_ASSERT(DT_NUM_INST_STATUS_OKAY(DT_DRV_COMPAT) == 1, "Invalid number of NPCX LCT peripherals");
|
|
|
|
|
|
|
|
|
|
|
|
BUILD_ASSERT(DT_NUM_INST_STATUS_OKAY(nuvoton_npcx_lct_v1) +
|
|
|
|
|
|
DT_NUM_INST_STATUS_OKAY(nuvoton_npcx_lct_v2) +
|
|
|
|
|
|
DT_NUM_INST_STATUS_OKAY(nuvoton_npck_lct) <= 1,
|
|
|
|
|
|
"Multiple npcx LCT instances in DT");
|
|
|
|
|
|
|
|
|
|
|
|
#define COUNTER_NPCX_LCT_MAX_SECOND DT_INST_PROP(0, maximum_cnt_in_sec)
|
|
|
|
|
|
#define COUNTER_NPCX_LCT_CHECK_TIMEOUT_US 200
|
|
|
|
|
|
|
|
|
|
|
|
#define DAY_PER_WEEK 7U
|
|
|
|
|
|
#define SEC_PER_WEEK ((DAY_PER_WEEK) * (SEC_PER_DAY))
|
|
|
|
|
|
|
|
|
|
|
|
#define NPCX_LCT_PWR_VCC1 0
|
|
|
|
|
|
#define NPCX_LCT_PWR_VSBY 1
|
|
|
|
|
|
|
|
|
|
|
|
#define NPCX_LCT_STAT_EV_MASK 0x01
|
|
|
|
|
|
|
|
|
|
|
|
struct counter_npcx_lct_config {
|
|
|
|
|
|
struct counter_config_info info;
|
|
|
|
|
|
struct lct_reg *reg_base;
|
|
|
|
|
|
bool pwr_by_vsby;
|
|
|
|
|
|
#if defined(CONFIG_COUNTER_NPCX_NPCXN_V1) || defined(CONFIG_COUNTER_NPCX_NPCXN_V2)
|
|
|
|
|
|
const struct npcx_wui lct_wui;
|
|
|
|
|
|
#endif
|
|
|
|
|
|
#if defined(CONFIG_COUNTER_NPCX_NPCKN)
|
|
|
|
|
|
int irq;
|
|
|
|
|
|
#endif
|
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
struct counter_npcx_lct_data {
|
|
|
|
|
|
struct k_sem lock;
|
|
|
|
|
|
#if defined(CONFIG_COUNTER_NPCX_NPCXN_V1) || defined(CONFIG_COUNTER_NPCX_NPCXN_V2)
|
|
|
|
|
|
struct miwu_callback lct_wui_cb;
|
|
|
|
|
|
#endif
|
|
|
|
|
|
counter_alarm_callback_t alarm_cb;
|
|
|
|
|
|
void *user_data;
|
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
static void npcx_lct_handle_isr(const struct device *dev)
|
|
|
|
|
|
{
|
|
|
|
|
|
const struct counter_npcx_lct_config *const config = dev->config;
|
|
|
|
|
|
struct counter_npcx_lct_data *data = dev->data;
|
|
|
|
|
|
struct lct_reg *const reg_base = config->reg_base;
|
|
|
|
|
|
counter_alarm_callback_t alarm_cb = data->alarm_cb;
|
|
|
|
|
|
|
|
|
|
|
|
/* The counter needs some time to stop. Wait for the LCT enable bit to clear, or the event
|
|
|
|
|
|
* status won’t clear properly.
|
|
|
|
|
|
*/
|
|
|
|
|
|
if (WAIT_FOR(!IS_BIT_SET(reg_base->LCTCONT, NPCX_LCTCONT_LCTEN),
|
|
|
|
|
|
COUNTER_NPCX_LCT_CHECK_TIMEOUT_US, NULL) == false) {
|
|
|
|
|
|
LOG_ERR("The LCT function is still working");
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
reg_base->LCTCONT &= ~BIT(NPCX_LCTCONT_LCTEVEN);
|
|
|
|
|
|
reg_base->LCTSTAT |= BIT(NPCX_LCTSTAT_LCTEVST);
|
|
|
|
|
|
|
|
|
|
|
|
if (data->alarm_cb) {
|
|
|
|
|
|
data->alarm_cb = NULL;
|
|
|
|
|
|
alarm_cb(dev, 0, 0, data->user_data);
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
#if defined(CONFIG_COUNTER_NPCX_NPCKN)
|
|
|
|
|
|
static void counter_npcx_lct_isr(const struct device *dev)
|
|
|
|
|
|
{
|
|
|
|
|
|
npcx_lct_handle_isr(dev);
|
|
|
|
|
|
}
|
|
|
|
|
|
#endif
|
|
|
|
|
|
#if defined(CONFIG_COUNTER_NPCX_NPCXN_V1) || defined(CONFIG_COUNTER_NPCX_NPCXN_V2)
|
|
|
|
|
|
static void counter_npcx_lct_isr(const struct device *dev, struct npcx_wui *wui)
|
|
|
|
|
|
{
|
|
|
|
|
|
npcx_lct_handle_isr(dev);
|
|
|
|
|
|
}
|
|
|
|
|
|
#endif
|
|
|
|
|
|
|
|
|
|
|
|
#if defined(CONFIG_COUNTER_NPCX_NPCXN_V2)
|
|
|
|
|
|
#define LCT_REG_WEEKM(base) (base->LCTWEEKM)
|
|
|
|
|
|
#else
|
|
|
|
|
|
#define LCT_REG_WEEKM(base) 0U
|
|
|
|
|
|
#endif
|
|
|
|
|
|
|
|
|
|
|
|
static int npcx_lct_enable(struct lct_reg *const reg_base, bool enable)
|
|
|
|
|
|
{
|
|
|
|
|
|
if (enable) {
|
|
|
|
|
|
reg_base->LCTCONT |= BIT(NPCX_LCTCONT_LCTEN);
|
|
|
|
|
|
} else {
|
|
|
|
|
|
reg_base->LCTCONT &= ~BIT(NPCX_LCTCONT_LCTEN);
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/* The counter takes time to start and stop. Wait until the LCT enable bit is in the correct
|
|
|
|
|
|
* state, otherwise the hardware behavior may be incorrect.
|
|
|
|
|
|
*/
|
|
|
|
|
|
if (WAIT_FOR(IS_BIT_SET(reg_base->LCTCONT, NPCX_LCTCONT_LCTEN) == enable,
|
|
|
|
|
|
COUNTER_NPCX_LCT_CHECK_TIMEOUT_US, NULL) == false) {
|
|
|
|
|
|
LOG_ERR("LCT enable/disable timeout");
|
|
|
|
|
|
return -ETIMEDOUT;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
static void npcx_lct_set_alarm_time(struct lct_reg *const reg_base, int32_t seconds)
|
|
|
|
|
|
{
|
|
|
|
|
|
uint32_t weeks;
|
|
|
|
|
|
|
|
|
|
|
|
weeks = seconds / SEC_PER_WEEK;
|
|
|
|
|
|
#if defined(CONFIG_COUNTER_NPCX_NPCXN_V2)
|
|
|
|
|
|
reg_base->LCTWEEKM = (weeks >> 8) & 0xf;
|
|
|
|
|
|
#endif
|
|
|
|
|
|
reg_base->LCTWEEK = weeks & 0xff;
|
|
|
|
|
|
seconds %= SEC_PER_WEEK;
|
|
|
|
|
|
reg_base->LCTDAY = seconds / SEC_PER_DAY;
|
|
|
|
|
|
seconds %= SEC_PER_DAY;
|
|
|
|
|
|
reg_base->LCTHOUR = seconds / SEC_PER_HOUR;
|
|
|
|
|
|
seconds %= SEC_PER_HOUR;
|
|
|
|
|
|
reg_base->LCTMINUTE = seconds / SEC_PER_MIN;
|
|
|
|
|
|
reg_base->LCTSECOND = seconds % SEC_PER_MIN;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
static int counter_npcx_lct_cancel_alarm(const struct device *dev, uint8_t chan_id)
|
|
|
|
|
|
{
|
|
|
|
|
|
const struct counter_npcx_lct_config *const config = dev->config;
|
|
|
|
|
|
struct counter_npcx_lct_data *data = dev->data;
|
|
|
|
|
|
struct lct_reg *const reg_base = config->reg_base;
|
|
|
|
|
|
int ret = 0;
|
|
|
|
|
|
|
|
|
|
|
|
if (chan_id != 0) {
|
|
|
|
|
|
LOG_ERR("Invalid channel id %u", chan_id);
|
|
|
|
|
|
return -ENOTSUP;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
k_sem_take(&data->lock, K_FOREVER);
|
|
|
|
|
|
|
|
|
|
|
|
ret = npcx_lct_enable(reg_base, false);
|
|
|
|
|
|
if (ret != 0) {
|
|
|
|
|
|
LOG_ERR("disable LCT failed");
|
|
|
|
|
|
ret = -EBUSY;
|
|
|
|
|
|
goto return_exit;
|
|
|
|
|
|
}
|
|
|
|
|
|
reg_base->LCTCONT &= ~BIT(NPCX_LCTCONT_LCTEVEN);
|
|
|
|
|
|
|
|
|
|
|
|
#if defined(CONFIG_COUNTER_NPCX_NPCXN_V2)
|
|
|
|
|
|
reg_base->LCTWEEKM = 0;
|
|
|
|
|
|
#endif
|
|
|
|
|
|
reg_base->LCTWEEK = 0;
|
|
|
|
|
|
reg_base->LCTDAY = 0;
|
|
|
|
|
|
reg_base->LCTHOUR = 0;
|
|
|
|
|
|
reg_base->LCTMINUTE = 0;
|
|
|
|
|
|
reg_base->LCTSECOND = 0;
|
|
|
|
|
|
|
|
|
|
|
|
data->alarm_cb = NULL;
|
|
|
|
|
|
data->user_data = NULL;
|
|
|
|
|
|
|
|
|
|
|
|
return_exit:
|
|
|
|
|
|
k_sem_give(&data->lock);
|
|
|
|
|
|
|
|
|
|
|
|
return ret;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
static int counter_npcx_lct_start(const struct device *dev)
|
|
|
|
|
|
{
|
|
|
|
|
|
|
|
|
|
|
|
const struct counter_npcx_lct_config *const config = dev->config;
|
|
|
|
|
|
struct counter_npcx_lct_data *data = dev->data;
|
|
|
|
|
|
struct lct_reg *const reg_base = config->reg_base;
|
|
|
|
|
|
int ret = 0;
|
|
|
|
|
|
|
|
|
|
|
|
k_sem_take(&data->lock, K_FOREVER);
|
|
|
|
|
|
|
|
|
|
|
|
if (IS_BIT_SET(reg_base->LCTCONT, NPCX_LCTCONT_LCTEN)) {
|
|
|
|
|
|
ret = -EALREADY;
|
|
|
|
|
|
goto return_exit;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
ret = npcx_lct_enable(reg_base, true);
|
|
|
|
|
|
if (ret != 0) {
|
|
|
|
|
|
LOG_ERR("enable LCT failed");
|
|
|
|
|
|
ret = -EBUSY;
|
|
|
|
|
|
goto return_exit;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
return_exit:
|
|
|
|
|
|
k_sem_give(&data->lock);
|
|
|
|
|
|
|
|
|
|
|
|
return ret;
|
|
|
|
|
|
}
|
|
|
|
|
|
static int counter_npcx_lct_stop(const struct device *dev)
|
|
|
|
|
|
{
|
|
|
|
|
|
const struct counter_npcx_lct_config *const config = dev->config;
|
|
|
|
|
|
struct counter_npcx_lct_data *data = dev->data;
|
|
|
|
|
|
struct lct_reg *const reg_base = config->reg_base;
|
|
|
|
|
|
int ret = 0;
|
|
|
|
|
|
|
|
|
|
|
|
k_sem_take(&data->lock, K_FOREVER);
|
|
|
|
|
|
|
|
|
|
|
|
if (!IS_BIT_SET(reg_base->LCTCONT, NPCX_LCTCONT_LCTEN)) {
|
|
|
|
|
|
/* Already stop, nothing to do. */
|
|
|
|
|
|
goto return_exit;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
ret = npcx_lct_enable(reg_base, false);
|
|
|
|
|
|
if (ret != 0) {
|
|
|
|
|
|
LOG_ERR("disable LCT failed");
|
|
|
|
|
|
ret = -EBUSY;
|
|
|
|
|
|
goto return_exit;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
return_exit:
|
|
|
|
|
|
k_sem_give(&data->lock);
|
|
|
|
|
|
|
|
|
|
|
|
return ret;
|
|
|
|
|
|
}
|
|
|
|
|
|
static int counter_npcx_lct_get_value(const struct device *dev, uint32_t *ticks)
|
|
|
|
|
|
{
|
|
|
|
|
|
const struct counter_npcx_lct_config *const config = dev->config;
|
|
|
|
|
|
struct lct_reg *const reg_base = config->reg_base;
|
|
|
|
|
|
struct counter_npcx_lct_data *data = dev->data;
|
|
|
|
|
|
uint32_t second;
|
|
|
|
|
|
uint8_t week, day, hour, minute;
|
|
|
|
|
|
uint16_t weekm;
|
|
|
|
|
|
|
|
|
|
|
|
k_sem_take(&data->lock, K_FOREVER);
|
|
|
|
|
|
|
|
|
|
|
|
do {
|
|
|
|
|
|
weekm = LCT_REG_WEEKM(reg_base);
|
|
|
|
|
|
week = reg_base->LCTWEEK;
|
|
|
|
|
|
day = reg_base->LCTDAY;
|
|
|
|
|
|
hour = reg_base->LCTHOUR;
|
|
|
|
|
|
minute = reg_base->LCTMINUTE;
|
|
|
|
|
|
second = reg_base->LCTSECOND;
|
|
|
|
|
|
} while (weekm != LCT_REG_WEEKM(reg_base) || week != reg_base->LCTWEEK ||
|
|
|
|
|
|
day != reg_base->LCTDAY || hour != reg_base->LCTHOUR ||
|
|
|
|
|
|
minute != reg_base->LCTMINUTE || second != reg_base->LCTSECOND);
|
|
|
|
|
|
|
|
|
|
|
|
weekm = (weekm << 8) + week;
|
|
|
|
|
|
|
|
|
|
|
|
*ticks = weekm * SEC_PER_WEEK + day * SEC_PER_DAY + hour * SEC_PER_HOUR +
|
|
|
|
|
|
minute * SEC_PER_MIN + second;
|
|
|
|
|
|
|
|
|
|
|
|
k_sem_give(&data->lock);
|
|
|
|
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
static int counter_npcx_lct_set_alarm(const struct device *dev, uint8_t chan_id,
|
|
|
|
|
|
const struct counter_alarm_cfg *alarm_cfg)
|
|
|
|
|
|
{
|
|
|
|
|
|
const struct counter_npcx_lct_config *const config = dev->config;
|
|
|
|
|
|
struct counter_npcx_lct_data *data = dev->data;
|
|
|
|
|
|
struct lct_reg *const reg_base = config->reg_base;
|
|
|
|
|
|
int ret;
|
|
|
|
|
|
|
|
|
|
|
|
if (chan_id != 0) {
|
|
|
|
|
|
LOG_ERR("Invalid channel id %u", chan_id);
|
|
|
|
|
|
ret = -ENOTSUP;
|
|
|
|
|
|
goto return_exit;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
|
* Interrupts are only triggered when the counter reaches 0.
|
|
|
|
|
|
* So only relative alarms are supported.
|
|
|
|
|
|
*/
|
|
|
|
|
|
if (alarm_cfg->flags & COUNTER_ALARM_CFG_ABSOLUTE) {
|
|
|
|
|
|
LOG_ERR("Invalid flags %x", alarm_cfg->flags);
|
|
|
|
|
|
ret = -ENOTSUP;
|
|
|
|
|
|
goto return_exit;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
if (data->alarm_cb != NULL) {
|
|
|
|
|
|
ret = -EBUSY;
|
|
|
|
|
|
goto return_exit;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
if (alarm_cfg->ticks > COUNTER_NPCX_LCT_MAX_SECOND) {
|
|
|
|
|
|
ret = -EINVAL;
|
|
|
|
|
|
goto return_exit;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
k_sem_take(&data->lock, K_FOREVER);
|
|
|
|
|
|
|
|
|
|
|
|
data->alarm_cb = alarm_cfg->callback;
|
|
|
|
|
|
data->user_data = alarm_cfg->user_data;
|
|
|
|
|
|
|
|
|
|
|
|
npcx_lct_set_alarm_time(reg_base, alarm_cfg->ticks);
|
|
|
|
|
|
/* Clear pending LCT event */
|
|
|
|
|
|
reg_base->LCTSTAT |= BIT(NPCX_LCTSTAT_LCTEVST);
|
|
|
|
|
|
|
|
|
|
|
|
reg_base->LCTCONT |= BIT(NPCX_LCTCONT_LCTEVEN);
|
|
|
|
|
|
|
|
|
|
|
|
if (config->pwr_by_vsby == true) {
|
|
|
|
|
|
reg_base->LCTCONT |= BIT(NPCX_LCTCONT_LCTPSLEN);
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
ret = npcx_lct_enable(reg_base, true);
|
|
|
|
|
|
|
|
|
|
|
|
return_exit:
|
|
|
|
|
|
k_sem_give(&data->lock);
|
|
|
|
|
|
|
|
|
|
|
|
return ret;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
static uint32_t counter_npcx_get_pending_int(const struct device *dev)
|
|
|
|
|
|
{
|
|
|
|
|
|
const struct counter_npcx_lct_config *const config = dev->config;
|
|
|
|
|
|
struct lct_reg *const reg_base = config->reg_base;
|
|
|
|
|
|
|
|
|
|
|
|
return reg_base->LCTSTAT & NPCX_LCT_STAT_EV_MASK;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2026-02-10 16:28:37 +01:00
|
|
|
|
static DEVICE_API(counter, counter_npcx_lct_api) = {
|
2025-10-16 10:44:21 +08:00
|
|
|
|
.start = counter_npcx_lct_start,
|
|
|
|
|
|
.stop = counter_npcx_lct_stop,
|
|
|
|
|
|
.get_value = counter_npcx_lct_get_value,
|
|
|
|
|
|
.set_alarm = counter_npcx_lct_set_alarm,
|
|
|
|
|
|
.cancel_alarm = counter_npcx_lct_cancel_alarm,
|
|
|
|
|
|
.get_pending_int = counter_npcx_get_pending_int,
|
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
static int counter_npcx_lct_init(const struct device *dev)
|
|
|
|
|
|
{
|
|
|
|
|
|
const struct counter_npcx_lct_config *const config = dev->config;
|
|
|
|
|
|
struct counter_npcx_lct_data *const data = dev->data;
|
|
|
|
|
|
struct lct_reg *const reg_base = config->reg_base;
|
|
|
|
|
|
|
|
|
|
|
|
#if defined(CONFIG_COUNTER_NPCX_NPCXN_V1) || defined(CONFIG_COUNTER_NPCX_NPCXN_V2)
|
|
|
|
|
|
npcx_miwu_init_dev_callback(&data->lct_wui_cb, &config->lct_wui, counter_npcx_lct_isr, dev);
|
|
|
|
|
|
npcx_miwu_manage_callback(&data->lct_wui_cb, true);
|
|
|
|
|
|
npcx_miwu_interrupt_configure(&config->lct_wui, NPCX_MIWU_MODE_EDGE, NPCX_MIWU_TRIG_HIGH);
|
|
|
|
|
|
/* Enable irq of t0-out expired event */
|
|
|
|
|
|
npcx_miwu_irq_enable(&config->lct_wui);
|
|
|
|
|
|
|
|
|
|
|
|
reg_base->LCTCONT |= BIT(NPCX_LCTCONT_LCT_CLK_EN);
|
|
|
|
|
|
|
|
|
|
|
|
#endif
|
|
|
|
|
|
#if defined(CONFIG_COUNTER_NPCX_NPCKN)
|
|
|
|
|
|
IRQ_CONNECT(DT_INST_IRQN(0), DT_INST_IRQ(0, priority), counter_npcx_lct_isr,
|
|
|
|
|
|
DEVICE_DT_INST_GET(0), 0);
|
|
|
|
|
|
irq_enable(DT_INST_IRQN(0));
|
|
|
|
|
|
#endif
|
|
|
|
|
|
|
|
|
|
|
|
k_sem_init(&data->lock, 1, 1);
|
|
|
|
|
|
|
|
|
|
|
|
if (config->pwr_by_vsby == true) {
|
|
|
|
|
|
reg_base->LCTCONT |= BIT(NPCX_LCTCONT_LCT_VSBY_PWR);
|
|
|
|
|
|
|
|
|
|
|
|
} else {
|
|
|
|
|
|
reg_base->LCTCONT &= ~BIT(NPCX_LCTCONT_LCT_VSBY_PWR);
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
static const struct counter_npcx_lct_config npcx_lct_cfg = {
|
|
|
|
|
|
.info = {
|
|
|
|
|
|
.channels = 1,
|
|
|
|
|
|
},
|
|
|
|
|
|
.reg_base = (struct lct_reg *)DT_INST_REG_ADDR(0),
|
|
|
|
|
|
.pwr_by_vsby = DT_INST_PROP(0, pwr_by_vsby),
|
|
|
|
|
|
#if defined(CONFIG_COUNTER_NPCX_NPCKN)
|
|
|
|
|
|
.irq = DT_INST_IRQN(0),
|
|
|
|
|
|
#endif
|
|
|
|
|
|
#if defined(CONFIG_COUNTER_NPCX_NPCXN_V1) || defined(CONFIG_COUNTER_NPCX_NPCXN_V2)
|
|
|
|
|
|
.lct_wui = NPCX_DT_WUI_ITEM_BY_NAME(0, lct_wui),
|
|
|
|
|
|
#endif
|
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
static struct counter_npcx_lct_data npcx_lct_data;
|
|
|
|
|
|
|
|
|
|
|
|
DEVICE_DT_INST_DEFINE(0, counter_npcx_lct_init, NULL, &npcx_lct_data, &npcx_lct_cfg, POST_KERNEL,
|
|
|
|
|
|
CONFIG_COUNTER_INIT_PRIORITY, &counter_npcx_lct_api);
|