diff --git a/drivers/sensor/CMakeLists.txt b/drivers/sensor/CMakeLists.txt index d6e60d6b380..86f65c04ee4 100644 --- a/drivers/sensor/CMakeLists.txt +++ b/drivers/sensor/CMakeLists.txt @@ -172,6 +172,7 @@ add_subdirectory_ifdef(CONFIG_WSEN_PADS wsen_pads) add_subdirectory_ifdef(CONFIG_WSEN_PDUS wsen_pdus) add_subdirectory_ifdef(CONFIG_WSEN_TIDS wsen_tids) add_subdirectory_ifdef(CONFIG_XMC4XXX_TEMP xmc4xxx_temp) +add_subdirectory_ifdef(CONFIG_TACH_ENE_KB1200 ene_tach_kb1200) zephyr_syscall_header(${ZEPHYR_BASE}/include/zephyr/drivers/sensor.h) diff --git a/drivers/sensor/Kconfig b/drivers/sensor/Kconfig index d3957f257b9..f939950d01c 100644 --- a/drivers/sensor/Kconfig +++ b/drivers/sensor/Kconfig @@ -252,5 +252,6 @@ source "drivers/sensor/wsen_pads/Kconfig" source "drivers/sensor/wsen_pdus/Kconfig" source "drivers/sensor/wsen_tids/Kconfig" source "drivers/sensor/xmc4xxx_temp/Kconfig" +source "drivers/sensor/ene_tach_kb1200/Kconfig" endif # SENSOR diff --git a/drivers/sensor/ene_tach_kb1200/CMakeLists.txt b/drivers/sensor/ene_tach_kb1200/CMakeLists.txt new file mode 100644 index 00000000000..a99828fc6e5 --- /dev/null +++ b/drivers/sensor/ene_tach_kb1200/CMakeLists.txt @@ -0,0 +1,4 @@ +# SPDX-License-Identifier: Apache-2.0 + +zephyr_library() +zephyr_library_sources_ifdef(CONFIG_TACH_ENE_KB1200 tach_ene_kb1200.c) diff --git a/drivers/sensor/ene_tach_kb1200/Kconfig b/drivers/sensor/ene_tach_kb1200/Kconfig new file mode 100644 index 00000000000..fa0555cf937 --- /dev/null +++ b/drivers/sensor/ene_tach_kb1200/Kconfig @@ -0,0 +1,12 @@ +# KB1200 tachometer sensor configuration options + +# Copyright (c) 2024 ENE Technology Inc. +# SPDX-License-Identifier: Apache-2.0 + +config TACH_ENE_KB1200 + bool "ENE KB1200 tachometer sensor" + default y + depends on DT_HAS_ENE_KB1200_TACH_ENABLED + select PINCTRL + help + Enable tachometer sensor for ENE KB1200. diff --git a/drivers/sensor/ene_tach_kb1200/tach_ene_kb1200.c b/drivers/sensor/ene_tach_kb1200/tach_ene_kb1200.c new file mode 100644 index 00000000000..d7493109e47 --- /dev/null +++ b/drivers/sensor/ene_tach_kb1200/tach_ene_kb1200.c @@ -0,0 +1,143 @@ +/* + * Copyright (c) 2024 ENE Technology Inc. + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#define DT_DRV_COMPAT ene_kb1200_tach + +#include +#include +#include + +/* Device config */ +struct tach_kb1200_config { + /* tachometer controller base address */ + struct tacho_regs *tacho; + /* number of pulses (holes) per round of tachometer's input (encoder) */ + int pulses_per_round; + /* sampling clock timing of tachometer (us) */ + int sample_time_us; + const struct pinctrl_dev_config *pcfg; +}; + +/* Driver data */ +struct tach_kb1200_data { + /* Captured counts of tachometer */ + uint32_t capture; +}; + +/* TACH local functions */ +static int tach_kb1200_configure(const struct device *dev) +{ + const struct tach_kb1200_config *const config = dev->config; + uint8_t sample_us = 0; + + /* Configure clock module and its frequency of tachometer */ + switch (config->sample_time_us) { + case 2: + sample_us = TACHO_MONITOR_CLK_2US; + break; + case 8: + sample_us = TACHO_MONITOR_CLK_8US; + break; + case 16: + sample_us = TACHO_MONITOR_CLK_16US; + break; + case 64: + sample_us = TACHO_MONITOR_CLK_64US; + break; + default: + return -ENOTSUP; + } + config->tacho->TACHOCFG = (sample_us << 4) | TACHO_FUNCTION_ENABLE; + + return 0; +} + +/* TACH api functions */ +int tach_kb1200_sample_fetch(const struct device *dev, enum sensor_channel chan) +{ + ARG_UNUSED(chan); + struct tach_kb1200_data *const data = dev->data; + const struct tach_kb1200_config *const config = dev->config; + + /* Check tachometer timeout flag*/ + if (config->tacho->TACHOPF & TACHO_TIMEOUT_EVENT) { + /* Clear timeout flags and update flag */ + config->tacho->TACHOPF = (TACHO_TIMEOUT_EVENT | TACHO_UPDATE_EVENT); + data->capture = 0; + return 0; + } + + /* Check tachometer update flag is set */ + if (config->tacho->TACHOPF & TACHO_UPDATE_EVENT) { + /* Clear pending flags */ + config->tacho->TACHOPF = TACHO_UPDATE_EVENT; + /* Save captured count */ + data->capture = config->tacho->TACHOCV & TACHO_CNT_MAX_VALUE; + } + return 0; +} + +static int tach_kb1200_channel_get(const struct device *dev, enum sensor_channel chan, + struct sensor_value *val) +{ + struct tach_kb1200_data *const data = dev->data; + const struct tach_kb1200_config *const config = dev->config; + + if (chan != SENSOR_CHAN_RPM) { + return -ENOTSUP; + } + + if (data->capture > 0) { + /* + * RPM = (60000000/t) / n + * t: One Pulses length(us) = sample_time_us * cnt + * n: One Round pulses Number + */ + val->val1 = (60000000 / (config->sample_time_us * data->capture)) / + config->pulses_per_round; + } else { + val->val1 = 0U; + } + val->val2 = 0U; + + return 0; +} + +/* TACH driver registration */ +static int tach_kb1200_init(const struct device *dev) +{ + int ret; + const struct tach_kb1200_config *config = dev->config; + + ret = pinctrl_apply_state(config->pcfg, PINCTRL_STATE_DEFAULT); + if (ret != 0) { + return ret; + } + + tach_kb1200_configure(dev); + + return 0; +} + +static const struct sensor_driver_api tach_kb1200_driver_api = { + .sample_fetch = tach_kb1200_sample_fetch, + .channel_get = tach_kb1200_channel_get, +}; + +#define KB1200_TACH_INIT(inst) \ + PINCTRL_DT_INST_DEFINE(inst); \ + static const struct tach_kb1200_config tach_cfg_##inst = { \ + .tacho = (struct tacho_regs *)DT_INST_REG_ADDR(inst), \ + .pulses_per_round = DT_INST_PROP(inst, pulses_per_round), \ + .sample_time_us = DT_INST_PROP(inst, sample_time_us), \ + .pcfg = PINCTRL_DT_INST_DEV_CONFIG_GET(inst), \ + }; \ + static struct tach_kb1200_data tach_data_##inst; \ + SENSOR_DEVICE_DT_INST_DEFINE(inst, tach_kb1200_init, NULL, &tach_data_##inst, \ + &tach_cfg_##inst, POST_KERNEL, CONFIG_SENSOR_INIT_PRIORITY, \ + &tach_kb1200_driver_api); + +DT_INST_FOREACH_STATUS_OKAY(KB1200_TACH_INIT)