144 lines
4.1 KiB
C
144 lines
4.1 KiB
C
/*
|
|
* Copyright (c) 2024 ENE Technology Inc.
|
|
*
|
|
* SPDX-License-Identifier: Apache-2.0
|
|
*/
|
|
|
|
#define DT_DRV_COMPAT ene_kb1200_tach
|
|
|
|
#include <zephyr/drivers/pinctrl.h>
|
|
#include <zephyr/drivers/sensor.h>
|
|
#include <reg/tacho.h>
|
|
|
|
/* 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)
|