1 /*
2 * SPDX-FileCopyrightText: 2015-2023 Espressif Systems (Shanghai) CO LTD
3 *
4 * SPDX-License-Identifier: Apache-2.0
5 */
6
7 /*******************************************************************************
8 * NOTICE
9 * The hal is not public api, don't use in application code.
10 * See readme.md in hal/include/hal/readme.md
11 ******************************************************************************/
12
13 // The LL layer for ESP32-S2 SPI register operations
14
15 #pragma once
16
17 #include <stdlib.h> //for abs()
18 #include <string.h>
19 #include "esp_types.h"
20 #include "esp_attr.h"
21 #include "soc/spi_periph.h"
22 #include "soc/spi_struct.h"
23 #include "soc/lldesc.h"
24 #include "hal/assert.h"
25 #include "hal/misc.h"
26 #include "hal/spi_types.h"
27
28 #ifdef __cplusplus
29 extern "C" {
30 #endif
31
32 /// Registers to reset during initialization. Don't use in app.
33 #define SPI_LL_DMA_FIFO_RST_MASK (SPI_AHBM_RST | SPI_AHBM_FIFO_RST)
34 /// Interrupt not used. Don't use in app.
35 #define SPI_LL_UNUSED_INT_MASK (SPI_INT_TRANS_DONE_EN | SPI_INT_WR_DMA_DONE_EN | SPI_INT_RD_DMA_DONE_EN | SPI_INT_WR_BUF_DONE_EN | SPI_INT_RD_BUF_DONE_EN)
36 /// These 2 masks together will set SPI transaction to one line mode
37 #define SPI_LL_ONE_LINE_CTRL_MASK (SPI_FREAD_OCT | SPI_FREAD_QUAD | SPI_FREAD_DUAL | SPI_FCMD_OCT | \
38 SPI_FCMD_QUAD | SPI_FCMD_DUAL | SPI_FADDR_OCT | SPI_FADDR_QUAD | SPI_FADDR_DUAL)
39 #define SPI_LL_ONE_LINE_USER_MASK (SPI_FWRITE_OCT | SPI_FWRITE_QUAD | SPI_FWRITE_DUAL)
40 /// Swap the bit order to its correct place to send
41 #define HAL_SPI_SWAP_DATA_TX(data, len) HAL_SWAP32((uint32_t)(data) << (32 - len))
42 #define SPI_LL_GET_HW(ID) ((ID)==0? ({abort();NULL;}):((ID)==1? &GPSPI2 : &GPSPI3))
43
44 #define SPI_LL_DMA_MAX_BIT_LEN (1 << 23) //reg len: 23 bits
45 #define SPI_LL_CPU_MAX_BIT_LEN (18 * 32) //Fifo len: 18 words
46 #define SPI_LL_MOSI_FREE_LEVEL 1 //Default level after bus initialized
47
48 /**
49 * The data structure holding calculated clock configuration. Since the
50 * calculation needs long time, it should be calculated during initialization and
51 * stored somewhere to be quickly used.
52 */
53 typedef uint32_t spi_ll_clock_val_t;
54
55 //On ESP32-S2 and earlier chips, DMA registers are part of SPI registers. So set the registers of SPI peripheral to control DMA.
56 typedef spi_dev_t spi_dma_dev_t;
57
58 /// Type definition of all supported interrupts
59 typedef enum {
60 SPI_LL_INTR_TRANS_DONE = BIT(0), ///< A transaction has done
61 SPI_LL_INTR_IN_SUC_EOF = BIT(1), ///< DMA in_suc_eof triggered
62 SPI_LL_INTR_OUT_EOF = BIT(2), ///< DMA out_eof triggered
63 SPI_LL_INTR_OUT_TOTAL_EOF = BIT(3), ///< DMA out_total_eof triggered
64 SPI_LL_INTR_IN_FULL = BIT(4), ///< DMA in_full error happened
65 SPI_LL_INTR_OUT_EMPTY = BIT(5), ///< DMA out_empty error happened
66 SPI_LL_INTR_RDBUF = BIT(6), ///< Has received RDBUF command. Only available in slave HD.
67 SPI_LL_INTR_WRBUF = BIT(7), ///< Has received WRBUF command. Only available in slave HD.
68 SPI_LL_INTR_RDDMA = BIT(8), ///< Has received RDDMA command. Only available in slave HD.
69 SPI_LL_INTR_WRDMA = BIT(9), ///< Has received WRDMA command. Only available in slave HD.
70 SPI_LL_INTR_CMD7 = BIT(10), ///< Has received CMD7 command. Only available in slave HD.
71 SPI_LL_INTR_CMD8 = BIT(11), ///< Has received CMD8 command. Only available in slave HD.
72 SPI_LL_INTR_CMD9 = BIT(12), ///< Has received CMD9 command. Only available in slave HD.
73 SPI_LL_INTR_CMDA = BIT(13), ///< Has received CMDA command. Only available in slave HD.
74 SPI_LL_INTR_SEG_DONE = BIT(14),
75 } spi_ll_intr_t;
76 FLAG_ATTR(spi_ll_intr_t)
77
78 ///< Flags for conditions under which the transaction length should be recorded
79 typedef enum {
80 SPI_LL_TRANS_LEN_COND_WRBUF = BIT(0), ///< WRBUF length will be recorded
81 SPI_LL_TRANS_LEN_COND_RDBUF = BIT(1), ///< RDBUF length will be recorded
82 SPI_LL_TRANS_LEN_COND_WRDMA = BIT(2), ///< WRDMA length will be recorded
83 SPI_LL_TRANS_LEN_COND_RDDMA = BIT(3), ///< RDDMA length will be recorded
84 } spi_ll_trans_len_cond_t;
85 FLAG_ATTR(spi_ll_trans_len_cond_t)
86
87 // SPI base command in esp32s2
88 typedef enum {
89 /* Slave HD Only */
90 SPI_LL_BASE_CMD_HD_WRBUF = 0x01,
91 SPI_LL_BASE_CMD_HD_RDBUF = 0x02,
92 SPI_LL_BASE_CMD_HD_WRDMA = 0x03,
93 SPI_LL_BASE_CMD_HD_RDDMA = 0x04,
94 SPI_LL_BASE_CMD_HD_SEG_END = 0x05,
95 SPI_LL_BASE_CMD_HD_EN_QPI = 0x06,
96 SPI_LL_BASE_CMD_HD_WR_END = 0x07,
97 SPI_LL_BASE_CMD_HD_INT0 = 0x08,
98 SPI_LL_BASE_CMD_HD_INT1 = 0x09,
99 SPI_LL_BASE_CMD_HD_INT2 = 0x0A,
100 } spi_ll_base_command_t;
101
102 /*------------------------------------------------------------------------------
103 * Control
104 *----------------------------------------------------------------------------*/
105
106 /**
107 * Select SPI peripheral clock source (master).
108 *
109 * @param hw Beginning address of the peripheral registers.
110 * @param clk_source clock source to select, see valid sources in type `spi_clock_source_t`
111 */
spi_ll_set_clk_source(spi_dev_t * hw,spi_clock_source_t clk_source)112 static inline void spi_ll_set_clk_source(spi_dev_t *hw, spi_clock_source_t clk_source)
113 {
114 //empty, keep this for compatibility
115 }
116
117 /**
118 * Initialize SPI peripheral (master).
119 *
120 * @param hw Beginning address of the peripheral registers.
121 */
spi_ll_master_init(spi_dev_t * hw)122 static inline void spi_ll_master_init(spi_dev_t *hw)
123 {
124 //Reset timing
125 hw->ctrl2.val = 0;
126
127 //use all 64 bytes of the buffer
128 hw->user.usr_miso_highpart = 0;
129 hw->user.usr_mosi_highpart = 0;
130
131 //Disable unneeded ints
132 hw->slave.val &= ~SPI_LL_UNUSED_INT_MASK;
133
134 //disable a feature may cause transaction to be too long
135 hw->user.usr_prep_hold = 0;
136 }
137
138 /**
139 * Initialize SPI peripheral (slave).
140 *
141 * @param hw Beginning address of the peripheral registers.
142 */
spi_ll_slave_init(spi_dev_t * hw)143 static inline void spi_ll_slave_init(spi_dev_t *hw)
144 {
145 //Configure slave
146 hw->clock.val = 0;
147 hw->user.val = 0;
148 hw->ctrl.val = 0;
149 hw->user.doutdin = 1; //we only support full duplex
150 hw->user.sio = 0;
151 hw->slave.slave_mode = 1;
152 hw->slave.soft_reset = 1;
153 hw->slave.soft_reset = 0;
154 //use all 64 bytes of the buffer
155 hw->user.usr_miso_highpart = 0;
156 hw->user.usr_mosi_highpart = 0;
157
158 // Configure DMA In-Link to not be terminated when transaction bit counter exceeds
159 hw->dma_conf.rx_eof_en = 0;
160
161 //Disable unneeded ints
162 hw->slave.val &= ~SPI_LL_UNUSED_INT_MASK;
163 }
164
spi_ll_slave_hd_init(spi_dev_t * hw)165 static inline void spi_ll_slave_hd_init(spi_dev_t *hw)
166 {
167 hw->clock.val = 0;
168 hw->user.val = 0;
169 hw->ctrl.val = 0;
170 hw->user.sio = 0;
171
172 hw->slave.soft_reset = 1;
173 hw->slave.soft_reset = 0;
174
175 hw->user.doutdin = 0; //we only support half duplex
176 hw->slave.slave_mode = 1;
177 }
178
179 /**
180 * Determine and unify the default level of mosi line when bus free
181 *
182 * @param hw Beginning address of the peripheral registers.
183 */
spi_ll_set_mosi_free_level(spi_dev_t * hw,bool level)184 static inline void spi_ll_set_mosi_free_level(spi_dev_t *hw, bool level)
185 {
186 hw->ctrl.d_pol = level; //set default level for MOSI only on IDLE state
187 }
188
189 /**
190 * Apply the register configurations and wait until it's done
191 *
192 * @param hw Beginning address of the peripheral registers.
193 */
spi_ll_apply_config(spi_dev_t * hw)194 static inline void spi_ll_apply_config(spi_dev_t *hw)
195 {
196 // S2 don't need this option
197 }
198
199 /**
200 * Check whether user-defined transaction is done.
201 *
202 * @param hw Beginning address of the peripheral registers.
203 *
204 * @return true if transaction is done, otherwise false.
205 */
spi_ll_usr_is_done(spi_dev_t * hw)206 static inline bool spi_ll_usr_is_done(spi_dev_t *hw)
207 {
208 return hw->slave.trans_done;
209 }
210
211 /**
212 * Trigger start of user-defined transaction.
213 *
214 * @param hw Beginning address of the peripheral registers.
215 */
spi_ll_user_start(spi_dev_t * hw)216 static inline void spi_ll_user_start(spi_dev_t *hw)
217 {
218 hw->cmd.usr = 1;
219 }
220
221 /**
222 * Get current running command bit-mask. (Preview)
223 *
224 * @param hw Beginning address of the peripheral registers.
225 *
226 * @return Bitmask of running command, see ``SPI_CMD_REG``. 0 if no in-flight command.
227 */
spi_ll_get_running_cmd(spi_dev_t * hw)228 static inline uint32_t spi_ll_get_running_cmd(spi_dev_t *hw)
229 {
230 return hw->cmd.val;
231 }
232
233 /**
234 * Reset SPI CPU TX FIFO
235 *
236 * @param hw Beginning address of the peripheral registers.
237 */
spi_ll_cpu_tx_fifo_reset(spi_dev_t * hw)238 static inline void spi_ll_cpu_tx_fifo_reset(spi_dev_t *hw)
239 {
240 //This is not used in esp32s2
241 }
242
243 /**
244 * Reset SPI CPU RX FIFO
245 *
246 * @param hw Beginning address of the peripheral registers.
247 */
spi_ll_cpu_rx_fifo_reset(spi_dev_t * hw)248 static inline void spi_ll_cpu_rx_fifo_reset(spi_dev_t *hw)
249 {
250 //This is not used in esp32s2
251 }
252
253 /**
254 * Reset SPI DMA TX FIFO
255 *
256 * On ESP32S2, this function is not seperated
257 *
258 * @param hw Beginning address of the peripheral registers.
259 */
spi_ll_dma_tx_fifo_reset(spi_dev_t * hw)260 static inline void spi_ll_dma_tx_fifo_reset(spi_dev_t *hw)
261 {
262 hw->dma_conf.val |= SPI_LL_DMA_FIFO_RST_MASK;
263 hw->dma_conf.val &= ~SPI_LL_DMA_FIFO_RST_MASK;
264 }
265
266 /**
267 * Reset SPI DMA RX FIFO
268 *
269 * On ESP32S2, this function is not seperated
270 *
271 * @param hw Beginning address of the peripheral registers.
272 */
spi_ll_dma_rx_fifo_reset(spi_dev_t * hw)273 static inline void spi_ll_dma_rx_fifo_reset(spi_dev_t *hw)
274 {
275 hw->dma_conf.val |= SPI_LL_DMA_FIFO_RST_MASK;
276 hw->dma_conf.val &= ~SPI_LL_DMA_FIFO_RST_MASK;
277 }
278
279 /**
280 * Clear in fifo full error
281 *
282 * @param hw Beginning address of the peripheral registers.
283 */
spi_ll_infifo_full_clr(spi_dev_t * hw)284 static inline void spi_ll_infifo_full_clr(spi_dev_t *hw)
285 {
286 hw->dma_conf.infifo_full_clr = 1;
287 hw->dma_conf.infifo_full_clr = 0;
288 }
289
290 /**
291 * Clear out fifo empty error
292 *
293 * @param hw Beginning address of the peripheral registers.
294 */
spi_ll_outfifo_empty_clr(spi_dev_t * hw)295 static inline void spi_ll_outfifo_empty_clr(spi_dev_t *hw)
296 {
297 hw->dma_conf.outfifo_empty_clr = 1;
298 hw->dma_conf.outfifo_empty_clr = 0;
299 }
300
301 /*------------------------------------------------------------------------------
302 * SPI configuration for DMA
303 *----------------------------------------------------------------------------*/
304 /**
305 * Enable/Disable RX DMA (Peripherals->DMA->RAM)
306 *
307 * @param hw Beginning address of the peripheral registers.
308 * @param enable 1: enable; 2: disable
309 */
spi_ll_dma_rx_enable(spi_dev_t * hw,bool enable)310 static inline void spi_ll_dma_rx_enable(spi_dev_t *hw, bool enable)
311 {
312 //This is not used in esp32s2
313 }
314
315 /**
316 * Enable/Disable TX DMA (RAM->DMA->Peripherals)
317 *
318 * @param hw Beginning address of the peripheral registers.
319 * @param enable 1: enable; 2: disable
320 */
spi_ll_dma_tx_enable(spi_dev_t * hw,bool enable)321 static inline void spi_ll_dma_tx_enable(spi_dev_t *hw, bool enable)
322 {
323 //This is not used in esp32s2
324 }
325
326 /**
327 * Configuration of RX DMA EOF interrupt generation way
328 *
329 * @param hw Beginning address of the peripheral registers.
330 * @param enable 1: spi_dma_inlink_eof is set when the number of dma pushed data bytes is equal to the value of spi_slv/mst_dma_rd_bytelen[19:0] in spi dma transition. 0: spi_dma_inlink_eof is set by spi_trans_done in non-seg-trans or spi_dma_seg_trans_done in seg-trans.
331 */
spi_ll_dma_set_rx_eof_generation(spi_dev_t * hw,bool enable)332 static inline void spi_ll_dma_set_rx_eof_generation(spi_dev_t *hw, bool enable)
333 {
334 hw->dma_conf.rx_eof_en = enable;
335 }
336
337 /*------------------------------------------------------------------------------
338 * Buffer
339 *----------------------------------------------------------------------------*/
340 /**
341 * Write to SPI buffer.
342 *
343 * @param hw Beginning address of the peripheral registers.
344 * @param buffer_to_send Data address to copy to the buffer.
345 * @param bitlen Length to copy, in bits.
346 */
spi_ll_write_buffer(spi_dev_t * hw,const uint8_t * buffer_to_send,size_t bitlen)347 static inline void spi_ll_write_buffer(spi_dev_t *hw, const uint8_t *buffer_to_send, size_t bitlen)
348 {
349 for (size_t x = 0; x < bitlen; x += 32) {
350 //Use memcpy to get around alignment issues for txdata
351 uint32_t word;
352 memcpy(&word, &buffer_to_send[x / 8], 4);
353 hw->data_buf[(x / 32)] = word;
354 }
355 }
356
357 /**
358 * Read from SPI buffer.
359 *
360 * @param hw Beginning address of the peripheral registers.
361 * @param buffer_to_rcv Address to copy buffer data to.
362 * @param bitlen Length to copy, in bits.
363 */
spi_ll_read_buffer(spi_dev_t * hw,uint8_t * buffer_to_rcv,size_t bitlen)364 static inline void spi_ll_read_buffer(spi_dev_t *hw, uint8_t *buffer_to_rcv, size_t bitlen)
365 {
366 for (size_t x = 0; x < bitlen; x += 32) {
367 //Do a memcpy to get around possible alignment issues in rx_buffer
368 uint32_t word = hw->data_buf[x / 32];
369 int len = bitlen - x;
370 if (len > 32) {
371 len = 32;
372 }
373 memcpy(&buffer_to_rcv[x / 8], &word, (len + 7) / 8);
374 }
375 }
376
spi_ll_read_buffer_byte(spi_dev_t * hw,int byte_addr,uint8_t * out_data,int len)377 static inline void spi_ll_read_buffer_byte(spi_dev_t *hw, int byte_addr, uint8_t *out_data, int len)
378 {
379 while (len > 0) {
380 uint32_t word = hw->data_buf[byte_addr / 4];
381 int offset = byte_addr % 4;
382
383 int copy_len = 4 - offset;
384 if (copy_len > len) {
385 copy_len = len;
386 }
387
388 memcpy(out_data, ((uint8_t *)&word) + offset, copy_len);
389 byte_addr += copy_len;
390 out_data += copy_len;
391 len -= copy_len;
392 }
393 }
394
spi_ll_write_buffer_byte(spi_dev_t * hw,int byte_addr,uint8_t * data,int len)395 static inline void spi_ll_write_buffer_byte(spi_dev_t *hw, int byte_addr, uint8_t *data, int len)
396 {
397 HAL_ASSERT(byte_addr + len <= 72);
398 HAL_ASSERT(len > 0);
399 HAL_ASSERT(byte_addr >= 0);
400
401 while (len > 0) {
402 uint32_t word;
403 int offset = byte_addr % 4;
404
405 int copy_len = 4 - offset;
406 if (copy_len > len) {
407 copy_len = len;
408 }
409
410 //read-modify-write
411 if (copy_len != 4) {
412 word = hw->data_buf[byte_addr / 4];
413 }
414
415 memcpy(((uint8_t *)&word) + offset, data, copy_len);
416 hw->data_buf[byte_addr / 4] = word;
417 data += copy_len;
418 byte_addr += copy_len;
419 len -= copy_len;
420 }
421 }
422
423 /*------------------------------------------------------------------------------
424 * Configs: mode
425 *----------------------------------------------------------------------------*/
426 /**
427 * Enable/disable the postive-cs feature.
428 *
429 * @param hw Beginning address of the peripheral registers.
430 * @param cs One of the CS (0-2) to enable/disable the feature.
431 * @param pos_cs true to enable the feature, otherwise disable (default).
432 */
spi_ll_master_set_pos_cs(spi_dev_t * hw,int cs,uint32_t pos_cs)433 static inline void spi_ll_master_set_pos_cs(spi_dev_t *hw, int cs, uint32_t pos_cs)
434 {
435 if (pos_cs) {
436 hw->misc.master_cs_pol |= (1 << cs);
437 } else {
438 hw->misc.master_cs_pol &= ~(1 << cs);
439 }
440 }
441
442 /**
443 * Enable/disable the LSBFIRST feature for TX data.
444 *
445 * @param hw Beginning address of the peripheral registers.
446 * @param lsbfirst true if LSB of TX data to be sent first, otherwise MSB is sent first (default).
447 */
spi_ll_set_tx_lsbfirst(spi_dev_t * hw,bool lsbfirst)448 static inline void spi_ll_set_tx_lsbfirst(spi_dev_t *hw, bool lsbfirst)
449 {
450 hw->ctrl.wr_bit_order = lsbfirst;
451 }
452
453 /**
454 * Enable/disable the LSBFIRST feature for RX data.
455 *
456 * @param hw Beginning address of the peripheral registers.
457 * @param lsbfirst true if first bit received as LSB, otherwise as MSB (default).
458 */
spi_ll_set_rx_lsbfirst(spi_dev_t * hw,bool lsbfirst)459 static inline void spi_ll_set_rx_lsbfirst(spi_dev_t *hw, bool lsbfirst)
460 {
461 hw->ctrl.rd_bit_order = lsbfirst;
462 }
463
464 /**
465 * Set SPI mode for the peripheral as master.
466 *
467 * @param hw Beginning address of the peripheral registers.
468 * @param mode SPI mode to work at, 0-3.
469 */
spi_ll_master_set_mode(spi_dev_t * hw,uint8_t mode)470 static inline void spi_ll_master_set_mode(spi_dev_t *hw, uint8_t mode)
471 {
472 //Configure polarity
473 if (mode == 0) {
474 hw->misc.ck_idle_edge = 0;
475 hw->user.ck_out_edge = 0;
476 } else if (mode == 1) {
477 hw->misc.ck_idle_edge = 0;
478 hw->user.ck_out_edge = 1;
479 } else if (mode == 2) {
480 hw->misc.ck_idle_edge = 1;
481 hw->user.ck_out_edge = 1;
482 } else if (mode == 3) {
483 hw->misc.ck_idle_edge = 1;
484 hw->user.ck_out_edge = 0;
485 }
486 }
487
488 /**
489 * Set SPI mode for the peripheral as slave.
490 *
491 * @param hw Beginning address of the peripheral registers.
492 * @param mode SPI mode to work at, 0-3.
493 */
spi_ll_slave_set_mode(spi_dev_t * hw,const int mode,bool dma_used)494 static inline void spi_ll_slave_set_mode(spi_dev_t *hw, const int mode, bool dma_used)
495 {
496 if (mode == 0) {
497 hw->misc.ck_idle_edge = 0;
498 hw->user.rsck_i_edge = 0;
499 hw->user.tsck_i_edge = 0;
500 hw->ctrl1.clk_mode_13 = 0;
501 } else if (mode == 1) {
502 hw->misc.ck_idle_edge = 0;
503 hw->user.rsck_i_edge = 1;
504 hw->user.tsck_i_edge = 1;
505 hw->ctrl1.clk_mode_13 = 1;
506 } else if (mode == 2) {
507 hw->misc.ck_idle_edge = 1;
508 hw->user.rsck_i_edge = 1;
509 hw->user.tsck_i_edge = 1;
510 hw->ctrl1.clk_mode_13 = 0;
511 } else if (mode == 3) {
512 hw->misc.ck_idle_edge = 1;
513 hw->user.rsck_i_edge = 0;
514 hw->user.tsck_i_edge = 0;
515 hw->ctrl1.clk_mode_13 = 1;
516 }
517 hw->ctrl1.rsck_data_out = 0;
518 }
519
520 /**
521 * Set SPI to work in full duplex or half duplex mode.
522 *
523 * @param hw Beginning address of the peripheral registers.
524 * @param half_duplex true to work in half duplex mode, otherwise in full duplex mode.
525 */
spi_ll_set_half_duplex(spi_dev_t * hw,bool half_duplex)526 static inline void spi_ll_set_half_duplex(spi_dev_t *hw, bool half_duplex)
527 {
528 hw->user.doutdin = !half_duplex;
529 }
530
531 /**
532 * Set SPI to work in SIO mode or not.
533 *
534 * SIO is a mode which MOSI and MISO share a line. The device MUST work in half-duplexmode.
535 *
536 * @param hw Beginning address of the peripheral registers.
537 * @param sio_mode true to work in SIO mode, otherwise false.
538 */
spi_ll_set_sio_mode(spi_dev_t * hw,int sio_mode)539 static inline void spi_ll_set_sio_mode(spi_dev_t *hw, int sio_mode)
540 {
541 hw->user.sio = sio_mode;
542 }
543
544 /**
545 * Configure the SPI transaction line mode for the master to use.
546 *
547 * @param hw Beginning address of the peripheral registers.
548 * @param line_mode SPI transaction line mode to use, see ``spi_line_mode_t``.
549 */
spi_ll_master_set_line_mode(spi_dev_t * hw,spi_line_mode_t line_mode)550 static inline void spi_ll_master_set_line_mode(spi_dev_t *hw, spi_line_mode_t line_mode)
551 {
552 hw->ctrl.val &= ~SPI_LL_ONE_LINE_CTRL_MASK;
553 hw->user.val &= ~SPI_LL_ONE_LINE_USER_MASK;
554 hw->ctrl.fcmd_dual = (line_mode.cmd_lines == 2);
555 hw->ctrl.fcmd_quad = (line_mode.cmd_lines == 4);
556 hw->ctrl.fcmd_oct = (line_mode.cmd_lines == 8);
557 hw->ctrl.faddr_dual = (line_mode.addr_lines == 2);
558 hw->ctrl.faddr_quad = (line_mode.addr_lines == 4);
559 hw->ctrl.faddr_oct = (line_mode.addr_lines == 8);
560 hw->ctrl.fread_dual = (line_mode.data_lines == 2);
561 hw->user.fwrite_dual = (line_mode.data_lines == 2);
562 hw->ctrl.fread_quad = (line_mode.data_lines == 4);
563 hw->user.fwrite_quad = (line_mode.data_lines == 4);
564 hw->ctrl.fread_oct = (line_mode.data_lines == 8);
565 hw->user.fwrite_oct = (line_mode.data_lines == 8);
566 }
567
spi_ll_slave_set_seg_mode(spi_dev_t * hw,bool seg_trans)568 static inline void spi_ll_slave_set_seg_mode(spi_dev_t *hw, bool seg_trans)
569 {
570 hw->dma_conf.dma_seg_trans_en = seg_trans;
571 }
572
573 /**
574 * Select one of the CS to use in current transaction.
575 *
576 * @param hw Beginning address of the peripheral registers.
577 * @param cs_id The cs to use, 0-2, otherwise none of them is used.
578 */
spi_ll_master_select_cs(spi_dev_t * hw,int cs_id)579 static inline void spi_ll_master_select_cs(spi_dev_t *hw, int cs_id)
580 {
581 hw->misc.cs0_dis = (cs_id == 0) ? 0 : 1;
582 hw->misc.cs1_dis = (cs_id == 1) ? 0 : 1;
583 hw->misc.cs2_dis = (cs_id == 2) ? 0 : 1;
584 hw->misc.cs3_dis = (cs_id == 3) ? 0 : 1;
585 hw->misc.cs4_dis = (cs_id == 4) ? 0 : 1;
586 hw->misc.cs5_dis = (cs_id == 5) ? 0 : 1;
587 }
588
589 /**
590 * Keep Chip Select activated after the current transaction.
591 *
592 * @param hw Beginning address of the peripheral registers.
593 * @param keep_active if 0 don't keep CS activated, else keep CS activated
594 */
spi_ll_master_keep_cs(spi_dev_t * hw,int keep_active)595 static inline void spi_ll_master_keep_cs(spi_dev_t *hw, int keep_active)
596 {
597 hw->misc.cs_keep_active = (keep_active != 0) ? 1 : 0;
598 }
599
600 /*------------------------------------------------------------------------------
601 * Configs: parameters
602 *----------------------------------------------------------------------------*/
603 /**
604 * Set the clock for master by stored value.
605 *
606 * @param hw Beginning address of the peripheral registers.
607 * @param val stored clock configuration calculated before (by ``spi_ll_cal_clock``).
608 */
spi_ll_master_set_clock_by_reg(spi_dev_t * hw,const spi_ll_clock_val_t * val)609 static inline void spi_ll_master_set_clock_by_reg(spi_dev_t *hw, const spi_ll_clock_val_t *val)
610 {
611 hw->clock.val = *(uint32_t *)val;
612 }
613
614 /**
615 * Get the frequency of given dividers. Don't use in app.
616 *
617 * @param fapb APB clock of the system.
618 * @param pre Pre devider.
619 * @param n main divider.
620 *
621 * @return Frequency of given dividers.
622 */
spi_ll_freq_for_pre_n(int fapb,int pre,int n)623 static inline int spi_ll_freq_for_pre_n(int fapb, int pre, int n)
624 {
625 return (fapb / (pre * n));
626 }
627
628 /**
629 * Calculate the nearest frequency avaliable for master.
630 *
631 * @param fapb APB clock of the system.
632 * @param hz Frequncy desired.
633 * @param duty_cycle Duty cycle desired.
634 * @param out_reg Output address to store the calculated clock configurations for the return frequency.
635 *
636 * @return Actual (nearest) frequency.
637 */
spi_ll_master_cal_clock(int fapb,int hz,int duty_cycle,spi_ll_clock_val_t * out_reg)638 static inline int spi_ll_master_cal_clock(int fapb, int hz, int duty_cycle, spi_ll_clock_val_t *out_reg)
639 {
640 typeof(GPSPI2.clock) reg;
641 int eff_clk;
642
643 //In hw, n, h and l are 1-64, pre is 1-8K. Value written to register is one lower than used value.
644 if (hz > ((fapb / 4) * 3)) {
645 //Using Fapb directly will give us the best result here.
646 reg.clkcnt_l = 0;
647 reg.clkcnt_h = 0;
648 reg.clkcnt_n = 0;
649 reg.clkdiv_pre = 0;
650 reg.clk_equ_sysclk = 1;
651 eff_clk = fapb;
652 } else {
653 //For best duty cycle resolution, we want n to be as close to 32 as possible, but
654 //we also need a pre/n combo that gets us as close as possible to the intended freq.
655 //To do this, we bruteforce n and calculate the best pre to go along with that.
656 //If there's a choice between pre/n combos that give the same result, use the one
657 //with the higher n.
658 int pre, n, h, l;
659 int bestn = -1;
660 int bestpre = -1;
661 int besterr = 0;
662 int errval;
663 for (n = 2; n <= 64; n++) { //Start at 2: we need to be able to set h/l so we have at least one high and one low pulse.
664 //Effectively, this does pre=round((fapb/n)/hz).
665 pre = ((fapb / n) + (hz / 2)) / hz;
666 if (pre <= 0) {
667 pre = 1;
668 }
669 if (pre > 8192) {
670 pre = 8192;
671 }
672 errval = abs(spi_ll_freq_for_pre_n(fapb, pre, n) - hz);
673 if (bestn == -1 || errval <= besterr) {
674 besterr = errval;
675 bestn = n;
676 bestpre = pre;
677 }
678 }
679
680 n = bestn;
681 pre = bestpre;
682 l = n;
683 //This effectively does round((duty_cycle*n)/256)
684 h = (duty_cycle * n + 127) / 256;
685 if (h <= 0) {
686 h = 1;
687 }
688
689 reg.clk_equ_sysclk = 0;
690 reg.clkcnt_n = n - 1;
691 reg.clkdiv_pre = pre - 1;
692 reg.clkcnt_h = h - 1;
693 reg.clkcnt_l = l - 1;
694 eff_clk = spi_ll_freq_for_pre_n(fapb, pre, n);
695 }
696 if (out_reg != NULL) {
697 *(uint32_t *)out_reg = reg.val;
698 }
699 return eff_clk;
700 }
701
702 /**
703 * Calculate and set clock for SPI master according to desired parameters.
704 *
705 * This takes long, suggest to calculate the configuration during
706 * initialization by ``spi_ll_master_cal_clock`` and store the result, then
707 * configure the clock by stored value when used by
708 * ``spi_ll_msater_set_clock_by_reg``.
709 *
710 * @param hw Beginning address of the peripheral registers.
711 * @param fapb APB clock of the system.
712 * @param hz Frequncy desired.
713 * @param duty_cycle Duty cycle desired.
714 *
715 * @return Actual frequency that is used.
716 */
spi_ll_master_set_clock(spi_dev_t * hw,int fapb,int hz,int duty_cycle)717 static inline int spi_ll_master_set_clock(spi_dev_t *hw, int fapb, int hz, int duty_cycle)
718 {
719 spi_ll_clock_val_t reg_val;
720 int freq = spi_ll_master_cal_clock(fapb, hz, duty_cycle, ®_val);
721 spi_ll_master_set_clock_by_reg(hw, ®_val);
722 return freq;
723 }
724
725 /**
726 * Set the mosi delay after the output edge to the signal. (Preview)
727 *
728 * The delay mode/num is a Espressif conception, may change in the new chips.
729 *
730 * @param hw Beginning address of the peripheral registers.
731 * @param delay_mode Delay mode, see TRM.
732 * @param delay_num APB clocks to delay.
733 */
spi_ll_set_mosi_delay(spi_dev_t * hw,int delay_mode,int delay_num)734 static inline void spi_ll_set_mosi_delay(spi_dev_t *hw, int delay_mode, int delay_num)
735 {
736 //TODO: this doesn't make sense
737 hw->dout_num.dout0_num = 0;
738 hw->dout_num.dout1_num = 0;
739 }
740
741 /**
742 * Set the miso delay applied to the input signal before the internal peripheral. (Preview)
743 *
744 * The delay mode/num is a Espressif conception, may change in the new chips.
745 *
746 * @param hw Beginning address of the peripheral registers.
747 * @param delay_mode Delay mode, see TRM.
748 * @param delay_num APB clocks to delay.
749 */
spi_ll_set_miso_delay(spi_dev_t * hw,int delay_mode,int delay_num)750 static inline void spi_ll_set_miso_delay(spi_dev_t *hw, int delay_mode, int delay_num)
751 {
752 //TODO: this doesn't make sense
753 hw->din_num.din0_num = 1;
754 hw->din_num.din1_num = 1;
755 }
756
757 /**
758 * Set dummy clocks to output before RX phase (master), or clocks to skip
759 * before the data phase and after the address phase (slave).
760 *
761 * Note this phase is also used to compensate RX timing in half duplex mode.
762 *
763 * @param hw Beginning address of the peripheral registers.
764 * @param dummy_n Dummy cycles used. 0 to disable the dummy phase.
765 */
spi_ll_set_dummy(spi_dev_t * hw,int dummy_n)766 static inline void spi_ll_set_dummy(spi_dev_t *hw, int dummy_n)
767 {
768 hw->user.usr_dummy = dummy_n ? 1 : 0;
769 HAL_FORCE_MODIFY_U32_REG_FIELD(hw->user1, usr_dummy_cyclelen, dummy_n - 1);
770 }
771
772 /**
773 * Set the delay of SPI clocks before the CS inactive edge after the last SPI clock.
774 *
775 * @param hw Beginning address of the peripheral registers.
776 * @param hold Delay of SPI clocks after the last clock, 0 to disable the hold phase.
777 */
spi_ll_master_set_cs_hold(spi_dev_t * hw,int hold)778 static inline void spi_ll_master_set_cs_hold(spi_dev_t *hw, int hold)
779 {
780 hw->ctrl2.cs_hold_time = hold;
781 hw->user.cs_hold = hold ? 1 : 0;
782 }
783
784 /**
785 * Set the delay of SPI clocks before the first SPI clock after the CS active edge.
786 *
787 * Note ESP32 doesn't support to use this feature when command/address phases
788 * are used in full duplex mode.
789 *
790 * @param hw Beginning address of the peripheral registers.
791 * @param setup Delay of SPI clocks after the CS active edge, 0 to disable the setup phase.
792 */
spi_ll_master_set_cs_setup(spi_dev_t * hw,uint8_t setup)793 static inline void spi_ll_master_set_cs_setup(spi_dev_t *hw, uint8_t setup)
794 {
795 hw->ctrl2.cs_setup_time = setup - 1;
796 hw->user.cs_setup = setup ? 1 : 0;
797 }
798
799 /**
800 * Enable/disable the segment transfer feature for the slave.
801 *
802 * @param hw Beginning address of the peripheral registers.
803 * @param en true to enable, false to disable.
804 */
spi_ll_slave_set_seg_en(spi_dev_t * hw,bool en)805 static inline void spi_ll_slave_set_seg_en(spi_dev_t *hw, bool en)
806 {
807 hw->dma_conf.dma_seg_trans_en = en;
808 }
809
810 /*------------------------------------------------------------------------------
811 * Configs: data
812 *----------------------------------------------------------------------------*/
813 /**
814 * Set the input length (master).
815 *
816 * @param hw Beginning address of the peripheral registers.
817 * @param bitlen input length, in bits.
818 */
spi_ll_set_miso_bitlen(spi_dev_t * hw,size_t bitlen)819 static inline void spi_ll_set_miso_bitlen(spi_dev_t *hw, size_t bitlen)
820 {
821 hw->miso_dlen.usr_miso_bit_len = bitlen - 1;
822 }
823
824 /**
825 * Set the output length (master).
826 *
827 * @param hw Beginning address of the peripheral registers.
828 * @param bitlen output length, in bits.
829 */
spi_ll_set_mosi_bitlen(spi_dev_t * hw,size_t bitlen)830 static inline void spi_ll_set_mosi_bitlen(spi_dev_t *hw, size_t bitlen)
831 {
832 hw->mosi_dlen.usr_mosi_bit_len = bitlen - 1;
833 }
834
835 /**
836 * Set the maximum input length (slave).
837 *
838 * @param hw Beginning address of the peripheral registers.
839 * @param bitlen input length, in bits.
840 */
spi_ll_slave_set_rx_bitlen(spi_dev_t * hw,size_t bitlen)841 static inline void spi_ll_slave_set_rx_bitlen(spi_dev_t *hw, size_t bitlen)
842 {
843 //This is not used in esp32s2
844 }
845
846 /**
847 * Set the maximum output length (slave).
848 *
849 * @param hw Beginning address of the peripheral registers.
850 * @param bitlen output length, in bits.
851 */
spi_ll_slave_set_tx_bitlen(spi_dev_t * hw,size_t bitlen)852 static inline void spi_ll_slave_set_tx_bitlen(spi_dev_t *hw, size_t bitlen)
853 {
854 //This is not used in esp32s2
855 }
856
857 /**
858 * Set the length of command phase.
859 *
860 * When in 4-bit mode, the SPI cycles of the phase will be shorter. E.g. 16-bit
861 * command phases takes 4 cycles in 4-bit mode.
862 *
863 * @param hw Beginning address of the peripheral registers.
864 * @param bitlen Length of command phase, in bits. 0 to disable the command phase.
865 */
spi_ll_set_command_bitlen(spi_dev_t * hw,int bitlen)866 static inline void spi_ll_set_command_bitlen(spi_dev_t *hw, int bitlen)
867 {
868 hw->user2.usr_command_bitlen = bitlen - 1;
869 hw->user.usr_command = bitlen ? 1 : 0;
870 }
871
872 /**
873 * Set the length of address phase.
874 *
875 * When in 4-bit mode, the SPI cycles of the phase will be shorter. E.g. 16-bit
876 * address phases takes 4 cycles in 4-bit mode.
877 *
878 * @param hw Beginning address of the peripheral registers.
879 * @param bitlen Length of address phase, in bits. 0 to disable the address phase.
880 */
spi_ll_set_addr_bitlen(spi_dev_t * hw,int bitlen)881 static inline void spi_ll_set_addr_bitlen(spi_dev_t *hw, int bitlen)
882 {
883 hw->user1.usr_addr_bitlen = bitlen - 1;
884 hw->user.usr_addr = bitlen ? 1 : 0;
885 }
886
887 /**
888 * Set the address value in an intuitive way.
889 *
890 * The length and lsbfirst is required to shift and swap the address to the right place.
891 *
892 * @param hw Beginning address of the peripheral registers.
893 * @param address Address to set
894 * @param addrlen Length of the address phase
895 * @param lsbfirst whether the LSB first feature is enabled.
896 */
spi_ll_set_address(spi_dev_t * hw,uint64_t addr,int addrlen,uint32_t lsbfirst)897 static inline void spi_ll_set_address(spi_dev_t *hw, uint64_t addr, int addrlen, uint32_t lsbfirst)
898 {
899 if (lsbfirst) {
900 /* The output address start from the LSB of the highest byte, i.e.
901 * addr[24] -> addr[31]
902 * ...
903 * addr[0] -> addr[7]
904 * So swap the byte order to let the LSB sent first.
905 */
906 addr = HAL_SWAP32(addr);
907 //otherwise only addr register is sent
908 hw->addr = addr;
909 } else {
910 // shift the address to MSB of addr register.
911 // output address will be sent from MSB to LSB of addr register
912 hw->addr = addr << (32 - addrlen);
913 }
914 }
915
916 /**
917 * Set the command value in an intuitive way.
918 *
919 * The length and lsbfirst is required to shift and swap the command to the right place.
920 *
921 * @param hw Beginning command of the peripheral registers.
922 * @param command Command to set
923 * @param addrlen Length of the command phase
924 * @param lsbfirst whether the LSB first feature is enabled.
925 */
spi_ll_set_command(spi_dev_t * hw,uint16_t cmd,int cmdlen,bool lsbfirst)926 static inline void spi_ll_set_command(spi_dev_t *hw, uint16_t cmd, int cmdlen, bool lsbfirst)
927 {
928 if (lsbfirst) {
929 // The output command start from bit0 to bit 15, kept as is.
930 HAL_FORCE_MODIFY_U32_REG_FIELD(hw->user2, usr_command_value, cmd);
931 } else {
932 /* Output command will be sent from bit 7 to 0 of command_value, and
933 * then bit 15 to 8 of the same register field. Shift and swap to send
934 * more straightly.
935 */
936 HAL_FORCE_MODIFY_U32_REG_FIELD(hw->user2, usr_command_value, HAL_SPI_SWAP_DATA_TX(cmd, cmdlen));
937
938 }
939 }
940
941 /**
942 * Enable/disable the RX data phase.
943 *
944 * @param hw Beginning address of the peripheral registers.
945 * @param enable true if RX phase exist, otherwise false.
946 */
spi_ll_enable_miso(spi_dev_t * hw,int enable)947 static inline void spi_ll_enable_miso(spi_dev_t *hw, int enable)
948 {
949 hw->user.usr_miso = enable;
950 }
951
952 /**
953 * Enable/disable the TX data phase.
954 *
955 * @param hw Beginning address of the peripheral registers.
956 * @param enable true if TX phase exist, otherwise false.
957 */
spi_ll_enable_mosi(spi_dev_t * hw,int enable)958 static inline void spi_ll_enable_mosi(spi_dev_t *hw, int enable)
959 {
960 hw->user.usr_mosi = enable;
961 }
962
963 /**
964 * Reset the slave peripheral before next transaction.
965 *
966 * @param hw Beginning address of the peripheral registers.
967 */
spi_ll_slave_reset(spi_dev_t * hw)968 static inline void spi_ll_slave_reset(spi_dev_t *hw)
969 {
970 hw->slave.soft_reset = 1;
971 hw->slave.soft_reset = 0;
972 }
973
974 /**
975 * Get the received bit length of the slave.
976 *
977 * @param hw Beginning address of the peripheral registers.
978 *
979 * @return Received bits of the slave.
980 */
spi_ll_slave_get_rcv_bitlen(spi_dev_t * hw)981 static inline uint32_t spi_ll_slave_get_rcv_bitlen(spi_dev_t *hw)
982 {
983 return hw->slv_rd_byte.data_bytelen * 8;
984 }
985
986 /*------------------------------------------------------------------------------
987 * Interrupts
988 *----------------------------------------------------------------------------*/
989 //helper macros to generate code for each interrupts
990 #define FOR_EACH_ITEM(op, list) do { list(op) } while(0)
991 #define INTR_LIST(item) \
992 item(SPI_LL_INTR_TRANS_DONE, slave.int_trans_done_en, slave.trans_done, slave.trans_done=0) \
993 item(SPI_LL_INTR_RDBUF, slave.int_rd_buf_done_en, slv_rdbuf_dlen.rd_buf_done, slv_rdbuf_dlen.rd_buf_done=0) \
994 item(SPI_LL_INTR_WRBUF, slave.int_wr_buf_done_en, slv_wrbuf_dlen.wr_buf_done, slv_wrbuf_dlen.wr_buf_done=0) \
995 item(SPI_LL_INTR_RDDMA, slave.int_rd_dma_done_en, slv_rd_byte.rd_dma_done, slv_rd_byte.rd_dma_done=0) \
996 item(SPI_LL_INTR_WRDMA, slave.int_wr_dma_done_en, slave1.wr_dma_done, slave1.wr_dma_done=0) \
997 item(SPI_LL_INTR_IN_SUC_EOF, dma_int_ena.in_suc_eof, dma_int_raw.in_suc_eof, dma_int_clr.in_suc_eof=1) \
998 item(SPI_LL_INTR_OUT_EOF, dma_int_ena.out_eof, dma_int_raw.out_eof, dma_int_clr.out_eof=1) \
999 item(SPI_LL_INTR_OUT_TOTAL_EOF, dma_int_ena.out_total_eof, dma_int_raw.out_total_eof, dma_int_clr.out_total_eof=1) \
1000 item(SPI_LL_INTR_SEG_DONE, slave.int_dma_seg_trans_en, hold.dma_seg_trans_done, hold.dma_seg_trans_done=0) \
1001 item(SPI_LL_INTR_IN_FULL, dma_int_ena.infifo_full_err, dma_int_raw.infifo_full_err, dma_int_clr.infifo_full_err=1) \
1002 item(SPI_LL_INTR_OUT_EMPTY, dma_int_ena.outfifo_empty_err, dma_int_raw.outfifo_empty_err, dma_int_clr.outfifo_empty_err=1) \
1003 item(SPI_LL_INTR_CMD7, dma_int_ena.cmd7, dma_int_raw.cmd7, dma_int_clr.cmd7=1) \
1004 item(SPI_LL_INTR_CMD8, dma_int_ena.cmd8, dma_int_raw.cmd8, dma_int_clr.cmd8=1) \
1005 item(SPI_LL_INTR_CMD9, dma_int_ena.cmd9, dma_int_raw.cmd9, dma_int_clr.cmd9=1) \
1006 item(SPI_LL_INTR_CMDA, dma_int_ena.cmda, dma_int_raw.cmda, dma_int_clr.cmda=1)
1007
1008
1009 __attribute__((always_inline))
spi_ll_enable_intr(spi_dev_t * hw,spi_ll_intr_t intr_mask)1010 static inline void spi_ll_enable_intr(spi_dev_t *hw, spi_ll_intr_t intr_mask)
1011 {
1012 #define ENA_INTR(intr_bit, en_reg, ...) if (intr_mask & (intr_bit)) hw->en_reg = 1;
1013 FOR_EACH_ITEM(ENA_INTR, INTR_LIST);
1014 #undef ENA_INTR
1015 }
1016
1017 __attribute__((always_inline))
spi_ll_disable_intr(spi_dev_t * hw,spi_ll_intr_t intr_mask)1018 static inline void spi_ll_disable_intr(spi_dev_t *hw, spi_ll_intr_t intr_mask)
1019 {
1020 #define DIS_INTR(intr_bit, en_reg, ...) if (intr_mask & (intr_bit)) hw->en_reg = 0;
1021 FOR_EACH_ITEM(DIS_INTR, INTR_LIST);
1022 #undef DIS_INTR
1023 }
1024
spi_ll_set_intr(spi_dev_t * hw,spi_ll_intr_t intr_mask)1025 static inline void spi_ll_set_intr(spi_dev_t *hw, spi_ll_intr_t intr_mask)
1026 {
1027 #define SET_INTR(intr_bit, _, st_reg, ...) if (intr_mask & (intr_bit)) hw->st_reg = 1;
1028 FOR_EACH_ITEM(SET_INTR, INTR_LIST);
1029 #undef SET_INTR
1030 }
1031
1032 __attribute__((always_inline))
spi_ll_clear_intr(spi_dev_t * hw,spi_ll_intr_t intr_mask)1033 static inline void spi_ll_clear_intr(spi_dev_t *hw, spi_ll_intr_t intr_mask)
1034 {
1035 #define CLR_INTR(intr_bit, _, __, clr_reg) if (intr_mask & (intr_bit)) hw->clr_reg;
1036 FOR_EACH_ITEM(CLR_INTR, INTR_LIST);
1037 #undef CLR_INTR
1038 }
1039
1040 __attribute__((always_inline))
spi_ll_get_intr(spi_dev_t * hw,spi_ll_intr_t intr_mask)1041 static inline bool spi_ll_get_intr(spi_dev_t *hw, spi_ll_intr_t intr_mask)
1042 {
1043 #define GET_INTR(intr_bit, _, st_reg, ...) if (intr_mask & (intr_bit) && hw->st_reg) return true;
1044 FOR_EACH_ITEM(GET_INTR, INTR_LIST);
1045 return false;
1046 #undef GET_INTR
1047 }
1048
1049 #undef FOR_EACH_ITEM
1050 #undef INTR_LIST
1051
1052 /**
1053 * Disable the trans_done interrupt.
1054 *
1055 * @param hw Beginning address of the peripheral registers.
1056 */
spi_ll_disable_int(spi_dev_t * hw)1057 static inline void spi_ll_disable_int(spi_dev_t *hw)
1058 {
1059 hw->slave.int_trans_done_en = 0;
1060 }
1061
1062 /**
1063 * Clear the trans_done interrupt.
1064 *
1065 * @param hw Beginning address of the peripheral registers.
1066 */
spi_ll_clear_int_stat(spi_dev_t * hw)1067 static inline void spi_ll_clear_int_stat(spi_dev_t *hw)
1068 {
1069 hw->slave.trans_done = 0;
1070 }
1071
1072 /**
1073 * Set the trans_done interrupt.
1074 *
1075 * @param hw Beginning address of the peripheral registers.
1076 */
spi_ll_set_int_stat(spi_dev_t * hw)1077 static inline void spi_ll_set_int_stat(spi_dev_t *hw)
1078 {
1079 hw->slave.trans_done = 1;
1080 }
1081
1082 /**
1083 * Enable the trans_done interrupt.
1084 *
1085 * @param hw Beginning address of the peripheral registers.
1086 */
spi_ll_enable_int(spi_dev_t * hw)1087 static inline void spi_ll_enable_int(spi_dev_t *hw)
1088 {
1089 hw->slave.int_trans_done_en = 1;
1090 }
1091
1092 /*------------------------------------------------------------------------------
1093 * Slave HD
1094 *----------------------------------------------------------------------------*/
spi_ll_slave_hd_set_len_cond(spi_dev_t * hw,spi_ll_trans_len_cond_t cond_mask)1095 static inline void spi_ll_slave_hd_set_len_cond(spi_dev_t *hw, spi_ll_trans_len_cond_t cond_mask)
1096 {
1097 hw->slv_rd_byte.rdbuf_bytelen_en = (cond_mask & SPI_LL_TRANS_LEN_COND_RDBUF) ? 1 : 0;
1098 hw->slv_rd_byte.wrbuf_bytelen_en = (cond_mask & SPI_LL_TRANS_LEN_COND_WRBUF) ? 1 : 0;
1099 hw->slv_rd_byte.rddma_bytelen_en = (cond_mask & SPI_LL_TRANS_LEN_COND_RDDMA) ? 1 : 0;
1100 hw->slv_rd_byte.wrdma_bytelen_en = (cond_mask & SPI_LL_TRANS_LEN_COND_WRDMA) ? 1 : 0;
1101 }
1102
spi_ll_slave_get_rx_byte_len(spi_dev_t * hw)1103 static inline int spi_ll_slave_get_rx_byte_len(spi_dev_t *hw)
1104 {
1105 return hw->slv_rd_byte.data_bytelen;
1106 }
1107
spi_ll_slave_hd_get_last_addr(spi_dev_t * hw)1108 static inline uint32_t spi_ll_slave_hd_get_last_addr(spi_dev_t *hw)
1109 {
1110 return HAL_FORCE_READ_U32_REG_FIELD(hw->slave1, last_addr);
1111 }
1112
1113 /*------------------------------------------------------------------------------
1114 * DMA:
1115 * RX DMA (Peripherals->DMA->RAM)
1116 * TX DMA (RAM->DMA->Peripherals)
1117 *----------------------------------------------------------------------------*/
1118 //---------------------------------------------------RX-------------------------------------------------//
1119 /**
1120 * Reset RX DMA which stores the data received from a peripheral into RAM.
1121 *
1122 * @param dma_in Beginning address of the DMA peripheral registers which stores the data received from a peripheral into RAM.
1123 * @param channel DMA channel, for chip version compatibility, not used.
1124 */
spi_dma_ll_rx_reset(spi_dma_dev_t * dma_in,uint32_t channel)1125 static inline void spi_dma_ll_rx_reset(spi_dma_dev_t *dma_in, uint32_t channel)
1126 {
1127 dma_in->dma_conf.in_rst = 1;
1128 dma_in->dma_conf.in_rst = 0;
1129 }
1130
1131 /**
1132 * Start RX DMA.
1133 *
1134 * @param dma_in Beginning address of the DMA peripheral registers which stores the data received from a peripheral into RAM.
1135 * @param channel DMA channel, for chip version compatibility, not used.
1136 * @param addr Address of the beginning DMA descriptor.
1137 */
spi_dma_ll_rx_start(spi_dma_dev_t * dma_in,uint32_t channel,lldesc_t * addr)1138 static inline void spi_dma_ll_rx_start(spi_dma_dev_t *dma_in, uint32_t channel, lldesc_t *addr)
1139 {
1140 dma_in->dma_in_link.addr = (int) addr & 0xFFFFF;
1141 dma_in->dma_in_link.start = 1;
1142 }
1143
1144 /**
1145 * Stop RX DMA.
1146 *
1147 * @param dma_in Beginning address of the DMA peripheral registers which stores the data received from a peripheral into RAM.
1148 * @param channel DMA channel, for chip version compatibility, not used.
1149 */
spi_dma_ll_rx_stop(spi_dma_dev_t * dma_in,uint32_t channel)1150 static inline void spi_dma_ll_rx_stop(spi_dma_dev_t *dma_in, uint32_t channel)
1151 {
1152 dma_in->dma_in_link.stop = 1;
1153 }
1154
1155 /**
1156 * Enable DMA RX channel burst for data
1157 *
1158 * @param dma_in Beginning address of the DMA peripheral registers which stores the data received from a peripheral into RAM.
1159 * @param channel DMA channel, for chip version compatibility, not used.
1160 * @param enable True to enable, false to disable
1161 */
spi_dma_ll_rx_enable_burst_data(spi_dma_dev_t * dma_in,uint32_t channel,bool enable)1162 static inline void spi_dma_ll_rx_enable_burst_data(spi_dma_dev_t *dma_in, uint32_t channel, bool enable)
1163 {
1164 //This is not supported in esp32s2
1165 }
1166
1167 /**
1168 * Enable DMA RX channel burst for descriptor
1169 *
1170 * @param dma_in Beginning address of the DMA peripheral registers which stores the data received from a peripheral into RAM.
1171 * @param channel DMA channel, for chip version compatibility, not used.
1172 * @param enable True to enable, false to disable
1173 */
spi_dma_ll_rx_enable_burst_desc(spi_dma_dev_t * dma_in,uint32_t channel,bool enable)1174 static inline void spi_dma_ll_rx_enable_burst_desc(spi_dma_dev_t *dma_in, uint32_t channel, bool enable)
1175 {
1176 dma_in->dma_conf.indscr_burst_en = enable;
1177 }
1178
1179 /**
1180 * Get the last inlink descriptor address when DMA produces in_suc_eof interrupt
1181 *
1182 * @param dma_in Beginning address of the DMA peripheral registers which stores the data received from a peripheral into RAM.
1183 * @param channel DMA channel, for chip version compatibility, not used.
1184 * @return The address
1185 */
1186 __attribute__((always_inline))
spi_dma_ll_get_in_suc_eof_desc_addr(spi_dma_dev_t * dma_in,uint32_t channel)1187 static inline uint32_t spi_dma_ll_get_in_suc_eof_desc_addr(spi_dma_dev_t *dma_in, uint32_t channel)
1188 {
1189 return dma_in->dma_in_suc_eof_des_addr;
1190 }
1191
1192 //---------------------------------------------------TX-------------------------------------------------//
1193 /**
1194 * Reset TX DMA which transmits the data from RAM to a peripheral.
1195 *
1196 * @param dma_out Beginning address of the DMA peripheral registers which transmits the data from RAM to a peripheral.
1197 * @param channel DMA channel, for chip version compatibility, not used.
1198 */
spi_dma_ll_tx_reset(spi_dma_dev_t * dma_out,uint32_t channel)1199 static inline void spi_dma_ll_tx_reset(spi_dma_dev_t *dma_out, uint32_t channel)
1200 {
1201 //Reset TX DMA peripheral
1202 dma_out->dma_conf.out_rst = 1;
1203 dma_out->dma_conf.out_rst = 0;
1204 }
1205
1206 /**
1207 * Start TX DMA.
1208 *
1209 * @param dma_out Beginning address of the DMA peripheral registers which transmits the data from RAM to a peripheral.
1210 * @param channel DMA channel, for chip version compatibility, not used.
1211 * @param addr Address of the beginning DMA descriptor.
1212 */
spi_dma_ll_tx_start(spi_dma_dev_t * dma_out,uint32_t channel,lldesc_t * addr)1213 static inline void spi_dma_ll_tx_start(spi_dma_dev_t *dma_out, uint32_t channel, lldesc_t *addr)
1214 {
1215 dma_out->dma_out_link.addr = (int) addr & 0xFFFFF;
1216 dma_out->dma_out_link.start = 1;
1217 }
1218
1219 /**
1220 * Stop TX DMA.
1221 *
1222 * @param dma_out Beginning address of the DMA peripheral registers which transmits the data from RAM to a peripheral.
1223 * @param channel DMA channel, for chip version compatibility, not used.
1224 */
spi_dma_ll_tx_stop(spi_dma_dev_t * dma_out,uint32_t channel)1225 static inline void spi_dma_ll_tx_stop(spi_dma_dev_t *dma_out, uint32_t channel)
1226 {
1227 dma_out->dma_out_link.stop = 1;
1228 }
1229
1230 /**
1231 * Enable DMA TX channel burst for data
1232 *
1233 * @param dma_out Beginning address of the DMA peripheral registers which transmits the data from RAM to a peripheral.
1234 * @param channel DMA channel, for chip version compatibility, not used.
1235 * @param enable True to enable, false to disable
1236 */
spi_dma_ll_tx_enable_burst_data(spi_dma_dev_t * dma_out,uint32_t channel,bool enable)1237 static inline void spi_dma_ll_tx_enable_burst_data(spi_dma_dev_t *dma_out, uint32_t channel, bool enable)
1238 {
1239 dma_out->dma_conf.out_data_burst_en = enable;
1240 }
1241
1242 /**
1243 * Enable DMA TX channel burst for descriptor
1244 *
1245 * @param dma_out Beginning address of the DMA peripheral registers which transmits the data from RAM to a peripheral.
1246 * @param channel DMA channel, for chip version compatibility, not used.
1247 * @param enable True to enable, false to disable
1248 */
spi_dma_ll_tx_enable_burst_desc(spi_dma_dev_t * dma_out,uint32_t channel,bool enable)1249 static inline void spi_dma_ll_tx_enable_burst_desc(spi_dma_dev_t *dma_out, uint32_t channel, bool enable)
1250 {
1251 dma_out->dma_conf.outdscr_burst_en = enable;
1252 }
1253
1254 /**
1255 * Configuration of OUT EOF flag generation way
1256 *
1257 * @param dma_out Beginning address of the DMA peripheral registers which transmits the data from RAM to a peripheral.
1258 * @param channel DMA channel, for chip version compatibility, not used.
1259 * @param enable 1: when dma pop all data from fifo 0:when ahb push all data to fifo.
1260 */
spi_dma_ll_set_out_eof_generation(spi_dma_dev_t * dma_out,uint32_t channel,bool enable)1261 static inline void spi_dma_ll_set_out_eof_generation(spi_dma_dev_t *dma_out, uint32_t channel, bool enable)
1262 {
1263 dma_out->dma_conf.out_eof_mode = enable;
1264 }
1265
1266 /**
1267 * Enable automatic outlink-writeback
1268 *
1269 * @param dma_out Beginning address of the DMA peripheral registers which transmits the data from RAM to a peripheral.
1270 * @param channel DMA channel, for chip version compatibility, not used.
1271 * @param enable True to enable, false to disable
1272 */
spi_dma_ll_enable_out_auto_wrback(spi_dma_dev_t * dma_out,uint32_t channel,bool enable)1273 static inline void spi_dma_ll_enable_out_auto_wrback(spi_dma_dev_t *dma_out, uint32_t channel, bool enable)
1274 {
1275 dma_out->dma_conf.out_auto_wrback = enable;
1276 }
1277
1278 /**
1279 * Get the last outlink descriptor address when DMA produces out_eof intrrupt
1280 *
1281 * @param dma_out Beginning address of the DMA peripheral registers which transmits the data from RAM to a peripheral.
1282 * @param channel DMA channel, for chip version compatibility, not used.
1283 * @return The address
1284 */
1285 __attribute__((always_inline))
spi_dma_ll_get_out_eof_desc_addr(spi_dma_dev_t * dma_out,uint32_t channel)1286 static inline uint32_t spi_dma_ll_get_out_eof_desc_addr(spi_dma_dev_t *dma_out, uint32_t channel)
1287 {
1288 return dma_out->dma_out_eof_des_addr;
1289 }
1290
spi_dma_ll_rx_restart(spi_dma_dev_t * dma_in,uint32_t channel)1291 static inline void spi_dma_ll_rx_restart(spi_dma_dev_t *dma_in, uint32_t channel)
1292 {
1293 dma_in->dma_in_link.restart = 1;
1294 }
1295
spi_dma_ll_tx_restart(spi_dma_dev_t * dma_out,uint32_t channel)1296 static inline void spi_dma_ll_tx_restart(spi_dma_dev_t *dma_out, uint32_t channel)
1297 {
1298 dma_out->dma_out_link.restart = 1;
1299 }
1300
spi_dma_ll_rx_disable(spi_dma_dev_t * dma_in)1301 static inline void spi_dma_ll_rx_disable(spi_dma_dev_t *dma_in)
1302 {
1303 dma_in->dma_in_link.dma_rx_ena = 0;
1304 }
1305
spi_dma_ll_tx_disable(spi_dma_dev_t * dma_out)1306 static inline void spi_dma_ll_tx_disable(spi_dma_dev_t *dma_out)
1307 {
1308 dma_out->dma_out_link.dma_tx_ena = 0;
1309 }
1310
spi_ll_tx_get_empty_err(spi_dev_t * hw)1311 static inline bool spi_ll_tx_get_empty_err(spi_dev_t *hw)
1312 {
1313 return hw->dma_int_raw.outfifo_empty_err;
1314 }
1315
1316 #undef SPI_LL_RST_MASK
1317 #undef SPI_LL_UNUSED_INT_MASK
1318
1319 /**
1320 * Get the base spi command in esp32s2
1321 *
1322 * @param cmd_t Command value
1323 */
spi_ll_get_slave_hd_base_command(spi_command_t cmd_t)1324 static inline uint8_t spi_ll_get_slave_hd_base_command(spi_command_t cmd_t)
1325 {
1326 uint8_t cmd_base = 0x00;
1327 switch (cmd_t)
1328 {
1329 case SPI_CMD_HD_WRBUF:
1330 cmd_base = SPI_LL_BASE_CMD_HD_WRBUF;
1331 break;
1332 case SPI_CMD_HD_RDBUF:
1333 cmd_base = SPI_LL_BASE_CMD_HD_RDBUF;
1334 break;
1335 case SPI_CMD_HD_WRDMA:
1336 cmd_base = SPI_LL_BASE_CMD_HD_WRDMA;
1337 break;
1338 case SPI_CMD_HD_RDDMA:
1339 cmd_base = SPI_LL_BASE_CMD_HD_RDDMA;
1340 break;
1341 case SPI_CMD_HD_SEG_END:
1342 cmd_base = SPI_LL_BASE_CMD_HD_SEG_END;
1343 break;
1344 case SPI_CMD_HD_EN_QPI:
1345 cmd_base = SPI_LL_BASE_CMD_HD_EN_QPI;
1346 break;
1347 case SPI_CMD_HD_WR_END:
1348 cmd_base = SPI_LL_BASE_CMD_HD_WR_END;
1349 break;
1350 case SPI_CMD_HD_INT0:
1351 cmd_base = SPI_LL_BASE_CMD_HD_INT0;
1352 break;
1353 case SPI_CMD_HD_INT1:
1354 cmd_base = SPI_LL_BASE_CMD_HD_INT1;
1355 break;
1356 case SPI_CMD_HD_INT2:
1357 cmd_base = SPI_LL_BASE_CMD_HD_INT2;
1358 break;
1359 default:
1360 HAL_ASSERT(cmd_base);
1361 }
1362 return cmd_base;
1363 }
1364
1365 /**
1366 * Get the spi communication command
1367 *
1368 * @param cmd_t Base command value
1369 * @param line_mode Line mode of SPI transaction phases: CMD, ADDR, DOUT/DIN.
1370 */
spi_ll_get_slave_hd_command(spi_command_t cmd_t,spi_line_mode_t line_mode)1371 static inline uint16_t spi_ll_get_slave_hd_command(spi_command_t cmd_t, spi_line_mode_t line_mode)
1372 {
1373 uint8_t cmd_base = spi_ll_get_slave_hd_base_command(cmd_t);
1374 uint8_t cmd_mod = 0x00; //CMD:1-bit, ADDR:1-bit, DATA:1-bit
1375
1376 if (line_mode.data_lines == 2) {
1377 if (line_mode.addr_lines == 2) {
1378 cmd_mod = 0x50; //CMD:1-bit, ADDR:2-bit, DATA:2-bit
1379 } else {
1380 cmd_mod = 0x10; //CMD:1-bit, ADDR:1-bit, DATA:2-bit
1381 }
1382 } else if (line_mode.data_lines == 4) {
1383 if (line_mode.addr_lines == 4) {
1384 cmd_mod = 0xA0; //CMD:1-bit, ADDR:4-bit, DATA:4-bit
1385 } else {
1386 cmd_mod = 0x20; //CMD:1-bit, ADDR:1-bit, DATA:4-bit
1387 }
1388 }
1389 if (cmd_base == SPI_LL_BASE_CMD_HD_SEG_END || cmd_base == SPI_LL_BASE_CMD_HD_EN_QPI) {
1390 cmd_mod = 0x00;
1391 }
1392
1393 return cmd_base | cmd_mod;
1394 }
1395
1396 /**
1397 * Get the dummy bits
1398 *
1399 * @param line_mode Line mode of SPI transaction phases: CMD, ADDR, DOUT/DIN.
1400 */
spi_ll_get_slave_hd_dummy_bits(spi_line_mode_t line_mode)1401 static inline int spi_ll_get_slave_hd_dummy_bits(spi_line_mode_t line_mode)
1402 {
1403 uint8_t dummy_bits = 0;
1404
1405 if (line_mode.data_lines == 2) {
1406 dummy_bits = 4;
1407 } else if (line_mode.data_lines == 4) {
1408 dummy_bits = 4;
1409 } else {
1410 dummy_bits = 8;
1411 }
1412
1413 HAL_ASSERT(dummy_bits);
1414 return dummy_bits;
1415 }
1416
1417 #ifdef __cplusplus
1418 }
1419 #endif
1420