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 Flash Channel ----
17  * eSPI target controller in the EC can access the flash device(s) attached
18  * to the Host eSPI controller.
19  */
20 #define MEC_ESPI_FC_ECIA_INFO MEC5_ECIA_INFO(19, 6, 11, 109)
21 
22 /* Flash erase request size must be non-zero.
23  * Actual erase size is chosen by eSPI Host.
24  * Specification recommands a value of 1.
25  */
26 #define MEC_ESPI_FC_ERASE_SIZE 1u
27 
28 /* Flash channel status errors */
29 #define MEC_ESPI_FC_ERR_ALL \
30     (MEC_BIT(MEC_ESPI_IO_FCSTS_BAD_REQ_Pos) | MEC_BIT(MEC_ESPI_IO_FCSTS_START_OVRFL_Pos) \
31      | MEC_BIT(MEC_ESPI_IO_FCSTS_FAIL_Pos) | MEC_BIT(MEC_ESPI_IO_FCSTS_DATA_INCOMPL_Pos) \
32      | MEC_BIT(MEC_ESPI_IO_FCSTS_DATA_OVRUN_Pos) | MEC_BIT(MEC_ESPI_IO_FCSTS_ABORT_FW_Pos) \
33      | MEC_BIT(MEC_ESPI_IO_FCSTS_EC_BUS_ERR_Pos) | MEC_BIT(MEC_ESPI_IO_FCSTS_DIS_BY_HOST_Pos))
34 
35 /* ---- Public API ---- */
36 
mec_hal_espi_fc_girq_ctrl(uint8_t enable)37 void mec_hal_espi_fc_girq_ctrl(uint8_t enable)
38 {
39     mec_hal_girq_ctrl(MEC_ESPI_FC_ECIA_INFO, (int)enable);
40 }
41 
mec_hal_espi_fc_girq_status_clr(void)42 void mec_hal_espi_fc_girq_status_clr(void)
43 {
44     mec_hal_girq_clr_src(MEC_ESPI_FC_ECIA_INFO);
45 }
46 
mec_hal_espi_fc_girq_status(void)47 uint32_t mec_hal_espi_fc_girq_status(void)
48 {
49     return mec_hal_girq_src(MEC_ESPI_FC_ECIA_INFO);
50 }
51 
mec_hal_espi_fc_girq_result(void)52 uint32_t mec_hal_espi_fc_girq_result(void)
53 {
54     return mec_hal_girq_result(MEC_ESPI_FC_ECIA_INFO);
55 }
56 
57 /* Flash channel HW bits for channel enable state and enable change match API definition:
58  * bit[0] = enable state
59  * bit[1] = enable state changed
60  */
mec_hal_espi_fc_en_status(struct mec_espi_io_regs * iobase)61 uint32_t mec_hal_espi_fc_en_status(struct mec_espi_io_regs *iobase)
62 {
63     return (iobase->FCSTS & 0x3u);
64 }
65 
mec_hal_espi_fc_ready_set(struct mec_espi_io_regs * iobase)66 void mec_hal_espi_fc_ready_set(struct mec_espi_io_regs *iobase)
67 {
68     iobase->FCRDY = MEC_BIT(MEC_ESPI_IO_FCRDY_FC_READY_Pos);
69 }
70 
mec_hal_espi_fc_is_ready(struct mec_espi_io_regs * iobase)71 int mec_hal_espi_fc_is_ready(struct mec_espi_io_regs *iobase)
72 {
73     if (iobase->FCRDY & MEC_BIT(MEC_ESPI_IO_FCRDY_FC_READY_Pos)) {
74         return 1;
75     }
76 
77     return 0;
78 }
79 
mec_hal_espi_fc_is_busy(struct mec_espi_io_regs * iobase)80 int mec_hal_espi_fc_is_busy(struct mec_espi_io_regs *iobase)
81 {
82     if (iobase->FCCFG & MEC_BIT(MEC_ESPI_IO_FCCFG_BUSY_Pos)) {
83         return 1;
84     }
85 
86     return 0;
87 }
88 
89 /* Start previoulsy configured Flash channel operation.
90  * 1. Clear R/W1C status except for Flash channel enable change as this
91  *    is asynchronous and must be handled separately. Preferably by
92  *    by an ISR.
93  * 2. Enable or disable FC transfer done interrupt per passed flag
94  * 3. Start transaction.
95  */
mec_hal_espi_fc_op_start(struct mec_espi_io_regs * iobase,uint32_t flags)96 void mec_hal_espi_fc_op_start(struct mec_espi_io_regs *iobase, uint32_t flags)
97 {
98     iobase->FCSTS = MEC_ESPI_FC_ERR_ALL | MEC_BIT(MEC_ESPI_IO_FCSTS_DONE_Pos);
99 
100     if (flags & MEC_BIT(MEC_ESPI_FC_XFR_FLAG_START_IEN_POS)) {
101         iobase->FCIEN |= MEC_BIT(MEC_ESPI_IO_FCIEN_DONE_Pos);
102     } else {
103         iobase->FCIEN &= (uint32_t)~MEC_BIT(MEC_ESPI_IO_FCIEN_DONE_Pos);
104     }
105 
106     iobase->FCCTL |= MEC_BIT(MEC_ESPI_IO_FCCTL_START_Pos);
107 }
108 
mec_hal_espi_fc_op_abort(struct mec_espi_io_regs * iobase)109 void mec_hal_espi_fc_op_abort(struct mec_espi_io_regs *iobase)
110 {
111     iobase->FCCTL |= MEC_BIT(MEC_ESPI_IO_FCCTL_ABORT_Pos);
112 }
113 
mec_hal_espi_fc_intr_ctrl(struct mec_espi_io_regs * iobase,uint32_t msk,uint8_t en)114 void mec_hal_espi_fc_intr_ctrl(struct mec_espi_io_regs *iobase, uint32_t msk, uint8_t en)
115 {
116     uint32_t r = 0;
117 
118     if (!iobase) {
119         return;
120     }
121 
122     if (msk & MEC_BIT(MEC_ESPI_FC_INTR_DONE_POS)) {
123         r |= MEC_BIT(MEC_ESPI_IO_FCIEN_DONE_Pos);
124     }
125     if (msk & MEC_BIT(MEC_ESPI_FC_INTR_CHEN_CHG_POS)) {
126         r |= MEC_BIT(MEC_ESPI_IO_FCIEN_CHEN_CHG_Pos);
127     }
128 
129     if (en) {
130         iobase->FCIEN |= r;
131     } else {
132         iobase->FCIEN &= ~r;
133     }
134 }
135 
mec_hal_espi_fc_status(struct mec_espi_io_regs * iobase)136 uint32_t mec_hal_espi_fc_status(struct mec_espi_io_regs *iobase)
137 {
138     if (!iobase) {
139         return 0;
140     }
141 
142     return iobase->FCSTS;
143 }
144 
mec_hal_espi_fc_status_clr(struct mec_espi_io_regs * iobase,uint32_t msk)145 void mec_hal_espi_fc_status_clr(struct mec_espi_io_regs *iobase, uint32_t msk)
146 {
147     if (!iobase) {
148         return;
149     }
150 
151     iobase->FCSTS = msk;
152     mec_hal_girq_clr_src(MEC_ESPI_FC_ECIA_INFO);
153 }
154 
mec_hal_espi_fc_is_error(uint32_t fc_status)155 int mec_hal_espi_fc_is_error(uint32_t fc_status)
156 {
157     if (fc_status & (MEC_ESPI_FC_ERR_ALL)) {
158         return 1;
159     }
160 
161     return 0;
162 }
163 
164 /* Return flash channel maximum read size selected by eSPI Host */
mec_hal_espi_fc_max_read_req_sz(struct mec_espi_io_regs * iobase)165 uint32_t mec_hal_espi_fc_max_read_req_sz(struct mec_espi_io_regs *iobase)
166 {
167     uint32_t exp = 0;
168 
169     exp = ((iobase->FCCFG & MEC_ESPI_IO_FCCFG_MAX_RD_REQ_SZ_Msk) >>
170             MEC_ESPI_IO_FCCFG_MAX_RD_REQ_SZ_Pos);
171     if (exp == 0u) {
172         return 0u;
173     }
174 
175     exp += 5u;
176 
177     return (1u << exp);
178 }
179 
180 /* Return flash channel maximum payload size selected by eSPI Host */
mec_hal_espi_fc_max_pld_sz(struct mec_espi_io_regs * iobase)181 uint32_t mec_hal_espi_fc_max_pld_sz(struct mec_espi_io_regs *iobase)
182 {
183     uint32_t exp = 0;
184 
185     exp = (iobase->FCCFG & MEC_ESPI_IO_FCCFG_MAX_PLD_SZ_Msk) >> MEC_ESPI_IO_FCCFG_MAX_PLD_SZ_Pos;
186     if ((exp == 0u) || (exp > 3u)) { /* reserved values */
187         return 0u;
188     }
189 
190     exp += 5u;
191 
192     return (1u << exp);
193 }
194 
195 /* Return the two allowed erase block sizes in b[15:0] and b[31:16] in units
196  * of KB. If only one erase size allowed both fields will be identical.
197  * A return value of 0 indicates the flash channel has not been properly
198  * configured during eSPI link negoitation.
199  */
mec_hal_espi_fc_get_erase_sz(struct mec_espi_io_regs * iobase)200 uint32_t mec_hal_espi_fc_get_erase_sz(struct mec_espi_io_regs *iobase)
201 {
202     uint16_t erb1, erb2;
203     uint8_t ersz_encoding;
204 
205     if (!iobase) {
206         return 0;
207     }
208 
209     ersz_encoding =
210         (uint8_t)((iobase->FCCFG & MEC_ESPI_IO_FCCFG_EBSZ_Msk) >> MEC_ESPI_IO_FCCFG_EBSZ_Pos);
211     switch (ersz_encoding) {
212     case MEC_ESPI_IO_FCCFG_EBSZ_4KB:
213         erb1 = 4u;
214         erb2 = erb1;
215         break;
216     case MEC_ESPI_IO_FCCFG_EBSZ_64KB:
217         erb1 = 64u;
218         erb2 = erb1;
219         break;
220     case MEC_ESPI_IO_FCCFG_EBSZ_4KB_OR_64KB:
221         erb1 = 4u;
222         erb2 = 64u;
223         break;
224     case MEC_ESPI_IO_FCCFG_EBSZ_128KB:
225         erb1 = 128u;
226         erb2 = erb1;
227         break;
228     case MEC_ESPI_IO_FCCFG_EBSZ_256KB:
229         erb1 = 256u;
230         erb2 = erb1;
231         break;
232     default:
233         erb1 = 0;
234         erb2 = 0;
235         break;
236     }
237 
238     return (uint32_t)erb1 + ((uint32_t)erb2 << 16);
239 }
240 
mec_hal_espi_fc_check_erase_sz(struct mec_espi_io_regs * iobase,uint32_t ersz_bytes)241 int mec_hal_espi_fc_check_erase_sz(struct mec_espi_io_regs *iobase, uint32_t ersz_bytes)
242 {
243     uint32_t ersz = mec_hal_espi_fc_get_erase_sz(iobase);
244     uint32_t er1 = (ersz & 0xffffu) * 1024u;
245     uint32_t er2 = ((ersz >> 16) & 0xffffu) * 1024u;
246 
247     if ((ersz_bytes == er1) || (ersz_bytes == er2)) {
248         return MEC_RET_OK;
249     }
250 
251     return MEC_RET_ERR_DATA_LEN;
252 }
253 
254 /* Start transmit of a flash request to the eSPI Host Controller.
255  * Operations are: read, erase, or write. The caller can select
256  * from two erase operations: Ask Host to erase smaller or larger
257  * of two address ranges if the Host has a choice. This is based
258  * upon flash devices connected to Host chipset and its policies.
259  * The specs recommend using a value of 1 for erase size in the
260  * request packet sent to the Host.
261  * Read and write operations data lengths must be non-zero. The
262  * FC hardware will break up requests into chunks of maximum payload
263  * size. FC hardware will signal done or error when the last request
264  * is done or there was an error on any packet in the transaction.
265  */
mec_hal_espi_fc_xfr_start(struct mec_espi_io_regs * iobase,struct mec_espi_fc_xfr * pxfr,uint32_t flags)266 int mec_hal_espi_fc_xfr_start(struct mec_espi_io_regs *iobase,
267                               struct mec_espi_fc_xfr *pxfr,
268                               uint32_t flags)
269 {
270     uint32_t xfr_len, fc_op;
271 
272     if (!iobase || !pxfr || !pxfr->byte_len || !pxfr->buf_addr
273         || (pxfr->operation >= MEC_ESPI_FC_OP_MAX)) {
274         return MEC_RET_ERR_INVAL;
275     }
276 
277     if (!MEC_IS_PTR_ALIGNED32(pxfr->buf_addr)) {
278         return MEC_RET_ERR_DATA_ALIGN;
279     }
280 
281     if (mec_hal_espi_fc_is_ready(iobase)) {
282         return MEC_RET_ERR_HW_NOT_INIT;
283     }
284 
285     if (mec_hal_espi_fc_is_busy(iobase)) {
286         return MEC_RET_ERR_BUSY;
287     }
288 
289     switch (pxfr->operation) {
290     case MEC_ESPI_FC_OP_ERASE_L:
291         fc_op = MEC_ESPI_IO_FCCTL_OP_ERASE_LARGER;
292         xfr_len = MEC_ESPI_FC_ERASE_SIZE;
293         break;
294     case MEC_ESPI_FC_OP_ERASE_S:
295         fc_op = MEC_ESPI_IO_FCCTL_OP_ERASE_SMALLER;
296         xfr_len = MEC_ESPI_FC_ERASE_SIZE;
297         break;
298     case MEC_ESPI_FC_OP_WRITE:
299         fc_op = MEC_ESPI_IO_FCCTL_OP_WRITE;
300         xfr_len = pxfr->byte_len;
301         break;
302     default:
303         fc_op = MEC_ESPI_IO_FCCTL_OP_READ;
304         xfr_len = pxfr->byte_len;
305         break;
306     }
307 
308     iobase->FCIEN &= (uint32_t)~MEC_BIT(MEC_ESPI_IO_FCIEN_DONE_Pos);
309     iobase->FCSTS = MEC_ESPI_FC_ERR_ALL | MEC_BIT(MEC_ESPI_IO_FCSTS_DONE_Pos);
310     iobase->FCFA = pxfr->flash_addr;
311     iobase->FCBA = pxfr->buf_addr;
312     iobase->FCLEN = xfr_len;
313     if (flags & MEC_BIT(MEC_ESPI_FC_XFR_FLAG_START_IEN_POS)) {
314         iobase->FCIEN |= MEC_BIT(MEC_ESPI_IO_FCIEN_DONE_Pos);
315     }
316 
317     iobase->FCCTL = ((((uint32_t)pxfr->tag << MEC_ESPI_IO_FCCTL_TAG_Pos)
318                       & MEC_ESPI_IO_FCCTL_TAG_Msk)
319                      | ((fc_op << MEC_ESPI_IO_FCCTL_OP_Pos) & MEC_ESPI_IO_FCCTL_OP_Msk)
320                      | MEC_BIT(MEC_ESPI_IO_FCCTL_START_Pos));
321 
322     return MEC_RET_OK;
323 }
324 
325 /* end mec_espi_fc.c */
326