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_acpi_ec_api.h"
13 #include "mec_ecia_api.h"
14 #include "mec_espi_api.h"
15 #include "mec_pcr_api.h"
16 #include "mec_retval.h"
17 
18 #define MEC_ACPI_EC_GIRQ 15
19 
20 #define MEC_ACPI_EC0_IBF_GIRQ_POS 5
21 #define MEC_ACPI_EC0_OBE_GIRQ_POS 6
22 #define MEC_ACPI_EC1_IBF_GIRQ_POS 7
23 #define MEC_ACPI_EC1_OBE_GIRQ_POS 8
24 #define MEC_ACPI_EC2_IBF_GIRQ_POS 9
25 #define MEC_ACPI_EC2_OBE_GIRQ_POS 10
26 #define MEC_ACPI_EC3_IBF_GIRQ_POS 11
27 #define MEC_ACPI_EC3_OBE_GIRQ_POS 12
28 #define MEC_ACPI_EC4_IBF_GIRQ_POS 13
29 #define MEC_ACPI_EC4_OBE_GIRQ_POS 14
30 
31 #define MEC_ACPI_EC0_IBF_ECIA_INFO MEC5_ECIA_INFO(15, 5, 7, 45)
32 #define MEC_ACPI_EC0_OBE_ECIA_INFO MEC5_ECIA_INFO(15, 6, 7, 46)
33 #define MEC_ACPI_EC1_IBF_ECIA_INFO MEC5_ECIA_INFO(15, 7, 7, 47)
34 #define MEC_ACPI_EC1_OBE_ECIA_INFO MEC5_ECIA_INFO(15, 8, 7, 48)
35 #define MEC_ACPI_EC2_IBF_ECIA_INFO MEC5_ECIA_INFO(15, 9, 7, 49)
36 #define MEC_ACPI_EC2_OBE_ECIA_INFO MEC5_ECIA_INFO(15, 10, 7, 50)
37 #define MEC_ACPI_EC3_IBF_ECIA_INFO MEC5_ECIA_INFO(15, 11, 7, 51)
38 #define MEC_ACPI_EC3_OBE_ECIA_INFO MEC5_ECIA_INFO(15, 12, 7, 52)
39 #define MEC_ACPI_EC4_IBF_ECIA_INFO MEC5_ECIA_INFO(15, 13, 7, 53)
40 #define MEC_ACPI_EC4_OBE_ECIA_INFO MEC5_ECIA_INFO(15, 14, 7, 54)
41 
42 #define MEC_ACPI_EC_IBF_DEVI_IDX 0
43 #define MEC_ACPI_EC_OBE_DEVI_IDX 1
44 
45 /* Hardware has a mode where each ACPI EC's IBF and OBE interrupt signal are
46  * OR'd together and connected to the NVIC bypassing the aggregator (GIRQ)
47  * hardware. Each ISR would determine IBF/OBE by looking at the ACPI EC
48  * status register.
49  */
50 #define MEC_ACPI_EC0_NVIC_NUM 175
51 #define MEC_ACPI_EC1_NVIC_NUM 176
52 #define MEC_ACPI_EC2_NVIC_NUM 177
53 #define MEC_ACPI_EC3_NVIC_NUM 178
54 #define MEC_ACPI_EC4_NVIC_NUM 179
55 
56 #define MEC_ACPI_EC_STS_RW_MSK (MEC_BIT(2) | MEC_BIT(4) | MEC_BIT(5) | MEC_BIT(6) | MEC_BIT(7))
57 #define MEC_ACPI_EC_STS_RO_MSK (MEC_BIT(0) | MEC_BIT(1) | MEC_BIT(3))
58 
59 struct mec_acpi_ec_info {
60     uintptr_t base_addr;
61     uint16_t pcr_id;
62     uint8_t ldn;
63     uint32_t devi[MEC_ACPI_EC_NUM_IRQS];
64 };
65 
66 static const struct mec_acpi_ec_info acpi_ec_instances[] = {
67     { MEC_ACPI_EC0_BASE, MEC_PCR_ACPI_EC0, MEC_ESPI_LDN_ACPI_EC0,
68       {MEC_ACPI_EC0_IBF_ECIA_INFO, MEC_ACPI_EC0_OBE_ECIA_INFO} },
69     { MEC_ACPI_EC1_BASE, MEC_PCR_ACPI_EC1, MEC_ESPI_LDN_ACPI_EC1,
70       {MEC_ACPI_EC1_IBF_ECIA_INFO, MEC_ACPI_EC1_OBE_ECIA_INFO} },
71     { MEC_ACPI_EC2_BASE, MEC_PCR_ACPI_EC2, MEC_ESPI_LDN_ACPI_EC2,
72       {MEC_ACPI_EC2_IBF_ECIA_INFO, MEC_ACPI_EC2_OBE_ECIA_INFO} },
73     { MEC_ACPI_EC3_BASE, MEC_PCR_ACPI_EC3, MEC_ESPI_LDN_ACPI_EC3,
74       {MEC_ACPI_EC3_IBF_ECIA_INFO, MEC_ACPI_EC3_OBE_ECIA_INFO} },
75     { MEC_ACPI_EC4_BASE, MEC_PCR_ACPI_EC4, MEC_ESPI_LDN_ACPI_EC4,
76       {MEC_ACPI_EC4_IBF_ECIA_INFO, MEC_ACPI_EC4_OBE_ECIA_INFO} },
77 };
78 #define NUM_ACPI_EC_INSTANCES \
79     (sizeof(acpi_ec_instances) / sizeof(struct mec_acpi_ec_info))
80 
find_acpi_ec_info(uintptr_t base_addr)81 static struct mec_acpi_ec_info const *find_acpi_ec_info(uintptr_t base_addr)
82 {
83     for (size_t i = 0; i < NUM_ACPI_EC_INSTANCES; i++) {
84         if (base_addr == acpi_ec_instances[i].base_addr) {
85             return &acpi_ec_instances[i];
86         }
87     }
88 
89     return NULL;
90 }
91 
92 /* ---- Public API ---- */
93 
94 /* Initialize an ACPI EC controller.
95  * This peripheral is reset by chip reset (RESET_SYS).
96  * The Host I/O and Memory BAR's in the eSPI I/O component are reset by
97  * RESET_VCC and RESET_HOST (PCI_RESET# or PLTRST#).
98  */
mec_hal_acpi_ec_init(struct mec_acpi_ec_regs * regs,uint32_t flags)99 int mec_hal_acpi_ec_init(struct mec_acpi_ec_regs *regs, uint32_t flags)
100 {
101     const struct mec_acpi_ec_info *info = find_acpi_ec_info((uintptr_t)regs);
102 
103 #ifdef MEC_ACPI_EC_BASE_CHECK
104     if (!info) {
105         return MEC_RET_ERR_INVAL;
106     }
107 #endif
108 
109     mec_hal_acpi_ec_girq_dis(regs, MEC_ACPI_EC_IBF_IRQ | MEC_ACPI_EC_OBE_IRQ);
110     mec_hal_pcr_clr_blk_slp_en(info->pcr_id);
111     if (flags & MEC_ACPI_EC_RESET) {
112         mec_hal_pcr_blk_reset(info->pcr_id);
113     } else { /* clear IBF and OBE status */
114         regs->AEC_H2E_DATA;
115     }
116 
117     mec_hal_acpi_ec_girq_clr(regs, MEC_ACPI_EC_IBF_IRQ | MEC_ACPI_EC_OBE_IRQ);
118 
119     if (flags & MEC_ACPI_EC_4BYTE_MODE) {
120         regs->AEC_BYTE_CTRL |= MEC_BIT(MEC_ACPI_EC_AEC_BYTE_CTRL_FOUR_BYTE_MODE_Pos);
121     } else {
122         regs->AEC_BYTE_CTRL &= (uint8_t)~MEC_BIT(MEC_ACPI_EC_AEC_BYTE_CTRL_FOUR_BYTE_MODE_Pos);
123     }
124 
125     if (flags & MEC_ACPI_EC_UD0A_SET) {
126         if (flags & MEC_ACPI_EC_UD0A_ONE) {
127             regs->AEC_STATUS |= MEC_BIT(MEC_ACPI_EC_AEC_STATUS_UD0A_Pos);
128         } else {
129             regs->AEC_STATUS &= (uint8_t)~MEC_BIT(MEC_ACPI_EC_AEC_STATUS_UD0A_Pos);
130         }
131     }
132 
133     if (flags & MEC_ACPI_EC_UD1A_SET) {
134         if (flags & MEC_ACPI_EC_UD1A_ONE) {
135             regs->AEC_STATUS |= MEC_BIT(MEC_ACPI_EC_AEC_STATUS_UD1A_Pos);
136         } else {
137             regs->AEC_STATUS &= (uint8_t)~MEC_BIT(MEC_ACPI_EC_AEC_STATUS_UD1A_Pos);
138         }
139     }
140 
141     mec_hal_acpi_ec_girq_dis(regs, flags);
142 
143     return MEC_RET_OK;
144 }
145 
acpi_ec_irq_bitmap(const struct mec_acpi_ec_info * info,uint32_t flags)146 static uint32_t acpi_ec_irq_bitmap(const struct mec_acpi_ec_info *info, uint32_t flags)
147 {
148     uint32_t bm = 0;
149 
150     if (flags & MEC_ACPI_EC_IBF_IRQ) {
151         bm |= MEC_BIT(MEC5_ECIA_INFO_GIRQ_POS(info->devi[MEC_ACPI_EC_IBF_DEVI_IDX]));
152     }
153 
154     if (flags & MEC_ACPI_EC_OBE_IRQ) {
155         bm |= MEC_BIT(MEC5_ECIA_INFO_GIRQ_POS(info->devi[MEC_ACPI_EC_OBE_DEVI_IDX]));
156     }
157 
158     return bm;
159 }
160 
mec_hal_acpi_ec_girq_en(struct mec_acpi_ec_regs * regs,uint32_t flags)161 int mec_hal_acpi_ec_girq_en(struct mec_acpi_ec_regs *regs, uint32_t flags)
162 {
163     const struct mec_acpi_ec_info *info = find_acpi_ec_info((uintptr_t)regs);
164     uint32_t bitmap = 0;
165 
166 #ifdef MEC_ACPI_EC_BASE_CHECK
167     if (!info) {
168         return MEC_RET_ERR_INVAL;
169     }
170 #endif
171 
172     bitmap = acpi_ec_irq_bitmap(info, flags);
173     mec_hal_girq_bm_en(MEC_ACPI_EC_GIRQ, bitmap, 1u);
174 
175     return MEC_RET_OK;
176 }
177 
mec_hal_acpi_ec_girq_dis(struct mec_acpi_ec_regs * regs,uint32_t flags)178 int mec_hal_acpi_ec_girq_dis(struct mec_acpi_ec_regs *regs, uint32_t flags)
179 {
180     const struct mec_acpi_ec_info *info = find_acpi_ec_info((uintptr_t)regs);
181     uint32_t bitmap = 0;
182 
183 #ifdef MEC_ACPI_EC_BASE_CHECK
184     if (!info) {
185         return MEC_RET_ERR_INVAL;
186     }
187 #endif
188     bitmap = acpi_ec_irq_bitmap(info, flags);
189     mec_hal_girq_bm_en(MEC_ACPI_EC_GIRQ, bitmap, 0);
190 
191     return MEC_RET_OK;
192 }
193 
mec_hal_acpi_ec_girq_clr(struct mec_acpi_ec_regs * regs,uint32_t flags)194 int mec_hal_acpi_ec_girq_clr(struct mec_acpi_ec_regs *regs, uint32_t flags)
195 {
196     const struct mec_acpi_ec_info *info = find_acpi_ec_info((uintptr_t)regs);
197 
198 #ifdef MEC_ACPI_EC_BASE_CHECK
199     if (!info) {
200         return MEC_RET_ERR_INVAL;
201     }
202 #endif
203     uint32_t clr_bitmap = acpi_ec_irq_bitmap(info, flags);
204 
205     mec_hal_girq_bm_clr_src(MEC_ACPI_EC_GIRQ, clr_bitmap);
206 
207     return MEC_RET_OK;
208 }
209 
mec_hal_acpi_ec_girq_result(struct mec_acpi_ec_regs * regs)210 uint32_t mec_hal_acpi_ec_girq_result(struct mec_acpi_ec_regs *regs)
211 {
212     const struct mec_acpi_ec_info *info = find_acpi_ec_info((uintptr_t)regs);
213     uint32_t temp = 0u, result = 0u, ibf_bit = 0, obe_bit = 0;
214 
215 #ifdef MEC_ACPI_EC_BASE_CHECK
216     if (!info) {
217         return result;
218     }
219 #endif
220 
221     ibf_bit = MEC5_ECIA_INFO_GIRQ_POS(info->devi[MEC_ACPI_EC_IBF_DEVI_IDX]);
222     obe_bit = MEC5_ECIA_INFO_GIRQ_POS(info->devi[MEC_ACPI_EC_OBE_DEVI_IDX]);
223     temp = mec_hal_girq_result_get(MEC_ACPI_EC_GIRQ);
224     if (temp & MEC_BIT(ibf_bit)) {
225         result |= MEC_ACPI_EC_IBF_IRQ;
226     }
227     if (temp & MEC_BIT(obe_bit)) {
228         result |= MEC_ACPI_EC_OBE_IRQ;
229     }
230 
231     return result;
232 }
233 
234 /* ACPI EC has no block enable. Check the eSPI BARs? If either of the I/O or Mem
235  * BAR is enabled then report enabled.
236  */
mec_hal_acpi_ec_is_enabled(struct mec_acpi_ec_regs * regs)237 int mec_hal_acpi_ec_is_enabled(struct mec_acpi_ec_regs *regs)
238 {
239     struct mec_espi_io_regs *espi_io_base = (struct mec_espi_io_regs *)MEC_ESPI_IO_BASE;
240     struct mec_espi_mem_regs *espi_mem_base = (struct mec_espi_mem_regs *)MEC_ESPI_MEM_BASE;
241     const struct mec_acpi_ec_info *info = find_acpi_ec_info((uintptr_t)regs);
242 
243 #ifdef MEC_ACPI_EC_BASE_CHECK
244     if (!info) {
245         return 0;
246     }
247 #endif
248 
249     if (mec_hal_espi_iobar_is_enabled(espi_io_base, info->ldn)) {
250         return 1;
251     }
252 
253     if (mec_hal_espi_mbar_is_enabled(espi_mem_base, info->ldn)) {
254         return 1;
255     }
256 
257     return 0;
258 }
259 
mec_hal_acpi_ec_is_4byte_mode(struct mec_acpi_ec_regs * regs)260 int mec_hal_acpi_ec_is_4byte_mode(struct mec_acpi_ec_regs *regs)
261 {
262 #ifdef MEC_ACPI_EC_BASE_CHECK
263     if (!regs) {
264         return 0u;
265     }
266 #endif
267     if (regs && (regs->AEC_BYTE_CTRL & MEC_BIT(MEC_ACPI_EC_AEC_BYTE_CTRL_FOUR_BYTE_MODE_Pos))) {
268         return 1;
269     }
270 
271     return 0;
272 }
273 
mec_hal_acpi_ec_status(struct mec_acpi_ec_regs * regs)274 uint8_t mec_hal_acpi_ec_status(struct mec_acpi_ec_regs *regs)
275 {
276 #ifdef MEC_ACPI_EC_BASE_CHECK
277     if (!regs) {
278         return 0u;
279     }
280 #endif
281     return regs->AEC_STATUS;
282 }
283 
mec_hal_acpi_ec_status_wr(struct mec_acpi_ec_regs * regs,uint8_t val)284 void mec_hal_acpi_ec_status_wr(struct mec_acpi_ec_regs *regs, uint8_t val)
285 {
286 #ifdef MEC_ACPI_EC_BASE_CHECK
287     if (!regs) {
288         return;
289     }
290 #endif
291     regs->AEC_STATUS = val;
292 }
293 
mec_hal_acpi_ec_status_set(struct mec_acpi_ec_regs * regs,uint8_t val)294 void mec_hal_acpi_ec_status_set(struct mec_acpi_ec_regs *regs, uint8_t val)
295 {
296 #ifdef MEC_ACPI_EC_BASE_CHECK
297     if (!regs) {
298         return;
299     }
300 #endif
301     regs->AEC_STATUS |= val;
302 }
303 
mec_hal_acpi_ec_status_mask(struct mec_acpi_ec_regs * regs,uint8_t val,uint8_t msk)304 void mec_hal_acpi_ec_status_mask(struct mec_acpi_ec_regs *regs, uint8_t val, uint8_t msk)
305 {
306 #ifdef MEC_ACPI_EC_BASE_CHECK
307     if (!regs) {
308         return;
309     }
310 #endif
311     regs->AEC_STATUS = (regs->AEC_STATUS & ~msk) | (val & msk);
312 }
313 
mec_hal_acpi_ec_status_obf(struct mec_acpi_ec_regs * regs)314 uint8_t mec_hal_acpi_ec_status_obf(struct mec_acpi_ec_regs *regs)
315 {
316 #ifdef MEC_ACPI_EC_BASE_CHECK
317     if (!regs) {
318         return 0;
319     }
320 #endif
321     return (regs->AEC_STATUS & MEC_ACPI_EC_AEC_STATUS_OBF_Msk) >> MEC_ACPI_EC_AEC_STATUS_OBF_Pos;
322 }
323 
mec_hal_acpi_ec_status_ibf(struct mec_acpi_ec_regs * regs)324 uint8_t mec_hal_acpi_ec_status_ibf(struct mec_acpi_ec_regs *regs)
325 {
326 #ifdef MEC_ACPI_EC_BASE_CHECK
327     if (!regs) {
328         return 0;
329     }
330 #endif
331     return (regs->AEC_STATUS & MEC_ACPI_EC_AEC_STATUS_IBF_Msk) >> MEC_ACPI_EC_AEC_STATUS_IBF_Pos;
332 }
333 
mec_hal_acpi_ec_host_to_ec_data_rd32(struct mec_acpi_ec_regs * regs)334 uint32_t mec_hal_acpi_ec_host_to_ec_data_rd32(struct mec_acpi_ec_regs *regs)
335 {
336 #ifdef MEC_ACPI_EC_BASE_CHECK
337     if (!regs) {
338         return 0;
339     }
340 #endif
341     return regs->AEC_H2E_DATA;  /* defined as 32-bit register */
342 }
343 
mec_hal_acpi_ec_host_to_ec_data_wr32(struct mec_acpi_ec_regs * regs,uint32_t data)344 void mec_hal_acpi_ec_host_to_ec_data_wr32(struct mec_acpi_ec_regs *regs, uint32_t data)
345 {
346 #ifdef MEC_ACPI_EC_BASE_CHECK
347     if (!regs) {
348         return;
349     }
350 #endif
351     regs->AEC_H2E_DATA = data;
352 }
353 
mec_hal_acpi_ec_host_to_ec_data_rd8(struct mec_acpi_ec_regs * regs,uint8_t offset)354 uint8_t mec_hal_acpi_ec_host_to_ec_data_rd8(struct mec_acpi_ec_regs *regs, uint8_t offset)
355 {
356 #ifdef MEC_ACPI_EC_BASE_CHECK
357     if (!regs) {
358         return 0u;
359     }
360 #endif
361     uint32_t addr = (uint32_t)&regs->AEC_H2E_DATA + (uint32_t)(offset & 0x3u);
362 
363     return MEC_MMCR8(addr);
364 }
365 
mec_hal_acpi_ec_host_to_ec_data_wr8(struct mec_acpi_ec_regs * regs,uint8_t offset,uint8_t data)366 void mec_hal_acpi_ec_host_to_ec_data_wr8(struct mec_acpi_ec_regs *regs, uint8_t offset,
367                                          uint8_t data)
368 {
369 #ifdef MEC_ACPI_EC_BASE_CHECK
370     if (!regs) {
371         return;
372     }
373 #endif
374     uint32_t addr = (uint32_t)&regs->AEC_H2E_DATA + (uint32_t)(offset & 0x3u);
375 
376     MEC_MMCR8(addr) = data;
377 }
378 
379 /* --- */
mec_hal_acpi_ec_e2h_data_rd32(struct mec_acpi_ec_regs * regs)380 uint32_t mec_hal_acpi_ec_e2h_data_rd32(struct mec_acpi_ec_regs *regs)
381 {
382 #ifdef MEC_ACPI_EC_BASE_CHECK
383     if (!regs) {
384         return 0;
385     }
386 #endif
387     return regs->AEC_E2H_DATA;  /* defined as 32-bit register */
388 }
389 
mec_hal_acpi_ec_e2h_to_ec_data_wr32(struct mec_acpi_ec_regs * regs,uint32_t data)390 void mec_hal_acpi_ec_e2h_to_ec_data_wr32(struct mec_acpi_ec_regs *regs, uint32_t data)
391 {
392 #ifdef MEC_ACPI_EC_BASE_CHECK
393     if (!regs) {
394         return;
395     }
396 #endif
397     regs->AEC_E2H_DATA = data;
398 }
399 
mec_hal_acpi_ec_e2h_data_rd8(struct mec_acpi_ec_regs * regs,uint8_t offset)400 uint8_t mec_hal_acpi_ec_e2h_data_rd8(struct mec_acpi_ec_regs *regs, uint8_t offset)
401 {
402 #ifdef MEC_ACPI_EC_BASE_CHECK
403     if (!regs) {
404         return 0u;
405     }
406 #endif
407     uint32_t addr = (uint32_t)&regs->AEC_E2H_DATA + (uint32_t)(offset & 0x3u);
408 
409     return MEC_MMCR8(addr);
410 }
411 
mec_hal_acpi_ec_e2h_data_wr8(struct mec_acpi_ec_regs * regs,uint8_t offset,uint8_t data)412 void mec_hal_acpi_ec_e2h_data_wr8(struct mec_acpi_ec_regs *regs, uint8_t offset, uint8_t data)
413 {
414 #ifdef MEC_ACPI_EC_BASE_CHECK
415     if (!regs) {
416         return;
417     }
418 #endif
419     uint32_t addr = (uint32_t)&regs->AEC_E2H_DATA + (uint32_t)(offset & 0x3u);
420 
421     MEC_MMCR8(addr) = data;
422 }
423 
424 /* end mec_acpi_ec.c */
425