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 <device_mec5.h>
10 #include "mec_pcfg.h"
11 #include "mec_defs.h"
12 #include "mec_ecia_api.h"
13 #include "mec_pcr_api.h"
14 #include "mec_wktimer_api.h"
15 #include "mec_retval.h"
16 
17 /* week counter has three hardware counters:
18  * week counter:
19  *   28-bit counter incremented at a 1 Hz rate with a 28-bit compare
20  * sub-week:
21  *   9-bit counter down counter. Frequency source is either
22  *   derived from the sub-second counter (2, 4, ..., 32768 Hz) or
23  *   the week counter (125, 31.25, 7.8125, or 1.95) Hz.
24  * sub-second: derived from a 15-bit counter incremented at 32.768 Hz
25  *   Rate is 2, 4, 8, ..., 32768 Hz.
26  *
27  * The week timer perpheral also includes Battery Powered General Purpose Outputs (BGPO)
28  * functionality. These pins states are controlled by the week timer BGPO registers. The
29  * pins are powered by the VBAT power rail and maintain state when VTR power rails are off.
30  * Some BGPO pins are multiplexed with GPIO's. Configuration of these pins is:
31  * GPIO Control register        BGPO Power register
32  * MUX = BGPO function          Corresponding bit = 1, pin powered by VBAT
33  * MUX = GPIO function          Corresponding bit = 0, pin powered by VTR
34  */
35 
36 #define MEC_WKTMR_GIRQ                  21
37 #define MEC_WKTMR_AGGR_NVIC_NUM         13
38 #define MEC_WKTMR_WK_ALARM_GIRQ_POS     3
39 #define MEC_WKTMR_SUB_WK_ALARM_GIRQ_POS 4
40 #define MEC_WKTMR_ONE_SEC_GIRQ_POS      5
41 #define MEC_WKTMR_SUB_SEC_GIRQ_POS      6
42 #define MEC_WKTMR_SYS_PWR_PRES_GIRQ_POS 7
43 
44 /* Direct NVIC interrupt numbers */
45 #define MEC_WKTMR_WK_ALARM_NVIC_NUM     114
46 #define MEC_WKTMR_SUB_WK_ALARM_NVIC_NUM 115
47 #define MEC_WKTMR_ONE_SEC_NVIC_NUM      116
48 #define MEC_WKTMR_SUB_SEC_NVIC_NUM      117
49 #define MEC_WKTMR_SYS_PWR_PRES_NVIC_NUM 118
50 
51 #define MEC_WKTMR_WK_ALARM_ECIA_INFO \
52     MEC5_ECIA_INFO(MEC_WKTMR_GIRQ, MEC_WKTMR_WK_ALARM_GIRQ_POS, \
53                    MEC_WKTMR_AGGR_NVIC_NUM, MEC_WKTMR_WK_ALARM_NVIC_NUM)
54 
55 #define MEC_WKTMR_SUB_WK_ALARM_ECIA_INFO \
56     MEC5_ECIA_INFO(MEC_WKTMR_GIRQ, MEC_WKTMR_SUB_WK_ALARM_GIRQ_POS, \
57                    MEC_WKTMR_AGGR_NVIC_NUM, MEC_WKTMR_SUB_WK_ALARM_NVIC_NUM)
58 
59 #define MEC_WKTMR_ONE_SEC_ECIA_INFO \
60     MEC5_ECIA_INFO(MEC_WKTMR_GIRQ, MEC_WKTMR_ONE_SEC_GIRQ_POS, \
61                    MEC_WKTMR_AGGR_NVIC_NUM, MEC_WKTMR_ONE_SEC_NVIC_NUM)
62 
63 #define MEC_WKTMR_SUB_SEC_ECIA_INFO \
64     MEC5_ECIA_INFO(MEC_WKTMR_GIRQ, MEC_WKTMR_SUB_SEC_GIRQ_POS, \
65                    MEC_WKTMR_AGGR_NVIC_NUM, MEC_WKTMR_SUB_SEC_NVIC_NUM)
66 
67 #define MEC_WKTMR_SYS_PWR_PRES_ECIA_INFO \
68     MEC5_ECIA_INFO(MEC_WKTMR_GIRQ, MEC_WKTMR_SYS_PWR_PRES_GIRQ_POS, \
69                    MEC_WKTMR_AGGR_NVIC_NUM, MEC_WKTMR_SYS_PWR_PRES_NVIC_NUM)
70 
71 /* configuration:
72  * 4-bit field for sub-week rate (interrupt when count down reaches 0)
73  * 9-bit field for sub-week counter value
74  * 28-bit field for initial value of 1Hz week counter
75  * 28-bit field for compare value (week alarm interrupt)
76  * NOTE: not all feature implemented since these timers are interlinked.
77  */
78 
mec_hal_wktimer_init(struct mec_wktmr_regs * regs,struct mec_wktmr_config * cfg)79 int mec_hal_wktimer_init(struct mec_wktmr_regs *regs, struct mec_wktmr_config *cfg)
80 {
81     uint32_t ctrl = 0, swctrl = 0;
82 
83 #ifdef MEC_WKTMR_BASE_CHECK
84     if ((uintptr_t)regs != (uintptr_t)(MEC_WKTMR0_BASE)) {
85         return MEC_RET_ERR_INVAL;
86     }
87 #endif
88 
89     if (!cfg) {
90         return MEC_RET_ERR_INVAL;
91     }
92 
93     regs->CTRL = 0; /* disable */
94     regs->SWCR = MEC_BIT(MEC_WKTMR_SWCR_SUB_PUPEV_Pos) | MEC_BIT(MEC_WKTMR_SWCR_PUPEV_Pos);
95 
96     if (cfg->cfg_flags & MEC_BIT(MEC_WKTMR_CFG_SYS_PWR_PRES_EN_POS)) {
97         swctrl |= MEC_BIT(MEC_WKTMR_SWCR_SYSPWR_PRES_Pos);
98     }
99 
100     if (cfg->cfg_flags & MEC_BIT(MEC_WKTMR_CFG_SUBWK_RELOAD_POS)) {
101         swctrl |= MEC_BIT(MEC_WKTMR_SWCR_AUTO_RELOAD_Pos);
102     }
103 
104     if (cfg->cfg_flags & MEC_BIT(MEC_WKTMR_CFG_VCI_PWR_UP_EV_EN_POS)) {
105         ctrl |= MEC_BIT(MEC_WKTMR_CTRL_PUPEV_Pos);
106     }
107 
108     if (cfg->cfg_flags & MEC_BIT(MEC_WKTMR_CFG_ENABLE_POS)) {
109         ctrl |= MEC_BIT(MEC_WKTMR_CTRL_TIMER_Pos);
110     }
111 
112     regs->COUNT = cfg->one_sec_count;
113     regs->COMP = cfg->one_sec_alarm_count;
114     regs->SWAC = (regs->SWAC & (uint32_t)~MEC_WKTMR_SWAC_SUB_LOAD_Msk)
115                  | (cfg->sub_week_reload & MEC_WKTMR_SWAC_SUB_LOAD_Msk);
116     regs->SWCR = swctrl;
117     regs->CTRL = ctrl;
118 
119     return MEC_RET_OK;
120 }
121 
122 /* Control Week Timer BGPO pins.
123  * API has three functions: Enable pin in BGPO hardware, select pins reset power rail,
124  * and set pins output state.
125  * NOTE: BGPO pins multiplexed with GPIO's require GPIO mux set to BGPO function.
126  */
mec_hal_bgpo_set(struct mec_wktmr_regs * regs,enum mec_wktmr_bgpo_prop prop,uint16_t pin_bm,uint16_t val_bm)127 int mec_hal_bgpo_set(struct mec_wktmr_regs *regs, enum mec_wktmr_bgpo_prop prop,
128                      uint16_t pin_bm, uint16_t val_bm)
129 {
130 #ifdef MEC_WKTMR_BASE_CHECK
131     if ((uintptr_t)regs != (uintptr_t)(MEC_WKTMR0_BASE)) {
132         return MEC_RET_ERR_INVAL;
133     }
134 #endif
135 
136     if (!pin_bm) {
137         return MEC_RET_OK;
138     }
139 
140     switch (prop) {
141     case MEC_WKTMR_BGPO_STATE:
142         regs->BGPO_DATA = (regs->BGPO_PWR & (uint32_t)~pin_bm) | (val_bm & pin_bm);
143         break;
144     case MEC_WKTMR_BGPO_ENABLE:
145         regs->BGPO_PWR = (regs->BGPO_PWR & (uint32_t)~pin_bm) | (val_bm & pin_bm);
146         break;
147     case MEC_WKTMR_BGPO_RESET_EVENT:
148         regs->BGPO_RESET = (regs->BGPO_RESET & (uint32_t)~pin_bm) | (val_bm & pin_bm);
149         break;
150     default:
151         return MEC_RET_ERR_INVAL;
152     }
153 
154     return MEC_RET_OK;
155 }
156 
157 /* end mec_wktimer.c */
158