1 /*
2 * Copyright (c) 2021 ITE Technology Corporation.
3 *
4 * SPDX-License-Identifier: Apache-2.0
5 */
6
7 #define DT_DRV_COMPAT ite_it8xxx2_tach
8
9 /**
10 * @file
11 * @brief ITE it8xxx2 tachometer sensor module driver
12 *
13 * This file contains a driver for the tachometer sensor module which contains
14 * two independent counters (F1TL/MRR and F2TL/MRR). The content of the
15 * Tachometer Reading Register is still update based on the sampling counter
16 * that samples the tachometer input (T0A, T0B, T1A or T1B pins).
17 * The following is block diagram of this module:
18 *
19 * Sample Rate = TACH_FREQ / 128
20 * |
21 * | Tachometer 0 | T0A (GPD6)
22 * | | | +-----------+ |
23 * | +-----+-----+ | | _ _ |<--+
24 * |------>| F1TL/MRR |<-+-| | |_| |_ |<--+
25 * | +-----------+ +-----------+ |
26 * | capture pulses T0B (GPJ2)
27 * | in sample rate
28 * | period
29 * +-----------+ |
30 * Crystal-->| Prescaler |--->| Tachometer 1 T1A (GPD7)
31 * 32.768k +-----------+ | | +-----------+ |
32 * | +-----+-----+ | _ _ |<--+
33 * |------>| F2TL/MRR |<-+-| | |_| |_ |<--+
34 * | +-----------+ +-----------+ |
35 * | capture pulses T1B (GPJ3)
36 * | in one second
37 * | period
38 * |
39 *
40 * Based on the counter value, we can compute the current RPM of external signal
41 * from encoders.
42 */
43
44 #include <zephyr/device.h>
45 #include <zephyr/drivers/pinctrl.h>
46 #include <zephyr/drivers/sensor.h>
47 #include <zephyr/dt-bindings/sensor/it8xxx2_tach.h>
48 #include <errno.h>
49 #include <soc.h>
50 #include <soc_dt.h>
51
52 #include <zephyr/logging/log.h>
53 LOG_MODULE_REGISTER(tach_ite_it8xxx2, CONFIG_SENSOR_LOG_LEVEL);
54
55 /*
56 * NOTE: The PWM output maximum is 324Hz in EC LPM, so if we need fan to work
57 * then don't let EC enter LPM.
58 */
59 #define TACH_FREQ EC_FREQ
60
61 struct tach_it8xxx2_config {
62 /* Fan x tachometer LSB reading register */
63 uintptr_t reg_fxtlrr;
64 /* Fan x tachometer MSB reading register */
65 uintptr_t reg_fxtmrr;
66 /* Tachometer switch control register */
67 uintptr_t reg_tswctlr;
68 /* Tachometer data valid bit of tswctlr register */
69 int dvs_bit;
70 /* Tachometer data valid status bit of tswctlr register */
71 int chsel_bit;
72 /* Tachometer alternate configuration */
73 const struct pinctrl_dev_config *pcfg;
74 /* Select channel of tachometer */
75 int channel;
76 /* Number of pulses per round of tachometer's input */
77 int pulses_per_round;
78 };
79
80 /* Driver data */
81 struct tach_it8xxx2_data {
82 /* Captured counts of tachometer */
83 uint32_t capture;
84 };
85
tach_ch_is_valid(const struct device * dev,int tach_ch)86 static bool tach_ch_is_valid(const struct device *dev, int tach_ch)
87 {
88 const struct tach_it8xxx2_config *const config = dev->config;
89 volatile uint8_t *reg_tswctlr = (uint8_t *)config->reg_tswctlr;
90 int dvs_bit = config->dvs_bit;
91 int chsel_bit = config->chsel_bit;
92 int mask = (dvs_bit | chsel_bit);
93 bool valid = false;
94
95 switch (tach_ch) {
96 case IT8XXX2_TACH_CHANNEL_A:
97 if ((*reg_tswctlr & mask) == dvs_bit) {
98 valid = true;
99 }
100 break;
101 case IT8XXX2_TACH_CHANNEL_B:
102 if ((*reg_tswctlr & mask) == mask) {
103 valid = true;
104 }
105 break;
106 default:
107 break;
108 }
109
110 return valid;
111 }
112
tach_it8xxx2_sample_fetch(const struct device * dev,enum sensor_channel chan)113 static int tach_it8xxx2_sample_fetch(const struct device *dev,
114 enum sensor_channel chan)
115 {
116 const struct tach_it8xxx2_config *const config = dev->config;
117 volatile uint8_t *reg_fxtlrr = (uint8_t *)config->reg_fxtlrr;
118 volatile uint8_t *reg_fxtmrr = (uint8_t *)config->reg_fxtmrr;
119 volatile uint8_t *reg_tswctlr = (uint8_t *)config->reg_tswctlr;
120 int tach_ch = config->channel;
121 struct tach_it8xxx2_data *const data = dev->data;
122
123 if ((chan != SENSOR_CHAN_RPM) && (chan != SENSOR_CHAN_ALL)) {
124 return -ENOTSUP;
125 }
126
127 if (tach_ch_is_valid(dev, tach_ch)) {
128 /* If channel data of tachometer is valid, then save it */
129 data->capture = ((*reg_fxtmrr) << 8) | (*reg_fxtlrr);
130 /* Clear tachometer data valid status */
131 *reg_tswctlr |= config->dvs_bit;
132 } else {
133 /* If channel data of tachometer isn't valid, then clear it */
134 data->capture = 0;
135 }
136
137 return 0;
138 }
139
tach_it8xxx2_channel_get(const struct device * dev,enum sensor_channel chan,struct sensor_value * val)140 static int tach_it8xxx2_channel_get(const struct device *dev,
141 enum sensor_channel chan,
142 struct sensor_value *val)
143 {
144 const struct tach_it8xxx2_config *const config = dev->config;
145 int tachx = ((config->dvs_bit) == IT8XXX2_PWM_T0DVS) ? 0 : 1;
146 int p = config->pulses_per_round;
147 struct tach_it8xxx2_data *const data = dev->data;
148
149 if (chan != SENSOR_CHAN_RPM) {
150 LOG_ERR("Sensor chan %d, only support SENSOR_CHAN_RPM", chan);
151 return -ENOTSUP;
152 }
153
154 /* Transform count unit to RPM */
155 if (data->capture > 0) {
156 if (tachx == 0) {
157 /*
158 * Fan Speed (RPM) = 60 / (1/fs * {F1TMRR, F1TLRR} * P)
159 * - P denotes the numbers of pulses per round
160 * - {F1TMRR, F1TLRR} = 0000h denotes Fan Speed is zero
161 * - The sampling rate (fs) is TACH_FREQ / 128
162 */
163 val->val1 = (60 * TACH_FREQ / 128 / p / (data->capture));
164 } else {
165 /*
166 * Fan Speed (RPM) = {F2TMRR, F2TLRR} * 60 / P
167 * - P denotes the numbers of pulses per round
168 * - {F2TMRR, F2TLRR} = 0000h denotes Fan Speed is zero
169 */
170 val->val1 = ((data->capture) * 120 / (p * 2));
171 }
172 } else {
173 val->val1 = 0U;
174 }
175
176 val->val2 = 0U;
177
178 return 0;
179 }
180
tach_it8xxx2_init(const struct device * dev)181 static int tach_it8xxx2_init(const struct device *dev)
182 {
183 const struct tach_it8xxx2_config *const config = dev->config;
184 volatile uint8_t *reg_tswctlr = (uint8_t *)config->reg_tswctlr;
185 int tach_ch = config->channel;
186 int status;
187
188 if (tach_ch > IT8XXX2_TACH_CHANNEL_B) {
189 LOG_ERR("Tach channel %d, only support 0 or 1", tach_ch);
190 return -EINVAL;
191 }
192
193 /* Select pin to alternate mode for tachometer */
194 status = pinctrl_apply_state(config->pcfg, PINCTRL_STATE_DEFAULT);
195 if (status < 0) {
196 LOG_ERR("Failed to configure TACH pins");
197 return status;
198 }
199
200 if (tach_ch == IT8XXX2_TACH_CHANNEL_A) {
201 /* Select IT8XXX2_TACH_CHANNEL_A output to tachometer */
202 *reg_tswctlr &= ~(config->chsel_bit);
203 /* Clear tachometer data valid status */
204 *reg_tswctlr |= config->dvs_bit;
205 } else {
206 /* Select IT8XXX2_TACH_CHANNEL_B output to tachometer */
207 *reg_tswctlr |= config->chsel_bit;
208 /* Clear tachometer data valid status */
209 *reg_tswctlr |= config->dvs_bit;
210 }
211
212 /* Tachometer sensor already start */
213 return 0;
214 }
215
216 static DEVICE_API(sensor, tach_it8xxx2_driver_api) = {
217 .sample_fetch = tach_it8xxx2_sample_fetch,
218 .channel_get = tach_it8xxx2_channel_get,
219 };
220
221 #define TACH_IT8XXX2_INIT(inst) \
222 PINCTRL_DT_INST_DEFINE(inst); \
223 \
224 static const struct tach_it8xxx2_config tach_it8xxx2_cfg_##inst = { \
225 .reg_fxtlrr = DT_INST_REG_ADDR_BY_IDX(inst, 0), \
226 .reg_fxtmrr = DT_INST_REG_ADDR_BY_IDX(inst, 1), \
227 .reg_tswctlr = DT_INST_REG_ADDR_BY_IDX(inst, 2), \
228 .dvs_bit = DT_INST_PROP(inst, dvs_bit), \
229 .chsel_bit = DT_INST_PROP(inst, chsel_bit), \
230 .pcfg = PINCTRL_DT_INST_DEV_CONFIG_GET(inst), \
231 .channel = DT_INST_PROP(inst, channel), \
232 .pulses_per_round = DT_INST_PROP(inst, pulses_per_round), \
233 }; \
234 \
235 static struct tach_it8xxx2_data tach_it8xxx2_data_##inst; \
236 \
237 SENSOR_DEVICE_DT_INST_DEFINE(inst, \
238 tach_it8xxx2_init, \
239 NULL, \
240 &tach_it8xxx2_data_##inst, \
241 &tach_it8xxx2_cfg_##inst, \
242 POST_KERNEL, \
243 CONFIG_SENSOR_INIT_PRIORITY, \
244 &tach_it8xxx2_driver_api);
245
246 DT_INST_FOREACH_STATUS_OKAY(TACH_IT8XXX2_INIT)
247