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_kscan_api.h"
15 #include "mec_retval.h"
16 
17 #define MEC_KSCAN_GIRQ      21
18 #define MEC_KSCAN_GIRQ_POS  25
19 #define MEC_KSCAN_GIRQ_NVIC 13
20 #define MEC_KSCAN_GIRQ_NVIC_DIRECT 135
21 
22 #define MEC_KSCAN_ECIA_INFO MEC5_ECIA_INFO(MEC_KSCAN_GIRQ, MEC_KSCAN_GIRQ_POS, \
23                                            MEC_KSCAN_GIRQ_NVIC, MEC_KSCAN_GIRQ_NVIC_DIRECT)
24 
25 #define MEC_KSCAN_KSO_SEL_DLFT 0x40u
26 
27 /* Key scan EC-only registers
28  * Host-to-EC Data (RO) returns data written by Host to Data/Cmd registers
29  * EC Data (WO)
30  * EC KB status (RW except OBF, IBF, and CD)
31  * KB Control RW
32  * EC AUX Data (WO). Writes clear CD bit and set IBF in KB Status
33  * PCOBF bit[0] is PCOBF (RW) cleared when Host reads Data or AUX Data.
34  */
35 
kscan_default(struct mec_kscan_regs * regs)36 static void kscan_default(struct mec_kscan_regs *regs)
37 {
38     regs->KSI_INT_EN = 0;
39     regs->KSO_SEL = MEC_KSCAN_KSO_SEL_DLFT;
40     regs->EXT_CTRL = 0;
41     regs->KSI_STS = 0xffu;
42 }
43 
kscan_girq_dis_clr(void)44 static void kscan_girq_dis_clr(void)
45 {
46     mec_hal_girq_ctrl(MEC_KSCAN_ECIA_INFO, 0);
47     mec_hal_girq_clr_src(MEC_KSCAN_ECIA_INFO);
48 }
49 
50 /* ---- Public API ---- */
51 
52 /* Initialize the key scan controller */
mec_hal_kscan_init(struct mec_kscan_regs * regs,uint32_t flags,uint8_t ksi_in_intr_mask)53 int mec_hal_kscan_init(struct mec_kscan_regs *regs, uint32_t flags, uint8_t ksi_in_intr_mask)
54 {
55 #ifdef MEC_KSCAN_BASE_CHECK
56     if ((uintptr_t)regs != (uintptr_t)MEC_KSCAN0_BASE) {
57         return MEC_RET_ERR_INVAL;
58     }
59 #endif
60 
61     mec_hal_pcr_clr_blk_slp_en(MEC_PCR_KSCAN0);
62     if (flags & MEC_KSCAN_CFG_RESET) {
63         mec_hal_pcr_blk_reset(MEC_PCR_KSCAN0);
64     } else {
65         kscan_default(regs);
66     }
67 
68     kscan_girq_dis_clr();
69 
70     if (flags & MEC_KSCAN_KSO_PREDRIVE_EN) {
71         regs->EXT_CTRL |= MEC_BIT(MEC_KSCAN_EXT_CTRL_PREDRIVE_Pos);
72     }
73 
74     /* When a KSO is selected individually via the KSO_SELECT field
75      * it can be driven low (default) or high if this flag is selected.
76      */
77     if (flags & MEC_KSCAN_KSO_SELECT_DRV_HI) {
78         regs->KSO_SEL |= MEC_BIT(MEC_KSCAN_KSO_SEL_KSO_INVERT_Pos);
79     }
80 
81     regs->KSI_INT_EN = ksi_in_intr_mask;
82     regs->KSI_STS = 0xffu;
83 
84     if (flags & MEC_KSCAN_INTR_EN) {
85             mec_hal_girq_ctrl(MEC_KSCAN_ECIA_INFO, 1);
86     }
87 
88     if (flags & MEC_KSCAN_CFG_ENABLE) {
89         regs->KSO_SEL &= (uint8_t)~MEC_BIT(MEC_KSCAN_KSO_SEL_KSCAN_DIS_Pos);
90     }
91 
92     return MEC_RET_OK;
93 }
94 
mec_hal_kscan_enable(struct mec_kscan_regs * regs,uint8_t enable)95 int mec_hal_kscan_enable(struct mec_kscan_regs *regs, uint8_t enable)
96 {
97 #ifdef MEC_KSCAN_BASE_CHECK
98     if ((uintptr_t)regs != (uintptr_t)MEC_KSCAN0_BASE) {
99         return MEC_RET_ERR_INVAL;
100     }
101 #endif
102 
103     if (enable) {
104         regs->KSO_SEL &= (uint8_t)~MEC_BIT(MEC_KSCAN_KSO_SEL_KSCAN_DIS_Pos);
105     } else {
106         regs->KSO_SEL |= MEC_BIT(MEC_KSCAN_KSO_SEL_KSCAN_DIS_Pos);
107     }
108 
109     return MEC_RET_OK;
110 }
111 
mec_hal_kscan_is_enabled(struct mec_kscan_regs * regs)112 bool mec_hal_kscan_is_enabled(struct mec_kscan_regs *regs)
113 {
114 #ifdef MEC_KSCAN_BASE_CHECK
115     if ((uintptr_t)regs != (uintptr_t)MEC_KSCAN0_BASE) {
116         return false;
117     }
118 #endif
119 
120     if (regs->KSO_SEL & MEC_BIT(MEC_KSCAN_KSO_SEL_KSCAN_DIS_Pos)) {
121         return false;
122     }
123 
124     return true;
125 }
126 
mec_hal_kscan_kso_pre_drive_enable(struct mec_kscan_regs * regs,uint8_t enable)127 int mec_hal_kscan_kso_pre_drive_enable(struct mec_kscan_regs *regs, uint8_t enable)
128 {
129 #ifdef MEC_KSCAN_BASE_CHECK
130     if ((uintptr_t)regs != (uintptr_t)MEC_KSCAN0_BASE) {
131         return false;
132     }
133 #endif
134 
135     if (enable) {
136         regs->EXT_CTRL |= MEC_BIT(MEC_KSCAN_EXT_CTRL_PREDRIVE_Pos);
137     } else {
138         regs->EXT_CTRL &= (uint8_t)~MEC_BIT(MEC_KSCAN_EXT_CTRL_PREDRIVE_Pos);
139     }
140 
141     return MEC_RET_OK;
142 }
143 
mec_hal_kscan_girq_en(struct mec_kscan_regs * regs)144 int mec_hal_kscan_girq_en(struct mec_kscan_regs *regs)
145 {
146 #ifdef MEC_KSCAN_BASE_CHECK
147     if ((uintptr_t)regs != (uintptr_t)MEC_KSCAN0_BASE) {
148         return MEC_RET_ERR_INVAL;
149     }
150 #else
151     (void)regs;
152 #endif
153 
154     mec_hal_girq_ctrl(MEC_KSCAN_ECIA_INFO, 1);
155 
156     return MEC_RET_OK;
157 }
158 
mec_hal_kscan_girq_dis(struct mec_kscan_regs * regs)159 int mec_hal_kscan_girq_dis(struct mec_kscan_regs *regs)
160 {
161 #ifdef MEC_KSCAN_BASE_CHECK
162     if ((uintptr_t)regs != (uintptr_t)MEC_KSCAN0_BASE) {
163         return MEC_RET_ERR_INVAL;
164     }
165 #else
166     (void)regs;
167 #endif
168 
169     mec_hal_girq_ctrl(MEC_KSCAN_ECIA_INFO, 0);
170 
171     return MEC_RET_OK;
172 }
173 
mec_hal_kscan_girq_clr(struct mec_kscan_regs * regs)174 int mec_hal_kscan_girq_clr(struct mec_kscan_regs *regs)
175 {
176 #ifdef MEC_KSCAN_BASE_CHECK
177     if ((uintptr_t)regs != (uintptr_t)MEC_KSCAN0_BASE) {
178         return MEC_RET_ERR_INVAL;
179     }
180 #else
181     (void)regs;
182 #endif
183 
184     mec_hal_girq_clr_src(MEC_KSCAN_ECIA_INFO);
185 
186     return MEC_RET_OK;
187 }
188 
mec_hal_kscan_girq_result(struct mec_kscan_regs * regs)189 uint32_t mec_hal_kscan_girq_result(struct mec_kscan_regs *regs)
190 {
191 #ifdef MEC_KSCAN_BASE_CHECK
192     if ((uintptr_t)regs != (uintptr_t)MEC_KSCAN0_BASE) {
193         return MEC_RET_ERR_INVAL;
194     }
195 #else
196     (void)regs;
197 #endif
198 
199     return mec_hal_girq_result(MEC_KSCAN_ECIA_INFO);
200 }
201 
mec_hal_kscan_wake_enable(uint8_t enable)202 void mec_hal_kscan_wake_enable(uint8_t enable)
203 {
204     if (MEC_KSCAN0->KSO_SEL & MEC_BIT(MEC_KSCAN_KSO_SEL_KSCAN_DIS_Pos)) {
205         return;
206     }
207 
208     if (enable) {
209         mec_hal_girq_ctrl(MEC_KSCAN_ECIA_INFO, 1);
210     } else {
211         mec_hal_girq_ctrl(MEC_KSCAN_ECIA_INFO, 0);
212         mec_hal_girq_clr_src(MEC_KSCAN_ECIA_INFO);
213     }
214 }
215 /* end mec_kscan.c */
216