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 /* Logical device to BAR index table. Note: not all logical devices have
16 * a memory BAR. BAR indices are stored +1. A value of zero indicates no
17 * BAR of that type exists for the logical device.
18 */
19 struct ld_info {
20 uint8_t ldn;
21 uint8_t io_bar_idx;
22 uint8_t mem_bar_idx;
23 uint8_t num_sirqs;
24 uint8_t sirq_idx;
25 uint8_t rsvd[3];
26 };
27
28 const struct ld_info ld_table[] = {
29 { MEC_ESPI_LDN_MBOX, 3, 1, 2, 0, {0, 0, 0} },
30 { MEC_ESPI_LDN_KBC, 4, 0, 2, 2, {0, 0, 0} },
31 { MEC_ESPI_LDN_ACPI_EC0, 5, 2, 1, 4, {0, 0, 0} },
32 { MEC_ESPI_LDN_ACPI_EC1, 6, 3, 1, 5, {0, 0, 0} },
33 { MEC_ESPI_LDN_ACPI_EC2, 7, 4, 1, 6, {0, 0, 0} },
34 { MEC_ESPI_LDN_ACPI_EC3, 8, 5, 1, 7, {0, 0, 0} },
35 { MEC_ESPI_LDN_ACPI_EC4, 9, 6, 1, 8, {0, 0, 0} },
36 { MEC_ESPI_LDN_ACPI_PM1, 10, 0, 0, 0, {0, 0, 0} },
37 { MEC_ESPI_LDN_KB_PORT92, 11, 0, 0, 0, {0, 0, 0} },
38 { MEC_ESPI_LDN_UART0, 12, 0, 1, 9, {0, 0, 0} },
39 { MEC_ESPI_LDN_UART1, 13, 0, 1, 10, {0, 0, 0} },
40 { MEC_ESPI_LDN_UART2, 22, 0, 1, 19, {0, 0, 0} },
41 { MEC_ESPI_LDN_UART3, 24, 0, 1, 21, {0, 0, 0} },
42 { MEC_ESPI_LDN_IOC, 1, 0, 0, 0, {0, 0, 0} },
43 { MEC_ESPI_LDN_IOMC, 2, 0, 0, 0, {0, 0, 0} },
44 { MEC_ESPI_LDN_GLUE, 23, 0, 0, 0, {0, 0, 0} },
45 { MEC_ESPI_LDN_EMI0, 14, 7, 2, 11, {0, 0, 0} },
46 { MEC_ESPI_LDN_EMI1, 15, 8, 2, 13, {0, 0, 0} },
47 { MEC_ESPI_LDN_EMI2, 16, 9, 2, 15, {0, 0, 0} },
48 { MEC_ESPI_LDN_RTC, 19, 0, 1, 17, {0, 0, 0} },
49 { MEC_ESPI_LDN_PP0, 25, 0, 0, 0, {0, 0, 0} }, /* desktop devices */
50 { MEC_ESPI_LDN_BDBG0, 17, 0, 0, 0, {0, 0, 0} },
51 { MEC_ESPI_LDN_BDBG0_ALIAS, 18, 0, 0, 0, {0, 0, 0} },
52 { MEC_ESPI_LDN_TB32, 21, 0, 0, 0, {0, 0, 0} },
53 { MEC_ESPI_LDN_EC, 0, 0, 1, 18, {0, 0, 0} },
54 };
55 #define LD_TBL_NUM_ENTRIES (sizeof(ld_table) / sizeof(struct ld_info))
56
find_bar(uint8_t ldn)57 static struct ld_info const *find_bar(uint8_t ldn)
58 {
59 if (ldn >= MEC_ESPI_LDN_MAX) {
60 return NULL;
61 }
62
63 for (size_t i = 0; i < LD_TBL_NUM_ENTRIES; i++) {
64 if (ld_table[i].ldn == ldn) {
65 return &ld_table[i];
66 }
67 }
68
69 return NULL;
70 }
71
ldn_has_iob(uint8_t ldn)72 static inline int ldn_has_iob(uint8_t ldn)
73 {
74 if (ldn < 32) {
75 return (int)(MEC_BIT(ldn) & (uint32_t)(MEC5_ESPI_LDN_IOB_MSK_LO));
76 } else {
77 ldn = ldn - (uint8_t)32u;
78 return (int)(MEC_BIT(ldn) & (uint32_t)(MEC5_ESPI_LDN_IOB_MSK_HI));
79 }
80 }
81
ldn_has_memb(uint8_t ldn)82 static inline int ldn_has_memb(uint8_t ldn)
83 {
84 if (ldn < 32) {
85 return (int)(MEC_BIT(ldn) & (uint32_t)(MEC5_ESPI_LDN_MEMB_MSK_LO));
86 } else {
87 ldn = ldn - (uint8_t)32u;
88 return (int)(MEC_BIT(ldn) & (uint32_t)(MEC5_ESPI_LDN_MEMB_MSK_HI));
89 }
90 }
91
mec_espi_sirq_get(struct mec_espi_io_regs * iobase,uint8_t sirq_idx)92 static uint8_t mec_espi_sirq_get(struct mec_espi_io_regs *iobase, uint8_t sirq_idx)
93 {
94 if ((sirq_idx > 31) || !(MEC_BIT(sirq_idx) & MEC5_ESPI_PC_SIRQ_BITMAP)) {
95 return MEC_ESPI_SIRQ_SLOT_DIS;
96 }
97
98 return iobase->SERIRQ[sirq_idx];
99 }
100
101 /* Set SERIRQ slot number for specified SERIRQ index */
espi_sirq_set(struct mec_espi_io_regs * iobase,uint8_t sirq_idx,uint8_t slot)102 static void espi_sirq_set(struct mec_espi_io_regs *iobase, uint8_t sirq_idx, uint8_t slot)
103 {
104 if ((sirq_idx > 31) || !(MEC_BIT(sirq_idx) & MEC5_ESPI_PC_SIRQ_BITMAP)) {
105 return;
106 }
107
108 iobase->SERIRQ[sirq_idx] = slot;
109 }
110
111 /*-----------------------------------------------------------------------*/
112
mec_hal_espi_iobar_cfg(struct mec_espi_io_regs * base,uint8_t ldn,uint16_t io_base,uint8_t enable)113 int mec_hal_espi_iobar_cfg(struct mec_espi_io_regs *base, uint8_t ldn,
114 uint16_t io_base, uint8_t enable)
115 {
116 const struct ld_info *ldi = find_bar(ldn);
117 uint32_t bar_val = (uint32_t)io_base << 16;
118 uint8_t idx = 0;
119
120 if (!base || !ldi) {
121 return MEC_RET_ERR_INVAL;
122 }
123
124 if (!ldi->io_bar_idx) { /* Logical device does not implement an I/O BAR */
125 return MEC_RET_ERR_INVAL;
126 }
127
128 idx = (uint8_t)(ldi->io_bar_idx - 1u);
129
130 /* disable and update */
131 base->HOST_BAR[idx] = bar_val;
132
133 if (enable) {
134 base->HOST_BAR[idx] |= MEC_BIT(MEC_ESPI_IO_HOST_BAR_VALID_Pos);
135 }
136
137 return MEC_RET_OK;
138 }
139
mec_hal_espi_iobar_enable(struct mec_espi_io_regs * base,uint8_t ldn,uint8_t enable)140 int mec_hal_espi_iobar_enable(struct mec_espi_io_regs *base, uint8_t ldn, uint8_t enable)
141 {
142 const struct ld_info *ldi = find_bar(ldn);
143 uint8_t idx;
144
145 if (!base || !ldi) {
146 return MEC_RET_ERR_INVAL;
147 }
148
149 if (!ldi->io_bar_idx) { /* Logical device does not implement an I/O BAR */
150 return MEC_RET_ERR_INVAL;
151 }
152
153 idx = (uint8_t)(ldi->io_bar_idx - 1u);
154
155 if (enable) {
156 base->HOST_BAR[idx] |= MEC_BIT(MEC_ESPI_IO_HOST_BAR_VALID_Pos);
157 } else {
158 base->HOST_BAR[idx] &= (uint32_t)~MEC_BIT(MEC_ESPI_IO_HOST_BAR_VALID_Pos);
159 }
160
161 return MEC_RET_OK;
162 }
163
mec_hal_espi_iobar_is_enabled(struct mec_espi_io_regs * base,uint8_t ldn)164 int mec_hal_espi_iobar_is_enabled(struct mec_espi_io_regs *base, uint8_t ldn)
165 {
166 const struct ld_info *ldi = find_bar(ldn);
167 uint8_t idx;
168
169 if (!base || !ldi) {
170 return 0;
171 }
172
173 if (!ldi->io_bar_idx) { /* Logical device does not implement an I/O BAR */
174 return 0;
175 }
176
177 idx = (uint8_t)(ldi->io_bar_idx - 1u);
178 if (base->HOST_BAR[idx] & MEC_BIT(MEC_ESPI_IO_HOST_BAR_VALID_Pos)) {
179 return 1;
180 }
181
182 return 0;
183 }
184
mec_hal_espi_iobar_mask(struct mec_espi_io_regs * base,uint8_t ldn)185 uint32_t mec_hal_espi_iobar_mask(struct mec_espi_io_regs *base, uint8_t ldn)
186 {
187 const struct ld_info *ldi = find_bar(ldn);
188 uint8_t idx;
189
190 if (!base || !ldi) {
191 return MEC_RET_ERR_INVAL;
192 }
193
194 if (!ldi->io_bar_idx) { /* Logical device does not implement an I/O BAR */
195 return MEC_RET_ERR_INVAL;
196 }
197
198 idx = (uint8_t)(ldi->io_bar_idx - 1u);
199
200 return (base->EC_LDN_MSK[idx] & 0xffu);
201 }
202
203 /* Set the logical device's I/O BAR mask field.
204 * NOTE1: Only the ACPI_EC logical devices mask fiels is writable.
205 * NOTE2: The mask field is only writable when the I/O BAR is not in reset
206 * and the valid bit in the corresponding LDN's Host I/O BAR is not set.
207 */
mec_hal_espi_iobar_mask_set(struct mec_espi_io_regs * base,uint8_t ldn,uint8_t mask)208 int mec_hal_espi_iobar_mask_set(struct mec_espi_io_regs *base, uint8_t ldn, uint8_t mask)
209 {
210 const struct ld_info *ldi = find_bar(ldn);
211
212 if (!base || !ldi) {
213 return MEC_RET_ERR_INVAL;
214 }
215
216 if (!ldi->io_bar_idx) { /* Logical device does not implement an I/O BAR */
217 return MEC_RET_ERR_INVAL;
218 }
219
220 uint8_t idx = (uint8_t)(ldi->io_bar_idx - 1u);
221 uint32_t temp = base->EC_LDN_MSK[idx];
222
223 temp &= ~(MEC_ESPI_IO_EC_LDN_MSK_MSK_Msk << MEC_ESPI_IO_EC_LDN_MSK_MSK_Pos);
224 temp |= (((uint32_t)mask << MEC_ESPI_IO_EC_LDN_MSK_MSK_Pos) | MEC_ESPI_IO_EC_LDN_MSK_MSK_Msk);
225
226 *((volatile uint32_t *)&base->EC_LDN_MSK[idx]) = temp;
227
228 return MEC_RET_OK;
229 }
230
231 /* eSPI logical device memory BAR's are 80-bit registers packed in address space
232 * resulting 16-bit alignment.
233 * b[0] = 0(disabled), 1(enabled/valid)
234 * b[47:16] = bits[31:0] of the Host address.
235 * NOTE: If Host requires more than a 32-bit memory address, all eSPI I/O memory
236 * BAR's must be located in the same 4GB region and the upper address bits are
237 * specified in the MBAR Host Extended Address register.
238 */
mec_hal_espi_mbar_cfg(struct mec_espi_mem_regs * base,uint8_t ldn,uint32_t mem_base,uint8_t enable)239 int mec_hal_espi_mbar_cfg(struct mec_espi_mem_regs *base, uint8_t ldn,
240 uint32_t mem_base, uint8_t enable)
241 {
242 const struct ld_info *ldi = find_bar(ldn);
243 uint8_t idx;
244
245 if (!base || !ldi) {
246 return MEC_RET_ERR_INVAL;
247 }
248
249 if (!ldi->mem_bar_idx) { /* Logical device does not implement a memory BAR */
250 return MEC_RET_ERR_INVAL;
251 }
252
253 idx = (uint8_t)(ldi->mem_bar_idx - 1u);
254
255 volatile struct mec_espi_mem_host_mem_bar_regs *mbar = &base->HOST_MEM_BAR[idx];
256
257 mbar->VALID &= (uint16_t)~MEC_BIT(MEC_ESPI_MEM_HOST_MEM_BAR_VALID_EN_Pos);
258 mbar->HOST_MEM_ADDR_B15_0 = (uint16_t)mem_base;
259 mbar->HOST_MEM_ADDR_B31_16 = (uint16_t)(mem_base >> 16);
260
261 if (enable) {
262 mbar->VALID |= MEC_BIT(MEC_ESPI_MEM_HOST_MEM_BAR_VALID_EN_Pos);
263 }
264
265 return MEC_RET_OK;
266 }
267
mec_hal_espi_sram_bar_cfg(struct mec_espi_mem_regs * base,const struct espi_mec5_sram_bar_cfg * barcfg,uint8_t sram_bar_id,uint8_t enable)268 int mec_hal_espi_sram_bar_cfg(struct mec_espi_mem_regs *base,
269 const struct espi_mec5_sram_bar_cfg *barcfg,
270 uint8_t sram_bar_id, uint8_t enable)
271 {
272 uint32_t temp;
273
274 if (!base || !barcfg || (sram_bar_id >= MEC_ESPI_SRAM_BAR_MAX)
275 || (barcfg->access > MEC_ESPI_SRAM_HOST_ACCESS_RW)
276 || (barcfg->size > MEC_ESPI_SRAM_BAR_SIZE_32KB)) {
277 return MEC_RET_ERR_INVAL;
278 }
279
280 base->EC_SRAM_BAR[sram_bar_id].VASZ = 0; /* disable before modification */
281 temp = barcfg->size;
282 temp = (temp << MEC_ESPI_MEM_EC_SRAM_BAR_VASZ_SIZE_Pos)
283 & MEC_ESPI_MEM_EC_SRAM_BAR_VASZ_SIZE_Msk;
284 temp |= (((uint32_t)barcfg->access << MEC_ESPI_MEM_EC_SRAM_BAR_VASZ_ACCESS_Pos) &
285 MEC_ESPI_MEM_EC_SRAM_BAR_VASZ_ACCESS_Msk);
286 base->EC_SRAM_BAR[sram_bar_id].VASZ = (uint16_t)temp;
287
288 base->EC_SRAM_BAR[sram_bar_id].EC_SRAM_ADDR_15_0 = barcfg->maddr & 0xffffu;
289 base->EC_SRAM_BAR[sram_bar_id].EC_SRAM_ADDR_31_16 = (uint16_t)(barcfg->maddr >> 16);
290
291 base->HOST_SRAM_BAR[sram_bar_id].HOST_ADDR_15_0 = barcfg->haddr & 0xffffu;
292 base->HOST_SRAM_BAR[sram_bar_id].HOST_ADDR_31_16 = (uint16_t)(barcfg->haddr >> 16);
293
294 if (enable) {
295 base->EC_SRAM_BAR[sram_bar_id].VASZ |= MEC_BIT(MEC_ESPI_MEM_EC_SRAM_BAR_VASZ_VALID_Pos);
296 }
297
298 return MEC_RET_OK;
299 }
300
301 /* Set host address bits[47:32] for memory BAR's
302 * Each Logical device implementing a memory BAR includes Host address bits [31:0].
303 * Host address bits [47:32] are the same for all memory BAR's. Therefore all memory
304 * BAR's must be located in the same 4GB host address space range.
305 */
mec_hal_espi_mbar_extended_addr_set(struct mec_espi_mem_regs * base,uint32_t extended_addr)306 int mec_hal_espi_mbar_extended_addr_set(struct mec_espi_mem_regs *base, uint32_t extended_addr)
307 {
308 if (!base) {
309 return MEC_RET_ERR_INVAL;
310 }
311
312 base->MBAR_HOST_EXTEND = extended_addr;
313
314 return MEC_RET_OK;
315 }
316
mec_hal_espi_sram_bar_extended_addr_set(struct mec_espi_mem_regs * base,uint32_t extended_addr)317 int mec_hal_espi_sram_bar_extended_addr_set(struct mec_espi_mem_regs *base,
318 uint32_t extended_addr)
319 {
320 if (!base) {
321 return MEC_RET_ERR_INVAL;
322 }
323
324 base->SRAM_BAR_HOST_EXTEND = extended_addr;
325
326 return MEC_RET_OK;
327 }
328
mec_hal_espi_mbar_enable(struct mec_espi_mem_regs * base,uint8_t ldn,uint8_t enable)329 int mec_hal_espi_mbar_enable(struct mec_espi_mem_regs *base, uint8_t ldn, uint8_t enable)
330 {
331 const struct ld_info *ldi = find_bar(ldn);
332 uint8_t idx;
333
334 if (!base || !ldi) {
335 return MEC_RET_ERR_INVAL;
336 }
337
338 if (!ldi->mem_bar_idx) { /* Logical device does not implement a memory BAR */
339 return MEC_RET_ERR_INVAL;
340 }
341
342 idx = (uint8_t)(ldi->mem_bar_idx - 1u);
343
344 volatile struct mec_espi_mem_host_mem_bar_regs *mbar = &base->HOST_MEM_BAR[idx];
345
346 if (enable) {
347 mbar->VALID |= MEC_BIT(MEC_ESPI_MEM_HOST_MEM_BAR_VALID_EN_Pos);
348 } else {
349 mbar->VALID &= (uint16_t)~MEC_BIT(MEC_ESPI_MEM_HOST_MEM_BAR_VALID_EN_Pos);
350 }
351
352 return MEC_RET_OK;
353 }
354
mec_hal_espi_mbar_is_enabled(struct mec_espi_mem_regs * base,uint8_t ldn)355 int mec_hal_espi_mbar_is_enabled(struct mec_espi_mem_regs *base, uint8_t ldn)
356 {
357 const struct ld_info *ldi = find_bar(ldn);
358 uint8_t idx;
359
360 if (!base || !ldi) {
361 return MEC_RET_ERR_INVAL;
362 }
363
364 if (!ldi->mem_bar_idx) { /* Logical device does not implement a memory BAR */
365 return MEC_RET_ERR_INVAL;
366 }
367
368 idx = (uint8_t)(ldi->mem_bar_idx - 1u);
369
370 volatile struct mec_espi_mem_host_mem_bar_regs *mbar = &base->HOST_MEM_BAR[idx];
371
372 if (mbar->VALID & MEC_BIT(MEC_ESPI_MEM_HOST_MEM_BAR_VALID_EN_Pos)) {
373 return 1;
374 }
375
376 return 0;
377 }
378
379 /* Disable I/O and Memory BARs for a logical device */
mec_hal_espi_bar_inhibit(struct mec_espi_io_regs * base,uint8_t ldn,uint8_t inhibit)380 int mec_hal_espi_bar_inhibit(struct mec_espi_io_regs *base, uint8_t ldn, uint8_t inhibit)
381 {
382 const struct ld_info *ldi = find_bar(ldn);
383
384 if (!base || !ldi) {
385 return MEC_RET_ERR_INVAL;
386 }
387
388 if (!ldi->io_bar_idx && !ldi->mem_bar_idx) { /* Logical device does not implement any BAR */
389 return MEC_RET_ERR_INVAL;
390 }
391
392 if (ldn < 32) {
393 if (inhibit) {
394 base->PCBINH[0] |= MEC_BIT(ldn);
395 } else {
396 base->PCBINH[0] &= (uint32_t)~MEC_BIT(ldn);
397 }
398 } else {
399 ldn = ldn - (uint8_t)32u;
400 if (inhibit) {
401 base->PCBINH[1] |= MEC_BIT(ldn);
402 } else {
403 base->PCBINH[1] &= (uint32_t)~MEC_BIT(ldn);
404 }
405 }
406
407 return MEC_RET_OK;
408 }
409
mec_hal_espi_bar_inhibit_msk(struct mec_espi_io_regs * base,uint8_t inhibit,uint32_t msklo,uint32_t mskhi)410 int mec_hal_espi_bar_inhibit_msk(struct mec_espi_io_regs *base, uint8_t inhibit,
411 uint32_t msklo, uint32_t mskhi)
412 {
413 if (!base) {
414 return MEC_RET_ERR_INVAL;
415 }
416
417 if (inhibit) {
418 base->PCBINH[0] |= msklo;
419 base->PCBINH[1] |= mskhi;
420 } else {
421 base->PCBINH[0] &= ~msklo;
422 base->PCBINH[1] &= ~mskhi;
423 }
424
425 return MEC_RET_OK;
426 }
427
428 /* ---- Logical Device Serial IRQ ---- */
429
430 /* Return the number of Serial IRQs a logical device implements */
mec_hal_espi_ld_sirq_num(struct mec_espi_io_regs * iobase,uint8_t ldn)431 uint8_t mec_hal_espi_ld_sirq_num(struct mec_espi_io_regs *iobase, uint8_t ldn)
432 {
433 const struct ld_info *ldi = find_bar(ldn);
434
435 if (!iobase || !ldi) {
436 return 0;
437 }
438
439 return ldi->num_sirqs;
440 }
441
442 /* get current slot number the specified logical device SIRQ instance is programmed to.
443 * NOTE: a value of 255 (0xff) indicates this SIRQ is disabled.
444 */
mec_hal_espi_ld_sirq_get(struct mec_espi_io_regs * iobase,uint8_t ldn,uint8_t ldn_sirq_id)445 uint8_t mec_hal_espi_ld_sirq_get(struct mec_espi_io_regs *iobase, uint8_t ldn, uint8_t ldn_sirq_id)
446 {
447 const struct ld_info *ldi = find_bar(ldn);
448 uint8_t idx = 0;
449
450 if (!iobase || !ldi) {
451 return 0;
452 }
453
454 if ((!ldi->num_sirqs) || (ldn_sirq_id > ldi->num_sirqs)) {
455 return 0xffu;
456 }
457
458 idx = ldi->sirq_idx + ldn_sirq_id;
459
460 return mec_espi_sirq_get(iobase, idx);
461 }
462
mec_hal_espi_ld_sirq_set(struct mec_espi_io_regs * iobase,uint8_t ldn,uint8_t ldn_sirq_id,uint8_t slot)463 void mec_hal_espi_ld_sirq_set(struct mec_espi_io_regs *iobase, uint8_t ldn,
464 uint8_t ldn_sirq_id, uint8_t slot)
465 {
466 const struct ld_info *ldi = find_bar(ldn);
467 uint8_t idx = 0;
468
469 if (!iobase || !ldi) {
470 return;
471 }
472
473 if ((!ldi->num_sirqs) || (ldn_sirq_id > ldi->num_sirqs)) {
474 return;
475 }
476
477 idx = ldi->sirq_idx + ldn_sirq_id;
478
479 espi_sirq_set(iobase, idx, slot);
480 }
481
482 /* Generate EC_IRQ Serial IRQ to the Host using the Serial IRQ slot
483 * number previously programmed by mec_espi_ld_sirq_set().
484 */
mec_hal_espi_gen_ec_sirq(struct mec_espi_io_regs * iobase)485 int mec_hal_espi_gen_ec_sirq(struct mec_espi_io_regs *iobase)
486 {
487 if (!iobase) {
488 return MEC_RET_ERR_INVAL;
489 }
490
491 iobase->PCECIRQ |= MEC_BIT(MEC_ESPI_IO_PCECIRQ_GEN_EC_IRQ_Pos);
492
493 return MEC_RET_OK;
494 }
495
496 /* end mec_espi_host_dev.c */
497