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_ecia_api.h"
13 #include "mec_espi_api.h"
14 #include "mec_retval.h"
15 
16 /* ---- eSPI Peripheral Channel ---- */
17 #define MEC_ESPI_PC_ECIA_INFO MEC5_ECIA_INFO(19, 0, 11, 103)
18 #define MEC_ESPI_LTR_ECIA_INFO MEC5_ECIA_INFO(19, 3, 11, 106)
19 
xlat_intr_to_hw(uint32_t bitmap)20 static uint32_t xlat_intr_to_hw(uint32_t bitmap)
21 {
22     uint32_t hwbm = 0;
23 
24     if (bitmap & MEC_BIT(MEC_ESPI_PC_INTR_CHEN_CHG_POS)) {
25         hwbm |= MEC_BIT(MEC_ESPI_IO_PCSTS_PCEN_CHG_Pos);
26     }
27 
28     if (bitmap & MEC_BIT(MEC_ESPI_PC_INTR_BMEN_CHG_POS)) {
29         hwbm |= MEC_BIT(MEC_ESPI_IO_PCSTS_PCBMEN_CHG_Pos);
30     }
31 
32     if (bitmap & MEC_BIT(MEC_ESPI_PC_INTR_BERR_POS)) {
33         hwbm |= MEC_BIT(MEC_ESPI_IO_PCSTS_EC_BUS_ERR_Pos);
34     }
35 
36     return hwbm;
37 }
38 
39 /* ---- Public API ---- */
40 
mec_hal_espi_pc_ready_set(struct mec_espi_io_regs * iobase)41 void mec_hal_espi_pc_ready_set(struct mec_espi_io_regs *iobase)
42 {
43     iobase->PCRDY = MEC_BIT(MEC_ESPI_IO_PCRDY_PC_READY_Pos);
44 }
45 
mec_hal_espi_pc_is_ready(struct mec_espi_io_regs * iobase)46 int mec_hal_espi_pc_is_ready(struct mec_espi_io_regs *iobase)
47 {
48     if (iobase->PCRDY & MEC_BIT(MEC_ESPI_IO_PCRDY_PC_READY_Pos)) {
49         return 1u;
50     }
51 
52     return 0;
53 }
54 
55 /* Peripheral channel enable state is status register bit[24]; move to bit[0].
56  * Enable change is status register bit[25]; move to bit[1].
57  */
mec_hal_espi_pc_en_status(struct mec_espi_io_regs * iobase)58 uint32_t mec_hal_espi_pc_en_status(struct mec_espi_io_regs *iobase)
59 {
60     uint32_t temp = iobase->PCSTS & (MEC_ESPI_IO_PCSTS_PCEN_VAL_Msk
61                                      | MEC_ESPI_IO_PCSTS_PCEN_CHG_Msk);
62 
63     return (temp >> MEC_ESPI_IO_PCSTS_PCEN_VAL_Pos);
64 }
65 
66 /* Peripheral channel bus master enable state is status register bit[27]; move to bit[0].
67  * BM enable change is bit[28]; move to bit[1].
68  * the enable's current state.
69  */
mec_hal_espi_pc_bm_status(struct mec_espi_io_regs * iobase)70 uint32_t mec_hal_espi_pc_bm_status(struct mec_espi_io_regs *iobase)
71 {
72     uint32_t temp = iobase->PCSTS & (MEC_ESPI_IO_PCSTS_PCBM_VAL_Msk
73                                      | MEC_ESPI_IO_PCSTS_PCBMEN_CHG_Msk);
74 
75     return (temp >> MEC_ESPI_IO_PCSTS_PCBM_VAL_Pos);
76 }
77 
mec_hal_espi_pc_status(struct mec_espi_io_regs * iobase)78 uint32_t mec_hal_espi_pc_status(struct mec_espi_io_regs *iobase)
79 {
80     uint32_t sts = 0;
81     uint32_t temp = iobase->PCSTS;
82 
83     if (temp & MEC_BIT(MEC_ESPI_IO_PCSTS_EC_BUS_ERR_Pos)) {
84         sts |= MEC_BIT(MEC_ESPI_PC_ISTS_BERR_POS);
85     }
86     if (temp & MEC_BIT(MEC_ESPI_IO_PCSTS_PCEN_VAL_Pos)) {
87         sts |= MEC_BIT(MEC_ESPI_PC_ISTS_CHEN_CHG_POS);
88     }
89     if (temp & MEC_BIT(MEC_ESPI_IO_PCSTS_PCEN_CHG_Pos)) {
90         sts |= MEC_BIT(MEC_ESPI_PC_ISTS_CHEN_STATE_POS);
91     }
92     if (temp & MEC_BIT(MEC_ESPI_IO_PCSTS_PCBM_VAL_Pos)) {
93         sts |= MEC_BIT(MEC_ESPI_PC_ISTS_BMEN_STATE_POS);
94     }
95     if (temp & MEC_BIT(MEC_ESPI_IO_PCSTS_PCBMEN_CHG_Pos)) {
96         sts |= MEC_BIT(MEC_ESPI_PC_ISTS_BMEN_CHG_POS);
97     }
98 
99     return sts;
100 }
101 
mec_hal_espi_pc_status_clr(struct mec_espi_io_regs * iobase,uint32_t bitmap)102 void mec_hal_espi_pc_status_clr(struct mec_espi_io_regs *iobase, uint32_t bitmap)
103 {
104     uint32_t regval = 0;
105 
106     regval = xlat_intr_to_hw(bitmap);
107     iobase->PCSTS = regval;
108 }
109 
mec_hal_espi_pc_intr_en(struct mec_espi_io_regs * iobase,uint32_t bitmap)110 void mec_hal_espi_pc_intr_en(struct mec_espi_io_regs *iobase, uint32_t bitmap)
111 {
112     uint32_t regval = 0;
113 
114     regval = xlat_intr_to_hw(bitmap);
115     iobase->PCIEN |= regval;
116 }
117 
mec_hal_espi_pc_intr_dis(struct mec_espi_io_regs * iobase,uint32_t bitmap)118 void mec_hal_espi_pc_intr_dis(struct mec_espi_io_regs *iobase, uint32_t bitmap)
119 {
120     uint32_t regval = 0;
121 
122     regval = xlat_intr_to_hw(bitmap);
123     iobase->PCIEN &= ~regval;
124 }
125 
mec_hal_espi_pc_status_clr_all(struct mec_espi_io_regs * iobase)126 void mec_hal_espi_pc_status_clr_all(struct mec_espi_io_regs *iobase)
127 {
128     iobase->PCSTS = (MEC_ESPI_IO_PCSTS_EC_BUS_ERR_Msk
129                      | MEC_ESPI_IO_PCSTS_PCEN_CHG_Msk
130                      | MEC_ESPI_IO_PCSTS_PCBMEN_CHG_Msk);
131 }
132 
mec_hal_espi_pc_error_addr(struct mec_espi_io_regs * iobase)133 uint64_t mec_hal_espi_pc_error_addr(struct mec_espi_io_regs *iobase)
134 {
135     union {
136         uint64_t lw;
137         uint32_t w[2];
138     } err_addr;
139 
140     err_addr.w[0] = iobase->PCERR[0];
141     err_addr.w[1] = iobase->PCERR[1];
142 
143     return err_addr.lw;
144 }
145 
mec_hal_espi_pc_last_cycle(struct mec_espi_io_regs * iobase,struct mec_espi_pc_last_cycle * lc)146 void mec_hal_espi_pc_last_cycle(struct mec_espi_io_regs *iobase,
147                                 struct mec_espi_pc_last_cycle *lc)
148 {
149     uint32_t temp;
150 
151     lc->host_pc_addr_lsw = iobase->PCLC[0];
152     lc->host_pc_addr_msw = iobase->PCLC[1];
153     temp = iobase->PCLC[2];
154     lc->len = (uint16_t)(temp & 0xfffu);
155     lc->cycle_type = (uint8_t)((temp >> 12) & 0xffu);
156     lc->tag = (uint8_t)((temp >> 20) & 0xfu);
157 }
158 
159 /* PC GIRQ */
mec_hal_espi_pc_girq_ctrl(uint8_t enable)160 void mec_hal_espi_pc_girq_ctrl(uint8_t enable)
161 {
162     mec_hal_girq_ctrl(MEC_ESPI_PC_ECIA_INFO, (int)enable);
163 }
164 
mec_hal_espi_pc_girq_status_clr(void)165 void mec_hal_espi_pc_girq_status_clr(void)
166 {
167     mec_hal_girq_clr_src(MEC_ESPI_PC_ECIA_INFO);
168 }
169 
mec_hal_espi_pc_girq_status(void)170 uint32_t mec_hal_espi_pc_girq_status(void)
171 {
172     return mec_hal_girq_src(MEC_ESPI_PC_ECIA_INFO);
173 }
174 
mec_hal_espi_pc_girq_result(void)175 uint32_t mec_hal_espi_pc_girq_result(void)
176 {
177     return mec_hal_girq_result(MEC_ESPI_PC_ECIA_INFO);
178 }
179 
180 /* Peripheral Channel LTR */
181 
mec_hal_espi_pc_ltr_status(struct mec_espi_io_regs * iobase)182 uint32_t mec_hal_espi_pc_ltr_status(struct mec_espi_io_regs *iobase)
183 {
184     return iobase->PCLTRSTS;
185 }
186 
mec_hal_espi_pc_ltr_intr_en(struct mec_espi_io_regs * iobase,uint32_t enmask)187 void mec_hal_espi_pc_ltr_intr_en(struct mec_espi_io_regs *iobase, uint32_t enmask)
188 {
189     iobase->PCLTREN = enmask;
190 }
191 
mec_hal_espi_pc_ltr_ctrl(struct mec_espi_io_regs * iobase,uint8_t tag,uint8_t start)192 void mec_hal_espi_pc_ltr_ctrl(struct mec_espi_io_regs *iobase, uint8_t tag, uint8_t start)
193 {
194     uint32_t ctrl = iobase->PCLTRCTL & (uint32_t)~(MEC_ESPI_IO_PCLTRCTL_LTR_TX_TAG_Msk);
195 
196     ctrl |= (((uint32_t)tag << MEC_ESPI_IO_PCLTRCTL_LTR_TX_TAG_Pos)
197              & MEC_ESPI_IO_PCLTRCTL_LTR_TX_TAG_Msk);
198 
199     iobase->PCLTRCTL = ctrl;
200 
201     if (start) {
202         iobase->PCLTRCTL |= MEC_BIT(MEC_ESPI_IO_PCLTRCTL_START_Pos);
203     }
204 }
205 
mec_hal_espi_pc_ltr_msg(struct mec_espi_io_regs * iobase,uint16_t nunits,uint8_t time_unit,uint8_t rsvd_bits,uint8_t max_lat)206 void mec_hal_espi_pc_ltr_msg(struct mec_espi_io_regs *iobase, uint16_t nunits, uint8_t time_unit,
207                             uint8_t rsvd_bits, uint8_t max_lat)
208 {
209     uint32_t msg = (((uint32_t)nunits << MEC_ESPI_IO_PCLTRM_VALUE_Pos)
210                     & MEC_ESPI_IO_PCLTRM_VALUE_Msk);
211 
212     msg |= (((uint32_t)time_unit << MEC_ESPI_IO_PCLTRM_SCALE_Pos) & MEC_ESPI_IO_PCLTRM_SCALE_Msk);
213     msg |= (((uint32_t)rsvd_bits << MEC_ESPI_IO_PCLTRM_TX_RSVD_BITS_Pos)
214             & MEC_ESPI_IO_PCLTRM_TX_RSVD_BITS_Msk);
215     if (max_lat) {
216         msg |= MEC_BIT(MEC_ESPI_IO_PCLTRM_SEL_MAX_LAT_Pos);
217     }
218 
219     iobase->PCLTRM = (iobase->PCLTRM & ~(0xffffu)) | msg;
220 }
221 
mec_hal_espi_pc_ltr_girq_ctrl(uint8_t enable)222 void mec_hal_espi_pc_ltr_girq_ctrl(uint8_t enable)
223 {
224     mec_hal_girq_ctrl(MEC_ESPI_LTR_ECIA_INFO, (int)enable);
225 }
226 
mec_hal_espi_pc_ltr_girq_status_clr(void)227 void mec_hal_espi_pc_ltr_girq_status_clr(void)
228 {
229     mec_hal_girq_clr_src(MEC_ESPI_LTR_ECIA_INFO);
230 }
231 
mec_hal_espi_pc_ltr_girq_status(void)232 uint32_t mec_hal_espi_pc_ltr_girq_status(void)
233 {
234     return mec_hal_girq_src(MEC_ESPI_LTR_ECIA_INFO);
235 }
236 
mec_hal_espi_pc_ltr_girq_result(void)237 uint32_t mec_hal_espi_pc_ltr_girq_result(void)
238 {
239     return mec_hal_girq_result(MEC_ESPI_LTR_ECIA_INFO);
240 }
241 
242 /* end mec_espi_pc.c */
243