1 /*
2 * Copyright 2024 Microchip Technology Inc. and its subsidiaries.
3 *
4 * SPDX-License-Identifier: Apache-2.0
5 */
6 #include <stdbool.h>
7 #include <stddef.h>
8 #include <stdint.h>
9
10 #include <device_mec5.h>
11 #include "mec_pcfg.h"
12 #include "mec_defs.h"
13 #include "mec_ecia_api.h"
14 #include "mec_pcr_api.h"
15 #include "mec_qspi_api.h"
16 #include "mec_retval.h"
17
18 #define MEC_QSPI_GIRQ 18
19 #define MEC_QSPI0_GIRQ_POS 1
20 #define MEC_QSPI0_AGGR_NVIC 10
21 #define MEC_QSPI0_NVIC 91
22
23 #define MEC_QSPI0_ECIA_INFO \
24 MEC5_ECIA_INFO(MEC_QSPI_GIRQ, MEC_QSPI0_GIRQ_POS, MEC_QSPI0_AGGR_NVIC, MEC_QSPI0_NVIC)
25
26 #define MEC_QSPI_M_FDIV_MAX 0x10000
27 #define MEC_QSPI_SOFT_RESET_WAIT_LOOPS 16
28 #define MEC_QSPI_CLR_FIFOS_WAIT_LOOPS 16
29 #define MEC_QSPI_FORCE_STOP_WAIT_LOOPS 1000
30 #define MEC_QSPI_DESCR_NU_MAX 0x7fffu
31
32 #define MEC_QSPI_STATUS_ERRORS (MEC_BIT(MEC_QSPI_STATUS_TXBERR_Pos) \
33 | MEC_BIT(MEC_QSPI_STATUS_RXBERR_Pos) \
34 | MEC_BIT(MEC_QSPI_STATUS_PROGERR_Pos) \
35 | MEC_BIT(MEC_QSPI_STATUS_LDRXERR_Pos) \
36 | MEC_BIT(MEC_QSPI_STATUS_LDTXERR_Pos))
37
38 #define MEC_QSPI_SIG_MODE_POS MEC_QSPI_MODE_CPOL_Pos
39 #define MEC_QSPI_SIG_MODE_MSK \
40 (MEC_QSPI_MODE_CPOL_Msk | MEC_QSPI_MODE_CPHA_MOSI_Msk | MEC_QSPI_MODE_CPHA_MISO_Msk)
41
42 #define MEC5_QSPI_START_DESCR_MSK0 ((uint32_t)MEC_QSPI_CTRL_DPTR_Msk >> MEC_QSPI_CTRL_DPTR_Pos)
43 #define MEC5_QSPI_NEXT_DESCR_MSK0 ((uint32_t)MEC_QSPI_DESCR_NEXT_Msk >> MEC_QSPI_DESCR_NEXT_Pos)
44
45 /* QSPI SPI frequencies less than or equal to this value use
46 * normal CPHA and CPOL settings. For frequencies above this
47 * value we must transmit and sample on the same edge.
48 */
49 #define MEC_QSPI_SIGNAL_NORM_FREQ 24000000u
50
51 struct mec_qspi_info {
52 uintptr_t base_addr;
53 uint32_t devi;
54 uint16_t pcr_id;
55 };
56
57 const struct mec_qspi_info qspi_instances[MEC5_QSPI_INSTANCES] = {
58 {MEC_QSPI0_BASE, MEC_QSPI0_ECIA_INFO, MEC_PCR_QSPI0},
59 };
60
qspi_get_info(struct mec_qspi_regs * base)61 static struct mec_qspi_info const *qspi_get_info(struct mec_qspi_regs *base)
62 {
63 for (size_t n = 0u; n < MEC5_QSPI_INSTANCES; n++) {
64 const struct mec_qspi_info *p = &qspi_instances[n];
65
66 if (p->base_addr == (uintptr_t)base) {
67 return p;
68 }
69 }
70
71 return NULL;
72 }
73
74 /* Return the QSPI controller clock source frequency in Hz. */
qspi_max_spi_clock(void)75 static uint32_t qspi_max_spi_clock(void)
76 {
77 /* QMSPI uses the same PLL output clock as the CPU domain */
78 return mec_hal_pcr_cpu_max_freq();
79 }
80
qspi_get_freq(struct mec_qspi_regs * base)81 static uint32_t qspi_get_freq(struct mec_qspi_regs *base)
82 {
83 uint32_t srcfreq = qspi_max_spi_clock();
84 uint32_t fdiv = (base->MODE & MEC_QSPI_MODE_CLKDIV_Msk) >> MEC_QSPI_MODE_CLKDIV_Pos;
85
86 if (fdiv == 0u) { /* zero is maximum clock divider */
87 fdiv = MEC_QSPI_M_FDIV_MAX;
88 }
89
90 return (srcfreq / fdiv);
91 }
92
mec_hal_qspi_get_freq(struct mec_qspi_regs * base)93 uint32_t mec_hal_qspi_get_freq(struct mec_qspi_regs *base)
94 {
95 if (!base) {
96 return MEC_RET_ERR_INVAL;
97 }
98
99 return qspi_get_freq(base);
100 }
101
mec_hal_qspi_freq_div(struct mec_qspi_regs * base)102 uint32_t mec_hal_qspi_freq_div(struct mec_qspi_regs *base)
103 {
104 uint32_t fdiv = 0;
105
106 if ((uintptr_t)base == (uintptr_t)(MEC_QSPI0_BASE)) {
107 fdiv = (base->MODE & MEC_QSPI_MODE_CLKDIV_Msk) >> MEC_QSPI_MODE_CLKDIV_Pos;
108 }
109
110 if (fdiv == 0) {
111 fdiv = 0x10000u;
112 }
113
114 return fdiv;
115 }
116
117 /* Return the raw 16-bit clock divider field from QSPI Mode register.
118 * 0 = divide by maximum (0x10000)
119 * 1 - 0xffff is divide by this value
120 */
mec_hal_qspi_freq_div_raw(struct mec_qspi_regs * base)121 uint16_t mec_hal_qspi_freq_div_raw(struct mec_qspi_regs *base)
122 {
123 if ((uintptr_t)base != (uintptr_t)(MEC_QSPI0_BASE)) {
124 return 0;
125 }
126
127 return (uint16_t)((base->MODE & MEC_QSPI_MODE_CLKDIV_Msk) >> MEC_QSPI_MODE_CLKDIV_Pos);
128 }
129
mec_hal_qspi_is_enabled(struct mec_qspi_regs * regs)130 bool mec_hal_qspi_is_enabled(struct mec_qspi_regs *regs)
131 {
132 if ((uintptr_t)regs != (uintptr_t)MEC_QSPI0_BASE) {
133 return false;
134 }
135
136 return (regs->MODE & MEC_BIT(MEC_QSPI_MODE_ACTV_Pos)) ? true : false;
137 }
138
139 /* Compute an estimate of time in nanoseconds to clock in/out one byte.
140 * Maximum: F = 96 MHz, T = 10.42 ns
141 * Single: 83.3 ns
142 * Dual = 41.7 ns
143 * Quad = 20.8 ns
144 * Minimum: F = 48 MHz / 65536 = 732.4 Hz, T = 1.365 ms
145 * Single: 10922667 (0x00a6_aaab) ns
146 * Dual: 5461333 ns
147 * Quad = 2730666 ns
148 *
149 * Maximum clock divider Fin = 96MHz
150 * Tsingle = 1e9 * ((65536 / 96,000,000) * 8) = 5461333.33333 ns
151 * Tdual = 1e9 * ((65536 / 96,000,000) * 4) = 2730666.66666 ns
152 * Tquad = 1e9 * ((65536 / 96,000,000) * 2) = 1365333.33333 ns
153 *
154 * Fin = 48MHz
155 * Tsingle = 1e9 * ((65536 / 48,000,000) * 8) = 10922666.66666
156 *
157 */
qspi_byte_time_ns(struct mec_qspi_regs * base)158 static uint32_t qspi_byte_time_ns(struct mec_qspi_regs *base)
159 {
160 uint32_t clkdiv = (base->MODE & MEC_QSPI_MODE_CLKDIV_Msk) >> MEC_QSPI_MODE_CLKDIV_Pos;
161 uint32_t iom = (base->CTRL & MEC_QSPI_CTRL_IFM_Msk) >> MEC_QSPI_CTRL_IFM_Pos;
162 uint32_t byte_time_ns = 10922667u; /* 8-bits full duplex 48MHz clock source, max clock divider */
163
164 if (mec_hal_pcr_is_turbo_clock()) { /* 96MHz clock source? */
165 byte_time_ns = 5461333u; /* max clock divider */
166 }
167
168 /* adjust for IO mode */
169 if (iom == MEC_QSPI_CTRL_IFM_QUAD) {
170 byte_time_ns >>= 2u;
171 } else if (iom == MEC_QSPI_CTRL_IFM_DUAL) {
172 byte_time_ns >>= 1u;
173 }
174
175 /* HW clkdiv == 0 special value is maximum divider = 65536 */
176 if (!clkdiv) {
177 clkdiv = 65536u;
178 }
179
180 /* adjust for clock divider */
181 byte_time_ns = byte_time_ns / (65536u / clkdiv);
182
183 return byte_time_ns;
184 }
185
mec_hal_qspi_byte_time_ns(struct mec_qspi_regs * base,uint32_t * btime_ns)186 int mec_hal_qspi_byte_time_ns(struct mec_qspi_regs *base, uint32_t *btime_ns)
187 {
188 if ((!base) || (!btime_ns)) {
189 return MEC_RET_ERR_INVAL;
190 }
191
192 *btime_ns = qspi_byte_time_ns(base);
193
194 return MEC_RET_OK;
195 }
196
197 /* Computer QSPI frequency divider given desired SPI clock in Hz.
198 * Hardware fdiv = 1 to pow(2, fdiv_field_bit_length) - 1 is Source_Freq / n
199 * Hardware fdiv = 0 is Source_Freq / pow(2, fdiv_field_bit_length)
200 * fdiv_field_bit_length = 8 for MEC152x and 16 for MEC172x
201 * NOTE: Truncation from integer division may result in an actual frequency
202 * lower than requested.
203 */
compute_freq_divisor(uint32_t freq_hz)204 static uint32_t compute_freq_divisor(uint32_t freq_hz)
205 {
206 uint32_t src_freq = qspi_max_spi_clock();
207 uint32_t fdiv;
208
209 if (freq_hz < (src_freq / MEC_QSPI_M_FDIV_MAX)) {
210 fdiv = 0u; /* HW divider of 0 is divide by MEC_QSPI_M_FDIV_MAX */
211 } else if (freq_hz > src_freq) {
212 fdiv = 1u;
213 } else {
214 fdiv = src_freq / freq_hz;
215 }
216
217 return fdiv;
218 }
219
qspi_set_freq(struct mec_qspi_regs * base,uint32_t freqhz)220 static void qspi_set_freq(struct mec_qspi_regs *base, uint32_t freqhz)
221 {
222 uint32_t fdiv = compute_freq_divisor(freqhz);
223
224 base->MODE = ((base->MODE & (uint32_t)~MEC_QSPI_MODE_CLKDIV_Msk)
225 | (fdiv << MEC_QSPI_MODE_CLKDIV_Pos));
226 }
227
mec_hal_qspi_set_freq(struct mec_qspi_regs * base,uint32_t freqhz)228 int mec_hal_qspi_set_freq(struct mec_qspi_regs *base, uint32_t freqhz)
229 {
230 if (!base) {
231 return MEC_RET_ERR_INVAL;
232 }
233
234 qspi_set_freq(base, freqhz);
235
236 return MEC_RET_OK;
237 }
238
qspi_intr_clr_dis(struct mec_qspi_regs * base)239 static void qspi_intr_clr_dis(struct mec_qspi_regs *base)
240 {
241 const struct mec_qspi_info *info = qspi_get_info(base);
242
243 if (!info) {
244 return;
245 }
246
247 base->INTR_CTRL = 0;
248 base->STATUS = UINT32_MAX;
249 mec_hal_girq_ctrl(info->devi, 0);
250 mec_hal_girq_clr_src(info->devi);
251 }
252
qspi_reset(struct mec_qspi_regs * base)253 static void qspi_reset(struct mec_qspi_regs *base)
254 {
255 /* Self clearing soft reset bit (write-only) */
256 base->MODE |= MEC_BIT(MEC_QSPI_MODE_SRST_Pos);
257
258 qspi_intr_clr_dis(base);
259 }
260
261 /* Clear GIRQ source status. Current SoC's have one QSPI instance */
mec_hal_qspi_girq_clr(struct mec_qspi_regs * base)262 void mec_hal_qspi_girq_clr(struct mec_qspi_regs *base)
263 {
264 mec_hal_girq_clr_src(MEC_QSPI0_ECIA_INFO);
265 }
266
mec_hal_qspi_girq_ctrl(struct mec_qspi_regs * base,uint8_t enable)267 void mec_hal_qspi_girq_ctrl(struct mec_qspi_regs *base, uint8_t enable)
268 {
269 mec_hal_girq_ctrl(MEC_QSPI0_ECIA_INFO, enable);
270 }
271
272 /* Returns non-zero if QSPI0 GIRQ result bit is set else 0 */
mec_hal_qspi_girq_is_result(struct mec_qspi_regs * base)273 uint32_t mec_hal_qspi_girq_is_result(struct mec_qspi_regs *base)
274 {
275 return mec_hal_girq_result(MEC_QSPI0_ECIA_INFO);
276 }
277
mec_hal_qspi_reset(struct mec_qspi_regs * base)278 int mec_hal_qspi_reset(struct mec_qspi_regs *base)
279 {
280 if (!base) {
281 return MEC_RET_ERR_INVAL;
282 }
283
284 qspi_reset(base);
285
286 return MEC_RET_OK;
287 }
288
mec_hal_qspi_reset_sr(struct mec_qspi_regs * base)289 int mec_hal_qspi_reset_sr(struct mec_qspi_regs *base)
290 {
291 uint32_t saved[5];
292
293 if (!base) {
294 return MEC_RET_ERR_INVAL;
295 }
296
297 mec_hal_girq_ctrl(MEC_QSPI0_ECIA_INFO, 0);
298
299 saved[0] = base->MODE & (MEC_QSPI_MODE_CPOL_Msk | MEC_QSPI_MODE_CPHA_MOSI_Msk
300 | MEC_QSPI_MODE_CPHA_MISO_Msk | MEC_QSPI_MODE_CLKDIV_Msk);
301 saved[1] = base->CSTM;
302 saved[2] = base->TAPSS;
303 saved[3] = base->TAPSA;
304 saved[4] = base->TAPSC;
305
306 qspi_reset(base);
307 mec_hal_girq_clr_src(MEC_QSPI0_ECIA_INFO);
308
309 base->MODE = saved[0];
310 base->CSTM = saved[1];
311 base->TAPSS = saved[2];
312 base->TAPSA = saved[3];
313 base->TAPSC = saved[4];
314
315 return MEC_RET_OK;
316 }
317
318 /* Set frequency for chip select 1.
319 * param regs = QSPI instance register base address
320 * param freq = frequency use for CS1. Zero indicates use same as CS0.
321 */
qspi_cs1_freq(struct mec_qspi_regs * base,uint32_t freq)322 static void qspi_cs1_freq(struct mec_qspi_regs *base, uint32_t freq)
323 {
324 uint32_t fdiv;
325
326 if (freq) {
327 fdiv = compute_freq_divisor(freq);
328 base->ALT1_MODE = (fdiv << MEC_QSPI_MODE_CLKDIV_Pos) & MEC_QSPI_MODE_CLKDIV_Msk;
329 base->ALT1_MODE |= MEC_BIT(MEC_QSPI_ALT1_MODE_CS1_ALTEN_Pos);
330 } else {
331 base->ALT1_MODE = 0u;
332 }
333 }
334
mec_hal_qspi_cs1_freq(struct mec_qspi_regs * base,uint32_t freq)335 int mec_hal_qspi_cs1_freq(struct mec_qspi_regs *base, uint32_t freq)
336 {
337 if (!base) {
338 return MEC_RET_ERR_INVAL;
339 }
340
341 qspi_cs1_freq(base, freq);
342
343 return MEC_RET_OK;
344 }
345
qspi_compute_byte_time_ns(struct mec_qspi_regs * base)346 static uint32_t qspi_compute_byte_time_ns(struct mec_qspi_regs *base)
347 {
348 uint32_t freq = qspi_max_spi_clock();
349 uint32_t fdiv = (base->MODE & MEC_QSPI_MODE_CLKDIV_Msk) >> MEC_QSPI_MODE_CLKDIV_Pos;
350 uint32_t btime_ns;
351
352 /* Not CS0 and alternate frequency divider enabled */
353 if ((base->MODE & MEC_QSPI_MODE_CS_Msk) &&
354 (base->ALT1_MODE & MEC_BIT(MEC_QSPI_ALT1_MODE_CS1_ALTEN_Pos))) {
355 fdiv = ((base->ALT1_MODE & MEC_QSPI_ALT1_MODE_CS1_ALT_CLKDIV_Msk)
356 >> MEC_QSPI_ALT1_MODE_CS1_ALT_CLKDIV_Pos);
357 }
358
359 if (!fdiv) { /* divider reg field = 0 is maximum divider */
360 fdiv = MEC_QSPI_M_FDIV_MAX;
361 }
362
363 freq /= fdiv;
364
365 /* Pad to two byte times */
366 btime_ns = (uint32_t)(16000000000ULL / freq);
367
368 return btime_ns;
369 }
370
qspi_cs_select(struct mec_qspi_regs * base,enum mec_qspi_cs cs)371 static void qspi_cs_select(struct mec_qspi_regs *base, enum mec_qspi_cs cs)
372 {
373 uint32_t mode = base->MODE & (uint32_t)~MEC_QSPI_MODE_CS_Msk;
374
375 mode |= (((uint32_t)cs << MEC_QSPI_MODE_CS_Pos) & MEC_QSPI_MODE_CS_Msk);
376 base->MODE = mode;
377 }
378
mec_hal_qspi_cs_select(struct mec_qspi_regs * base,enum mec_qspi_cs cs)379 int mec_hal_qspi_cs_select(struct mec_qspi_regs *base, enum mec_qspi_cs cs)
380 {
381 if (!base || (cs >= MEC_QSPI_CS_MAX)) {
382 return MEC_RET_ERR_INVAL;
383 }
384
385 qspi_cs_select(base, cs);
386
387 return MEC_RET_OK;
388 }
389
390 static const uint8_t qspi_smode[MEC_SPI_SIGNAL_MODE_MAX] = { 0x0, 0x6, 0x1, 0x7, };
391 static const uint8_t qspi_smode_hi[MEC_SPI_SIGNAL_MODE_MAX] = { 0x4, 0x2, 0x5, 0x3, };
392
qspi_spi_signal_mode(struct mec_qspi_regs * base,enum mec_qspi_signal_mode spi_mode)393 static void qspi_spi_signal_mode(struct mec_qspi_regs *base, enum mec_qspi_signal_mode spi_mode)
394 {
395 uint32_t freq = qspi_get_freq(base);
396 uint32_t hwsm = 0;
397
398 if (freq > MEC_QSPI_SIGNAL_NORM_FREQ) {
399 hwsm = (uint32_t)qspi_smode_hi[spi_mode];
400 } else {
401 hwsm = (uint32_t)qspi_smode[spi_mode];
402 }
403
404 base->MODE = (base->MODE & ~0x700u) | (hwsm << MEC_QSPI_MODE_CPOL_Pos);
405 }
406
407 /* Requires frequency programmed first */
mec_hal_qspi_spi_signal_mode(struct mec_qspi_regs * base,enum mec_qspi_signal_mode spi_mode)408 int mec_hal_qspi_spi_signal_mode(struct mec_qspi_regs *base, enum mec_qspi_signal_mode spi_mode)
409 {
410 if ((base == NULL) || (spi_mode >= MEC_SPI_SIGNAL_MODE_MAX)) {
411 return MEC_RET_ERR_INVAL;
412 }
413
414 qspi_spi_signal_mode(base, spi_mode);
415
416 return MEC_RET_OK;
417 }
418
mec_hal_qspi_sampling_phase_pol(struct mec_qspi_regs * base,uint8_t phpol)419 int mec_hal_qspi_sampling_phase_pol(struct mec_qspi_regs *base, uint8_t phpol)
420 {
421 if (!base) {
422 return MEC_RET_ERR_INVAL;
423 }
424
425 base->MODE = (base->MODE & ~0x700u) | ((uint32_t)(phpol & 0x7u) << 8);
426
427 return MEC_RET_OK;
428 }
429
qspi_ifm(enum mec_qspi_io iom)430 static uint32_t qspi_ifm(enum mec_qspi_io iom)
431 {
432 uint32_t ifm;
433
434 if (iom == MEC_QSPI_IO_QUAD) {
435 ifm = (uint32_t)MEC_QSPI_CTRL_IFM_QUAD;
436 } else if (iom == MEC_QSPI_IO_DUAL) {
437 ifm = (uint32_t)MEC_QSPI_CTRL_IFM_DUAL;
438 } else {
439 ifm = (uint32_t)MEC_QSPI_CTRL_IFM_FD;
440 }
441
442 return (ifm << MEC_QSPI_CTRL_IFM_Pos);
443 }
444
qspi_io(struct mec_qspi_regs * base,enum mec_qspi_io io)445 static void qspi_io(struct mec_qspi_regs *base, enum mec_qspi_io io)
446 {
447 base->CTRL = (base->CTRL & (uint32_t)~MEC_QSPI_CTRL_IFM_Msk) | qspi_ifm(io);
448 }
449
mec_hal_qspi_io(struct mec_qspi_regs * base,enum mec_qspi_io io)450 int mec_hal_qspi_io(struct mec_qspi_regs *base, enum mec_qspi_io io)
451 {
452 if (!base || (io >= MEC_QSPI_IO_MAX)) {
453 return MEC_RET_ERR_INVAL;
454 }
455
456 qspi_io(base, io);
457
458 return MEC_RET_OK;
459 }
460
461 struct qspi_cstm_info {
462 uint8_t pos;
463 uint8_t msk0;
464 };
465
466 const struct qspi_cstm_info cstm_tbl[MEC_QSPI_CSTM_MAX] = {
467 {0, 0xfu},
468 {8, 0xfu},
469 {16, 0xfu},
470 {24, 0xffu},
471 };
472
mec_hal_qspi_cs_timing_adjust(struct mec_qspi_regs * base,enum mec_qspi_cstm field,uint8_t val)473 int mec_hal_qspi_cs_timing_adjust(struct mec_qspi_regs *base, enum mec_qspi_cstm field,
474 uint8_t val)
475 {
476 if ((!base) || (field >= MEC_QSPI_CSTM_MAX)) {
477 return MEC_RET_ERR_INVAL;
478 }
479
480 uint32_t pos = cstm_tbl[field].pos;
481 uint32_t msk0 = cstm_tbl[field].msk0;
482
483 base->CSTM = (base->CSTM & ~(msk0 << pos)) | ((val & msk0) << pos);
484
485 return MEC_RET_OK;
486 }
487
mec_hal_qspi_cs_timing(struct mec_qspi_regs * base,uint32_t cs_timing)488 int mec_hal_qspi_cs_timing(struct mec_qspi_regs *base, uint32_t cs_timing)
489 {
490 if (!base) {
491 return MEC_RET_ERR_INVAL;
492 }
493
494 base->CSTM = cs_timing;
495
496 return MEC_RET_OK;
497 }
498
mec_hal_qspi_tap_select(struct mec_qspi_regs * base,uint8_t sel_sck_tap,uint8_t sel_ctrl_tap)499 int mec_hal_qspi_tap_select(struct mec_qspi_regs *base, uint8_t sel_sck_tap, uint8_t sel_ctrl_tap)
500 {
501 uint32_t tapss = sel_sck_tap | ((uint32_t)sel_ctrl_tap << 8);
502
503 if (!base) {
504 return MEC_RET_ERR_INVAL;
505 }
506
507 tapss = ((uint32_t)sel_sck_tap << MEC_QSPI_TAPSS_TSCK_Pos) & MEC_QSPI_TAPSS_TSCK_Msk;
508 tapss |= (((uint32_t)sel_ctrl_tap << MEC_QSPI_TAPSS_TCTRL_Pos) & MEC_QSPI_TAPSS_TCTRL_Msk);
509 base->TAPSS = (base->TAPSS & (uint32_t)~(MEC_QSPI_TAPSS_TSCK_Msk | MEC_QSPI_TAPSS_TSCK_Msk)) | tapss;
510
511 return MEC_RET_OK;
512 }
513
514 /* Initialize QMSPI controller using local DMA. */
mec_hal_qspi_init(struct mec_qspi_regs * base,uint32_t freq_hz,enum mec_qspi_signal_mode spi_signal_mode,enum mec_qspi_io iom,enum mec_qspi_cs chip_sel)515 int mec_hal_qspi_init(struct mec_qspi_regs *base,
516 uint32_t freq_hz,
517 enum mec_qspi_signal_mode spi_signal_mode,
518 enum mec_qspi_io iom,
519 enum mec_qspi_cs chip_sel)
520 {
521 const struct mec_qspi_info *info = qspi_get_info(base);
522
523 if (!info) {
524 return MEC_RET_ERR_INVAL;
525 }
526
527 mec_hal_pcr_clr_blk_slp_en(info->pcr_id); /* clocks gated ON */
528 mec_hal_qspi_reset_sr(base);
529 qspi_set_freq(base, freq_hz);
530 qspi_spi_signal_mode(base, spi_signal_mode);
531 qspi_io(base, iom);
532 qspi_cs_select(base, chip_sel);
533
534 base->MODE |= MEC_BIT(MEC_QSPI_MODE_ACTV_Pos);
535
536 /* Enable QSPI interrupt signal to propagate to NVIC */
537 mec_hal_girq_ctrl(info->devi, 1);
538
539 return MEC_RET_OK;
540 }
541
mec_hal_qspi_options(struct mec_qspi_regs * regs,uint8_t en,uint32_t options)542 int mec_hal_qspi_options(struct mec_qspi_regs *regs, uint8_t en, uint32_t options)
543 {
544 uint32_t val = 0, msk = 0;
545
546 if (!regs) {
547 return MEC_RET_ERR_INVAL;
548 }
549
550 if (options & MEC_BIT(MEC_QSPI_OPT_ACTV_EN_POS)) {
551 msk |= MEC_BIT(MEC_QSPI_MODE_ACTV_Pos);
552 if (en) {
553 val |= MEC_BIT(MEC_QSPI_MODE_ACTV_Pos);
554 }
555 }
556 if (options & MEC_BIT(MEC_QSPI_OPT_TAF_DMA_EN_POS)) {
557 msk |= MEC_BIT(MEC_QSPI_MODE_TAFDMA_Pos);
558 if (en) {
559 val |= MEC_BIT(MEC_QSPI_MODE_TAFDMA_Pos);
560 }
561 }
562 if (options & MEC_BIT(MEC_QSPI_OPT_RX_LDMA_EN_POS)) {
563 msk |= MEC_BIT(MEC_QSPI_MODE_RX_LDMA_Pos);
564 if (en) {
565 val |= MEC_BIT(MEC_QSPI_MODE_RX_LDMA_Pos);
566 }
567 }
568 if (options & MEC_BIT(MEC_QSPI_OPT_TX_LDMA_EN_POS)) {
569 msk |= MEC_BIT(MEC_QSPI_MODE_TX_LDMA_Pos);
570 if (en) {
571 val |= MEC_BIT(MEC_QSPI_MODE_TX_LDMA_Pos);
572 }
573 }
574
575 regs->MODE = (regs->MODE & ~msk) | (val & msk);
576
577 return MEC_RET_OK;
578 }
579
580 /* Force QSPI to stop an on-going transaction.
581 * If QSPI is generating clocks, it will stop at the next byte boundary
582 * and de-assert chip select.
583 */
mec_hal_qspi_force_stop(struct mec_qspi_regs * base)584 int mec_hal_qspi_force_stop(struct mec_qspi_regs *base)
585 {
586 uint32_t btime_ns;
587
588 if (!base) {
589 return MEC_RET_ERR_INVAL;
590 }
591
592 base->EXE = MEC_BIT(MEC_QSPI_EXE_STOP_Pos);
593
594 /* computation uses up some of the time */
595 btime_ns = qspi_compute_byte_time_ns(base);
596
597 /* Timeout period, doesn't have to be accurate.
598 * EC running at 96MHz (~10 ns) or slower.
599 */
600 while (base->STATUS & MEC_BIT(MEC_QSPI_STATUS_ACTIVE_Pos)) {
601 if (!btime_ns) {
602 return MEC_RET_ERR_TIMEOUT;
603 }
604 btime_ns--;
605 }
606
607 return MEC_RET_OK;
608 }
609
mec_hal_qspi_done(struct mec_qspi_regs * base)610 int mec_hal_qspi_done(struct mec_qspi_regs *base)
611 {
612 uint32_t qsts;
613
614 if (!base) {
615 return MEC_RET_ERR_INVAL;
616 }
617
618 qsts = base->STATUS;
619
620 if (qsts & MEC_QSPI_STATUS_ERRORS) {
621 return MEC_RET_ERR_HW;
622 }
623
624 if (qsts & MEC_BIT(MEC_QSPI_STATUS_DONE_Pos)) {
625 return MEC_RET_OK;
626 }
627
628 return MEC_RET_ERR_BUSY;
629 }
630
mec_hal_qspi_hw_status(struct mec_qspi_regs * base)631 uint32_t mec_hal_qspi_hw_status(struct mec_qspi_regs *base)
632 {
633 if (!base) {
634 return 0;
635 }
636
637 return base->STATUS;
638 }
639
mec_hal_qspi_hw_status_clr(struct mec_qspi_regs * base,uint32_t msk)640 int mec_hal_qspi_hw_status_clr(struct mec_qspi_regs *base, uint32_t msk)
641 {
642 if (!base) {
643 return MEC_RET_ERR_INVAL;
644 }
645
646 base->STATUS = msk;
647
648 return MEC_RET_OK;
649 }
650
qspi_intr_ctrl(struct mec_qspi_regs * base,int enable)651 static void qspi_intr_ctrl(struct mec_qspi_regs *base, int enable)
652 {
653 uint32_t qien = 0u;
654
655 if (enable) {
656 qien = (MEC_BIT(MEC_QSPI_INTR_CTRL_DONE_Pos)
657 | MEC_BIT(MEC_QSPI_INTR_CTRL_TXBERR_Pos)
658 | MEC_BIT(MEC_QSPI_INTR_CTRL_PROGERR_Pos)
659 | MEC_BIT(MEC_QSPI_INTR_CTRL_LDRXERR_Pos)
660 | MEC_BIT(MEC_QSPI_INTR_CTRL_LDTXERR_Pos));
661 }
662
663 base->INTR_CTRL = qien;
664 }
665
mec_hal_qspi_intr_ctrl(struct mec_qspi_regs * base,int enable)666 int mec_hal_qspi_intr_ctrl(struct mec_qspi_regs *base, int enable)
667 {
668 if (!base) {
669 return MEC_RET_ERR_INVAL;
670 }
671
672 qspi_intr_ctrl(base, enable);
673
674 return MEC_RET_OK;
675 }
676
mec_hal_qspi_intr_ctrl_msk(struct mec_qspi_regs * base,int enable,uint32_t msk)677 int mec_hal_qspi_intr_ctrl_msk(struct mec_qspi_regs *base, int enable, uint32_t msk)
678 {
679 if (!base) {
680 return MEC_RET_ERR_INVAL;
681 }
682
683 if (enable) {
684 base->INTR_CTRL |= msk;
685 } else {
686 base->INTR_CTRL &= (uint32_t)~msk;
687 }
688
689 return MEC_RET_OK;
690 }
691
mec_hal_qspi_tx_fifo_is_empty(struct mec_qspi_regs * base)692 int mec_hal_qspi_tx_fifo_is_empty(struct mec_qspi_regs *base)
693 {
694 if (base) {
695 if (base->STATUS & MEC_BIT(MEC_QSPI_STATUS_TXBE_Pos)) {
696 return 1;
697 }
698 }
699
700 return 0;
701 }
702
mec_hal_qspi_tx_fifo_is_full(struct mec_qspi_regs * base)703 int mec_hal_qspi_tx_fifo_is_full(struct mec_qspi_regs *base)
704 {
705 if (base) {
706 if (base->STATUS & MEC_BIT(MEC_QSPI_STATUS_TXBF_Pos)) {
707 return 1;
708 }
709 }
710
711 return 0;
712 }
713
mec_hal_qspi_rx_fifo_is_empty(struct mec_qspi_regs * base)714 int mec_hal_qspi_rx_fifo_is_empty(struct mec_qspi_regs *base)
715 {
716 if (base) {
717 if (base->STATUS & MEC_BIT(MEC_QSPI_STATUS_RXBE_Pos)) {
718 return 1;
719 }
720 }
721
722 return 0;
723 }
724
mec_hal_qspi_rx_fifo_is_full(struct mec_qspi_regs * base)725 int mec_hal_qspi_rx_fifo_is_full(struct mec_qspi_regs *base)
726 {
727 if (base) {
728 if (base->STATUS & MEC_BIT(MEC_QSPI_STATUS_RXBF_Pos)) {
729 return 1;
730 }
731 }
732
733 return 0;
734 }
735
mec_hal_qspi_start(struct mec_qspi_regs * base,uint32_t ien_mask)736 int mec_hal_qspi_start(struct mec_qspi_regs *base, uint32_t ien_mask)
737 {
738 if (!base) {
739 return MEC_RET_ERR_INVAL;
740 }
741
742 base->STATUS = UINT32_MAX;
743 base->INTR_CTRL = ien_mask;
744 base->EXE = MEC_BIT(MEC_QSPI_EXE_START_Pos);
745
746 return MEC_RET_OK;
747 }
748
749 /* Write up to smaller of bufsz or space available in TX FIFO bytes.
750 * If pointer nloaded not NULL set to number of bytes written to TX FIFO.
751 */
mec_hal_qspi_wr_tx_fifo(struct mec_qspi_regs * regs,const uint8_t * buf,uint32_t bufsz,uint32_t * nwr)752 int mec_hal_qspi_wr_tx_fifo(struct mec_qspi_regs *regs, const uint8_t *buf, uint32_t bufsz,
753 uint32_t *nwr)
754 {
755 uint32_t loaded = 0;
756 volatile uint8_t *tx_fifo = (volatile uint8_t *)®s->TX_FIFO;
757
758 if (!regs || (!buf && bufsz)) {
759 return MEC_RET_ERR_INVAL;
760 }
761
762 while (bufsz--) {
763 if (regs->STATUS & MEC_BIT(MEC_QSPI_STATUS_TXBF_Pos)) {
764 break;
765 }
766 *tx_fifo = *buf++;
767 loaded++;
768 }
769
770 if (nwr) {
771 *nwr = loaded;
772 }
773
774 return MEC_RET_OK;
775 }
776
777 /* If data is available in QSPI RX FIFO read it and store into buffer data unless
778 * buf is NULL then discard the data.
779 * Stops reading when RX FIFO becomes empty.
780 * Stores number of bytes read in nrd if not NULL.
781 */
mec_hal_qspi_rd_rx_fifo(struct mec_qspi_regs * regs,uint8_t * buf,uint32_t bufsz,uint32_t * nrd)782 int mec_hal_qspi_rd_rx_fifo(struct mec_qspi_regs *regs, uint8_t *buf, uint32_t bufsz,
783 uint32_t *nrd)
784 {
785 volatile uint8_t *rx_fifo = (volatile uint8_t *)®s->RX_FIFO;
786 uint32_t nr = 0;
787 uint8_t db = 0;
788
789 if (!regs) {
790 return MEC_RET_ERR_INVAL;
791 }
792
793 while (bufsz--) {
794 if (regs->STATUS & MEC_BIT(MEC_QSPI_STATUS_RXBE_Pos)) {
795 break;
796 }
797 db = *rx_fifo;
798 if (buf) {
799 *buf++ = db;
800 }
801 nr++;
802 }
803
804 if (nrd) {
805 *nrd = nr;
806 }
807
808 return MEC_RET_OK;
809 }
810
qspi_ldma_init(struct mec_qspi_regs * base)811 static void qspi_ldma_init(struct mec_qspi_regs *base)
812 {
813 base->MODE &= ~(MEC_BIT(MEC_QSPI_MODE_RX_LDMA_Pos) | MEC_BIT(MEC_QSPI_MODE_TX_LDMA_Pos));
814 base->LDMA_RXEN = 0u;
815 base->LDMA_TXEN = 0u;
816 base->RX_LDMA_CHAN[0].CTRL = 0;
817 base->RX_LDMA_CHAN[1].CTRL = 0;
818 base->RX_LDMA_CHAN[2].CTRL = 0;
819 base->TX_LDMA_CHAN[0].CTRL = 0;
820 base->TX_LDMA_CHAN[1].CTRL = 0;
821 base->TX_LDMA_CHAN[2].CTRL = 0;
822 }
823
824 /* Configure QSPI LDMA RX channel 0 and LDMA TX channel 0 for rx/tx of lenb
825 * bytes. If RX buffer is NULL use read-only QSPI buffer count register
826 * as the target destination and do not set address increment.
827 * If TX buffer is NULL read the write-only QSPI Execute register as
828 * the data source to be written.
829 */
qspi_ldma_cfg1(struct mec_qspi_regs * base,const uint8_t * txb,uint8_t * rxb,size_t lenb)830 static void qspi_ldma_cfg1(struct mec_qspi_regs *base, const uint8_t *txb,
831 uint8_t *rxb, size_t lenb)
832 {
833 uint32_t rctrl = MEC_BIT(MEC_QSPI_LDMA_CHAN_CTRL_EN_Pos);
834 uint32_t wctrl = MEC_BIT(MEC_QSPI_LDMA_CHAN_CTRL_EN_Pos);
835 uint32_t temp = (uint32_t)MEC_QSPI_LDMA_CHAN_CTRL_ACCSZ_1B;
836
837 if ((((uintptr_t)rxb | (uintptr_t)lenb) & 0x03u) == 0u) {
838 temp = (uint32_t)MEC_QSPI_LDMA_CHAN_CTRL_ACCSZ_4B;
839 }
840 rctrl |= (temp << MEC_QSPI_LDMA_CHAN_CTRL_ACCSZ_Pos);
841
842 temp = (uint32_t)MEC_QSPI_LDMA_CHAN_CTRL_ACCSZ_1B;
843 if ((((uintptr_t)txb | (uintptr_t)lenb) & 0x03u) == 0u) {
844 temp = (uint32_t)MEC_QSPI_LDMA_CHAN_CTRL_ACCSZ_4B;
845 }
846 wctrl |= (temp << MEC_QSPI_LDMA_CHAN_CTRL_ACCSZ_Pos);
847
848 base->RX_LDMA_CHAN[0].LEN = lenb;
849 if (rxb) {
850 base->RX_LDMA_CHAN[0].MEM_START = (uintptr_t)rxb;
851 rctrl |= MEC_BIT(MEC_QSPI_LDMA_CHAN_CTRL_INCRA_Pos);
852 } else {
853 base->RX_LDMA_CHAN[0].MEM_START = (uintptr_t)&base->BCNT_STS;
854 }
855 base->RX_LDMA_CHAN[0].CTRL = rctrl;
856
857 if (txb) {
858 base->TX_LDMA_CHAN[0].LEN = lenb;
859 base->TX_LDMA_CHAN[0].MEM_START = (uintptr_t)txb;
860 base->TX_LDMA_CHAN[0].CTRL = wctrl | MEC_BIT(MEC_QSPI_LDMA_CHAN_CTRL_INCRA_Pos);
861 }
862 }
863
864 /* Build the intitial value used for all descriptors.
865 * param txb pointer to transmit buffer
866 * param interface mode field value (full-duplex, dual, or quad)
867 * return initial/constant descriptor field values.
868 * note Use RX LDMA channel 0 and TX LDMA channel 0.
869 * If transmit buffer is NULL make use of QSPI HW feature to
870 * transmit all 0's.
871 */
descr_ldma_init(const uint8_t * txb,uint32_t ifm)872 static uint32_t descr_ldma_init(const uint8_t *txb, uint32_t ifm)
873 {
874 uint32_t d = ifm;
875
876 if (txb) {
877 d |= (((uint32_t)MEC_QSPI_DESCR_TXEN_EN << MEC_QSPI_DESCR_TXEN_Pos)
878 | ((uint32_t)MEC_QSPI_DESCR_TXDMA_1B_LDMA_CH0 << MEC_QSPI_DESCR_TXDMA_Pos));
879 }
880
881 /* always enable receive LDMA for full duplex */
882 d |= (((uint32_t)MEC_QSPI_DESCR_RXEN_EN << MEC_QSPI_DESCR_RXEN_Pos)
883 | ((uint32_t)MEC_QSPI_DESCR_RXDMA_1B_LDMA_CH0 << MEC_QSPI_DESCR_RXDMA_Pos));
884
885 return d;
886 }
887
888 #ifdef MEC5_QSPI_LDMA_TX_NULL_LEN_ARE_CLOCKS
889 /*
890 * FD 1 bit = 1 clock
891 * Dual 2 bits = 1 clock
892 * Quad 4 bits = 1 clock
893 */
qspi_clocks_to_bits(uint32_t ctrl,uint32_t nclocks)894 static uint32_t qspi_clocks_to_bits(uint32_t ctrl, uint32_t nclocks)
895 {
896 uint32_t ifm = (ctrl & MEC_QSPI_CTRL_IFM_Msk) >> MEC_QSPI_CTRL_IFM_Pos;
897
898 if (ifm == MEC_QSPI_CTRL_IFM_QUAD) {
899 return (nclocks * 4u);
900 } else if (ifm == MEC_QSPI_CTRL_IFM_DUAL) {
901 return (nclocks * 2u);
902 } else {
903 return nclocks;
904 }
905 }
906
qspi_gen_ts_clocks(struct mec_qspi_regs * base,uint32_t nclocks,uint32_t flags)907 static int qspi_gen_ts_clocks(struct mec_qspi_regs *base, uint32_t nclocks, uint32_t flags)
908 {
909 uint32_t descr = qspi_clocks_to_bits(base->CTRL, nclocks);
910 int ien = 0;
911
912 descr <<= MEC_QSPI_DESCR_QNUNITS_Pos;
913 descr &= MEC_QSPI_DESCR_QNUNITS_Msk;
914 descr |= (base->CTRL & MEC_QSPI_CTRL_IFM_Msk);
915 descr |= (1u << MEC_QSPI_DESCR_NEXT_Pos);
916 descr |= MEC_BIT(MEC_QSPI_DESCR_LAST_Pos);
917
918 if (flags & MEC_BIT(MEC_QSPI_XFR_FLAG_CLOSE_POS)) {
919 descr |= MEC_BIT(MEC_QSPI_DESCR_CLOSE_Pos);
920 }
921 base->DESCR[0] = descr;
922
923 if (flags & MEC_BIT(MEC_QSPI_XFR_FLAG_IEN_POS)) {
924 ien = 1;
925 }
926
927 qspi_intr_ctrl(base, ien);
928
929 /* start HW */
930 if (flags & MEC_QSPI_XFR_FLAG_START_POS) {
931 base->EXE = MEC_BIT(MEC_QSPI_EXE_START_Pos);
932 }
933
934 return MEC_RET_OK;
935 }
936 #endif
937
938 /* Configure and start/continue a SPI transaction
939 * base is a pointer to the QSPI control instance hardware registers.
940 * txb is a pointer to a constant buffer containing bytes to transmit.
941 * rxb is a pointer to a r/w buffer to hold data received as each byte is
942 * transmitted. If rxb is NULL the received data is discarded. lenb is the size
943 * in bytes of each buffer. flags contains bits to enable interrupts before the
944 * transfer starts.
945 */
mec_hal_qspi_ldma(struct mec_qspi_regs * base,const uint8_t * txb,uint8_t * rxb,size_t lenb,uint32_t flags)946 int mec_hal_qspi_ldma(struct mec_qspi_regs *base, const uint8_t *txb,
947 uint8_t *rxb, size_t lenb, uint32_t flags)
948 {
949 uint32_t nbytes = lenb;
950 uint32_t shift = 0, nu = 0, descr = 0, descr_init = 0, didx = 0;
951 int ien = 0;
952
953 if (!base) {
954 return MEC_RET_ERR_INVAL;
955 }
956
957 if (!lenb) {
958 return 0;
959 }
960
961 qspi_ldma_init(base);
962
963 if (flags & MEC_BIT(MEC_QSPI_XFR_FLAG_CLR_FIFOS_POS)) {
964 base->EXE = MEC_BIT(MEC_QSPI_EXE_CLRF_Pos);
965 } else if (base->BCNT_STS) { /* data left in TX and/or RX FIFO */
966 return MEC_RET_ERR_HW;
967 }
968
969 base->STATUS = UINT32_MAX;
970 /* descriptor mode starting at descriptor 0 */
971 base->CTRL |= MEC_BIT(MEC_QSPI_CTRL_DESCR_MODE_Pos);
972
973 #ifdef MEC5_QSPI_LDMA_TX_NULL_LEN_ARE_CLOCKS
974 if (!txb && !rxb && lenb) {
975 return qspi_gen_ts_clocks(base, lenb, flags);
976 } else {
977 descr_init = descr_ldma_init(txb, base->CTRL & MEC_QSPI_CTRL_IFM_Msk);
978 }
979 #else
980 descr_init = descr_ldma_init(txb, base->CTRL & MEC_QSPI_CTRL_IFM_Msk);
981 #endif
982
983 while (nbytes && (didx < MEC5_QSPI_NUM_DESCRS)) {
984 descr = descr_init;
985 nu = nbytes;
986 shift = 0;
987 if (nu > MEC_QSPI_DESCR_NU_MAX) {
988 shift = 4;
989 nu >>= 4;
990 descr |= ((uint32_t)MEC_QSPI_DESCR_QUNITS_16B << MEC_QSPI_DESCR_QUNITS_Pos);
991 } else {
992 descr |= ((uint32_t)MEC_QSPI_DESCR_QUNITS_1B << MEC_QSPI_DESCR_QUNITS_Pos);
993 }
994
995 descr |= (nu << MEC_QSPI_DESCR_QNUNITS_Pos);
996 descr |= (((didx + 1u) << MEC_QSPI_DESCR_NEXT_Pos) & MEC_QSPI_DESCR_NEXT_Msk);
997 base->DESCR[didx] = descr;
998 base->LDMA_RXEN |= MEC_BIT(didx);
999 if (txb) {
1000 base->LDMA_TXEN |= MEC_BIT(didx);
1001 }
1002 nbytes -= (nu << shift);
1003 didx++;
1004 }
1005
1006 descr = base->DESCR[didx - 1u] | MEC_BIT(MEC_QSPI_DESCR_LAST_Pos);
1007 if (flags & MEC_BIT(MEC_QSPI_XFR_FLAG_CLOSE_POS)) {
1008 descr |= MEC_BIT(MEC_QSPI_DESCR_CLOSE_Pos);
1009 }
1010 base->DESCR[didx - 1u] = descr;
1011
1012 if (nbytes) {
1013 return MEC_RET_ERR_DATA_LEN;
1014 }
1015
1016 qspi_ldma_cfg1(base, txb, rxb, lenb);
1017
1018 base->MODE |= (MEC_BIT(MEC_QSPI_MODE_RX_LDMA_Pos) | MEC_BIT(MEC_QSPI_MODE_TX_LDMA_Pos));
1019
1020 if (flags & MEC_BIT(MEC_QSPI_XFR_FLAG_IEN_POS)) {
1021 ien = 1;
1022 }
1023
1024 qspi_intr_ctrl(base, ien);
1025
1026 /* start HW */
1027 if (flags & MEC_BIT(MEC_QSPI_XFR_FLAG_START_POS)) {
1028 base->EXE = MEC_BIT(MEC_QSPI_EXE_START_Pos);
1029 }
1030
1031 return 0;
1032 }
1033
1034 /* -------- 2024-02-24 -------- */
1035
mec_hal_qspi_context_init(struct mec_qspi_context * ctx)1036 void mec_hal_qspi_context_init(struct mec_qspi_context *ctx)
1037 {
1038 ctx->ndescrs = 0;
1039 ctx->ntxdma = 0;
1040 ctx->nrxdma = 0;
1041 ctx->xflags = 0;
1042 for (size_t n = 0; n < MEC5_QSPI_NUM_DESCRS; n++) {
1043 ctx->descrs[n] = 0;
1044 }
1045 }
1046
mec_hal_qspi_ctx_alloc_ldma_chan(struct mec_qspi_context * ctx,uint8_t is_tx)1047 uint8_t mec_hal_qspi_ctx_alloc_ldma_chan(struct mec_qspi_context *ctx, uint8_t is_tx)
1048 {
1049 if (!ctx) {
1050 return 0;
1051 }
1052
1053 if (is_tx) {
1054 if (ctx->ntxdma < MEC5_QSPI_LDMA_CHANNELS) {
1055 return ++ctx->ntxdma;
1056 }
1057 } else {
1058 if (ctx->nrxdma < MEC5_QSPI_LDMA_CHANNELS) {
1059 return ++ctx->nrxdma;
1060 }
1061 }
1062
1063 return 0;
1064 }
1065
qspi_nio_pins_to_ifm(uint8_t nio_pins)1066 static uint32_t qspi_nio_pins_to_ifm(uint8_t nio_pins)
1067 {
1068 uint8_t ifm_val;
1069
1070 if (nio_pins == 4) {
1071 ifm_val = MEC_QSPI_DESCR_IFM_QUAD;
1072 } else if (nio_pins == 2) {
1073 ifm_val = MEC_QSPI_DESCR_IFM_DUAL;
1074 } else {
1075 ifm_val = MEC_QSPI_DESCR_IFM_FD;
1076 }
1077
1078 return ((uint32_t)ifm_val << MEC_QSPI_DESCR_IFM_Pos);
1079 }
1080
mec_hal_qspi_cfg_gen_ts_clocks(struct mec_qspi_context * ctx,uint32_t nclocks,uint8_t nio_pins)1081 int mec_hal_qspi_cfg_gen_ts_clocks(struct mec_qspi_context *ctx, uint32_t nclocks,
1082 uint8_t nio_pins)
1083 {
1084 uint32_t didx = 0, descr = 0;
1085
1086 if (!((nio_pins == 1) || (nio_pins == 2) || (nio_pins == 4))) {
1087 return MEC_RET_ERR_INVAL;
1088 }
1089
1090 if (!nclocks) {
1091 return MEC_RET_ERR_NOP;
1092 }
1093
1094 didx = ctx->ndescrs;
1095 if (didx >= MEC5_QSPI_NUM_DESCRS) {
1096 return MEC_RET_ERR_NO_RES;
1097 }
1098
1099 descr |= qspi_nio_pins_to_ifm(nio_pins);
1100 if (!(nclocks & 0x7u)) { /* multiple of 8 bits? */
1101 descr |= (MEC_QSPI_DESCR_QUNITS_1B << MEC_QSPI_DESCR_QUNITS_Pos);
1102 descr |= ((((nclocks >> 3) * nio_pins) << MEC_QSPI_DESCR_QNUNITS_Pos)
1103 & MEC_QSPI_DESCR_QNUNITS_Msk);
1104 } else {
1105 descr |= (MEC_QSPI_DESCR_QUNITS_BITS << MEC_QSPI_DESCR_QUNITS_Pos);
1106 descr |= (((nclocks * nio_pins) << MEC_QSPI_DESCR_QNUNITS_Pos) & MEC_QSPI_DESCR_QNUNITS_Msk);
1107 }
1108 ctx->descrs[didx] = descr;
1109 ctx->ndescrs++;
1110
1111 return MEC_RET_OK;
1112 }
1113
1114 /* Configure the specified QSPI Local-DMA channel.
1115 * regs - pointer to QSPI hardware registers
1116 * buf_addr - address of source or destination buffer in memory
1117 * nbytes - requested number of bytes to transfer
1118 * chan_dir
1119 * b[3:0] = 1-based channel (1, 2, or 3)
1120 * b[4] = direction: 0(RX), 1(TX)
1121 * return 0 success
1122 * < 0 error
1123 *
1124 * Program the specified QSPI RX or TX LDMA channel with memory address
1125 * of source/destination buffer and transfer length in bytes.
1126 * If buffer address is 0 then source/destination memory address is set
1127 * to the QSPI buffer status count read-only register and LDMA channel
1128 * increment address is disabled.
1129 */
mec_hal_qspi_ldma_cfg1(struct mec_qspi_regs * regs,uintptr_t buf_addr,uint32_t nbytes,uint32_t ldflags)1130 int mec_hal_qspi_ldma_cfg1(struct mec_qspi_regs *regs, uintptr_t buf_addr, uint32_t nbytes,
1131 uint32_t ldflags)
1132 {
1133 volatile struct mec_qspi_ldma_chan_regs *ldma_regs = NULL;
1134 uint32_t ctrl = 0;
1135 uint8_t chanrx = 0, chantx = 0;
1136
1137 if (!regs) {
1138 return MEC_RET_ERR_INVAL;
1139 }
1140
1141 if (!nbytes) {
1142 return MEC_RET_OK;
1143 }
1144
1145 ctrl = ((uint32_t)MEC_QSPI_LDMA_CHAN_CTRL_ACCSZ_1B << MEC_QSPI_LDMA_CHAN_CTRL_ACCSZ_Pos);
1146 chanrx = (ldflags >> MEC5_QSPI_DCFG1_FLAG_DMA_RX_POS) & MEC5_QSPI_DCFG1_FLAG_DMA_MSK0;
1147 chantx = (ldflags >> MEC5_QSPI_DCFG1_FLAG_DMA_TX_POS) & MEC5_QSPI_DCFG1_FLAG_DMA_MSK0;
1148
1149 if ((ldflags & MEC5_QSPI_DCFG1_FLAG_DIR_TX) && chantx) {
1150 ldma_regs = ®s->TX_LDMA_CHAN[chantx - 1u];
1151 } else if ((ldflags & MEC5_QSPI_DCFG1_FLAG_DIR_RX) && chanrx) {
1152 ldma_regs = ®s->RX_LDMA_CHAN[chanrx - 1u];
1153 } else {
1154 return MEC_RET_ERR_INVAL;
1155 }
1156
1157 ldma_regs->CTRL = 0;
1158 ldma_regs->MEM_START = (uint32_t)buf_addr;
1159 ldma_regs->LEN = nbytes;
1160
1161 if (buf_addr) {
1162 ctrl |= MEC_BIT(MEC_QSPI_LDMA_CHAN_CTRL_INCRA_Pos);
1163 } else {
1164 ldma_regs->MEM_START = (uint32_t)((uintptr_t)®s->BCNT_STS & UINT32_MAX);
1165 }
1166
1167 if (!((buf_addr | nbytes) & 0x3u)) {
1168 ctrl &= (uint32_t)~MEC_QSPI_LDMA_CHAN_CTRL_ACCSZ_Msk;
1169 ctrl |= ((uint32_t)MEC_QSPI_LDMA_CHAN_CTRL_ACCSZ_4B << MEC_QSPI_LDMA_CHAN_CTRL_ACCSZ_Pos);
1170 }
1171
1172 ldma_regs->CTRL = ctrl | MEC_BIT(MEC_QSPI_LDMA_CHAN_CTRL_EN_Pos);
1173
1174 return 0;
1175 }
1176
1177 /* Configures descriptor(s):
1178 * IFM (full-duplex, dual, or quad)
1179 * xfr count unit size
1180 * number of units
1181 * TX enable (TX-Data only)
1182 * TX-LDMA channel select (disable or channel id)
1183 * RX enable
1184 * RX-LDMA channel select (disable or channel id)
1185 */
mec_hal_qspi_descrs_cfg1(struct mec_qspi_context * ctx,uint32_t nbytes,uint32_t flags)1186 uint32_t mec_hal_qspi_descrs_cfg1(struct mec_qspi_context *ctx, uint32_t nbytes, uint32_t flags)
1187 {
1188 uint32_t dbase;
1189 uint32_t nb;
1190 uint32_t nu;
1191 uint8_t didx;
1192
1193 if (!ctx) {
1194 return UINT32_MAX;
1195 }
1196
1197 dbase = qspi_nio_pins_to_ifm(flags & MEC5_QSPI_DCFG1_FLAG_IFM_MSK);
1198
1199 if (flags & MEC5_QSPI_DCFG1_FLAG_DIR_TX) {
1200 dbase |= (MEC_QSPI_DESCR_TXEN_EN << MEC_QSPI_DESCR_TXEN_Pos);
1201 /* b[5:4] = TX-DMA: 0=disabled, 1-2 specify LDMA channel */
1202 dbase |= ((flags >> MEC5_QSPI_DCFG1_FLAG_DMA_TX_POS)
1203 & MEC5_QSPI_DCFG1_FLAG_DMA_MSK0) << MEC_QSPI_DESCR_TXDMA_Pos;
1204 }
1205 if (flags & MEC5_QSPI_DCFG1_FLAG_DIR_RX) {
1206 dbase |= MEC_BIT(MEC_QSPI_DESCR_RXEN_Pos);
1207 /* b[8:7] = RX-DMA: 0=disabled, 1-2 specify LDMA channel */
1208 dbase |= ((flags >> MEC5_QSPI_DCFG1_FLAG_DMA_RX_POS)
1209 & MEC5_QSPI_DCFG1_FLAG_DMA_MSK0) << MEC_QSPI_DESCR_RXDMA_Pos;
1210 }
1211
1212 didx = ctx->ndescrs;
1213 nb = nbytes;
1214 while (nb) {
1215 if (didx >= MEC5_QSPI_NUM_DESCRS) {
1216 break;
1217 }
1218
1219 /* b[11:10] = 01b 1-byte units
1220 * 11b 16-byte units
1221 * b[31:17] = number of units
1222 */
1223 if (nb > MEC_QSPI_DESCR_NU_MAX) {
1224 nu = (nb >> 4);
1225 if (nu > MEC_QSPI_DESCR_NU_MAX) {
1226 nu = MEC_QSPI_DESCR_NU_MAX;
1227 }
1228 ctx->descrs[didx] = (((nu << MEC_QSPI_DESCR_QNUNITS_Pos) & MEC_QSPI_DESCR_QNUNITS_Msk)
1229 | (MEC_QSPI_DESCR_QUNITS_16B << MEC_QSPI_DESCR_QUNITS_Pos)
1230 | dbase);
1231 nb -= (nu << 4);
1232 } else {
1233 ctx->descrs[didx] = (((nb << MEC_QSPI_DESCR_QNUNITS_Pos) & MEC_QSPI_DESCR_QNUNITS_Msk)
1234 | (MEC_QSPI_DESCR_QUNITS_1B << MEC_QSPI_DESCR_QUNITS_Pos)
1235 | dbase);
1236 nb = 0;
1237 }
1238 didx++;
1239 }
1240
1241 ctx->ndescrs = didx;
1242
1243 return nb;
1244 }
1245
mec_hal_qspi_load_descrs(struct mec_qspi_regs * regs,struct mec_qspi_context * ctx,uint32_t flags)1246 int mec_hal_qspi_load_descrs(struct mec_qspi_regs *regs, struct mec_qspi_context *ctx,
1247 uint32_t flags)
1248 {
1249 size_t didx, max_ndescr;
1250 uint32_t descr, ldchan, mode;
1251
1252 if (!regs || !ctx) {
1253 return MEC_RET_ERR_INVAL;
1254 }
1255
1256 if (!ctx->ndescrs) {
1257 return MEC_RET_ERR_NOP;
1258 }
1259
1260 mode = 0;
1261 max_ndescr = (size_t)ctx->ndescrs;
1262
1263 if (max_ndescr > MEC5_QSPI_NUM_DESCRS) {
1264 max_ndescr = MEC5_QSPI_NUM_DESCRS;
1265 }
1266
1267 for (didx = 0; didx < max_ndescr; didx++) {
1268 descr = ctx->descrs[didx];
1269 descr &= (uint32_t)~(MEC_QSPI_DESCR_NEXT_Msk);
1270 descr |= ((((uint32_t)didx + 1u) << MEC_QSPI_DESCR_NEXT_Pos) & MEC_QSPI_DESCR_NEXT_Msk);
1271 regs->DESCR[didx] = descr;
1272
1273 if ((descr & MEC_QSPI_DESCR_TXEN_Msk) == (MEC_QSPI_DESCR_TXEN_EN << MEC_QSPI_DESCR_TXEN_Pos)) {
1274 /* TX-Data enabled? */
1275 ldchan = (descr & MEC_QSPI_DESCR_TXDMA_Msk) >> MEC_QSPI_DESCR_TXDMA_Pos;
1276 if (ldchan) {
1277 regs->LDMA_TXEN |= MEC_BIT(didx);
1278 mode |= MEC_BIT(MEC_QSPI_MODE_TX_LDMA_Pos);
1279 } else {
1280 regs->LDMA_TXEN &= (uint32_t)~MEC_BIT(didx);
1281 }
1282 }
1283
1284 if (descr & MEC_BIT(MEC_QSPI_DESCR_RXEN_Pos)) {
1285 ldchan = (descr & MEC_QSPI_DESCR_RXDMA_Msk) >> MEC_QSPI_DESCR_RXDMA_Pos;
1286 if (ldchan) {
1287 regs->LDMA_RXEN |= MEC_BIT(didx);
1288 mode |= MEC_BIT(MEC_QSPI_MODE_RX_LDMA_Pos);
1289 } else {
1290 regs->LDMA_RXEN &= (uint32_t)~MEC_BIT(didx);
1291 }
1292 }
1293 }
1294
1295 regs->MODE = (regs->MODE & ~(MEC_BIT(MEC_QSPI_MODE_TX_LDMA_Pos)
1296 | MEC_BIT(MEC_QSPI_MODE_RX_LDMA_Pos))) | mode;
1297
1298 didx = max_ndescr - 1u;
1299 if (flags & MEC_BIT(MEC5_QSPI_LD_FLAGS_LAST_POS)) {
1300 regs->DESCR[didx] |= MEC_BIT(MEC_QSPI_DESCR_LAST_Pos);
1301 }
1302
1303 if (flags & MEC_BIT(MEC5_QSPI_LD_FLAGS_CLOSE_ON_LAST_POS)) {
1304 regs->DESCR[didx] |= MEC_BIT(MEC_QSPI_DESCR_CLOSE_Pos);
1305 }
1306
1307 /* Enable descriptor mode with start descriptor = Descr[0] */
1308 regs->CTRL = MEC_BIT(MEC_QSPI_CTRL_DESCR_MODE_Pos);
1309
1310 return 0;
1311 }
1312
1313 /* Load descriptors register only. Does not touch other QSPI registers */
mec_hal_qspi_load_descrs_at(struct mec_qspi_regs * regs,const uint32_t * descrs,uint8_t ndescr,uint8_t start_descr_idx)1314 int mec_hal_qspi_load_descrs_at(struct mec_qspi_regs *regs, const uint32_t *descrs, uint8_t ndescr,
1315 uint8_t start_descr_idx)
1316 {
1317 uint32_t didx, didx_lim, n;
1318
1319 if (!regs || !descrs || !ndescr || (start_descr_idx >= MEC5_QSPI_NUM_DESCRS)) {
1320 return MEC_RET_ERR_INVAL;
1321 }
1322
1323 if (mec_hal_qspi_done(regs) == MEC_RET_ERR_BUSY) {
1324 return MEC_RET_ERR_BUSY;
1325 }
1326
1327 didx = start_descr_idx;
1328 didx_lim = didx + ndescr;
1329 if (didx_lim > MEC5_QSPI_NUM_DESCRS) {
1330 didx_lim = MEC5_QSPI_NUM_DESCRS;
1331 }
1332
1333 n = 0;
1334 while (didx < didx_lim) {
1335 regs->DESCR[didx++] = descrs[n++];
1336 }
1337
1338 return MEC_RET_OK;
1339 }
1340
1341 /* end mec_qspi.c */
1342