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