Browse Source
Add tachometer driver for Realtek rts5912. Signed-off-by: Jhan BoChao <jhan_bo_chao@realtek.com>pull/88608/head
11 changed files with 261 additions and 0 deletions
@ -0,0 +1,4 @@
@@ -0,0 +1,4 @@
|
||||
# Copyright (c) 2025, Realtek, SIBG-SD7 |
||||
# SPDX-License-Identifier: Apache-2.0 |
||||
|
||||
add_subdirectory_ifdef(CONFIG_TACH_RTS5912 rts5912) |
@ -0,0 +1,4 @@
@@ -0,0 +1,4 @@
|
||||
# Copyright (c) 2025, Realtek, SIBG-SD7 |
||||
# SPDX-License-Identifier: Apache-2.0 |
||||
|
||||
source "drivers/sensor/realtek/rts5912/Kconfig" |
@ -0,0 +1,6 @@
@@ -0,0 +1,6 @@
|
||||
# Copyright (c) 2025, Realtek, SIBG-SD7 |
||||
# SPDX-License-Identifier: Apache-2.0 |
||||
|
||||
zephyr_library() |
||||
|
||||
zephyr_library_sources(rts5912.c) |
@ -0,0 +1,9 @@
@@ -0,0 +1,9 @@
|
||||
# Copyright (c) 2025, Realtek, SIBG-SD7 |
||||
# SPDX-License-Identifier: Apache-2.0 |
||||
|
||||
config TACH_RTS5912 |
||||
bool "RTS5912 Tachometer sensor" |
||||
default y |
||||
depends on DT_HAS_REALTEK_RTS5912_TACH_ENABLED |
||||
help |
||||
Enable the Realtek RTS5912 tachometer sensor. |
@ -0,0 +1,150 @@
@@ -0,0 +1,150 @@
|
||||
/*
|
||||
* Copyright (c) 2025 Realtek, SIBG-SD7 |
||||
* |
||||
* SPDX-License-Identifier: Apache-2.0 |
||||
*/ |
||||
|
||||
#define DT_DRV_COMPAT realtek_rts5912_tach |
||||
|
||||
#include <errno.h> |
||||
#include <zephyr/device.h> |
||||
#include <zephyr/drivers/clock_control.h> |
||||
#include <zephyr/drivers/clock_control/clock_control_rts5912.h> |
||||
#include <zephyr/drivers/pinctrl.h> |
||||
#include <zephyr/drivers/sensor.h> |
||||
#include <zephyr/sys/sys_io.h> |
||||
#include <zephyr/logging/log.h> |
||||
|
||||
#include "reg/reg_tacho.h" |
||||
|
||||
LOG_MODULE_REGISTER(tach_rts5912, CONFIG_SENSOR_LOG_LEVEL); |
||||
|
||||
struct tach_rts5912_config { |
||||
volatile struct tacho_regs *regs; |
||||
uint32_t clk_grp; |
||||
uint32_t clk_idx; |
||||
uint32_t clk_src; |
||||
uint32_t clk_div; |
||||
const struct device *clk_dev; |
||||
const struct pinctrl_dev_config *pcfg; |
||||
int pulses_per_round; |
||||
}; |
||||
|
||||
struct tach_rts5912_data { |
||||
uint16_t count; |
||||
}; |
||||
|
||||
#define COUNT_100KHZ_SEC 100000U |
||||
#define SEC_TO_MINUTE 60U |
||||
#define PIN_STUCK_TIMEOUT (100U * USEC_PER_MSEC) |
||||
|
||||
int tach_rts5912_sample_fetch(const struct device *dev, enum sensor_channel chan) |
||||
{ |
||||
const struct tach_rts5912_config *const cfg = dev->config; |
||||
struct tach_rts5912_data *const data = dev->data; |
||||
volatile struct tacho_regs *const tach = cfg->regs; |
||||
|
||||
if (chan != SENSOR_CHAN_RPM && chan != SENSOR_CHAN_ALL) { |
||||
return -ENOTSUP; |
||||
} |
||||
|
||||
tach->status = TACHO_STS_CNTRDY; |
||||
|
||||
if (WAIT_FOR(tach->status & TACHO_STS_CNTRDY, PIN_STUCK_TIMEOUT, k_msleep(1))) { |
||||
/* See whether internal counter is already latched */ |
||||
if (tach->status & TACHO_STS_CNTRDY) { |
||||
tach->status = TACHO_STS_CNTRDY; |
||||
data->count = (tach->ctrl & TACHO_CTRL_CNT_Msk) >> TACHO_CTRL_CNT_Pos; |
||||
} |
||||
} else { |
||||
data->count = 0; |
||||
} |
||||
|
||||
return 0; |
||||
} |
||||
|
||||
static int tach_rts5912_channel_get(const struct device *dev, enum sensor_channel chan, |
||||
struct sensor_value *val) |
||||
{ |
||||
const struct tach_rts5912_config *const cfg = dev->config; |
||||
struct tach_rts5912_data *const data = dev->data; |
||||
|
||||
if (chan != SENSOR_CHAN_RPM) { |
||||
return -ENOTSUP; |
||||
} |
||||
|
||||
/* Convert the count per 100khz cycles to rpm */ |
||||
if (data->count != 0U) { |
||||
val->val1 = |
||||
(SEC_TO_MINUTE * COUNT_100KHZ_SEC) / (cfg->pulses_per_round * data->count); |
||||
} else { |
||||
val->val1 = 0U; |
||||
} |
||||
|
||||
val->val2 = 0U; |
||||
|
||||
return 0; |
||||
} |
||||
|
||||
static int tach_rts5912_init(const struct device *dev) |
||||
{ |
||||
const struct tach_rts5912_config *const cfg = dev->config; |
||||
volatile struct tacho_regs *const tach = cfg->regs; |
||||
int ret; |
||||
|
||||
struct rts5912_sccon_subsys sccon_subsys = { |
||||
.clk_grp = cfg->clk_grp, |
||||
.clk_idx = cfg->clk_idx, |
||||
}; |
||||
|
||||
if (!device_is_ready(cfg->clk_dev)) { |
||||
return -ENODEV; |
||||
} |
||||
|
||||
ret = clock_control_on(cfg->clk_dev, (clock_control_subsys_t)&sccon_subsys); |
||||
if (ret != 0) { |
||||
LOG_ERR("RTS5912 Tachometer clock control failed (%d)", ret); |
||||
return ret; |
||||
} |
||||
|
||||
#ifdef CONFIG_PINCTRL |
||||
ret = pinctrl_apply_state(cfg->pcfg, PINCTRL_STATE_DEFAULT); |
||||
|
||||
if (ret != 0) { |
||||
LOG_ERR("RTS5912 pinctrl failed (%d)", ret); |
||||
return ret; |
||||
} |
||||
#endif |
||||
|
||||
/* write one clear the status */ |
||||
tach->status = TACHO_STS_LIMIT | TACHO_STS_CHG | TACHO_STS_CNTRDY; |
||||
tach->ctrl &= ~TACHO_CTRL_SELEDGE_Msk; |
||||
tach->ctrl = ((0x01ul << TACHO_CTRL_SELEDGE_Pos) | TACHO_CTRL_READMODE | TACHO_CTRL_EN); |
||||
|
||||
return 0; |
||||
} |
||||
|
||||
static DEVICE_API(sensor, tach_rts5912_driver_api) = { |
||||
.sample_fetch = tach_rts5912_sample_fetch, |
||||
.channel_get = tach_rts5912_channel_get, |
||||
}; |
||||
|
||||
#define REALTEK_TACH_INIT(inst) \ |
||||
PINCTRL_DT_INST_DEFINE(inst); \ |
||||
\ |
||||
static const struct tach_rts5912_config tach_cfg_##inst = { \ |
||||
.regs = (struct tacho_regs *const)DT_INST_REG_ADDR(inst), \ |
||||
.pcfg = PINCTRL_DT_INST_DEV_CONFIG_GET(inst), \ |
||||
.clk_dev = DEVICE_DT_GET(DT_INST_CLOCKS_CTLR(inst)), \ |
||||
.clk_grp = DT_INST_CLOCKS_CELL_BY_NAME(inst, tacho, clk_grp), \ |
||||
.clk_idx = DT_INST_CLOCKS_CELL_BY_NAME(inst, tacho, clk_idx), \ |
||||
.pulses_per_round = DT_INST_PROP(inst, pulses_per_round), \ |
||||
}; \ |
||||
\ |
||||
static struct tach_rts5912_data tach_data_##inst; \ |
||||
\ |
||||
SENSOR_DEVICE_DT_INST_DEFINE(inst, tach_rts5912_init, NULL, &tach_data_##inst, \ |
||||
&tach_cfg_##inst, POST_KERNEL, CONFIG_SENSOR_INIT_PRIORITY, \ |
||||
&tach_rts5912_driver_api); |
||||
|
||||
DT_INST_FOREACH_STATUS_OKAY(REALTEK_TACH_INIT) |
@ -0,0 +1,28 @@
@@ -0,0 +1,28 @@
|
||||
# SPDX-License-Identifier: Apache-2.0 |
||||
# |
||||
# Copyright (c) 2025 Realtek Semiconductor Corporation, SIBG-SD7 |
||||
# |
||||
|
||||
description: Realtek rts5912 tachometer controller |
||||
|
||||
compatible: "realtek,rts5912-tach" |
||||
|
||||
include: [tach.yaml, pinctrl-device.yaml, sensor-device.yaml] |
||||
|
||||
properties: |
||||
reg: |
||||
required: true |
||||
|
||||
interrupts: |
||||
required: true |
||||
|
||||
pinctrl-0: |
||||
required: true |
||||
|
||||
pinctrl-names: |
||||
required: true |
||||
|
||||
pulses-per-round: |
||||
type: int |
||||
required: true |
||||
description: number of pulses per round of tachometer's input |
@ -0,0 +1,42 @@
@@ -0,0 +1,42 @@
|
||||
/*
|
||||
* Copyright (c) 2025 Realtek, SIBG-SD7 |
||||
* |
||||
* SPDX-License-Identifier: Apache-2.0 |
||||
*/ |
||||
|
||||
#ifndef ZEPHYR_SOC_REALTEK_RTS5912_REG_TACHO_H |
||||
#define ZEPHYR_SOC_REALTEK_RTS5912_REG_TACHO_H |
||||
|
||||
struct tacho_regs { |
||||
uint32_t ctrl; |
||||
uint32_t status; |
||||
uint32_t limit_high; |
||||
uint32_t limit_low; |
||||
uint32_t int_en; |
||||
}; |
||||
|
||||
/* CTRL */ |
||||
#define TACHO_CTRL_EN BIT(0UL) |
||||
#define TACHO_CTRL_FILTEREN BIT(1UL) |
||||
#define TACHO_CTRL_SELEDGE_Pos (2UL) |
||||
#define TACHO_CTRL_SELEDGE_Msk GENMASK(3, TACHO_CTRL_SELEDGE_Pos) |
||||
#define TACHO_CTRL_READMODE BIT(4UL) |
||||
#define TACHO_CTRL_CNT_Pos (16UL) |
||||
#define TACHO_CTRL_CNT_Msk GENMASK(31, TACHO_CTRL_CNT_Pos) |
||||
/* STS */ |
||||
#define TACHO_STS_LIMIT BIT(0UL) |
||||
#define TACHO_STS_PIN BIT(1UL) |
||||
#define TACHO_STS_CHG BIT(2UL) |
||||
#define TACHO_STS_CNTRDY BIT(3UL) |
||||
/* LIMITH */ |
||||
#define TACHO_LIMITH_VAL_Pos (0UL) |
||||
#define TACHO_LIMITH_VAL_Msk GENMASK(15, TACHO_LIMITH_VAL_Pos) |
||||
/* LIMITL */ |
||||
#define TACHO_LIMITL_VAL_Pos (0UL) |
||||
#define TACHO_LIMITL_VAL_Msk GENMASK(15, TACHO_LIMITL_VAL_Pos) |
||||
/* INTEN */ |
||||
#define TACHO_INTEN_LIMITEN BIT(0UL) |
||||
#define TACHO_INTEN_CNTRDYEN BIT(1UL) |
||||
#define TACHO_INTEN_CHGEN BIT(2UL) |
||||
|
||||
#endif /* ZEPHYR_SOC_REALTEK_RTS5912_REG_TACHO_H */ |
Loading…
Reference in new issue