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