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_defs.h"
11 #include "mec_ecia_api.h"
12 #include "mec_pcr_api.h"
13 #include "mec_ps2_api.h"
14 
15 #if MEC5_PS2_INSTANCES
16 
17 #define MEC_PS2_CTRL_BITMAP MEC_GENMASK(MEC5_PS2_INSTANCES, 0)
18 
19 #define MEC_PS2_GIRQ 18
20 #define MEC_PS2_0_GIRQ_POS 10
21 #define MEC_PS2_1_GIRQ_POS 11
22 
23 #define MEC_PS2_0_ECIA_INFO MEC5_ECIA_INFO(18, 10, 10, 100)
24 #define MEC_PS2_1_ECIA_INFO MEC5_ECIA_INFO(18, 11, 10, 101)
25 
26 /* PS/2 port wake event: start bit detection
27  * NOTE: PS/2 ports are separate pins and the controller can only be
28  * connected to one port at a time. Each port is two pins: clock and data.
29  * MEC5 PS/2 Controller 0 implements two ports.
30  * MEC5 PS/2 Controller 1 implements one port.
31  */
32 #define MEC_PS2_WAKE_GIRQ        21
33 #define MEC_PS2_WAKE_0A_GIRQ_POS 18 /* Controller 0 Port A */
34 #define MEC_PS2_WAKE_0B_GIRQ_POS 19 /* Controller 0 Port B */
35 #define MEC_PS2_WAKE_1B_GIRQ_POS 21 /* Controller 1 Port B */
36 
37 #define MEC_PS2_WAKE_0A_ECIA_INFO MEC5_ECIA_INFO(21, 13, 18, 129)
38 #define MEC_PS2_WAKE_0B_ECIA_INFO MEC5_ECIA_INFO(21, 13, 19, 130)
39 #define MEC_PS2_WAKE_1B_ECIA_INFO MEC5_ECIA_INFO(21, 13, 21, 132)
40 
41 struct mec_ps2_info {
42     uintptr_t base_addr;
43     uint16_t pcr_id;
44     uint8_t port_map;
45     uint8_t rsvd1;
46     uint32_t devi;
47     uint32_t port_a_wake_devi;
48     uint32_t port_b_wake_devi;
49 };
50 
51 static const struct mec_ps2_info ps2_instances[MEC5_PS2_INSTANCES] = {
52     { MEC_PS2CTL0_BASE, (uint16_t)MEC_PCR_PS2_0, 0x3u, 0, MEC_PS2_0_ECIA_INFO,
53       MEC_PS2_WAKE_0A_ECIA_INFO, MEC_PS2_WAKE_0B_ECIA_INFO },
54 #if MEC5_PS2_INSTANCES > 1
55     { MEC_PS2CTL1_BASE, (uint16_t)MEC_PCR_PS2_1, 0x2u, 0, MEC_PS2_1_ECIA_INFO,
56       MEC_PS2_WAKE_1B_ECIA_INFO, UINT32_MAX },
57 #endif
58 };
59 
find_ps2_info(uintptr_t base_addr)60 static struct mec_ps2_info const *find_ps2_info(uintptr_t base_addr)
61 {
62     for (size_t i = 0; i < MEC5_PS2_INSTANCES; i++) {
63         if (base_addr == ps2_instances[i].base_addr) {
64             return &ps2_instances[i];
65         }
66     }
67 
68     return NULL;
69 }
70 
ps2_clear_all_status(struct mec_ps2_regs * regs)71 static void ps2_clear_all_status(struct mec_ps2_regs *regs)
72 {
73     /* read and discard data to clear RX_RDY RO status */
74     regs->STATUS = regs->RTXB | (MEC_BIT(MEC_PS2_STATUS_RXTMO_Pos)
75                                  | MEC_BIT(MEC_PS2_STATUS_PE_Pos)
76                                  | MEC_BIT(MEC_PS2_STATUS_FE_Pos)
77                                  | MEC_BIT(MEC_PS2_STATUS_TXTMO_Pos)
78                                  | MEC_BIT(MEC_PS2_STATUS_TXSTTMO_Pos));
79 }
80 
81 /* PS/2 registers (not visible to the Host)
82  * Transmit buffer 8-bit W/O
83  * Receive data 8-bit R/O
84  * Control 8-bit R/W
85  * Status 8-bit mix of R/O and R/W1C bits.
86  *
87  * Writes to TX buffer triggers transmission unless the receive buffer is full.
88  * Once the receive data register is read and RDATA_RDY R/O status has cleared
89  * the pending transmit will begin.
90  */
91 
ps2_is_enabled(struct mec_ps2_regs * regs)92 static bool ps2_is_enabled(struct mec_ps2_regs *regs)
93 {
94     if (regs->CTRL & MEC_BIT(MEC_PS2_CTRL_ENABLE_Pos)) {
95         return true;
96     }
97 
98     return false;
99 }
100 
101 /* ---- Public API ---- */
102 
mec_hal_ps2_init(struct mec_ps2_regs * regs,uint32_t flags)103 int mec_hal_ps2_init(struct mec_ps2_regs *regs, uint32_t flags)
104 {
105     const struct mec_ps2_info *psi = find_ps2_info((uint32_t)regs);
106     uint32_t temp = 0u;
107     uint8_t ctrl = 0u;
108 
109     if (!psi) {
110         return MEC_RET_ERR_INVAL;
111     }
112 
113     mec_hal_pcr_clr_blk_slp_en(psi->pcr_id);
114     if (flags & MEC_PS2_FLAGS_RESET) {
115         mec_hal_pcr_blk_reset(psi->pcr_id);
116     } else {
117         regs->CTRL = 0u;
118     }
119 
120     mec_hal_girq_ctrl(psi->devi, 0);
121     mec_hal_girq_clr_src(psi->devi);
122     ps2_clear_all_status(regs);
123 
124     temp = ((flags & MEC_PS2_FLAGS_PARITY_MSK) >> MEC_PS2_FLAGS_PARITY_POS);
125     ctrl |= (uint8_t)((temp << MEC_PS2_CTRL_PARITY_Pos) & MEC_PS2_CTRL_PARITY_Msk);
126 
127     temp = ((flags & MEC_PS2_FLAGS_STOP_BITS_MSK) >> MEC_PS2_FLAGS_STOP_BITS_POS);
128     ctrl |= (uint8_t)((temp << MEC_PS2_CTRL_STOP_Pos) & MEC_PS2_CTRL_STOP_Msk);
129 
130     if (flags & MEC_PS2_FLAGS_ENABLE) {
131         ctrl |= MEC_BIT(MEC_PS2_CTRL_ENABLE_Pos);
132     }
133 
134     regs->CTRL = ctrl;
135 
136     if (flags & MEC_PS2_FLAGS_INTR_EN) {
137         mec_hal_girq_ctrl(psi->devi, 1);
138     }
139 
140     return MEC_RET_OK;
141 }
142 
mec_hal_ps2_control(struct mec_ps2_regs * regs,uint8_t operand,uint8_t opmask)143 int mec_hal_ps2_control(struct mec_ps2_regs *regs, uint8_t operand, uint8_t opmask)
144 {
145     const struct mec_ps2_info *psi = find_ps2_info((uint32_t)regs);
146 
147     if (!psi) {
148         return MEC_RET_ERR_INVAL;
149     }
150 
151     regs->CTRL = (regs->CTRL & (uint8_t)~(opmask & 0x03u)) | (operand & 0x03u);
152 
153     return MEC_RET_OK;
154 }
155 
mec_hal_ps2_is_enabled(struct mec_ps2_regs * regs)156 bool mec_hal_ps2_is_enabled(struct mec_ps2_regs *regs)
157 {
158     const struct mec_ps2_info *psi = find_ps2_info((uint32_t)regs);
159 
160     if (!psi) {
161         return false;
162     }
163 
164     return ps2_is_enabled(regs);
165 }
166 
mec_hal_ps2_girq_ctrl(struct mec_ps2_regs * base,uint8_t enable)167 int mec_hal_ps2_girq_ctrl(struct mec_ps2_regs *base, uint8_t enable)
168 {
169     const struct mec_ps2_info *psi = find_ps2_info((uint32_t)base);
170 
171     if (!psi) {
172         return MEC_RET_ERR_INVAL;
173     }
174 
175     mec_hal_girq_ctrl(psi->devi, enable);
176 
177     return MEC_RET_OK;
178 }
179 
mec_hal_ps2_girq_clr(struct mec_ps2_regs * base)180 int mec_hal_ps2_girq_clr(struct mec_ps2_regs *base)
181 {
182     const struct mec_ps2_info *psi = find_ps2_info((uint32_t)base);
183 
184     if (!psi) {
185         return MEC_RET_ERR_INVAL;
186     }
187 
188     mec_hal_girq_clr_src(psi->devi);
189 
190     return MEC_RET_OK;
191 }
192 
mec_hal_ps2_girq_result(struct mec_ps2_regs * base)193 uint32_t mec_hal_ps2_girq_result(struct mec_ps2_regs *base)
194 {
195     const struct mec_ps2_info *psi = find_ps2_info((uint32_t)base);
196 
197     if (!psi) {
198         return 0u;
199     }
200 
201     return mec_hal_girq_result(psi->devi);
202 }
203 
mec_hal_ps2_girq_wake_enable(struct mec_ps2_regs * base,uint8_t port,uint8_t enable)204 int mec_hal_ps2_girq_wake_enable(struct mec_ps2_regs *base, uint8_t port, uint8_t enable)
205 {
206     const struct mec_ps2_info *psi = find_ps2_info((uint32_t)base);
207     uint32_t devi = 0;
208 
209     if (!psi || (port >= MEC5_PS2_PORT_MAX)) {
210         return MEC_RET_ERR_INVAL;
211     }
212 
213     if ((uint32_t)psi->port_map & MEC_BIT(port)) {
214         return MEC_RET_ERR_INVAL;
215     }
216 
217     devi = psi->port_a_wake_devi;
218     if (port == MEC5_PS2_PORT_B) {
219         devi = psi->port_b_wake_devi;
220     }
221 
222     mec_hal_girq_ctrl(devi, enable);
223 
224     return MEC_RET_OK;
225 }
226 
mec_hal_ps2_girq_wake_result(struct mec_ps2_regs * base,uint8_t port)227 uint32_t mec_hal_ps2_girq_wake_result(struct mec_ps2_regs *base, uint8_t port)
228 {
229     const struct mec_ps2_info *psi = find_ps2_info((uint32_t)base);
230 
231     if (!psi) {
232         return 0u;
233     }
234 
235     if (port == MEC5_PS2_PORT_A) {
236         return mec_hal_girq_result(psi->port_a_wake_devi);
237     } else {
238         return mec_hal_girq_result(psi->port_b_wake_devi);
239     }
240 }
241 
mec_hal_ps2_girq_wake_clr(struct mec_ps2_regs * base,uint8_t port)242 void mec_hal_ps2_girq_wake_clr(struct mec_ps2_regs *base, uint8_t port)
243 {
244     const struct mec_ps2_info *psi = find_ps2_info((uint32_t)base);
245     uint32_t devi;
246 
247     if (!psi) {
248         return;
249     }
250 
251     devi = psi->port_a_wake_devi;
252     if (port != MEC5_PS2_PORT_A) {
253         devi = psi->port_b_wake_devi;
254     }
255 
256     mec_hal_girq_clr_src(devi);
257 }
258 
mec_hal_ps2_direction(struct mec_ps2_regs * regs,uint8_t dir_tx)259 void mec_hal_ps2_direction(struct mec_ps2_regs *regs, uint8_t dir_tx)
260 {
261     if (dir_tx) {
262         regs->CTRL |= MEC_BIT(MEC_PS2_CTRL_TREN_Pos);
263     } else {
264         regs->CTRL &= (uint8_t)~MEC_BIT(MEC_PS2_CTRL_TREN_Pos);
265     }
266 }
267 
mec_hal_ps2_get_status(struct mec_ps2_regs * regs)268 uint32_t mec_hal_ps2_get_status(struct mec_ps2_regs *regs)
269 {
270     return regs->STATUS;
271 }
272 
mec_hal_ps2_clr_status(struct mec_ps2_regs * regs,uint32_t clrmsk)273 void mec_hal_ps2_clr_status(struct mec_ps2_regs *regs, uint32_t clrmsk)
274 {
275     regs->STATUS = (uint8_t)(clrmsk & 0xffu);
276 }
277 
mec_hal_ps2_read_data(struct mec_ps2_regs * regs)278 uint8_t mec_hal_ps2_read_data(struct mec_ps2_regs *regs)
279 {
280     return regs->RTXB;
281 }
282 
mec_hal_ps2_send_data(struct mec_ps2_regs * regs,uint8_t data)283 void mec_hal_ps2_send_data(struct mec_ps2_regs *regs, uint8_t data)
284 {
285     regs->RTXB = data;
286 }
287 
mec_hal_ps2_inst_wake_enable(uint8_t instance,uint8_t port,uint8_t enable)288 int mec_hal_ps2_inst_wake_enable(uint8_t instance, uint8_t port, uint8_t enable)
289 {
290     if (instance >= MEC5_PS2_INSTANCES) {
291         return MEC_RET_ERR_INVAL;
292     }
293 
294     struct mec_ps2_regs *regs = (struct mec_ps2_regs *)ps2_instances[instance].base_addr;
295     int ret = mec_hal_ps2_girq_wake_enable(regs, port, enable);
296 
297     return ret;
298 }
299 
mec_hal_ps2_inst_wake_status_clr(uint8_t instance,uint8_t port)300 int mec_hal_ps2_inst_wake_status_clr(uint8_t instance, uint8_t port)
301 {
302     if (instance >= MEC5_PS2_INSTANCES) {
303         return MEC_RET_ERR_INVAL;
304     }
305 
306     struct mec_ps2_regs *regs = (struct mec_ps2_regs *)ps2_instances[instance].base_addr;
307 
308     mec_hal_ps2_girq_wake_clr(regs, port);
309 
310     return MEC_RET_OK;
311 }
312 
313 /* void mec_hal_ps2_girq_wake_clr(struct mec_ps2_regs *base, uint8_t port) */
314 /* int ret = mec_hal_ps2_girq_wake_enable(regs, port, enable); */
315 
316 /* Enable or disable wake enables for all PS/2 ports on all enabled controllers.
317  * If the port pins are configured for PS/2 mode then the port should not
318  * trigger a wake.
319  */
mec_hal_ps2_wake_enables(uint8_t enable)320 void mec_hal_ps2_wake_enables(uint8_t enable)
321 {
322     for (uint8_t i = 0; i < MEC5_PS2_INSTANCES; i++) {
323         const struct mec_ps2_info *info = &ps2_instances[i];
324         struct mec_ps2_regs *const regs = (struct mec_ps2_regs *)info->base_addr;
325 
326         if (ps2_is_enabled(regs)) {
327             if (info->port_map & MEC_BIT(0)) { /* port A? */
328                 mec_hal_girq_ctrl(info->port_a_wake_devi, enable);
329                 if (!enable) {
330                     mec_hal_girq_clr_src(info->port_a_wake_devi);
331                 }
332             }
333             if (info->port_map & MEC_BIT(1)) { /* port B? */
334                 mec_hal_girq_ctrl(info->port_b_wake_devi, enable);
335                 if (!enable) {
336                     mec_hal_girq_clr_src(info->port_b_wake_devi);
337                 }
338             }
339         }
340     }
341 }
342 #endif /* MEC5_PS2_INSTANCES */
343 
344 /* end mec_ps2.c */
345