1 /*
2 * Copyright 2024 Microchip Technology Inc. and its subsidiaries.
3 *
4 * SPDX-License-Identifier: Apache-2.0
5 */
6 #include <stddef.h>
7 #include <stdint.h>
8 #include <stdbool.h>
9
10 #include <device_mec5.h>
11 #include "mec_pcfg.h"
12 #include "mec_defs.h"
13 #include "mec_ecia_api.h"
14 #include "mec_pcr_api.h"
15 #include "mec_tach_api.h"
16 #include "mec_retval.h"
17
18 #if MEC5_TACH_INSTANCES > 0
19
20 #define MEC_TACH0_ECIA_INFO MEC5_ECIA_INFO(17, 1, 9, 71)
21 #define MEC_TACH1_ECIA_INFO MEC5_ECIA_INFO(17, 2, 9, 72)
22 #define MEC_TACH2_ECIA_INFO MEC5_ECIA_INFO(17, 3, 9, 73)
23 #define MEC_TACH3_ECIA_INFO MEC5_ECIA_INFO(17, 4, 9, 159)
24
25 struct mec_tach_info {
26 uintptr_t base_addr;
27 uint32_t devi;
28 uint16_t pcr_id;
29 };
30
31 static const struct mec_tach_info tach_instances[MEC5_TACH_INSTANCES] = {
32 {MEC_TACH0_BASE, MEC_TACH0_ECIA_INFO, MEC_PCR_TACH0 },
33 {MEC_TACH1_BASE, MEC_TACH1_ECIA_INFO, MEC_PCR_TACH1 },
34 {MEC_TACH2_BASE, MEC_TACH2_ECIA_INFO, MEC_PCR_TACH2 },
35 {MEC_TACH3_BASE, MEC_TACH3_ECIA_INFO, MEC_PCR_TACH3 },
36 };
37
tach_get_info(struct mec_tach_regs * regs)38 static struct mec_tach_info const *tach_get_info(struct mec_tach_regs *regs)
39 {
40 for (int i = 0; i < MEC5_TACH_INSTANCES; i++) {
41 const struct mec_tach_info *p = &tach_instances[i];
42
43 if (tach_instances[i].base_addr == (uintptr_t)regs) {
44 return p;
45 }
46 }
47
48 return NULL;
49 }
50
mec_hal_tach_init(struct mec_tach_regs * regs,uint32_t limits,uint32_t flags)51 int mec_hal_tach_init(struct mec_tach_regs *regs, uint32_t limits, uint32_t flags)
52 {
53 const struct mec_tach_info *info = tach_get_info(regs);
54 uint32_t ctrl = 0, temp = 0;
55 bool enable_girq = false;
56
57 if (!info) {
58 return MEC_RET_ERR_INVAL;
59 }
60
61 mec_hal_pcr_clr_blk_slp_en(info->pcr_id);
62 if (flags & MEC5_TACH_CFG_RESET) {
63 mec_hal_pcr_blk_reset(info->pcr_id);
64 } else {
65 regs->CTRL = 0u;
66 regs->STATUS = UINT32_MAX;
67 }
68
69 mec_hal_girq_ctrl(info->devi, 0);
70 mec_hal_girq_clr_src(info->devi);
71
72 /* program high and low 16-bit counter limits */
73 regs->LIMIT_LO = (uint16_t)(limits & 0xffffu);
74 regs->LIMIT_HI = (uint16_t)(limits >> 16);
75
76 /* program number of tach edges for the count interval */
77 temp = (flags & MEC5_TACH_CFG_INTERVAL_EDGES_MSK) >> MEC5_TACH_CFG_INTERVAL_EDGES_POS;
78 ctrl |= ((temp << MEC_TACH_CTRL_EDGES_Pos) & MEC_TACH_CTRL_EDGES_Msk);
79
80 if (flags & MEC5_TACH_CFG_FILTER_EN) {
81 ctrl |= MEC_BIT(MEC_TACH_CTRL_FILT_IN_Pos);
82 }
83
84 /* counter is incremented on rising edge of tach input or rising edge
85 * of Tach input clock. Input clock is the PCR slow clock.
86 */
87 if (flags & MEC5_TACH_CFG_CNT_INCR_CLK) {
88 ctrl |= MEC_BIT(MEC_TACH_CTRL_RDMODE_Pos);
89 }
90
91 if (flags & MEC5_TACH_CFG_OOL_INTR_EN) { /* out of limit interrupt? */
92 ctrl |= MEC_BIT(MEC_TACH_CTRL_ENOOL_Pos);
93 enable_girq = true;
94 }
95
96 if (flags & MEC5_TACH_CFG_CNT_RDY_INTR_EN) {
97 ctrl |= MEC_BIT(MEC_TACH_CTRL_CNTRDY_IEN_Pos);
98 enable_girq = true;
99 }
100
101 if (flags & MEC5_TACH_CFG_INPUT_CHG_INTR_EN) {
102 ctrl |= MEC_BIT(MEC_TACH_CTRL_INTOG_IEN_Pos);
103 enable_girq = true;
104 }
105
106 if (flags & MEC5_TACH_CFG_ENABLE) {
107 ctrl |= MEC_BIT(MEC_TACH_CTRL_ENABLE_Pos);
108 }
109
110 if (enable_girq) {
111 mec_hal_girq_ctrl(info->devi, 1);
112 }
113
114 regs->CTRL = ctrl;
115
116 return MEC_RET_OK;
117 }
118
mec_hal_tach_enable(struct mec_tach_regs * regs,uint8_t enable)119 void mec_hal_tach_enable(struct mec_tach_regs *regs, uint8_t enable)
120 {
121 if (enable) {
122 regs->CTRL |= MEC_BIT(MEC_TACH_CTRL_ENABLE_Pos);
123 } else {
124 regs->CTRL &= (uint32_t)~MEC_BIT(MEC_TACH_CTRL_ENABLE_Pos);
125 }
126 }
127
mec_hal_tach_is_enabled(struct mec_tach_regs * regs)128 bool mec_hal_tach_is_enabled(struct mec_tach_regs *regs)
129 {
130 if (!regs) {
131 return false;
132 }
133
134 return (regs->CTRL & MEC_BIT(MEC_TACH_CTRL_ENABLE_Pos)) ? true : false;
135 }
136
mec_hal_tach_clock_freq(void)137 uint32_t mec_hal_tach_clock_freq(void)
138 {
139 return mec_hal_pcr_slow_clock_freq_get();
140 }
141
mec_hal_tach_counter(struct mec_tach_regs * regs)142 uint32_t mec_hal_tach_counter(struct mec_tach_regs *regs)
143 {
144 const struct mec_tach_info *info = tach_get_info(regs);
145
146 if (!info) {
147 return 0;
148 }
149
150 return (regs->CTRL & MEC_TACH_CTRL_COUNT_Msk) >> MEC_TACH_CTRL_COUNT_Pos;
151 }
152
mec_hal_tach_status(struct mec_tach_regs * regs)153 uint32_t mec_hal_tach_status(struct mec_tach_regs *regs)
154 {
155 return regs->STATUS;
156 }
157
mec_hal_tach_status_clr(struct mec_tach_regs * regs,uint32_t status)158 void mec_hal_tach_status_clr(struct mec_tach_regs *regs, uint32_t status)
159 {
160 regs->STATUS = status;
161 }
162
mec_hal_tach_intr_enable(struct mec_tach_regs * regs,uint32_t intr_events,uint8_t enable)163 int mec_hal_tach_intr_enable(struct mec_tach_regs *regs, uint32_t intr_events, uint8_t enable)
164 {
165 uint32_t msk = 0;
166
167 if (!regs) {
168 return MEC_RET_ERR_INVAL;
169 }
170
171 if (intr_events & MEC_BIT(MEC5_TACH_IEN_OOL_POS)) {
172 msk |= MEC_BIT(MEC_TACH_CTRL_ENOOL_Pos);
173 }
174
175 if (intr_events & MEC_BIT(MEC5_TACH_IEN_CNT_RDY_POS)) {
176 msk |= MEC_BIT(MEC_TACH_CTRL_CNTRDY_IEN_Pos);
177 }
178
179 if (intr_events & MEC_BIT(MEC5_TACH_IEN_INPUT_TOGGLE_POS)) {
180 msk |= MEC_BIT(MEC_TACH_CTRL_INTOG_IEN_Pos);
181 }
182
183 if (msk) {
184 if (enable) {
185 regs->CTRL |= msk;
186 } else {
187 regs->CTRL &= (uint32_t)~msk;
188 }
189 }
190
191 return MEC_RET_OK;
192 };
193
mec_hal_tach_girq_status_clr(struct mec_tach_regs * regs)194 void mec_hal_tach_girq_status_clr(struct mec_tach_regs *regs)
195 {
196 const struct mec_tach_info *info = tach_get_info(regs);
197
198 if (!info) {
199 return;
200 }
201
202 mec_hal_girq_clr_src(info->devi);
203 }
204
mec_hal_tach_girq_enable(struct mec_tach_regs * regs,uint8_t enable)205 void mec_hal_tach_girq_enable(struct mec_tach_regs *regs, uint8_t enable)
206 {
207 const struct mec_tach_info *info = tach_get_info(regs);
208
209 if (!info) {
210 return;
211 }
212
213 mec_hal_girq_ctrl(info->devi, enable);
214 }
215
216 #endif /* MEC5_TACH_INSTANCES */
217 /* end mec_tach.c */
218