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