Browse Source

driver: sensor: add tachometer driver for rts5912

Add tachometer driver for Realtek rts5912.

Signed-off-by: Jhan BoChao <jhan_bo_chao@realtek.com>
pull/88608/head
Jhan BoChao 4 months ago committed by Benjamin Cabé
parent
commit
482d17f235
  1. 7
      boards/realtek/rts5912_evb/rts5912_evb.dts
  2. 1
      drivers/sensor/CMakeLists.txt
  3. 1
      drivers/sensor/Kconfig
  4. 4
      drivers/sensor/realtek/CMakeLists.txt
  5. 4
      drivers/sensor/realtek/Kconfig
  6. 6
      drivers/sensor/realtek/rts5912/CMakeLists.txt
  7. 9
      drivers/sensor/realtek/rts5912/Kconfig
  8. 150
      drivers/sensor/realtek/rts5912/rts5912.c
  9. 9
      dts/arm/realtek/ec/rts5912.dtsi
  10. 28
      dts/bindings/tach/realtek,rts5912-tach.yaml
  11. 42
      soc/realtek/ec/rts5912/reg/reg_tacho.h

7
boards/realtek/rts5912_evb/rts5912_evb.dts

@ -53,3 +53,10 @@ @@ -53,3 +53,10 @@
&swj_port {
status = "okay";
};
&tach0 {
status = "okay";
pinctrl-0 = <&tacho0_gpio052>;
pinctrl-names = "default";
pulses-per-round = <2>;
};

1
drivers/sensor/CMakeLists.txt

@ -22,6 +22,7 @@ add_subdirectory(nordic) @@ -22,6 +22,7 @@ add_subdirectory(nordic)
add_subdirectory(nuvoton)
add_subdirectory(nxp)
add_subdirectory(pixart)
add_subdirectory(realtek)
add_subdirectory(renesas)
add_subdirectory(rohm)
add_subdirectory(seeed)

1
drivers/sensor/Kconfig

@ -108,6 +108,7 @@ source "drivers/sensor/nordic/Kconfig" @@ -108,6 +108,7 @@ source "drivers/sensor/nordic/Kconfig"
source "drivers/sensor/nuvoton/Kconfig"
source "drivers/sensor/nxp/Kconfig"
source "drivers/sensor/pixart/Kconfig"
source "drivers/sensor/realtek/Kconfig"
source "drivers/sensor/renesas/Kconfig"
source "drivers/sensor/rohm/Kconfig"
source "drivers/sensor/seeed/Kconfig"

4
drivers/sensor/realtek/CMakeLists.txt

@ -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)

4
drivers/sensor/realtek/Kconfig

@ -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"

6
drivers/sensor/realtek/rts5912/CMakeLists.txt

@ -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)

9
drivers/sensor/realtek/rts5912/Kconfig

@ -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.

150
drivers/sensor/realtek/rts5912/rts5912.c

@ -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)

9
dts/arm/realtek/ec/rts5912.dtsi

@ -267,6 +267,15 @@ @@ -267,6 +267,15 @@
interrupt-parent = <&nvic>;
status = "disabled";
};
tach0: tach@4000fd00 {
compatible = "realtek,rts5912-tach";
reg = <0x4000fd00 0x40>;
clocks = <&sccon RTS5912_SCCON_PERIPH_GRP0 PERIPH_GRP0_TACH0_CLKPWR>;
clock-names = "tacho";
interrupts = <192 0>;
status = "disabled";
};
};
swj_port: swj-port {

28
dts/bindings/tach/realtek,rts5912-tach.yaml

@ -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

42
soc/realtek/ec/rts5912/reg/reg_tacho.h

@ -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…
Cancel
Save