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