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_espi_api.h"
13 #include "mec_retval.h"
14 
15 /* ---- eSPI Virtual Wire channel ----
16  * The eSPI design implements virtual wires in two directions:
17  * eSPI Host Controller to eSPI Target (EC)
18  * eSPI Target (EC) to eSPI Host Controller.
19  * Virtual wires are grouped into 4 VWires and transmitted in
20  * packet marked as the VWire channel. The grouping of the VWires
21  * is defined by the eSPI specification. The standard assigns a
22  * host index number to each group.
23  * MEC5 implements:
24  *   MEC5_ESPI_NUM_CTVW eSPI Host Controller To Target VWire 96-bit registers.
25  *   MEC5_ESPI_NUM_TCVW Target(EC) to eSPI Host Controller VWire 64-bit registers.
26  *
27  * CTVW hardware can generate an interrupt to the EC when any individual VWire
28  * changes state.
29  * TCVW hardware includes a transmit bit to send a group of VWires to the Host
30  * and a bit indicating the packet has been transmitted. No interrupt can be
31  * generated.
32  *
33  */
34 
35 #define MEC_ESPI_VW_CHEN_CHG_GIRQ19_POS 8
36 
37 static const uint8_t vw_ct_ien_xlat_tbl[] = {
38     [MEC_ESPI_VW_CT_IEN_DIS] = 0x4u,
39     [MEC_ESPI_VW_CT_IEN_LL] = 0u,
40     [MEC_ESPI_VW_CT_IEN_LH] = 0x1u,
41     [MEC_ESPI_VW_CT_IEN_RE] = 0xdu,
42     [MEC_ESPI_VW_CT_IEN_FE] = 0xeu,
43     [MEC_ESPI_VW_CT_IEN_BE] = 0xfu,
44 };
45 #define MEC_VW_CT_IXLAT_TBL_ENTRIES \
46     (sizeof(vw_ct_ien_xlat_tbl) / sizeof(uint8_t))
47 
xlat_isel(uint32_t logical_isel)48 static uint32_t xlat_isel(uint32_t logical_isel)
49 {
50     uint32_t isel = 0x4u; /* default to disabled */
51 
52     if (logical_isel < MEC_VW_CT_IXLAT_TBL_ENTRIES) {
53         isel = vw_ct_ien_xlat_tbl[logical_isel];
54     }
55 
56     return isel;
57 }
58 
59 /* ---- Public API ---- */
60 
mec_hal_espi_vw_is_enabled(struct mec_espi_io_regs * const iobase)61 int mec_hal_espi_vw_is_enabled(struct mec_espi_io_regs *const iobase)
62 {
63     if (iobase->VWSTS & MEC_BIT(MEC_ESPI_IO_VWSTS_CHEN_Pos)) {
64         return 1;
65     }
66 
67     return 0;
68 }
69 
70 /* VWire channel enable current state is in the VW Status register located in
71  * the eSPI I/O component. VWire channel enable change does not have a bit
72  * in the eSPI register spaces. Instead VW channel enable change signal is
73  * connected to GIRQ19 bit[8].
74  */
mec_hal_espi_vw_en_status(struct mec_espi_io_regs * const iobase)75 uint32_t mec_hal_espi_vw_en_status(struct mec_espi_io_regs *const iobase)
76 {
77     uint32_t ensts = iobase->VWSTS & MEC_BIT(MEC_ESPI_IO_VWSTS_CHEN_Pos);
78 
79     /* move bit[8] to bit[1] */
80     ensts |= ((MEC_ECIA0->GIRQ[MEC_GIRQ_IDX_GIRQ19].SOURCE >> 7) & 0x2u);
81 
82     return ensts;
83 }
84 
mec_hal_espi_vw_en_status_clr(void)85 void mec_hal_espi_vw_en_status_clr(void)
86 {
87     MEC_ECIA0->GIRQ[MEC_GIRQ_IDX_GIRQ19].SOURCE = MEC_BIT(MEC_ESPI_VW_CHEN_CHG_GIRQ19_POS);
88 }
89 
90 /* Returns non-zero if VW Enable Change interrupt is enabled and asserted else 0 */
mec_hal_espi_vw_en_result(void)91 uint32_t mec_hal_espi_vw_en_result(void)
92 {
93     return (MEC_ECIA0->GIRQ[MEC_GIRQ_IDX_GIRQ19].RESULT
94             & MEC_BIT(MEC_ESPI_VW_CHEN_CHG_GIRQ19_POS));
95 }
96 
mec_hal_espi_vw_en_ien(uint8_t enable)97 void mec_hal_espi_vw_en_ien(uint8_t enable)
98 {
99     if (enable) {
100         MEC_ECIA0->GIRQ[MEC_GIRQ_IDX_GIRQ19].EN_SET = MEC_BIT(MEC_ESPI_VW_CHEN_CHG_GIRQ19_POS);
101     } else {
102         MEC_ECIA0->GIRQ[MEC_GIRQ_IDX_GIRQ19].EN_CLR = MEC_BIT(MEC_ESPI_VW_CHEN_CHG_GIRQ19_POS);
103     }
104 }
105 
mec_hal_espi_vw_ready_set(struct mec_espi_io_regs * const iobase)106 void mec_hal_espi_vw_ready_set(struct mec_espi_io_regs * const iobase)
107 {
108     iobase->VWRDY = MEC_BIT(MEC_ESPI_IO_VWRDY_VW_READY_Pos);
109 }
110 
mec_hal_espi_vw_is_ready(struct mec_espi_io_regs * const iobase)111 int mec_hal_espi_vw_is_ready(struct mec_espi_io_regs * const iobase)
112 {
113     if (iobase->VWRDY & MEC_BIT(MEC_ESPI_IO_VWRDY_VW_READY_Pos)) {
114         return 1;
115     }
116 
117     return 0;
118 }
119 
120 /* Compute Controller-to-Target VWire register index given VW GIRQ bit
121  * position and VW GIRQ bank (0/1).
122  */
mec_hal_espi_vw_ct_from_girq_pos(uint8_t bank,uint8_t girq_pos,uint8_t * ctidx,uint8_t * ctsrc)123 void mec_hal_espi_vw_ct_from_girq_pos(uint8_t bank, uint8_t girq_pos,
124                                       uint8_t *ctidx, uint8_t *ctsrc)
125 {
126     uint32_t d, m;
127 
128     if (girq_pos > 31) {
129         return;
130     }
131 
132     if (ctidx) {
133         d = girq_pos / 4u;
134         if (bank) {
135             d += 7u;
136         }
137         *ctidx = (uint8_t)d;
138     }
139 
140     if (ctsrc) {
141         m = girq_pos % 4u;
142         *ctsrc = (uint8_t)m;
143     }
144 }
145 
146 /* Controller(Host) to Target(EC) VWires can be configured to generate
147  * an interrupt to the EC when they change. The CT VWire register do
148  * not contain any interrupt status only interrupt enable. GIRQ.SOURCE
149  * is the VWire interrupt change status.
150  *
151  * MEC5 conntect the CT VWire groups to the ECIA as follows:
152  * GIRQ24 bits [0 - 3] CTVW00 src[0 - 3]
153  * GIRQ24 bits [4 - 7] CTVW01 src[0 - 3]
154  * ...
155  * GIRQ24 bits [24 - 27] CTVW06 src[0 - 3]
156  * GIRQ25 bits [0 - 3] CTVW07 src[0 - 3]
157  * GIRQ25 bits [4 - 7] CTVW08 src[0 - 3]
158  * ...
159  * GIRQ25 bits [12 - 15] CTVW10 src[0 - 3]
160  *
161  * NOTE: ECIA GIRQ24 and GIRQ25 are both aggregated only.
162  * Hardware does not provide direct NVIC connection of all the
163  * GIRQ.SOURCE bits.
164  */
165 
mec_hal_espi_vw_ct_girq_ctrl(uint8_t ct_idx,uint8_t src_idx,uint8_t enable)166 int mec_hal_espi_vw_ct_girq_ctrl(uint8_t ct_idx, uint8_t src_idx, uint8_t enable)
167 {
168     uint32_t bitpos;
169 
170     if ((ct_idx > MEC_CTVW_IDX10) || (src_idx > 3)) {
171         return MEC_RET_ERR_INVAL;
172     }
173 
174     if (ct_idx < MEC_CTVW_IDX07) { /* GIRQ24 */
175         bitpos = (ct_idx * 4u) + src_idx;
176         if (enable) {
177             MEC_ECIA0->GIRQ[MEC_GIRQ_IDX_GIRQ24].EN_SET = MEC_BIT(bitpos);
178         } else {
179             MEC_ECIA0->GIRQ[MEC_GIRQ_IDX_GIRQ24].EN_CLR = MEC_BIT(bitpos);
180         }
181     } else { /* GIRQ25 */
182         bitpos = ((ct_idx - MEC_CTVW_IDX07) * 4u) + src_idx;
183         if (enable) {
184             MEC_ECIA0->GIRQ[MEC_GIRQ_IDX_GIRQ25].EN_SET = MEC_BIT(bitpos);
185         } else {
186             MEC_ECIA0->GIRQ[MEC_GIRQ_IDX_GIRQ25].EN_CLR = MEC_BIT(bitpos);
187         }
188     }
189 
190     return MEC_RET_OK;
191 }
192 
mec_hal_espi_vw_ct_girq_ctrl_all(uint8_t enable)193 void mec_hal_espi_vw_ct_girq_ctrl_all(uint8_t enable)
194 {
195     if (enable) {
196         MEC_ECIA0->GIRQ[MEC_GIRQ_IDX_GIRQ24].EN_SET = UINT32_MAX;
197         MEC_ECIA0->GIRQ[MEC_GIRQ_IDX_GIRQ25].EN_SET = UINT32_MAX;
198     } else {
199         MEC_ECIA0->GIRQ[MEC_GIRQ_IDX_GIRQ24].EN_CLR = UINT32_MAX;
200         MEC_ECIA0->GIRQ[MEC_GIRQ_IDX_GIRQ25].EN_CLR = UINT32_MAX;
201     }
202 }
203 
mec_hal_espi_vw_ct_girq_clr(uint8_t ct_idx,uint8_t src_idx)204 int mec_hal_espi_vw_ct_girq_clr(uint8_t ct_idx, uint8_t src_idx)
205 {
206     uint32_t bitpos;
207 
208     if ((ct_idx > MEC_CTVW_IDX10) || (src_idx > 3)) {
209         return MEC_RET_ERR_INVAL;
210     }
211 
212     if (ct_idx < MEC_CTVW_IDX07) { /* GIRQ24 */
213         bitpos = (ct_idx * 4u) + src_idx;
214         MEC_ECIA0->GIRQ[MEC_GIRQ_IDX_GIRQ24].SOURCE = MEC_BIT(bitpos);
215     } else { /* GIRQ25 */
216         bitpos = ((ct_idx - MEC_CTVW_IDX07) * 4u) + src_idx;
217         MEC_ECIA0->GIRQ[MEC_GIRQ_IDX_GIRQ25].SOURCE = MEC_BIT(bitpos);
218     }
219 
220     return MEC_RET_OK;
221 }
222 
mec_hal_espi_vw_ct_girq_clr_msk(uint8_t ct_idx,uint8_t clr_msk)223 int mec_hal_espi_vw_ct_girq_clr_msk(uint8_t ct_idx, uint8_t clr_msk)
224 {
225     uint32_t bitpos, idx;
226 
227     if (ct_idx > MEC_CTVW_IDX10) {
228         return MEC_RET_ERR_INVAL;
229     }
230 
231     if (ct_idx < MEC_CTVW_IDX07) { /* GIRQ24 */
232         bitpos = (ct_idx * 4u);
233         idx = MEC_GIRQ_IDX_GIRQ24;
234     } else { /* GIRQ25 */
235         bitpos = ((ct_idx - MEC_CTVW_IDX07) * 4u);
236         idx = MEC_GIRQ_IDX_GIRQ25;
237     }
238 
239     MEC_ECIA0->GIRQ[idx].SOURCE = ((uint32_t)clr_msk << bitpos);
240 
241     return MEC_RET_OK;
242 }
243 
mec_hal_espi_vw_ct_girq_clr_all(void)244 void mec_hal_espi_vw_ct_girq_clr_all(void)
245 {
246     MEC_ECIA0->GIRQ[MEC_GIRQ_IDX_GIRQ24].SOURCE = UINT32_MAX;
247     MEC_ECIA0->GIRQ[MEC_GIRQ_IDX_GIRQ25].SOURCE = UINT32_MAX;
248 }
249 
mec_hal_espi_vw_ct_girq_sts(uint8_t ct_idx,uint8_t src_idx)250 uint32_t mec_hal_espi_vw_ct_girq_sts(uint8_t ct_idx, uint8_t src_idx)
251 {
252     uint32_t bitpos, status;
253 
254     if ((ct_idx > MEC_CTVW_IDX10) || (src_idx > 3)) {
255         return 0;
256     }
257 
258     if (ct_idx < MEC_CTVW_IDX07) { /* GIRQ24 */
259         bitpos = (ct_idx * 4u) + src_idx;
260         status = MEC_ECIA0->GIRQ[MEC_GIRQ_IDX_GIRQ24].SOURCE;
261     } else { /* GIRQ25 */
262         bitpos = ((ct_idx - MEC_CTVW_IDX07) * 4u) + src_idx;
263         status = MEC_ECIA0->GIRQ[MEC_GIRQ_IDX_GIRQ25].SOURCE;
264     }
265 
266     return ((status >> bitpos) & 0x1u);
267 }
268 
mec_hal_espi_vw_ct_girq_bank_result(uint8_t bank)269 uint32_t mec_hal_espi_vw_ct_girq_bank_result(uint8_t bank)
270 {
271     if (bank == MEC_ESPI_CTVW_IRQ_BANK_0) {
272         return MEC_ECIA0->GIRQ[MEC_GIRQ_IDX_GIRQ24].RESULT;
273     } else {
274         return MEC_ECIA0->GIRQ[MEC_GIRQ_IDX_GIRQ25].RESULT;
275     }
276 }
277 
mec_hal_espi_vw_ct_girq_bank_clr(uint8_t bank,uint32_t clrmsk)278 void mec_hal_espi_vw_ct_girq_bank_clr(uint8_t bank, uint32_t clrmsk)
279 {
280     if (bank == MEC_ESPI_CTVW_IRQ_BANK_0) {
281         MEC_ECIA0->GIRQ[MEC_GIRQ_IDX_GIRQ24].SOURCE = clrmsk;
282     } else {
283         MEC_ECIA0->GIRQ[MEC_GIRQ_IDX_GIRQ25].SOURCE = clrmsk;
284     }
285 }
286 
mec_hal_espi_vw_ct_girq_res(uint8_t ct_idx,uint8_t src_idx)287 uint32_t mec_hal_espi_vw_ct_girq_res(uint8_t ct_idx, uint8_t src_idx)
288 {
289     uint32_t bitpos, result;
290 
291     if ((ct_idx > MEC_CTVW_IDX10) || (src_idx > 3)) {
292         return 0;
293     }
294 
295     if (ct_idx < MEC_CTVW_IDX07) { /* GIRQ24 */
296         bitpos = (ct_idx * 4u) + src_idx;
297         result = MEC_ECIA0->GIRQ[MEC_GIRQ_IDX_GIRQ24].RESULT;
298     } else { /* GIRQ25 */
299         bitpos = ((ct_idx - MEC_CTVW_IDX07) * 4u) + src_idx;
300         result = MEC_ECIA0->GIRQ[MEC_GIRQ_IDX_GIRQ25].RESULT;
301     }
302 
303     return ((result >> bitpos) & 0x1u);
304 }
305 
mec_hal_espi_vw_ct_group_girq_sts(uint8_t ct_idx)306 uint32_t mec_hal_espi_vw_ct_group_girq_sts(uint8_t ct_idx)
307 {
308     uint32_t bitpos, status;
309 
310     if (ct_idx > MEC_CTVW_IDX10) {
311         return 0;
312     }
313 
314     if (ct_idx < MEC_CTVW_IDX07) { /* GIRQ24 */
315         bitpos = ct_idx * 4u;
316         status = MEC_ECIA0->GIRQ[MEC_GIRQ_IDX_GIRQ24].SOURCE;
317     } else { /* GIRQ25 */
318         bitpos = (ct_idx - MEC_CTVW_IDX07) * 4u;
319         status = MEC_ECIA0->GIRQ[MEC_GIRQ_IDX_GIRQ25].SOURCE;
320     }
321 
322     return ((status >> bitpos) & 0xfu);
323 }
324 
mec_hal_espi_vw_ct_group_girq_sts_clr(uint8_t ct_idx)325 void mec_hal_espi_vw_ct_group_girq_sts_clr(uint8_t ct_idx)
326 {
327     uint32_t bitpos;
328 
329     if (ct_idx >MEC_CTVW_IDX10) {
330         return;
331     }
332 
333     if (ct_idx < MEC_CTVW_IDX07) { /* GIRQ24 */
334         bitpos = ct_idx * 4u;
335         MEC_ECIA0->GIRQ[MEC_GIRQ_IDX_GIRQ24].SOURCE = (0xfu << bitpos);
336     } else { /* GIRQ25 */
337         bitpos = (ct_idx - MEC_CTVW_IDX07) * 4u;
338         MEC_ECIA0->GIRQ[MEC_GIRQ_IDX_GIRQ25].SOURCE = (0xfu << bitpos);
339     }
340 }
341 
mec_hal_espi_vw_ct_group_girq_res(uint8_t ct_idx)342 uint32_t mec_hal_espi_vw_ct_group_girq_res(uint8_t ct_idx)
343 {
344     uint32_t bitpos, result;
345 
346     if (ct_idx > MEC_CTVW_IDX10) {
347         return 0;
348     }
349 
350     if (ct_idx < MEC_CTVW_IDX07) { /* GIRQ24 */
351         bitpos = ct_idx * 4u;
352         result = MEC_ECIA0->GIRQ[MEC_GIRQ_IDX_GIRQ24].SOURCE;
353     } else { /* GIRQ25 */
354         bitpos = (ct_idx - MEC_CTVW_IDX07) * 4u;
355         result = MEC_ECIA0->GIRQ[MEC_GIRQ_IDX_GIRQ25].SOURCE;
356     }
357 
358     return ((result >> bitpos) & 0xfu);
359 }
360 
mec_hal_espi_vw_ct_group_girq_ctrl(uint8_t ct_idx,uint8_t src_msk,uint8_t enable)361 int mec_hal_espi_vw_ct_group_girq_ctrl(uint8_t ct_idx, uint8_t src_msk, uint8_t enable)
362 {
363     uint32_t bitpos, regval;
364 
365     if (ct_idx > MEC_CTVW_IDX10) {
366         return MEC_RET_ERR_INVAL;
367     }
368 
369     regval = (uint32_t)(src_msk & 0xfu);
370     if (ct_idx < MEC_CTVW_IDX07) { /* GIRQ24 */
371         bitpos = ct_idx * 4u;
372         if (enable) {
373             MEC_ECIA0->GIRQ[MEC_GIRQ_IDX_GIRQ24].EN_SET = regval << bitpos;
374         } else {
375             MEC_ECIA0->GIRQ[MEC_GIRQ_IDX_GIRQ24].EN_CLR = regval << bitpos;
376         }
377     } else { /* GIRQ25 */
378         bitpos = (ct_idx - MEC_CTVW_IDX07) * 4u;
379         if (enable) {
380             MEC_ECIA0->GIRQ[MEC_GIRQ_IDX_GIRQ25].EN_SET = regval << bitpos;
381         } else {
382             MEC_ECIA0->GIRQ[MEC_GIRQ_IDX_GIRQ25].EN_CLR = regval << bitpos;
383         }
384     }
385 
386     return MEC_RET_OK;
387 }
mec_hal_espi_vw_ct_irq_sel_set(struct mec_espi_vw_regs * const vwbase,uint8_t vw_idx,uint8_t src_idx,uint8_t irq_sel)388 int mec_hal_espi_vw_ct_irq_sel_set(struct mec_espi_vw_regs * const vwbase, uint8_t vw_idx,
389                                    uint8_t src_idx, uint8_t irq_sel)
390 {
391     volatile struct mec_espi_vw_ctvw_regs *ctvw;
392     uint32_t isel = 0, msk = MEC_ESPI_VW_CTVW_SRC_ISELS_SRC0_IRQ_SEL_Msk;
393 
394     if ((vw_idx > MEC_ESPI_CTVW10_REG_IDX) || (src_idx > 3)
395         || (irq_sel >= MEC_VW_CT_IXLAT_TBL_ENTRIES)) {
396         return MEC_RET_ERR_INVAL;
397     }
398 
399     ctvw = &vwbase->CTVW[vw_idx];
400 
401     isel = vw_ct_ien_xlat_tbl[irq_sel] & msk;
402     isel <<= (src_idx * 8u);
403     msk <<= (src_idx * 8u);
404 
405     ctvw->SRC_ISELS = (ctvw->SRC_ISELS & ~msk) | isel;
406 
407     return MEC_RET_OK;
408 }
409 
410 /* Set all four VWires IRQ select fields in the CT VW group at vw_idx.
411  * irq_sels b[7:0] = Source 0, ..., b[31:24] = Source 3 IRQ select.
412  */
mec_hal_espi_vw_ct_irq_sel_set_all(struct mec_espi_vw_regs * const vwbase,uint8_t vw_idx,uint32_t irq_sels)413 int mec_hal_espi_vw_ct_irq_sel_set_all(struct mec_espi_vw_regs * const vwbase, uint8_t vw_idx,
414                                        uint32_t irq_sels)
415 {
416     volatile struct mec_espi_vw_ctvw_regs *ctvw;
417     uint32_t r = 0;
418     uint32_t temp = 0;
419 
420     if (vw_idx > MEC_ESPI_CTVW10_REG_IDX) {
421         return MEC_RET_ERR_INVAL;
422     }
423 
424     ctvw = &vwbase->CTVW[vw_idx];
425 
426     for (size_t n = 0; n < 4; n++) {
427         temp = irq_sels & 0x7u;
428 
429         if (temp >= MEC_VW_CT_IXLAT_TBL_ENTRIES) {
430             return MEC_RET_ERR_INVAL;
431         }
432 
433         temp = vw_ct_ien_xlat_tbl[temp] & MEC_ESPI_VW_CTVW_SRC_ISELS_SRC0_IRQ_SEL_Msk;
434         r |= (temp << (n * 8u));
435     }
436 
437     ctvw->SRC_ISELS = r;
438 
439     return MEC_RET_OK;
440 }
441 
442 /* Configure MEC5 Controller-to-Target(EC) Virtual Wire group register.
443  * All fields are set by RESET_SYS (chip reset) except the four VWire Source value
444  * fields. VWire Source value fields are reset by the reset source field. If we
445  * are requested to modify source values we must switch their reset source to
446  * RESET_SYS, modify, then switch to requested reset source or restore the
447  * original reset source.
448  */
mec_hal_espi_vwg_ct_config(struct mec_espi_vw_regs * const vwbase,uint8_t ctidx,struct mec_espi_vw_config * cfg,uint32_t flags)449 static void mec_hal_espi_vwg_ct_config(struct mec_espi_vw_regs * const vwbase, uint8_t ctidx,
450                                        struct mec_espi_vw_config *cfg, uint32_t flags)
451 {
452     volatile struct mec_espi_vw_ctvw_regs *ctvw = &vwbase->CTVW[ctidx];
453     uint32_t r[3];
454     unsigned int i;
455 
456     if (!flags) { /* do not modify anything */
457         return;
458     }
459 
460     r[0] = ctvw->HIRSS;
461     r[1] = ctvw->SRC_ISELS;
462     r[2] = ctvw->STATES;
463     if (flags & MEC_BIT(MEC_ESPI_VWG_CFG_HI_POS)) {
464         r[0] &= (uint32_t)~MEC_ESPI_VW_CTVW_HIRSS_HOST_IDX_Msk;
465         r[0] |= (((uint32_t)cfg->host_idx << MEC_ESPI_VW_CTVW_HIRSS_HOST_IDX_Pos)
466                  & MEC_ESPI_VW_CTVW_HIRSS_HOST_IDX_Msk);
467     }
468 
469     if (flags & MEC_BIT(MEC_ESPI_VWG_CFG_RST_SRC_POS)) {
470         r[0] &= (uint32_t)~MEC_ESPI_VW_CTVW_HIRSS_RST_SRC_Msk;
471         r[0] |= (((uint32_t)cfg->reset_src << MEC_ESPI_VW_CTVW_HIRSS_RST_SRC_Pos)
472                  & MEC_ESPI_VW_CTVW_HIRSS_RST_SRC_Msk);
473     }
474 
475     for (i = 0; i < 4; i++) {
476         if (flags & MEC_BIT(MEC_ESPI_VWG_CFG_SRC0_RST_VAL_POS + i)) {
477             if (cfg->reset_val_bm & MEC_BIT(i)) {
478                 r[0] |= MEC_BIT(i + MEC_ESPI_VW_CTVW_HIRSS_RST_STATE_Pos);
479             } else {
480                 r[0] &= ~MEC_BIT(i + MEC_ESPI_VW_CTVW_HIRSS_RST_STATE_Pos);
481             }
482             if (flags & MEC_BIT(MEC_ESPI_VWG_CFG_SRC0_IRQ_POS + i)) {
483                 uint32_t msk = 0xfu << i;
484                 uint8_t j = cfg->src_irq_sel[i];
485 
486                 if (j >= MEC_VW_CT_IXLAT_TBL_ENTRIES) {
487                     j = MEC_ESPI_VW_CT_IEN_DIS;
488                 }
489                 r[1] = ((r[1] & ~msk) | ((uint32_t)vw_ct_ien_xlat_tbl[j] << (i * 8)));
490             }
491             if (cfg->src_val_bm & MEC_BIT(i)) {
492                 r[2] |= MEC_BIT(i * 8);
493             } else {
494                 r[2] &= ~MEC_BIT(i * 8);
495             }
496         }
497     }
498 
499     ctvw->STATES = r[2];
500     ctvw->SRC_ISELS = r[1];
501     ctvw->HIRSS = r[0];
502 }
503 
mec_hal_espi_vw_ct_host_index_set(struct mec_espi_vw_regs * const vwbase,uint8_t ctidx,uint8_t host_index)504 int mec_hal_espi_vw_ct_host_index_set(struct mec_espi_vw_regs * const vwbase, uint8_t ctidx,
505                                       uint8_t host_index)
506 {
507     if (!vwbase || (ctidx > MEC_CTVW_IDX10)) {
508         return MEC_RET_ERR_INVAL;
509     }
510 
511     volatile struct mec_espi_vw_ctvw_regs *ctvw = &vwbase->CTVW[ctidx];
512     uint32_t temp = ctvw->HIRSS & (uint32_t)~MEC_ESPI_VW_CTVW_HIRSS_HOST_IDX_Msk;
513 
514     temp |= host_index;
515     ctvw->HIRSS = temp;
516 
517     return MEC_RET_OK;
518 }
519 
mec_hal_espi_vw_ct_reset_source_get(struct mec_espi_vw_regs * const vwbase,uint8_t ctidx,uint8_t * reset_source)520 int mec_hal_espi_vw_ct_reset_source_get(struct mec_espi_vw_regs * const vwbase,
521                                         uint8_t ctidx, uint8_t *reset_source)
522 {
523     if (!vwbase || (ctidx > MEC_CTVW_IDX10) || !reset_source) {
524         return MEC_RET_ERR_INVAL;
525     }
526 
527     volatile struct mec_espi_vw_ctvw_regs *ctvw = &vwbase->CTVW[ctidx];
528     uint32_t temp = ctvw->HIRSS;
529 
530     temp = (temp & MEC_ESPI_VW_CTVW_HIRSS_RST_SRC_Msk) >> MEC_ESPI_VW_CTVW_HIRSS_RST_SRC_Pos;
531     *reset_source = (uint8_t)(temp & 0xffu);
532 
533     return MEC_RET_OK;
534 }
535 
mec_hal_espi_vw_ct_reset_source_set(struct mec_espi_vw_regs * const vwbase,uint8_t ctidx,uint8_t reset_source)536 int mec_hal_espi_vw_ct_reset_source_set(struct mec_espi_vw_regs * const vwbase,
537                                         uint8_t ctidx, uint8_t reset_source)
538 {
539     if (!vwbase || (ctidx > MEC_CTVW_IDX10)) {
540         return MEC_RET_ERR_INVAL;
541     }
542 
543     volatile struct mec_espi_vw_ctvw_regs *ctvw = &vwbase->CTVW[ctidx];
544     uint32_t temp = ctvw->HIRSS;
545 
546     temp &= (uint32_t)~MEC_ESPI_VW_CTVW_HIRSS_RST_SRC_Msk;
547     temp |= (((uint32_t)reset_source << MEC_ESPI_VW_CTVW_HIRSS_RST_SRC_Pos)
548              & MEC_ESPI_VW_CTVW_HIRSS_RST_SRC_Msk);
549     ctvw->HIRSS = temp;
550 
551     return MEC_RET_OK;
552 }
553 
mec_hal_espi_vw_ct_reset_state_set(struct mec_espi_vw_regs * const vwbase,uint8_t ctidx,uint8_t src_idx,uint8_t reset_state)554 int mec_hal_espi_vw_ct_reset_state_set(struct mec_espi_vw_regs * const vwbase, uint8_t ctidx,
555                                        uint8_t src_idx, uint8_t reset_state)
556 {
557     if (!vwbase || (ctidx > MEC_CTVW_IDX10) || (src_idx > 3)) {
558         return MEC_RET_ERR_INVAL;
559     }
560 
561     volatile struct mec_espi_vw_ctvw_regs *ctvw = &vwbase->CTVW[ctidx];
562     uint32_t temp = ctvw->HIRSS;
563 
564     temp &= ~MEC_BIT(MEC_ESPI_VW_CTVW_HIRSS_RST_STATE_Pos + src_idx);
565     if (reset_state) {
566         temp |= MEC_BIT(MEC_ESPI_VW_CTVW_HIRSS_RST_STATE_Pos + src_idx);
567     }
568     ctvw->HIRSS = temp;
569 
570     return MEC_RET_OK;
571 }
572 
mec_hal_espi_vw_ct_irqsel_set(struct mec_espi_vw_regs * const vwbase,uint8_t ctidx,uint8_t src_idx,uint8_t irq_sel)573 int mec_hal_espi_vw_ct_irqsel_set(struct mec_espi_vw_regs * const vwbase, uint8_t ctidx,
574                                   uint8_t src_idx, uint8_t irq_sel)
575 {
576     if (!vwbase || (ctidx > MEC_CTVW_IDX10) || (src_idx > 3)) {
577         return MEC_RET_ERR_INVAL;
578     }
579 
580     volatile struct mec_espi_vw_ctvw_regs *ctvw = &vwbase->CTVW[ctidx];
581     uint32_t pos = MEC_ESPI_VW_CTVW_SRC_ISELS_SRC0_IRQ_SEL_Pos * 8u;
582     uint32_t msk = MEC_ESPI_VW_CTVW_SRC_ISELS_SRC0_IRQ_SEL_Msk << (src_idx * 8u);
583     uint32_t temp = ctvw->SRC_ISELS & ~msk;
584 
585     temp |= ((xlat_isel(irq_sel) << pos) & msk);
586     ctvw->SRC_ISELS = temp;
587 
588     return MEC_RET_OK;
589 }
590 
591 /* Configure specified fields of a Controller-to-Target VWire in a group.
592  * ctidx specifies the zero based index into the hardware array of 80-bit
593  * C2T VWire registers. Each 80-bit register controls 4 VWires.
594  * Properties affecting the whole group of 4 VWires:
595  *      Host Index and Reset Source
596  * Properities of the single VWire specified by src_idx:
597  *      Reset State and IRQ Select
598  * All of these fields are reset on POR or chip reset only.
599  * NOTE: Reset States are loaded into SRC bits on the de-asserting
600  * edge of Reset Source.
601  */
mec_hal_espi_vw_ct_config(struct mec_espi_vw_regs * const vwbase,uint8_t ctidx,uint8_t src_idx,uint8_t host_index,uint32_t config)602 static void mec_hal_espi_vw_ct_config(struct mec_espi_vw_regs * const vwbase, uint8_t ctidx,
603                                       uint8_t src_idx, uint8_t host_index, uint32_t config)
604 {
605     volatile struct mec_espi_vw_ctvw_regs *ctvw = &vwbase->CTVW[ctidx];
606     uint32_t regval = ctvw->HIRSS;
607     uint32_t temp;
608 
609     regval &= (uint32_t)~MEC_ESPI_VW_CTVW_HIRSS_HOST_IDX_Msk;
610     regval |= (((uint32_t)host_index << MEC_ESPI_VW_CTVW_HIRSS_HOST_IDX_Pos)
611              & MEC_ESPI_VW_CTVW_HIRSS_HOST_IDX_Msk);
612 
613     if (config & MEC_BIT(MEC_ESPI_VW_CFG_RSTSRC_DO_POS)) {
614         temp = (((uint32_t)config & MEC_ESPI_VW_CFG_RSTSRC_MSK) >> MEC_ESPI_VW_CFG_RSTSRC_POS);
615         regval &= (uint32_t)~MEC_ESPI_VW_CTVW_HIRSS_RST_SRC_Msk;
616         regval |= ((temp << MEC_ESPI_VW_CTVW_HIRSS_RST_SRC_Pos)
617                    & MEC_ESPI_VW_CTVW_HIRSS_RST_SRC_Msk);
618     }
619     if (config & MEC_BIT(MEC_ESPI_VW_CFG_RSTVAL_DO_POS)) {
620         temp = (((uint32_t)config & MEC_ESPI_VW_CFG_RSTVAL_MSK) >> MEC_ESPI_VW_CFG_RSTVAL_POS);
621         regval &= ~MEC_BIT(MEC_ESPI_VW_CTVW_HIRSS_RST_STATE_Pos + src_idx);
622         regval |= temp << (MEC_ESPI_VW_CTVW_HIRSS_RST_STATE_Pos + src_idx);
623     }
624     ctvw->HIRSS = regval;
625 
626     if (config & MEC_BIT(MEC_ESPI_VW_CFG_IRQSEL_DO_POS)) {
627         uint32_t bpos = src_idx * 8u;
628         uint32_t msk = MEC_ESPI_VW_CTVW_SRC_ISELS_SRC0_IRQ_SEL_Msk << (src_idx * 8u);
629         uint32_t val = ((config >> MEC_ESPI_VW_CFG_IRQSEL_POS) & MEC_ESPI_VW_CFG_IRQSEL_MSK0);
630 
631         val = xlat_isel(val);
632         regval = ctvw->SRC_ISELS & ~msk;
633         regval |= (val << bpos) & msk;
634         ctvw->SRC_ISELS = regval;
635     }
636 }
637 
638 
mec_hal_espi_vw_ct_wire_set(struct mec_espi_vw_regs * const vwbase,uint8_t ctidx,uint8_t widx,uint8_t val)639 int mec_hal_espi_vw_ct_wire_set(struct mec_espi_vw_regs * const vwbase, uint8_t ctidx,
640                                 uint8_t widx, uint8_t val)
641 {
642     if (!vwbase || (ctidx > MEC_CTVW_IDX10) || (widx > 3)) {
643         return MEC_RET_ERR_INVAL;
644     }
645 
646     volatile struct mec_espi_vw_ctvw_regs *ctvw = &vwbase->CTVW[ctidx];
647 
648     if (val) {
649         ctvw->STATES |= MEC_BIT(widx * 8u);
650     } else {
651         ctvw->STATES &= ~MEC_BIT(widx * 8u);
652     }
653 
654     return MEC_RET_OK;
655 }
656 
mec_hal_espi_vw_ct_wire_get(struct mec_espi_vw_regs * const vwbase,uint8_t ctidx,uint8_t widx,uint8_t * val)657 int mec_hal_espi_vw_ct_wire_get(struct mec_espi_vw_regs * const vwbase, uint8_t ctidx,
658                                 uint8_t widx, uint8_t *val)
659 {
660     if (!vwbase || !val || (ctidx > MEC_CTVW_IDX10) || (widx > 3)) {
661         return MEC_RET_ERR_INVAL;
662     }
663 
664     volatile struct mec_espi_vw_ctvw_regs *ctvw = &vwbase->CTVW[ctidx];
665 
666     *val = (uint8_t)((ctvw->STATES >> (widx * 8u)) & 0x1u);
667 
668     return MEC_RET_OK;
669 }
670 
671 /* Set 4 VWires in group from b[3:0] of val if in mask */
mec_hal_espi_vw_ct_group_set(struct mec_espi_vw_regs * const vwbase,uint8_t ctidx,uint8_t val,uint8_t msk)672 int mec_hal_espi_vw_ct_group_set(struct mec_espi_vw_regs * const vwbase, uint8_t ctidx,
673                                  uint8_t val, uint8_t msk)
674 {
675     if (!vwbase || !val || (ctidx > MEC_CTVW_IDX10)) {
676         return MEC_RET_ERR_INVAL;
677     }
678 
679     if (!msk) {
680         return MEC_RET_OK;
681     }
682 
683     volatile struct mec_espi_vw_ctvw_regs *ctvw = &vwbase->CTVW[ctidx];
684     uint32_t chgmsk = 0u;
685     uint32_t rval = 0u;
686 
687     for (unsigned int i = 0; i < 4u; i++) {
688         if (msk & MEC_BIT(i)) {
689             chgmsk |= MEC_BIT(i * 8);
690             if (val & MEC_BIT(i)) {
691                 rval |= MEC_BIT(i * 8);
692             }
693         }
694     }
695 
696     ctvw->STATES = (ctvw->STATES & ~chgmsk) | rval;
697 
698     return MEC_RET_OK;
699 }
700 
vw_group_get(uint32_t vw_states)701 static uint8_t vw_group_get(uint32_t vw_states)
702 {
703     uint32_t temp = 0u;
704 
705     for (unsigned int i = 0; i < 4u; i++) {
706         if (vw_states & MEC_BIT(i * 8u)) {
707             temp |= MEC_BIT(i);
708         }
709     }
710 
711     return (uint8_t)(temp & 0xffu);
712 }
713 
714 /* Copy 4 VWires in group to b[3:0] of byte pointed to by val */
mec_hal_espi_vw_ct_group_get(struct mec_espi_vw_regs * const vwbase,uint8_t ctidx,uint8_t * val)715 int mec_hal_espi_vw_ct_group_get(struct mec_espi_vw_regs * const vwbase, uint8_t ctidx,
716                                  uint8_t *val)
717 {
718     if (!vwbase || !val || (ctidx > MEC_CTVW_IDX10)) {
719         return MEC_RET_ERR_INVAL;
720     }
721 
722     volatile struct mec_espi_vw_ctvw_regs *ctvw = &vwbase->CTVW[ctidx];
723 
724     *val = vw_group_get(ctvw->STATES);
725 
726     return MEC_RET_OK;
727 }
728 
729 /* Configure MEC5 Target(EC)-to-Controller(Host) Virtual Wire group register.
730  * Similar to CT VWire group registers, the TC SRC bits are reset by the
731  * reset source specified in the TC VWire reset source field. If the reset
732  * source is active we will not be able to change the SRC bits. If SRC bits
733  * are to be changed, temporarily change reset source to RESET_SYS and
734  * restore/set to new reset source at the end of this routine.
735  * NOTE: Target-to-Controller VW groups have no EC interrupt capability.
736  * The struct mec_espi_vw_config src_irq_sec[] member is ignored.
737  */
mec_hal_espi_vwg_tc_config(struct mec_espi_vw_regs * const vwbase,uint8_t tcidx,struct mec_espi_vw_config * cfg,uint32_t flags)738 static void mec_hal_espi_vwg_tc_config(struct mec_espi_vw_regs * const vwbase, uint8_t tcidx,
739                                        struct mec_espi_vw_config *cfg, uint32_t flags)
740 {
741     volatile struct mec_espi_vw_tcvw_regs *tcvw = &vwbase->TCVW[tcidx];
742     uint32_t r[2];
743     unsigned int i;
744 
745     r[0] = tcvw->HIRCS;
746     r[1] = tcvw->STATES;
747     if (flags & MEC_BIT(MEC_ESPI_VWG_CFG_HI_POS)) {
748         r[0] &= (uint32_t)~MEC_ESPI_VW_TCVW_HIRCS_HOST_IDX_Msk;
749         r[0] |= (((uint32_t)cfg->host_idx << MEC_ESPI_VW_TCVW_HIRCS_HOST_IDX_Pos)
750                  & MEC_ESPI_VW_TCVW_HIRCS_HOST_IDX_Msk);
751     }
752 
753     if (flags & MEC_BIT(MEC_ESPI_VWG_CFG_RST_SRC_POS)) {
754         r[0] &= (uint32_t)~MEC_ESPI_VW_TCVW_HIRCS_RST_SRC_Msk;
755         r[0] |= (((uint32_t)cfg->reset_src << MEC_ESPI_VW_TCVW_HIRCS_RST_SRC_Pos)
756                  & MEC_ESPI_VW_TCVW_HIRCS_RST_SRC_Msk);
757     }
758 
759     for (i = 0; i < 4; i++) {
760         if (flags & MEC_BIT(MEC_ESPI_VWG_CFG_SRC0_RST_VAL_POS + i)) {
761             if (cfg->reset_val_bm & MEC_BIT(i)) {
762                 r[0] |= MEC_BIT(i + MEC_ESPI_VW_TCVW_HIRCS_RST_STATE_Pos);
763             } else {
764                 r[0] &= ~MEC_BIT(i + MEC_ESPI_VW_TCVW_HIRCS_RST_STATE_Pos);
765             }
766         }
767         if (flags & MEC_BIT(MEC_ESPI_VWG_CFG_SRC0_VAL_POS + i)) {
768             if (cfg->src_val_bm & MEC_BIT(i)) {
769                 r[1] |= MEC_BIT(i * 8);
770             } else {
771                 r[1] &= ~MEC_BIT(i * 8);
772             }
773         }
774     }
775 
776     tcvw->HIRCS = r[0];
777     tcvw->STATES = r[1];
778 }
779 
780 /* Configure specified fields of a Target-to-Controller VWire in a group.
781  * tcidx specifies the zero based index into the hardware array of 64-bit
782  * T2C VWire registers. Each 64-bit register controls 4 VWires.
783  * Properties affecting the whole group of 4 VWires:
784  *      Host Index and Reset Source
785  * Properities of the single VWire specified by src_idx:
786  *      Reset State
787  * All of these fields are reset on POR or chip reset only.
788  * NOTE: Reset States are loaded into SRC bits on the de-asserting
789  * edge of Reset Source.
790  * NOTE2: Target-to-Controller VWires do not generate interrupts to the EC.
791  */
mec_hal_espi_vw_tc_config(struct mec_espi_vw_regs * const vwbase,uint8_t tcidx,uint8_t src_idx,uint8_t host_index,uint32_t config)792 static void mec_hal_espi_vw_tc_config(struct mec_espi_vw_regs * const vwbase, uint8_t tcidx,
793                                       uint8_t src_idx, uint8_t host_index, uint32_t config)
794 {
795     volatile struct mec_espi_vw_tcvw_regs *tcvw = &vwbase->TCVW[tcidx];
796     uint32_t regval = tcvw->HIRCS; /* b[63:32] name is STATES */
797     uint32_t temp;
798 
799     regval &= (uint32_t)~MEC_ESPI_VW_TCVW_HIRCS_HOST_IDX_Msk;
800     regval |= (((uint32_t)host_index << MEC_ESPI_VW_TCVW_HIRCS_HOST_IDX_Pos)
801              & MEC_ESPI_VW_TCVW_HIRCS_HOST_IDX_Msk);
802 
803     if (config & MEC_BIT(MEC_ESPI_VW_CFG_RSTSRC_DO_POS)) {
804         temp = (((uint32_t)config & MEC_ESPI_VW_CFG_RSTSRC_MSK) >> MEC_ESPI_VW_CFG_RSTSRC_POS);
805         regval &= (uint32_t)~MEC_ESPI_VW_TCVW_HIRCS_RST_SRC_Msk;
806         regval |= ((temp << MEC_ESPI_VW_TCVW_HIRCS_RST_SRC_Pos)
807                    & MEC_ESPI_VW_TCVW_HIRCS_RST_SRC_Msk);
808     }
809     if (config & MEC_BIT(MEC_ESPI_VW_CFG_RSTVAL_DO_POS)) {
810         temp = (((uint32_t)config & MEC_ESPI_VW_CFG_RSTVAL_MSK) >> MEC_ESPI_VW_CFG_RSTVAL_POS);
811         regval &= ~MEC_BIT(MEC_ESPI_VW_TCVW_HIRCS_RST_STATE_Pos + src_idx);
812         regval |= temp << (MEC_ESPI_VW_TCVW_HIRCS_RST_STATE_Pos + src_idx);
813     }
814     tcvw->HIRCS = regval;
815 }
816 
mec_hal_espi_vw_tc_wire_set(struct mec_espi_vw_regs * const vwbase,uint8_t tcidx,uint8_t widx,uint8_t val,uint32_t flags)817 int mec_hal_espi_vw_tc_wire_set(struct mec_espi_vw_regs * const vwbase, uint8_t tcidx,
818                                 uint8_t widx, uint8_t val, uint32_t flags)
819 {
820     if (!vwbase || (tcidx > MEC_TCVW_IDX10) || (widx > 3)) {
821         return MEC_RET_ERR_INVAL;
822     }
823 
824     volatile struct mec_espi_vw_tcvw_regs *tcvw = &vwbase->TCVW[tcidx];
825 
826     if (val) {
827         tcvw->STATES |= MEC_BIT(widx * 8u);
828     } else {
829         tcvw->STATES &= ~MEC_BIT(widx * 8u);
830     }
831 
832     if (flags & MEC_BIT(MEC_ESPI_VW_FLAG_WAIT_TC_TX_POS)) {
833         while (vwbase->TCVW[tcidx].HIRCS & (0xfu << MEC_ESPI_VW_TCVW_HIRCS_CHANGE0_Pos)) {
834                 ;
835         }
836     }
837 
838     return MEC_RET_OK;
839 }
840 
mec_hal_espi_vw_tc_wire_set_cs(struct mec_espi_vw_regs * const vwbase,uint8_t tcidx,uint8_t widx,uint8_t val,const struct mec_espi_vw_poll * vwp)841 int mec_hal_espi_vw_tc_wire_set_cs(struct mec_espi_vw_regs * const vwbase, uint8_t tcidx,
842                                    uint8_t widx, uint8_t val, const struct mec_espi_vw_poll *vwp)
843 {
844     uint32_t delay_loops = 0;
845 
846     if (!vwbase || (tcidx > MEC_TCVW_IDX10) || (widx > 3)) {
847         return MEC_RET_ERR_INVAL;
848     }
849 
850     volatile struct mec_espi_vw_tcvw_regs *tcvw = &vwbase->TCVW[tcidx];
851 
852     if (val) {
853         tcvw->STATES |= MEC_BIT(widx * 8u);
854     } else {
855         tcvw->STATES &= ~MEC_BIT(widx * 8u);
856     }
857 
858     if (vwp && vwp->delayfp) {
859         while (vwbase->TCVW[tcidx].HIRCS & (0xfu << MEC_ESPI_VW_TCVW_HIRCS_CHANGE0_Pos)) {
860             if (!delay_loops) {
861                 return MEC_RET_ERR_TIMEOUT;
862             }
863             vwp->delayfp(vwp->delay_param);
864             --delay_loops;
865         }
866     }
867 
868     return MEC_RET_OK;
869 }
870 
mec_hal_espi_vw_tc_wire_get(struct mec_espi_vw_regs * const vwbase,uint8_t tcidx,uint8_t widx,uint8_t * val)871 int mec_hal_espi_vw_tc_wire_get(struct mec_espi_vw_regs * const vwbase, uint8_t tcidx,
872                                 uint8_t widx, uint8_t *val)
873 {
874     if (!vwbase || !val || (tcidx > MEC_TCVW_IDX10) || (widx > 3)) {
875         return MEC_RET_ERR_INVAL;
876     }
877 
878     volatile struct mec_espi_vw_tcvw_regs *tcvw = &vwbase->TCVW[tcidx];
879 
880     *val = (uint8_t)((tcvw->STATES >> (widx * 8u)) & 0x1u);
881 
882     return MEC_RET_OK;
883 }
884 
885 /* Obtains both the VWire state and its read-only change status.
886  * Change status is 1 when FW has changed the VWire state. A change bit == 1 causes
887  * the target eSPI to set the VWires Available status bit. If Alert mode is enabled
888  * an eSPI in-band or pin alert is asserted to the eSPI Host.  The eSPI Host will
889  * issue a GET_STATUS. The Host sees the VWires Available bit and issues a GET_VWIRES
890  * command. When the eSPI Target responds to GET_VWIRES it clears all read-only
891  * Target-to-Controller VWire change status bits.
892  * val bit[0] = state of VWire
893  * val bit[7] = Change bit. 1 = VWire state was changed by FW and the Host has not
894  * read it. 0 = VWire has not changed or Host has read the current value.
895  */
mec_hal_espi_vw_tc_wire_cs_get(struct mec_espi_vw_regs * const vwbase,uint8_t tcidx,uint8_t widx,uint8_t * val)896 int mec_hal_espi_vw_tc_wire_cs_get(struct mec_espi_vw_regs * const vwbase, uint8_t tcidx,
897                                    uint8_t widx, uint8_t *val)
898 {
899     if (!vwbase || !val || (tcidx > MEC_TCVW_IDX10) || (widx > 3)) {
900         return MEC_RET_ERR_INVAL;
901     }
902 
903     volatile struct mec_espi_vw_tcvw_regs *tcvw = &vwbase->TCVW[tcidx];
904     uint8_t change_bitpos = widx + MEC_ESPI_VW_TCVW_HIRCS_CHANGE0_Pos;
905     uint8_t vw = (uint8_t)((tcvw->STATES >> (widx * 8u)) & 0x1u);
906 
907 
908     if (vwbase->TCVW[tcidx].HIRCS & MEC_BIT(change_bitpos)) {
909         vw |= MEC_BIT(7);
910     }
911     *val = vw;
912 
913     return MEC_RET_OK;
914 }
915 
916 /* Set 4 VWires in group from b[3:0] of val if in mask */
mec_hal_espi_vw_tc_group_set(struct mec_espi_vw_regs * const vwbase,uint8_t tcidx,uint8_t val,uint8_t msk,uint32_t flags)917 int mec_hal_espi_vw_tc_group_set(struct mec_espi_vw_regs * const vwbase, uint8_t tcidx,
918                                  uint8_t val, uint8_t msk, uint32_t flags)
919 {
920     if (!vwbase || !val || (tcidx > MEC_TCVW_IDX10)) {
921         return MEC_RET_ERR_INVAL;
922     }
923 
924     if (!msk) {
925         return MEC_RET_OK;
926     }
927 
928     volatile struct mec_espi_vw_tcvw_regs *tcvw = &vwbase->TCVW[tcidx];
929     uint32_t chgmsk = 0u;
930     uint32_t rval = 0u;
931 
932     for (unsigned int i = 0; i < 4u; i++) {
933         if (msk & MEC_BIT(i)) {
934             chgmsk |= MEC_BIT(i * 8);
935             if (val & MEC_BIT(i)) {
936                 rval |= MEC_BIT(i * 8);
937             }
938         }
939     }
940 
941     tcvw->STATES = (tcvw->STATES & ~chgmsk) | rval;
942     if (flags & MEC_BIT(MEC_ESPI_VW_FLAG_WAIT_TC_TX_POS)) {
943         while (vwbase->TCVW[tcidx].HIRCS & (0xfu << MEC_ESPI_VW_TCVW_HIRCS_CHANGE0_Pos)) {
944                 ;
945         }
946     }
947     return MEC_RET_OK;
948 }
949 
950 /* Copy 4 VWires in TC group to b[3:0] of byte pointed to by val */
mec_hal_espi_vw_tc_group_get(struct mec_espi_vw_regs * const vwbase,uint8_t tcidx,uint8_t * val)951 int mec_hal_espi_vw_tc_group_get(struct mec_espi_vw_regs * const vwbase, uint8_t tcidx,
952                                  uint8_t *val)
953 {
954     if (!vwbase || !val || (tcidx > MEC_TCVW_IDX10)) {
955         return MEC_RET_ERR_INVAL;
956     }
957 
958     volatile struct mec_espi_vw_tcvw_regs *tcvw = &vwbase->TCVW[tcidx];
959 
960     *val = vw_group_get(tcvw->STATES);
961 
962     return MEC_RET_OK;
963 }
964 
mec_hal_espi_vwg_config(struct mec_espi_vw_regs * const vwbase,uint8_t vwidx,struct mec_espi_vw_config * cfg,uint32_t flags)965 int mec_hal_espi_vwg_config(struct mec_espi_vw_regs * const vwbase, uint8_t vwidx,
966                             struct mec_espi_vw_config *cfg, uint32_t flags)
967 {
968     if (!vwbase || !cfg || (vwidx >= MEC_ESPI_VW_MAX_REG_IDX)) {
969         return MEC_RET_ERR_INVAL;
970     }
971 
972     if (vwidx < MEC_ESPI_TCVW00_REG_IDX) {
973         mec_hal_espi_vwg_ct_config(vwbase, vwidx, cfg, flags);
974     } else {
975         vwidx -= MEC_ESPI_TCVW00_REG_IDX;
976         mec_hal_espi_vwg_tc_config(vwbase, vwidx, cfg, flags);
977     }
978 
979     return MEC_RET_OK;
980 }
981 
mec_hal_espi_vwire_config(struct mec_espi_vw_regs * const vwbase,uint8_t vwidx,uint8_t src_idx,uint8_t host_index,uint32_t config)982 int mec_hal_espi_vwire_config(struct mec_espi_vw_regs *const vwbase, uint8_t vwidx,
983                               uint8_t src_idx, uint8_t host_index, uint32_t config)
984 {
985     if (!vwbase || (vwidx >= MEC_ESPI_VW_MAX_REG_IDX) || (src_idx > 3u)) {
986         return MEC_RET_ERR_INVAL;
987     }
988 
989     if (vwidx < MEC_ESPI_TCVW00_REG_IDX) {
990         mec_hal_espi_vw_ct_config(vwbase, vwidx, src_idx, host_index, config);
991     } else {
992         vwidx -= MEC_ESPI_TCVW00_REG_IDX;
993         mec_hal_espi_vw_tc_config(vwbase, vwidx, src_idx, host_index, config);
994     }
995 
996     return MEC_RET_OK;
997 }
998 
999 /* Get value of a VWire specified by MEC5 logical register index and source position in
1000  * the HW register.
1001  */
mec_hal_espi_vw_get_src(struct mec_espi_vw_regs * const vwbase,struct mec_espi_vw * vw,uint32_t flags)1002 int mec_hal_espi_vw_get_src(struct mec_espi_vw_regs * const vwbase, struct mec_espi_vw *vw,
1003                             uint32_t flags __attribute__((__unused__)))
1004 {
1005     int ret;
1006     uint8_t regidx;
1007 
1008     if (!vw) {
1009         return MEC_RET_ERR_INVAL;
1010     }
1011 
1012     regidx = vw->vwidx;
1013     if (regidx < MEC_ESPI_TCVW00_REG_IDX) {
1014         ret = mec_hal_espi_vw_ct_wire_get(vwbase, regidx, vw->srcidx, &vw->val);
1015     } else {
1016         regidx -= MEC_ESPI_TCVW00_REG_IDX;
1017         ret = mec_hal_espi_vw_tc_wire_get(vwbase, regidx, vw->srcidx, &vw->val);
1018     }
1019 
1020     return ret;
1021 }
1022 
1023 /* Set value of VWire in a group
1024  * vwbase is base address of MEC5 VWire registers
1025  * vwidx is a zero based index of the MEC5 VWire register containing the VWire
1026  * src is the zero based VWire position in the group of 4. [0:3]
1027  * val is the new VWire value non-zero means 1 else 0.
1028  * flags: bit[0]=1 instructs this routine to wait forever for Target to
1029  * Controller (upstream) VWire value to be transmitted. NOTE: a packet is only
1030  * transmitted if the VWire value was changed.
1031  */
mec_hal_espi_vw_set_src(struct mec_espi_vw_regs * const vwbase,struct mec_espi_vw * vw,uint32_t flags)1032 int mec_hal_espi_vw_set_src(struct mec_espi_vw_regs *const vwbase, struct mec_espi_vw *vw,
1033                             uint32_t flags)
1034 {
1035     int ret;
1036     uint8_t regidx;
1037 
1038     if (!vw) {
1039         return MEC_RET_ERR_INVAL;
1040     }
1041 
1042     regidx = vw->vwidx;
1043     if (regidx < MEC_ESPI_TCVW00_REG_IDX) {
1044         ret = mec_hal_espi_vw_ct_wire_set(vwbase, regidx, vw->srcidx, vw->val);
1045     } else {
1046         regidx -= MEC_ESPI_TCVW00_REG_IDX;
1047         ret = mec_hal_espi_vw_tc_wire_set(vwbase, regidx, vw->srcidx, vw->val, flags);
1048     }
1049 
1050     return ret;
1051 }
1052 
mec_hal_espi_vw_set_src_cs(struct mec_espi_vw_regs * const vwbase,struct mec_espi_vw * vw,const struct mec_espi_vw_poll * vwp)1053 int mec_hal_espi_vw_set_src_cs(struct mec_espi_vw_regs *const vwbase, struct mec_espi_vw *vw,
1054                                const struct mec_espi_vw_poll *vwp)
1055 {
1056     int ret;
1057     uint8_t regidx;
1058 
1059     if (!vw) {
1060         return MEC_RET_ERR_INVAL;
1061     }
1062 
1063     regidx = vw->vwidx;
1064     if (regidx < MEC_ESPI_TCVW00_REG_IDX) {
1065         ret = mec_hal_espi_vw_ct_wire_set(vwbase, regidx, vw->srcidx, vw->val);
1066     } else {
1067         regidx -= MEC_ESPI_TCVW00_REG_IDX;
1068         ret = mec_hal_espi_vw_tc_wire_set_cs(vwbase, regidx, vw->srcidx, vw->val, vwp);
1069     }
1070 
1071     return ret;
1072 }
1073 
1074 /* Get VWire group source bits specified by struct mec_espi_vw.vwidx and
1075  * store in struct mec_espi_vw.val
1076  */
mec_hal_espi_vw_get_src_group(struct mec_espi_vw_regs * const vwbase,struct mec_espi_vw * vw,uint32_t flags)1077 int mec_hal_espi_vw_get_src_group(struct mec_espi_vw_regs * const vwbase, struct mec_espi_vw *vw,
1078                                   uint32_t flags __attribute__((__unused__)))
1079 {
1080     int ret;
1081     uint8_t regidx;
1082 
1083     if (!vw) {
1084         return MEC_RET_ERR_INVAL;
1085     }
1086 
1087     regidx = vw->vwidx;
1088     if (regidx < MEC_ESPI_TCVW00_REG_IDX) {
1089         ret = mec_hal_espi_vw_tc_group_get(vwbase, regidx, &vw->val);
1090     } else {
1091         regidx -= MEC_ESPI_TCVW00_REG_IDX;
1092         ret = mec_hal_espi_vw_tc_group_get(vwbase, regidx, &vw->val);
1093     }
1094 
1095     return ret;
1096 }
1097 
mec_hal_espi_vw_set_src_group(struct mec_espi_vw_regs * const vwbase,struct mec_espi_vw * vw,uint32_t flags)1098 int mec_hal_espi_vw_set_src_group(struct mec_espi_vw_regs * const vwbase, struct mec_espi_vw *vw,
1099                                   uint32_t flags)
1100 {
1101     int ret;
1102     uint8_t regidx;
1103 
1104     if (!vw || (vw->vwidx >= MEC_ESPI_VW_MAX_REG_IDX)) {
1105         return MEC_RET_ERR_INVAL;
1106     }
1107 
1108     if (!vw->msk) {
1109         return MEC_RET_OK;
1110     }
1111 
1112     regidx = vw->vwidx;
1113     if (regidx < MEC_ESPI_TCVW00_REG_IDX) {
1114         ret = mec_hal_espi_vw_ct_group_set(vwbase, regidx, vw->val, vw->msk);
1115     } else {
1116         regidx -= (uint8_t)MEC_ESPI_TCVW00_REG_IDX;
1117         ret = mec_hal_espi_vw_tc_group_set(vwbase, regidx, vw->val, vw->msk, flags);
1118     }
1119 
1120     return ret;
1121 }
1122 
1123 /* ---- API using eSPI Host Index and VWire src [0:3] for access ---- */
lookup_ct_vw_by_host_index(struct mec_espi_vw_regs * const vwbase,uint8_t host_index)1124 static int lookup_ct_vw_by_host_index(struct mec_espi_vw_regs *const vwbase, uint8_t host_index)
1125 {
1126     if (vwbase) {
1127         for (int i = 0; i < MEC_CTVW_IDX10; i++) {
1128             uint8_t hidx = vwbase->CTVW[i].HIRSS & 0xffu;
1129             if (hidx == host_index) {
1130                 return i;
1131             }
1132         }
1133     }
1134 
1135     return -1;
1136 }
1137 
lookup_tc_vw_by_host_index(struct mec_espi_vw_regs * const vwbase,uint8_t host_index)1138 static int lookup_tc_vw_by_host_index(struct mec_espi_vw_regs *const vwbase, uint8_t host_index)
1139 {
1140     if (vwbase) {
1141         for (int i = 0; i < MEC_TCVW_IDX10; i++) {
1142             uint8_t hidx = vwbase->TCVW[i].HIRCS & 0xffu;
1143             if (hidx == host_index) {
1144                 return i;
1145             }
1146         }
1147     }
1148 
1149     return -1;
1150 }
1151 
1152 /* Read the state of the VWire given by its Host Index and source (bit)
1153  * position in the 4 wire group.
1154  */
mec_hal_espi_vw_get(struct mec_espi_vw_regs * const vwbase,uint8_t host_index,uint8_t src_id,uint8_t * val)1155 int mec_hal_espi_vw_get(struct mec_espi_vw_regs *const vwbase, uint8_t host_index,
1156                         uint8_t src_id, uint8_t *val)
1157 {
1158     int ret = MEC_RET_ERR_INVAL;
1159     int idx = lookup_ct_vw_by_host_index(vwbase, host_index);
1160 
1161     if (idx >= 0) {
1162         ret = mec_hal_espi_vw_ct_wire_get(vwbase, (uint8_t)idx & 0x7fu, src_id, val);
1163     }
1164 
1165     idx = lookup_tc_vw_by_host_index(vwbase, host_index);
1166     if (idx >= 0) {
1167         ret = mec_hal_espi_vw_tc_wire_get(vwbase, (uint8_t)idx & 0x7fu, src_id, val);
1168     }
1169 
1170     return ret;
1171 }
1172 
mec_hal_espi_vw_set(struct mec_espi_vw_regs * const vwbase,uint8_t host_index,uint8_t src_id,uint8_t val,uint32_t flags)1173 int mec_hal_espi_vw_set(struct mec_espi_vw_regs *const vwbase, uint8_t host_index,
1174                         uint8_t src_id, uint8_t val, uint32_t flags)
1175 {
1176     int ret = MEC_RET_ERR_INVAL;
1177     int idx = lookup_ct_vw_by_host_index(vwbase, host_index);
1178 
1179     if (idx >= 0) {
1180         ret = mec_hal_espi_vw_ct_wire_set(vwbase, (uint8_t)idx & 0x7fu, src_id, val);
1181     }
1182 
1183     idx = lookup_tc_vw_by_host_index(vwbase, host_index);
1184     if (idx >= 0) {
1185         ret = mec_hal_espi_vw_tc_wire_set(vwbase, (uint8_t)idx & 0x7fu, src_id, val, flags);
1186     }
1187 
1188     return ret;
1189 }
1190 
mec_hal_espi_vw_set_cs(struct mec_espi_vw_regs * const vwbase,uint8_t host_index,uint8_t src_id,uint8_t val,const struct mec_espi_vw_poll * vwp)1191 int mec_hal_espi_vw_set_cs(struct mec_espi_vw_regs *const vwbase, uint8_t host_index,
1192                            uint8_t src_id, uint8_t val, const struct mec_espi_vw_poll *vwp)
1193 {
1194     int ret = MEC_RET_ERR_INVAL;
1195     int idx = lookup_ct_vw_by_host_index(vwbase, host_index);
1196 
1197     if (idx >= 0) {
1198         ret = mec_hal_espi_vw_ct_wire_set(vwbase, (uint8_t)idx & 0x7fu, src_id, val);
1199     }
1200 
1201     idx = lookup_tc_vw_by_host_index(vwbase, host_index);
1202     if (idx >= 0) {
1203         ret = mec_hal_espi_vw_tc_wire_set_cs(vwbase, (uint8_t)idx & 0x7fu, src_id, val, vwp);
1204     }
1205 
1206     return ret;
1207 }
1208 
1209 /* VWire's are grouped into 4 VWires per host index. Read the states of the VWires
1210  * and pack them into bits[3:0] of the byte pointed to by groupval.
1211  */
mec_hal_espi_vw_get_group(struct mec_espi_vw_regs * const vwbase,uint8_t host_index,uint8_t * groupval)1212 int mec_hal_espi_vw_get_group(struct mec_espi_vw_regs *const vwbase,
1213                               uint8_t host_index, uint8_t *groupval)
1214 {
1215     int ret = MEC_RET_ERR_INVAL;
1216     int idx = lookup_ct_vw_by_host_index(vwbase, host_index);
1217 
1218     if (idx >= 0) {
1219         ret = mec_hal_espi_vw_ct_group_get(vwbase, (uint8_t)idx & 0x7fu, groupval);
1220     }
1221 
1222     idx = lookup_tc_vw_by_host_index(vwbase, host_index);
1223     if (idx >= 0) {
1224         ret = mec_hal_espi_vw_tc_group_get(vwbase, (uint8_t)idx & 0x7fu, groupval);
1225     }
1226 
1227     return ret;
1228 }
1229 
1230 /* Each VWire group indentified by its Host Index implements 4 virtual wires.
1231  * Set the values of the VWires based upon the passed groupmsk. If groupmsk
1232  * b[3:0] is set then set that VWire's state to the corresponding bit in
1233  * groupval.
1234  */
mec_hal_espi_vw_set_group(struct mec_espi_vw_regs * const vwbase,uint8_t host_index,uint8_t groupval,uint8_t groupmsk,uint32_t flags)1235 int mec_hal_espi_vw_set_group(struct mec_espi_vw_regs *const vwbase, uint8_t host_index,
1236                               uint8_t groupval, uint8_t groupmsk, uint32_t flags)
1237 {
1238     int ret = MEC_RET_ERR_INVAL;
1239     int idx = lookup_ct_vw_by_host_index(vwbase, host_index);
1240 
1241     if (idx >= 0) {
1242         ret = mec_hal_espi_vw_ct_group_set(vwbase, (uint8_t)idx & 0x7fu, groupval, groupmsk);
1243     }
1244 
1245     idx = lookup_tc_vw_by_host_index(vwbase, host_index);
1246     if (idx >= 0) {
1247         ret = mec_hal_espi_vw_tc_group_set(vwbase, (uint8_t)idx & 0x7fu,
1248                                            groupval, groupmsk, flags);
1249     }
1250 
1251     return ret;
1252 }
1253 
1254 /* end mec_espi_vw.c */
1255