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 
9 #include "mec_pcfg.h"
10 #include "mec_defs.h"
11 #include "mec_vci_api.h"
12 #include "mec_retval.h"
13 #include "device_mec5.h"
14 
15 /* VCI_IN[0:6] are always bits[0:5] in registers referencing them */
16 #define MEC5_VCI_IN_0_6_MASK 0x3fu
17 
18 /* -------- VBAT Powered Control Interface (VCI) API -------- */
19 
mec_hal_vci_pin_disable(uint8_t vci_id)20 int mec_hal_vci_pin_disable(uint8_t vci_id)
21 {
22     if (vci_id >= MEC5_VCI_PINS) {
23         return MEC_RET_ERR_INVAL;
24     }
25 
26     MEC_VCI->VCI_INPUT_EN &= (uint32_t)~MEC_BIT(vci_id);
27     MEC_VCI->VCI_IN_VBAT_BUFEN &= (uint32_t)~MEC_BIT(vci_id);
28 
29     return MEC_RET_OK;
30 }
31 
32 /* Return current state of VCI pin inputs. If latching is enabled
33  * the current state is the latched state otherwise the state is
34  * live pin after filtering and polarity are applied.
35  * b[6:0] = VCI_IN[6:0]
36  * b[8] = current VCI_OVRD_IN state
37  * b[9] = current VCI_OUT state
38  * b[16] = Week Alarm state
39  * b[17] = RTC Alaram state
40  */
mec_hal_vci_in_pin_states(struct mec_vci_regs * regs)41 uint32_t mec_hal_vci_in_pin_states(struct mec_vci_regs *regs)
42 {
43     if (!regs) {
44         return 0;
45     }
46 
47     return (regs->CONFIG & 0x3037fu);
48 }
49 
mec_hal_vci_out_get(struct mec_vci_regs * regs)50 uint8_t mec_hal_vci_out_get(struct mec_vci_regs *regs)
51 {
52     if (!regs) {
53         return 0;
54     }
55 
56     return (uint8_t)((regs->CONFIG >> MEC_VCI_CONFIG_VCI_OUT_Pos) & MEC_BIT(0));
57 }
58 
mec_hal_vci_ovrd_in_get(struct mec_vci_regs * regs)59 uint8_t mec_hal_vci_ovrd_in_get(struct mec_vci_regs *regs)
60 {
61     if (!regs) {
62         return 0;
63     }
64 
65     return (uint8_t)((regs->CONFIG >> MEC_VCI_CONFIG_VCI_OVRD_IN_Pos) & MEC_BIT(0));
66 }
67 
68 /* VCI_IN[] pin filter enable/disable */
mec_hal_vci_in_filter_enable(struct mec_vci_regs * regs,uint8_t enable)69 int mec_hal_vci_in_filter_enable(struct mec_vci_regs *regs, uint8_t enable)
70 {
71     if (!regs) {
72         return MEC_RET_ERR_INVAL;
73     }
74 
75     if (enable) {
76         regs->CONFIG &= (uint32_t)~MEC_BIT(MEC_VCI_CONFIG_VCI_FILT_Pos);
77     } else {
78         regs->CONFIG |= MEC_BIT(MEC_VCI_CONFIG_VCI_FILT_Pos);
79     }
80 
81     return MEC_RET_OK;
82 }
83 
84 /* set the state of software controlled VCI_OUT pin state
85  * This value has no effect on VCI_OUT pin unless the FW_EXT bit is 1.
86  */
mec_hal_vci_sw_vci_out_set(struct mec_vci_regs * regs,uint8_t pin_state)87 int mec_hal_vci_sw_vci_out_set(struct mec_vci_regs *regs, uint8_t pin_state)
88 {
89     if (!regs) {
90         return MEC_RET_ERR_INVAL;
91     }
92 
93     if (pin_state) {
94         regs->CONFIG |= MEC_BIT(MEC_VCI_CONFIG_FW_VCI_OUT_Pos);
95     } else {
96         regs->CONFIG &= (uint32_t)~MEC_BIT(MEC_VCI_CONFIG_FW_VCI_OUT_Pos);
97     }
98 
99     return MEC_RET_OK;
100 }
101 
102 /* Enable software control of VCI_OUT pin state */
mec_hal_vci_sw_vci_out_enable(struct mec_vci_regs * regs,uint8_t enable)103 int mec_hal_vci_sw_vci_out_enable(struct mec_vci_regs *regs, uint8_t enable)
104 {
105     if (!regs) {
106         return MEC_RET_ERR_INVAL;
107     }
108 
109     if (enable) { /* VCI_OUT pin state is set by bit[10] of this register */
110         regs->CONFIG |= MEC_BIT(MEC_VCI_CONFIG_VCI_OUT_SRC_Pos);
111     } else { /* VCI_OUT pin controlled by external pin inputs */
112         regs->CONFIG &= (uint32_t)~MEC_BIT(MEC_VCI_CONFIG_VCI_OUT_SRC_Pos);
113     }
114 
115     return MEC_RET_OK;
116 }
117 
mec_hal_vci_in_latched_get(struct mec_vci_regs * regs)118 uint32_t mec_hal_vci_in_latched_get(struct mec_vci_regs *regs)
119 {
120     if (!regs) {
121         return 0;
122     }
123 
124     return (regs->CONFIG & MEC5_VCI_IN_0_6_MASK);
125 }
126 
mec_hal_vci_in_latch_enable(struct mec_vci_regs * regs,uint32_t latch_bitmap)127 int mec_hal_vci_in_latch_enable(struct mec_vci_regs *regs, uint32_t latch_bitmap)
128 {
129     if (!regs) {
130         return MEC_RET_ERR_INVAL;
131     }
132 
133     regs->LATCH_EN = latch_bitmap;
134 
135     return MEC_RET_OK;
136 }
137 
mec_hal_vci_in_latch_disable(struct mec_vci_regs * regs,uint32_t latch_bitmap)138 int mec_hal_vci_in_latch_disable(struct mec_vci_regs *regs, uint32_t latch_bitmap)
139 {
140     if (!regs) {
141         return MEC_RET_ERR_INVAL;
142     }
143 
144     regs->LATCH_EN &= (uint32_t)~latch_bitmap;
145 
146     return MEC_RET_OK;
147 }
148 
mec_hal_vci_in_latch_enable_get(struct mec_vci_regs * regs)149 uint32_t mec_hal_vci_in_latch_enable_get(struct mec_vci_regs *regs)
150 {
151     if (!regs) {
152         return 0;
153     }
154 
155     return regs->LATCH_EN;
156 }
157 
mec_hal_vci_in_latch_reset(struct mec_vci_regs * regs,uint32_t latch_bitmap)158 int mec_hal_vci_in_latch_reset(struct mec_vci_regs *regs, uint32_t latch_bitmap)
159 {
160     if (!regs) {
161         return MEC_RET_ERR_INVAL;
162     }
163 
164     regs->LATCH_RESET = latch_bitmap;
165 
166     return MEC_RET_OK;
167 }
168 
mec_hal_vci_in_input_enable(struct mec_vci_regs * regs,uint32_t latch_bitmap)169 int mec_hal_vci_in_input_enable(struct mec_vci_regs *regs, uint32_t latch_bitmap)
170 {
171     if (!regs) {
172         return MEC_RET_ERR_INVAL;
173     }
174 
175     regs->VCI_INPUT_EN = latch_bitmap;
176     regs->LATCH_RESET = latch_bitmap; /* clear spurious status */
177 
178     return MEC_RET_OK;
179 }
180 
mec_hal_vci_in_input_enable_get(struct mec_vci_regs * regs)181 uint32_t mec_hal_vci_in_input_enable_get(struct mec_vci_regs *regs)
182 {
183     if (!regs) {
184         return 0;
185     }
186 
187     return regs->VCI_INPUT_EN;
188 }
189 
mec_hal_vci_out_power_on_delay(struct mec_vci_regs * regs,uint32_t delay_ms)190 int mec_hal_vci_out_power_on_delay(struct mec_vci_regs *regs, uint32_t delay_ms)
191 {
192     uint32_t delay_cnt = 0;
193 
194     if (!regs) {
195         return MEC_RET_ERR_INVAL;
196     }
197 
198     if (delay_ms == 0) { /* disable */
199         regs->HOLD_OFF_CNT = 0;
200     }
201 
202     if ((delay_ms < 125u) || (delay_ms > (32u * 1000u))) {
203         return MEC_RET_ERR_INVAL;
204     }
205 
206     delay_cnt = delay_ms / 125u;
207     if (((delay_cnt % 125u) > 62u) && (delay_cnt < 0xffu)) {
208         delay_cnt++;
209     }
210 
211     regs->HOLD_OFF_CNT = delay_cnt;
212 
213     return MEC_RET_OK;
214 }
215 
216 /* Set the polarity of selected VCI_IN[n] pins.
217  * Polarity = 1 Active High
218  *          = 0 Active Low
219  */
mec_hal_vci_in_polarity(struct mec_vci_regs * regs,uint32_t vci_in_bitmap,uint32_t polarity_bitmap)220 int mec_hal_vci_in_polarity(struct mec_vci_regs *regs, uint32_t vci_in_bitmap,
221                             uint32_t polarity_bitmap)
222 {
223     uint32_t temp = 0;
224 
225     if (!regs) {
226         return MEC_RET_ERR_INVAL;
227     }
228 
229     temp = regs->VCI_POLARITY;
230     temp &= (uint32_t)~(vci_in_bitmap);
231     temp |= (polarity_bitmap & vci_in_bitmap);
232     regs->VCI_POLARITY = temp;
233 
234     return MEC_RET_OK;
235 }
236 
mec_hal_vci_pedge_detect(struct mec_vci_regs * regs)237 uint32_t mec_hal_vci_pedge_detect(struct mec_vci_regs *regs)
238 {
239     if (!regs) {
240         return 0;
241     }
242 
243     return regs->VCI_IN_POSED_STS;
244 }
245 
mec_hal_vci_nedge_detect(struct mec_vci_regs * regs)246 uint32_t mec_hal_vci_nedge_detect(struct mec_vci_regs *regs)
247 {
248     if (!regs) {
249         return 0;
250     }
251 
252     return regs->VCI_IN_NEGED_STS;
253 }
254 
mec_hal_vci_pedge_detect_clr(struct mec_vci_regs * regs,uint32_t bitmap)255 void mec_hal_vci_pedge_detect_clr(struct mec_vci_regs *regs, uint32_t bitmap)
256 {
257     if (!regs) {
258         return;
259     }
260 
261     regs->VCI_IN_POSED_STS = bitmap;
262 }
263 
mec_hal_vci_nedge_detect_clr(struct mec_vci_regs * regs,uint32_t bitmap)264 void mec_hal_vci_nedge_detect_clr(struct mec_vci_regs *regs, uint32_t bitmap)
265 {
266     if (!regs) {
267         return;
268     }
269 
270     regs->VCI_IN_NEGED_STS = bitmap;
271 }
272 
mec_hal_vci_edge_detect_clr_all(struct mec_vci_regs * regs)273 void mec_hal_vci_edge_detect_clr_all(struct mec_vci_regs *regs)
274 {
275     if (!regs) {
276         return;
277     }
278 
279     regs->VCI_IN_POSED_STS = UINT32_MAX;
280     regs->VCI_IN_NEGED_STS = UINT32_MAX;
281 }
282 
283 /* Select which VCI_IN[] pin edge detector are enabled when the chip
284  * is powered only by the VBAT power rail (VTR Core is off).
285  * When the chip is on (VTR Core ON) this register has no effect on
286  * the edge detector enables.
287  */
mec_hal_vci_vbat_edge_detect_get(struct mec_vci_regs * regs)288 uint32_t mec_hal_vci_vbat_edge_detect_get(struct mec_vci_regs *regs)
289 {
290     if (!regs) {
291         return 0;
292     }
293 
294     return regs->VCI_IN_VBAT_BUFEN;
295 }
296 
mec_hal_vci_vbat_edge_detect(struct mec_vci_regs * regs,uint32_t bitmap)297 int mec_hal_vci_vbat_edge_detect(struct mec_vci_regs *regs, uint32_t bitmap)
298 {
299     if (!regs) {
300         return MEC_RET_ERR_INVAL;
301     }
302 
303     regs->VCI_IN_VBAT_BUFEN = bitmap;
304 
305     return MEC_RET_OK;
306 }
307 
308 #ifdef MEC5_VCI_HAS_LID_DETECT
309 
mec_hal_vci_lid_detect_enable(struct mec_vci_regs * regs)310 int mec_hal_vci_lid_detect_enable(struct mec_vci_regs *regs)
311 {
312     if ((uintptr_t)regs != (uintptr_t)MEC_VCI_BASE) {
313         return MEC_RET_ERR_INVAL;
314     }
315 
316     regs->VCI_LID_OPEN_DET_EN |= MEC_BIT(MEC_VCI_VCI_LID_OPEN_DET_EN_VCI_LID_EN_Pos);
317 
318     return MEC_RET_OK;
319 }
320 
321 #endif
322 
323 /* end mec_vci.c */
324