-
Notifications
You must be signed in to change notification settings - Fork 6.1k
/
tach_ene_kb1200.c
143 lines (122 loc) · 4.07 KB
/
tach_ene_kb1200.c
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
/*
* 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)