feat: 添加Atguigu键盘板支持和IP5306电源管理驱动
添加了两个新的键盘板支持: - atguigu_keyboard_dongle (基于nrf52833) - atguigu_mini_keyboard (基于nrf52840) 同时添加了完整的IP5306电源管理芯片驱动,包括: - 支持充电状态检测 - 提供软硬件保活脉冲功能 - 硬件后端利用nRF的RTC+GPIOTE+GPPI实现低功耗保活 - 软件后端作为备用方案
This commit is contained in:
17
modules/ip5306/drivers/power/Kconfig
Normal file
17
modules/ip5306/drivers/power/Kconfig
Normal file
@@ -0,0 +1,17 @@
|
||||
config IP5306
|
||||
bool "Injoinic IP5306 PMIC driver"
|
||||
depends on I2C && GPIO
|
||||
default n
|
||||
help
|
||||
Enable IP5306 PMIC driver over I2C.
|
||||
|
||||
config IP5306_KEEPALIVE_HW_NRF
|
||||
bool "Enable nRF keepalive HW offload backend"
|
||||
depends on IP5306 && SOC_FAMILY_NORDIC_NRF
|
||||
select NRFX_GPIOTE
|
||||
select NRFX_GPPI
|
||||
select NRFX_RTC2
|
||||
default y
|
||||
help
|
||||
Enable low-power keepalive offload backend using RTC2 + GPIOTE + GPPI.
|
||||
Runtime selection is controlled by devicetree property keepalive-offload.
|
||||
152
modules/ip5306/drivers/power/ip5306.c
Normal file
152
modules/ip5306/drivers/power/ip5306.c
Normal file
@@ -0,0 +1,152 @@
|
||||
#include <errno.h>
|
||||
#include <stdbool.h>
|
||||
#include <stdint.h>
|
||||
|
||||
#include <zephyr/device.h>
|
||||
#include <zephyr/drivers/power/ip5306.h>
|
||||
#include <zephyr/logging/log.h>
|
||||
#include <zephyr/sys/util.h>
|
||||
|
||||
#include "ip5306_priv.h"
|
||||
|
||||
#if IS_ENABLED(CONFIG_IP5306_KEEPALIVE_HW_NRF)
|
||||
#include <soc_nrf_common.h>
|
||||
#define IP5306_CFG_KEEPALIVE_PSEL_INIT(inst) \
|
||||
.keepalive_psel = NRF_DT_GPIOS_TO_PSEL_OR(DT_DRV_INST(inst), keepalive_gpios, 0),
|
||||
#else
|
||||
#define IP5306_CFG_KEEPALIVE_PSEL_INIT(inst)
|
||||
#endif
|
||||
|
||||
LOG_MODULE_REGISTER(ip5306, LOG_LEVEL_INF);
|
||||
|
||||
#define DT_DRV_COMPAT injoinic_ip5306
|
||||
|
||||
#define IP5306_REG_READ0 0x70
|
||||
#define IP5306_REG_READ1 0x71
|
||||
#define IP5306_STATUS_BIT BIT(3)
|
||||
|
||||
static int ip5306_read_reg(const struct device *dev, uint8_t reg, uint8_t *val)
|
||||
{
|
||||
const struct ip5306_config *cfg = dev->config;
|
||||
|
||||
return i2c_reg_read_byte_dt(&cfg->i2c, reg, val);
|
||||
}
|
||||
|
||||
static int ip5306_get_status_bit(const struct device *dev, uint8_t reg, bool *flag)
|
||||
{
|
||||
uint8_t value = 0U;
|
||||
int ret;
|
||||
|
||||
if (flag == NULL) {
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
ret = ip5306_read_reg(dev, reg, &value);
|
||||
if (ret != 0) {
|
||||
return ret;
|
||||
}
|
||||
|
||||
*flag = ((value & IP5306_STATUS_BIT) != 0U);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int ip5306_api_is_charging(const struct device *dev, bool *charging)
|
||||
{
|
||||
return ip5306_get_status_bit(dev, IP5306_REG_READ0, charging);
|
||||
}
|
||||
|
||||
static int ip5306_api_is_charge_full(const struct device *dev, bool *full)
|
||||
{
|
||||
return ip5306_get_status_bit(dev, IP5306_REG_READ1, full);
|
||||
}
|
||||
|
||||
static void ip5306_keepalive_start(const struct device *dev)
|
||||
{
|
||||
struct ip5306_data *data = dev->data;
|
||||
const struct ip5306_config *cfg = dev->config;
|
||||
|
||||
if (!cfg->has_keepalive_gpio || (data->keepalive_interval_ms == 0U)) {
|
||||
data->backend = IP5306_KEEPALIVE_BACKEND_NONE;
|
||||
return;
|
||||
}
|
||||
|
||||
/*
|
||||
* 选择策略:
|
||||
* 1) DTS 显式请求硬件 offload 时,先尝试硬件后端;
|
||||
* 2) 若硬件依赖不可用或资源被占用,则告警后回退软件后端。
|
||||
*/
|
||||
if (cfg->keepalive_offload) {
|
||||
#if IS_ENABLED(CONFIG_IP5306_KEEPALIVE_HW_NRF)
|
||||
int ret = ip5306_keepalive_hw_nrf_start(dev);
|
||||
|
||||
if (ret == 0) {
|
||||
LOG_INF("Keepalive backend=HW(nRF), pulse=%ums interval=%ums",
|
||||
data->keepalive_pulse_ms, data->keepalive_interval_ms);
|
||||
return;
|
||||
}
|
||||
|
||||
LOG_WRN("HW keepalive unavailable (%d), fallback to SW backend", ret);
|
||||
#else
|
||||
LOG_WRN("HW keepalive requested but HW backend is not built, fallback to SW backend");
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
ip5306_keepalive_sw_start(dev);
|
||||
LOG_INF("Keepalive backend=SW, pulse=%ums interval=%ums",
|
||||
data->keepalive_pulse_ms, data->keepalive_interval_ms);
|
||||
}
|
||||
|
||||
static int ip5306_init(const struct device *dev)
|
||||
{
|
||||
const struct ip5306_config *cfg = dev->config;
|
||||
struct ip5306_data *data = dev->data;
|
||||
|
||||
if (!i2c_is_ready_dt(&cfg->i2c)) {
|
||||
return -ENODEV;
|
||||
}
|
||||
|
||||
if (cfg->has_keepalive_gpio) {
|
||||
if (!gpio_is_ready_dt(&cfg->keepalive_gpio)) {
|
||||
return -ENODEV;
|
||||
}
|
||||
|
||||
if (gpio_pin_configure_dt(&cfg->keepalive_gpio, GPIO_OUTPUT_INACTIVE) != 0) {
|
||||
return -EIO;
|
||||
}
|
||||
}
|
||||
|
||||
data->keepalive_high = false;
|
||||
data->dev = dev;
|
||||
data->backend = IP5306_KEEPALIVE_BACKEND_NONE;
|
||||
data->keepalive_pulse_ms = (cfg->keepalive_pulse_ms != 0U) ?
|
||||
cfg->keepalive_pulse_ms : IP5306_KEEPALIVE_DEFAULT_PULSE_MS;
|
||||
data->keepalive_interval_ms = (cfg->keepalive_interval_ms != 0U) ?
|
||||
cfg->keepalive_interval_ms : IP5306_KEEPALIVE_DEFAULT_INTERVAL_MS;
|
||||
|
||||
ip5306_keepalive_start(dev);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static const struct ip5306_driver_api ip5306_api = {
|
||||
.is_charging = ip5306_api_is_charging,
|
||||
.is_charge_full = ip5306_api_is_charge_full,
|
||||
};
|
||||
|
||||
#define IP5306_DEFINE(inst) \
|
||||
static struct ip5306_data ip5306_data_##inst; \
|
||||
static const struct ip5306_config ip5306_cfg_##inst = { \
|
||||
.i2c = I2C_DT_SPEC_INST_GET(inst), \
|
||||
.keepalive_gpio = GPIO_DT_SPEC_INST_GET_OR(inst, keepalive_gpios, {0}), \
|
||||
IP5306_CFG_KEEPALIVE_PSEL_INIT(inst) \
|
||||
.keepalive_pulse_ms = DT_INST_PROP(inst, keepalive_pulse_ms), \
|
||||
.keepalive_interval_ms = DT_INST_PROP(inst, keepalive_interval_ms), \
|
||||
.has_keepalive_gpio = DT_INST_NODE_HAS_PROP(inst, keepalive_gpios), \
|
||||
.keepalive_offload = DT_INST_PROP_OR(inst, keepalive_offload, false), \
|
||||
}; \
|
||||
DEVICE_DT_INST_DEFINE(inst, ip5306_init, NULL, &ip5306_data_##inst, \
|
||||
&ip5306_cfg_##inst, POST_KERNEL, CONFIG_KERNEL_INIT_PRIORITY_DEVICE, \
|
||||
&ip5306_api);
|
||||
|
||||
DT_INST_FOREACH_STATUS_OKAY(IP5306_DEFINE)
|
||||
198
modules/ip5306/drivers/power/ip5306_keepalive_nrf.c
Normal file
198
modules/ip5306/drivers/power/ip5306_keepalive_nrf.c
Normal file
@@ -0,0 +1,198 @@
|
||||
#include <errno.h>
|
||||
|
||||
#include <hal/nrf_rtc.h>
|
||||
#include <nrfx_gpiote.h>
|
||||
#include <nrfx_rtc.h>
|
||||
|
||||
#include <helpers/nrfx_gppi.h>
|
||||
|
||||
#include <zephyr/drivers/gpio.h>
|
||||
#include <zephyr/logging/log.h>
|
||||
#include <zephyr/sys/util.h>
|
||||
|
||||
#include "ip5306_priv.h"
|
||||
|
||||
LOG_MODULE_DECLARE(ip5306, LOG_LEVEL_INF);
|
||||
|
||||
#define IP5306_KEEPALIVE_RTC_FREQUENCY_HZ 32768U
|
||||
#define IP5306_KEEPALIVE_RTC_CC_HIGH 0U
|
||||
#define IP5306_KEEPALIVE_RTC_CC_LOW 1U
|
||||
#define IP5306_KEEPALIVE_RTC_CC_PERIOD 2U
|
||||
#define IP5306_KEEPALIVE_MIN_PERIOD_TICKS 3U
|
||||
|
||||
/* nRF52 单核场景默认使用 GPIOTE0 + RTC2。 */
|
||||
static nrfx_gpiote_t ip5306_keepalive_gpiote = NRFX_GPIOTE_INSTANCE(NRF_GPIOTE_INST_GET(0));
|
||||
static const nrfx_rtc_t ip5306_keepalive_rtc = NRFX_RTC_INSTANCE(2);
|
||||
static bool ip5306_keepalive_hw_claimed;
|
||||
|
||||
static void ip5306_keepalive_rtc_handler(nrfx_rtc_int_type_t int_type)
|
||||
{
|
||||
/*
|
||||
* 这里故意不处理任何中断逻辑:
|
||||
* 本模块的保活脉冲由 RTC event -> GPPI/PPI -> GPIOTE task 的硬件链路完成,
|
||||
* 不依赖线程或 ISR 参与,从而减少 CPU 唤醒次数、降低功耗。
|
||||
*/
|
||||
ARG_UNUSED(int_type);
|
||||
}
|
||||
|
||||
static uint32_t ip5306_keepalive_ms_to_rtc_ticks(uint32_t time_ms)
|
||||
{
|
||||
/* 四舍五入到最近 tick,降低长时间运行时累计漂移。 */
|
||||
uint64_t ticks = ((uint64_t)time_ms * IP5306_KEEPALIVE_RTC_FREQUENCY_HZ + 500U) / 1000U;
|
||||
|
||||
return (uint32_t)MAX(ticks, 1U);
|
||||
}
|
||||
|
||||
int ip5306_keepalive_hw_nrf_start(const struct device *dev)
|
||||
{
|
||||
struct ip5306_data *data = dev->data;
|
||||
const struct ip5306_config *cfg = dev->config;
|
||||
const bool active_high = ((cfg->keepalive_gpio.dt_flags & GPIO_ACTIVE_LOW) == 0U);
|
||||
const uint32_t period_ticks = ip5306_keepalive_ms_to_rtc_ticks(data->keepalive_interval_ms);
|
||||
uint32_t high_ticks = ip5306_keepalive_ms_to_rtc_ticks(data->keepalive_pulse_ms);
|
||||
int ret;
|
||||
|
||||
if (ip5306_keepalive_hw_claimed) {
|
||||
return -EBUSY;
|
||||
}
|
||||
|
||||
if (period_ticks < IP5306_KEEPALIVE_MIN_PERIOD_TICKS) {
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
if (high_ticks >= (period_ticks - 1U)) {
|
||||
high_ticks = period_ticks - 1U;
|
||||
}
|
||||
|
||||
if (!nrfx_gpiote_init_check(&ip5306_keepalive_gpiote)) {
|
||||
ret = nrfx_gpiote_init(&ip5306_keepalive_gpiote, NRFX_GPIOTE_DEFAULT_CONFIG_IRQ_PRIORITY);
|
||||
if ((ret != 0) && (ret != -EALREADY)) {
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
|
||||
ret = nrfx_gpiote_channel_alloc(&ip5306_keepalive_gpiote, &data->keepalive_gpiote_channel);
|
||||
if (ret != 0) {
|
||||
/* GPIOTE 通道不足通常意味着被其他驱动占用。 */
|
||||
LOG_ERR("Failed to allocate GPIOTE channel");
|
||||
return ret;
|
||||
}
|
||||
|
||||
const nrfx_gpiote_output_config_t output_config = {
|
||||
.drive = NRF_GPIO_PIN_S0S1,
|
||||
.input_connect = NRF_GPIO_PIN_INPUT_DISCONNECT,
|
||||
.pull = NRF_GPIO_PIN_NOPULL,
|
||||
};
|
||||
const nrfx_gpiote_task_config_t task_config = {
|
||||
.task_ch = data->keepalive_gpiote_channel,
|
||||
.polarity = NRF_GPIOTE_POLARITY_TOGGLE,
|
||||
.init_val = active_high ? NRF_GPIOTE_INITIAL_VALUE_LOW : NRF_GPIOTE_INITIAL_VALUE_HIGH,
|
||||
};
|
||||
|
||||
ret = nrfx_gpiote_output_configure(&ip5306_keepalive_gpiote, cfg->keepalive_psel,
|
||||
&output_config, &task_config);
|
||||
if (ret != 0) {
|
||||
goto err_free_channel;
|
||||
}
|
||||
|
||||
nrfx_gpiote_out_task_enable(&ip5306_keepalive_gpiote, cfg->keepalive_psel);
|
||||
nrfx_gpiote_out_task_force(&ip5306_keepalive_gpiote, cfg->keepalive_psel, active_high ? 0U : 1U);
|
||||
|
||||
/*
|
||||
* RTC2 初始化前先检查是否已被外部占用:
|
||||
* 若占用则直接返回 -EBUSY,让上层走软件保活回退。
|
||||
*/
|
||||
if (nrfx_rtc_init_check(&ip5306_keepalive_rtc)) {
|
||||
ret = -EBUSY;
|
||||
goto err_disable_task;
|
||||
}
|
||||
|
||||
const nrfx_rtc_config_t rtc_cfg = NRFX_RTC_DEFAULT_CONFIG;
|
||||
|
||||
ret = nrfx_rtc_init(&ip5306_keepalive_rtc, &rtc_cfg, ip5306_keepalive_rtc_handler);
|
||||
if ((ret != 0) && (ret != -EALREADY)) {
|
||||
goto err_disable_task;
|
||||
}
|
||||
|
||||
nrfx_rtc_disable(&ip5306_keepalive_rtc);
|
||||
nrfx_rtc_counter_clear(&ip5306_keepalive_rtc);
|
||||
|
||||
/*
|
||||
* RTC 角色:时间基准,按 compare 点产生事件。
|
||||
* - CC0 到点 -> 产生 COMPARE0 event(脉冲上升沿触发点)
|
||||
* - CC1 到点 -> 产生 COMPARE1 event(脉冲下降沿触发点)
|
||||
* - CC2 到点 -> 触发周期边界,配合 SHORT 实现自动循环
|
||||
*/
|
||||
ret = nrfx_rtc_cc_set(&ip5306_keepalive_rtc, IP5306_KEEPALIVE_RTC_CC_HIGH, period_ticks - high_ticks - 10U, false);
|
||||
if (ret != 0) {
|
||||
goto err_disable_task;
|
||||
}
|
||||
|
||||
ret = nrfx_rtc_cc_set(&ip5306_keepalive_rtc, IP5306_KEEPALIVE_RTC_CC_LOW, period_ticks - 10U, false);
|
||||
if (ret != 0) {
|
||||
goto err_disable_task;
|
||||
}
|
||||
|
||||
ret = nrfx_rtc_cc_set(&ip5306_keepalive_rtc, IP5306_KEEPALIVE_RTC_CC_PERIOD, period_ticks, false);
|
||||
if (ret != 0) {
|
||||
goto err_disable_task;
|
||||
}
|
||||
|
||||
const uint32_t set_task = active_high ?
|
||||
nrfx_gpiote_set_task_address_get(&ip5306_keepalive_gpiote, cfg->keepalive_psel) :
|
||||
nrfx_gpiote_clr_task_address_get(&ip5306_keepalive_gpiote, cfg->keepalive_psel);
|
||||
const uint32_t clr_task = active_high ?
|
||||
nrfx_gpiote_clr_task_address_get(&ip5306_keepalive_gpiote, cfg->keepalive_psel) :
|
||||
nrfx_gpiote_set_task_address_get(&ip5306_keepalive_gpiote, cfg->keepalive_psel);
|
||||
const uint32_t high_event = nrfx_rtc_event_address_get(&ip5306_keepalive_rtc, NRF_RTC_EVENT_COMPARE_0);
|
||||
const uint32_t low_event = nrfx_rtc_event_address_get(&ip5306_keepalive_rtc, NRF_RTC_EVENT_COMPARE_1);
|
||||
const uint32_t period_event = nrfx_rtc_event_address_get(&ip5306_keepalive_rtc, NRF_RTC_EVENT_COMPARE_2);
|
||||
const uint32_t clear_task = nrfx_rtc_task_address_get(&ip5306_keepalive_rtc, NRF_RTC_TASK_CLEAR);
|
||||
|
||||
/*
|
||||
* GPPI/PPI 角色:事件路由器。
|
||||
* 将 RTC compare event 直接连接到 GPIOTE task,不经过线程/ISR。
|
||||
*/
|
||||
ret = nrfx_gppi_conn_alloc(high_event, set_task, &data->keepalive_set_handle);
|
||||
if (ret != 0) {
|
||||
goto err_disable_task;
|
||||
}
|
||||
|
||||
ret = nrfx_gppi_conn_alloc(low_event, clr_task, &data->keepalive_clr_handle);
|
||||
if (ret != 0) {
|
||||
nrfx_gppi_conn_free(high_event, set_task, data->keepalive_set_handle);
|
||||
goto err_disable_task;
|
||||
}
|
||||
|
||||
/*
|
||||
* 某些 SoC/SDK 组合下 RTC SHORT 宏不可用,因此这里用第三条 GPPI 链路实现“周期自动清零”。
|
||||
* 这样仍保持纯硬件闭环:COMPARE2 event -> RTC CLEAR task,不需要 CPU/ISR 参与。
|
||||
*/
|
||||
ret = nrfx_gppi_conn_alloc(period_event, clear_task, &data->keepalive_period_handle);
|
||||
if (ret != 0) {
|
||||
nrfx_gppi_conn_free(low_event, clr_task, data->keepalive_clr_handle);
|
||||
nrfx_gppi_conn_free(high_event, set_task, data->keepalive_set_handle);
|
||||
goto err_disable_task;
|
||||
}
|
||||
|
||||
/*
|
||||
* GPIOTE 角色:GPIO 执行器。
|
||||
* 收到 task 后立即对目标 pin 执行 SET/CLR,输出保活脉冲波形。
|
||||
*/
|
||||
nrfx_gppi_conn_enable(data->keepalive_set_handle);
|
||||
nrfx_gppi_conn_enable(data->keepalive_clr_handle);
|
||||
nrfx_gppi_conn_enable(data->keepalive_period_handle);
|
||||
nrfx_rtc_enable(&ip5306_keepalive_rtc);
|
||||
|
||||
ip5306_keepalive_hw_claimed = true;
|
||||
data->backend = IP5306_KEEPALIVE_BACKEND_HW_NRF;
|
||||
data->dev = dev;
|
||||
|
||||
return 0;
|
||||
|
||||
err_disable_task:
|
||||
nrfx_gpiote_out_task_disable(&ip5306_keepalive_gpiote, cfg->keepalive_psel);
|
||||
err_free_channel:
|
||||
(void)nrfx_gpiote_channel_free(&ip5306_keepalive_gpiote, data->keepalive_gpiote_channel);
|
||||
return ret;
|
||||
}
|
||||
54
modules/ip5306/drivers/power/ip5306_keepalive_sw.c
Normal file
54
modules/ip5306/drivers/power/ip5306_keepalive_sw.c
Normal file
@@ -0,0 +1,54 @@
|
||||
#include <zephyr/logging/log.h>
|
||||
#include <zephyr/sys/util.h>
|
||||
|
||||
#include "ip5306_priv.h"
|
||||
|
||||
LOG_MODULE_DECLARE(ip5306, LOG_LEVEL_INF);
|
||||
|
||||
void ip5306_keepalive_sw_work_handler(struct k_work *work)
|
||||
{
|
||||
struct k_work_delayable *dwork = k_work_delayable_from_work(work);
|
||||
struct ip5306_data *data = CONTAINER_OF(dwork, struct ip5306_data, keepalive_work);
|
||||
const struct ip5306_config *cfg = data->dev->config;
|
||||
int ret;
|
||||
|
||||
if ((data->backend != IP5306_KEEPALIVE_BACKEND_SW) || (data->keepalive_interval_ms == 0U))
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if (!data->keepalive_high)
|
||||
{
|
||||
ret = gpio_pin_set_dt(&cfg->keepalive_gpio, GPIO_OUTPUT_ACTIVE);
|
||||
if (ret != 0)
|
||||
{
|
||||
LOG_ERR("SW keepalive set high failed: %d", ret);
|
||||
(void)k_work_schedule(&data->keepalive_work, K_MSEC(data->keepalive_interval_ms));
|
||||
return;
|
||||
}
|
||||
|
||||
data->keepalive_high = true;
|
||||
(void)k_work_schedule(&data->keepalive_work, K_MSEC(data->keepalive_pulse_ms));
|
||||
}
|
||||
else
|
||||
{
|
||||
ret = gpio_pin_set_dt(&cfg->keepalive_gpio, GPIO_OUTPUT_INACTIVE);
|
||||
if (ret != 0)
|
||||
{
|
||||
LOG_ERR("SW keepalive set low failed: %d", ret);
|
||||
}
|
||||
|
||||
data->keepalive_high = false;
|
||||
(void)k_work_schedule(&data->keepalive_work, K_MSEC(data->keepalive_interval_ms));
|
||||
}
|
||||
}
|
||||
|
||||
int ip5306_keepalive_sw_start(const struct device *dev)
|
||||
{
|
||||
struct ip5306_data *data = dev->data;
|
||||
|
||||
data->backend = IP5306_KEEPALIVE_BACKEND_SW;
|
||||
data->dev = dev;
|
||||
k_work_init_delayable(&data->keepalive_work, ip5306_keepalive_sw_work_handler);
|
||||
return (int)k_work_schedule(&data->keepalive_work, K_MSEC(data->keepalive_interval_ms));
|
||||
}
|
||||
58
modules/ip5306/drivers/power/ip5306_priv.h
Normal file
58
modules/ip5306/drivers/power/ip5306_priv.h
Normal file
@@ -0,0 +1,58 @@
|
||||
#ifndef IP5306_KEEPALIVE_PRIV_H_
|
||||
#define IP5306_KEEPALIVE_PRIV_H_
|
||||
|
||||
#include <stdbool.h>
|
||||
#include <stdint.h>
|
||||
|
||||
#include <zephyr/device.h>
|
||||
#include <zephyr/drivers/gpio.h>
|
||||
#include <zephyr/drivers/i2c.h>
|
||||
#include <zephyr/kernel.h>
|
||||
#include <zephyr/sys/util.h>
|
||||
|
||||
#if IS_ENABLED(CONFIG_IP5306_KEEPALIVE_HW_NRF)
|
||||
#include <helpers/nrfx_gppi.h>
|
||||
#endif
|
||||
|
||||
#define IP5306_KEEPALIVE_DEFAULT_PULSE_MS 100U
|
||||
#define IP5306_KEEPALIVE_DEFAULT_INTERVAL_MS 20000U
|
||||
|
||||
enum ip5306_keepalive_backend {
|
||||
IP5306_KEEPALIVE_BACKEND_NONE,
|
||||
IP5306_KEEPALIVE_BACKEND_SW,
|
||||
IP5306_KEEPALIVE_BACKEND_HW_NRF,
|
||||
};
|
||||
|
||||
struct ip5306_config {
|
||||
struct i2c_dt_spec i2c;
|
||||
struct gpio_dt_spec keepalive_gpio;
|
||||
#if IS_ENABLED(CONFIG_IP5306_KEEPALIVE_HW_NRF)
|
||||
uint32_t keepalive_psel;
|
||||
#endif
|
||||
uint32_t keepalive_pulse_ms;
|
||||
uint32_t keepalive_interval_ms;
|
||||
bool has_keepalive_gpio;
|
||||
bool keepalive_offload;
|
||||
};
|
||||
|
||||
struct ip5306_data {
|
||||
struct k_work_delayable keepalive_work;
|
||||
bool keepalive_high;
|
||||
uint32_t keepalive_pulse_ms;
|
||||
uint32_t keepalive_interval_ms;
|
||||
enum ip5306_keepalive_backend backend;
|
||||
const struct device *dev;
|
||||
|
||||
#if IS_ENABLED(CONFIG_IP5306_KEEPALIVE_HW_NRF)
|
||||
uint8_t keepalive_gpiote_channel;
|
||||
nrfx_gppi_handle_t keepalive_set_handle;
|
||||
nrfx_gppi_handle_t keepalive_clr_handle;
|
||||
nrfx_gppi_handle_t keepalive_period_handle;
|
||||
#endif
|
||||
};
|
||||
|
||||
int ip5306_keepalive_sw_start(const struct device *dev);
|
||||
|
||||
int ip5306_keepalive_hw_nrf_start(const struct device *dev);
|
||||
|
||||
#endif /* IP5306_KEEPALIVE_PRIV_H_ */
|
||||
Reference in New Issue
Block a user