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