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, &reg_val);
721     spi_ll_master_set_clock_by_reg(hw, &reg_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