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_htimer_api.h"
15 #include "mec_retval.h"
16 
17 #define MEC_HTMR_GIRQ       23
18 #define MEC_HTMR0_GIRQ_POS  16
19 #define MEC_HTMR1_GIRQ_POS  17
20 #define MEC_HTMR0_NVIC_NUM  112
21 #define MEC_HTMR0_ECIA_INFO MEC5_ECIA_INFO(MEC_HTMR_GIRQ, MEC_HTMR0_GIRQ_POS, 14, 112)
22 #define MEC_HTMR1_NVIC_NUM  113
23 #define MEC_HTMR1_ECIA_INFO MEC5_ECIA_INFO(MEC_HTMR_GIRQ, MEC_HTMR0_GIRQ_POS, 14, 113)
24 
mec_hal_htimer_init(struct mec_htmr_regs * regs,struct mec_htimer_context * ctx,uint8_t cfg_flags)25 int mec_hal_htimer_init(struct mec_htmr_regs *regs, struct mec_htimer_context *ctx,
26                         uint8_t cfg_flags)
27 {
28     int irq_en = 0;
29     uint16_t pcr_id = 0;
30 
31     if (!ctx) {
32         return MEC_RET_ERR_INVAL;
33     }
34 
35     switch ((uintptr_t)regs) {
36     case MEC_HTMR0_BASE:
37         ctx->regs = regs;
38         ctx->devi = MEC_HTMR0_ECIA_INFO;
39         pcr_id = MEC_PCR_HTMR0;
40         break;
41     case MEC_HTMR1_BASE:
42         ctx->regs = regs;
43         ctx->devi = MEC_HTMR1_ECIA_INFO;
44         pcr_id = MEC_PCR_HTMR1;
45         break;
46     default:
47         return MEC_RET_ERR_INVAL;
48     }
49 
50     mec_hal_pcr_clr_blk_slp_en(pcr_id);
51 
52     regs->PRELOAD = 0;
53     regs->CTRL = 0;
54 
55     mec_hal_girq_ctrl(ctx->devi, 0);
56 
57     if (cfg_flags & MEC_BIT(MEC_HTMR_CFG_RESOLUTION_125MS_POS)) {
58         regs->CTRL |= MEC_BIT(MEC_HTMR_CTRL_RES_Pos);
59     }
60 
61     if (cfg_flags & MEC_BIT(MEC_HTMR_CFG_IEN_POS)) {
62         irq_en = 1;
63     }
64 
65     mec_hal_girq_clr_src(ctx->devi);
66     mec_hal_girq_ctrl(ctx->devi, irq_en);
67 
68     /* Load count by writing it to the preload register.
69      * If the value != 0 the timer begins counting down.
70      */
71     ctx->count = ctx->preload;
72     regs->PRELOAD = ctx->preload;
73 
74     return MEC_RET_OK;
75 }
76 
mec_hal_htimer_intr_ctrl(struct mec_htimer_context * ctx,uint8_t enable)77 void mec_hal_htimer_intr_ctrl(struct mec_htimer_context *ctx, uint8_t enable)
78 {
79     mec_hal_girq_ctrl(ctx->devi, (int)enable);
80 }
81 
mec_hal_htimer_status(struct mec_htimer_context * ctx)82 uint32_t mec_hal_htimer_status(struct mec_htimer_context *ctx)
83 {
84     if (mec_hal_girq_src(ctx->devi)) {
85         return MEC_BIT(MEC_HTMR_STATUS_TERM_POS);
86     }
87 
88     return 0;
89 }
90 
mec_hal_htimer_status_clear(struct mec_htimer_context * ctx)91 void mec_hal_htimer_status_clear(struct mec_htimer_context *ctx)
92 {
93     mec_hal_girq_clr_src(ctx->devi);
94 }
95 
mec_hal_htimer_stop(struct mec_htmr_regs * regs)96 void mec_hal_htimer_stop(struct mec_htmr_regs *regs)
97 {
98     regs->PRELOAD = 0;
99 }
100 
101 /* Halt hibernation timer by writing PRELOAD to 0. A side effect is
102  * hardware also loads read-only COUNT register with 0. Read COUNT
103  * first and store in context structure. A race condition exists if
104  * the 32 KHz clock edge the timer decrements on occurs between reading
105  * COUNT and writing PRELOAD.
106  */
mec_hal_htimer_halt(struct mec_htimer_context * ctx)107 void mec_hal_htimer_halt(struct mec_htimer_context *ctx)
108 {
109     struct mec_htmr_regs *regs = ctx->regs;
110 
111     ctx->count = (uint16_t)(regs->COUNT & 0xffffu);
112     regs->PRELOAD = 0;
113 }
114 
115 /* Unhalt the hibernation timer by writing the COUNT value saved
116  * when timer was halted to the PRELOAD register.
117  */
mec_hal_htimer_unhalt(struct mec_htimer_context * ctx)118 void mec_hal_htimer_unhalt(struct mec_htimer_context *ctx)
119 {
120     struct mec_htmr_regs *regs = ctx->regs;
121 
122     regs->PRELOAD = ctx->count;
123 }
124 
125 /* Restart hibernation timer with a new count down value. */
mec_hal_htimer_restart(struct mec_htimer_context * ctx,uint16_t new_count)126 void mec_hal_htimer_restart(struct mec_htimer_context *ctx, uint16_t new_count)
127 {
128     struct mec_htmr_regs *regs = ctx->regs;
129 
130     regs->PRELOAD = 0;
131     regs->PRELOAD = new_count;
132 }
133 
134 /* end mec_rtimer.c */
135