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 SPI register operations
14 
15 #pragma once
16 
17 #include <string.h>
18 #include <stdlib.h> //for abs()
19 #include "esp_types.h"
20 #include "esp32/rom/lldesc.h"
21 #include "soc/spi_periph.h"
22 #include "soc/spi_struct.h"
23 #include "hal/misc.h"
24 #include "hal/spi_types.h"
25 #include "hal/assert.h"
26 
27 #ifdef __cplusplus
28 extern "C" {
29 #endif
30 
31 /// Registers to reset during initialization. Don't use in app.
32 #define SPI_LL_DMA_FIFO_RST_MASK (SPI_AHBM_RST | SPI_AHBM_FIFO_RST)
33 /// Interrupt not used. Don't use in app.
34 #define SPI_LL_UNUSED_INT_MASK  (SPI_INT_EN | SPI_SLV_WR_STA_DONE | SPI_SLV_RD_STA_DONE | SPI_SLV_WR_BUF_DONE | SPI_SLV_RD_BUF_DONE)
35 /// These 2 masks together will set SPI transaction to one line mode
36 #define SPI_LL_ONE_LINE_CTRL_MASK (SPI_FREAD_DUAL | SPI_FREAD_QUAD | SPI_FREAD_DIO | SPI_FREAD_QIO)
37 #define SPI_LL_ONE_LINE_USER_MASK (SPI_FWRITE_DUAL | SPI_FWRITE_QUAD | SPI_FWRITE_DIO | SPI_FWRITE_QIO)
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? &SPI1:((ID)==1? &SPI2 : &SPI3))
41 
42 #define SPI_LL_DMA_MAX_BIT_LEN    (1 << 24)    //reg len: 24 bits
43 #define SPI_LL_CPU_MAX_BIT_LEN    (16 * 32)    //Fifo len: 16 words
44 #define SPI_LL_MOSI_FREE_LEVEL    0            //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 
53 //On ESP32-S2 and earlier chips, DMA registers are part of SPI registers. So set the registers of SPI peripheral to control DMA.
54 typedef spi_dev_t spi_dma_dev_t;
55 
56 /*------------------------------------------------------------------------------
57  * Control
58  *----------------------------------------------------------------------------*/
59 
60 /**
61  * Select SPI peripheral clock source (master).
62  *
63  * @param hw Beginning address of the peripheral registers.
64  * @param clk_source clock source to select, see valid sources in type `spi_clock_source_t`
65  */
spi_ll_set_clk_source(spi_dev_t * hw,spi_clock_source_t clk_source)66 static inline void spi_ll_set_clk_source(spi_dev_t *hw, spi_clock_source_t clk_source)
67 {
68     //empty, keep this for compatibility
69 }
70 
71 /**
72  * Initialize SPI peripheral (master).
73  *
74  * @param hw Beginning address of the peripheral registers.
75  */
spi_ll_master_init(spi_dev_t * hw)76 static inline void spi_ll_master_init(spi_dev_t *hw)
77 {
78     //Reset timing
79     hw->ctrl2.val = 0;
80 
81     //use all 64 bytes of the buffer
82     hw->user.usr_miso_highpart = 0;
83     hw->user.usr_mosi_highpart = 0;
84 
85     //Disable unneeded ints
86     hw->slave.val &= ~SPI_LL_UNUSED_INT_MASK;
87 }
88 
89 /**
90  * Initialize SPI peripheral (slave).
91  *
92  * @param hw Beginning address of the peripheral registers.
93  */
spi_ll_slave_init(spi_dev_t * hw)94 static inline void spi_ll_slave_init(spi_dev_t *hw)
95 {
96     //Configure slave
97     hw->clock.val = 0;
98     hw->user.val = 0;
99     hw->ctrl.val = 0;
100     hw->slave.wr_rd_buf_en = 1; //no sure if needed
101     hw->user.doutdin = 1; //we only support full duplex
102     hw->user.sio = 0;
103     hw->slave.slave_mode = 1;
104     hw->slave.sync_reset = 1;
105     hw->slave.sync_reset = 0;
106     //use all 64 bytes of the buffer
107     hw->user.usr_miso_highpart = 0;
108     hw->user.usr_mosi_highpart = 0;
109 
110     //Disable unneeded ints
111     hw->slave.val &= ~SPI_LL_UNUSED_INT_MASK;
112 }
113 
114 /**
115  * Check whether user-defined transaction is done.
116  *
117  * @param hw Beginning address of the peripheral registers.
118  *
119  * @return true if transaction is done, otherwise false.
120  */
spi_ll_usr_is_done(spi_dev_t * hw)121 static inline bool spi_ll_usr_is_done(spi_dev_t *hw)
122 {
123     return hw->slave.trans_done;
124 }
125 
126 /**
127  * Apply the register configurations and wait until it's done
128  *
129  * @param hw Beginning address of the peripheral registers.
130  */
spi_ll_apply_config(spi_dev_t * hw)131 static inline void spi_ll_apply_config(spi_dev_t *hw)
132 {
133     // 32 don't need this option
134 }
135 
136 /**
137  * Trigger start of user-defined transaction.
138  *
139  * @param hw Beginning address of the peripheral registers.
140  */
spi_ll_user_start(spi_dev_t * hw)141 static inline void spi_ll_user_start(spi_dev_t *hw)
142 {
143     hw->cmd.usr = 1;
144 }
145 
146 /**
147  * Get current running command bit-mask. (Preview)
148  *
149  * @param hw Beginning address of the peripheral registers.
150  *
151  * @return Bitmask of running command, see ``SPI_CMD_REG``. 0 if no in-flight command.
152  */
spi_ll_get_running_cmd(spi_dev_t * hw)153 static inline uint32_t spi_ll_get_running_cmd(spi_dev_t *hw)
154 {
155     return hw->cmd.val;
156 }
157 
158 /**
159  * Reset SPI CPU TX FIFO
160  *
161  * @param hw Beginning address of the peripheral registers.
162  */
spi_ll_cpu_tx_fifo_reset(spi_dev_t * hw)163 static inline void spi_ll_cpu_tx_fifo_reset(spi_dev_t *hw)
164 {
165     //This is not used in esp32
166 }
167 
168 /**
169  * Reset SPI DMA FIFO
170  *
171  * @param hw Beginning address of the peripheral registers.
172  */
spi_ll_cpu_rx_fifo_reset(spi_dev_t * hw)173 static inline void spi_ll_cpu_rx_fifo_reset(spi_dev_t *hw)
174 {
175     //This is not used in esp32
176 }
177 
178 /**
179  * Reset SPI DMA TX FIFO
180  *
181  * On ESP32, this function is not seperated
182  *
183  * @param hw Beginning address of the peripheral registers.
184  */
spi_ll_dma_tx_fifo_reset(spi_dev_t * hw)185 static inline void spi_ll_dma_tx_fifo_reset(spi_dev_t *hw)
186 {
187     hw->dma_conf.val |= SPI_LL_DMA_FIFO_RST_MASK;
188     hw->dma_conf.val &= ~SPI_LL_DMA_FIFO_RST_MASK;
189 }
190 
191 /**
192  * Reset SPI DMA RX FIFO
193  *
194  * On ESP32, this function is not seperated
195  *
196  * @param hw Beginning address of the peripheral registers.
197  */
spi_ll_dma_rx_fifo_reset(spi_dev_t * hw)198 static inline void spi_ll_dma_rx_fifo_reset(spi_dev_t *hw)
199 {
200     hw->dma_conf.val |= SPI_LL_DMA_FIFO_RST_MASK;
201     hw->dma_conf.val &= ~SPI_LL_DMA_FIFO_RST_MASK;
202 }
203 
204 /**
205  * Clear in fifo full error
206  *
207  * @param hw Beginning address of the peripheral registers.
208  */
spi_ll_infifo_full_clr(spi_dev_t * hw)209 static inline void spi_ll_infifo_full_clr(spi_dev_t *hw)
210 {
211     //This is not used in esp32
212 }
213 
214 /**
215  * Clear out fifo empty error
216  *
217  * @param hw Beginning address of the peripheral registers.
218  */
spi_ll_outfifo_empty_clr(spi_dev_t * hw)219 static inline void spi_ll_outfifo_empty_clr(spi_dev_t *hw)
220 {
221     //This is not used in esp32
222 }
223 
224 /*------------------------------------------------------------------------------
225  * SPI configuration for DMA
226  *----------------------------------------------------------------------------*/
227 
228 /**
229  * Enable/Disable RX DMA (Peripherals->DMA->RAM)
230  *
231  * @param hw     Beginning address of the peripheral registers.
232  * @param enable 1: enable; 2: disable
233  */
spi_ll_dma_rx_enable(spi_dev_t * hw,bool enable)234 static inline void spi_ll_dma_rx_enable(spi_dev_t *hw, bool enable)
235 {
236     //This is not used in esp32
237 }
238 
239 /**
240  * Enable/Disable TX DMA (RAM->DMA->Peripherals)
241  *
242  * @param hw     Beginning address of the peripheral registers.
243  * @param enable 1: enable; 2: disable
244  */
spi_ll_dma_tx_enable(spi_dev_t * hw,bool enable)245 static inline void spi_ll_dma_tx_enable(spi_dev_t *hw, bool enable)
246 {
247     //This is not used in esp32
248 }
249 
250 /**
251  * Configuration of RX DMA EOF interrupt generation way
252  *
253  * @param hw     Beginning address of the peripheral registers.
254  * @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.
255  */
spi_ll_dma_set_rx_eof_generation(spi_dev_t * hw,bool enable)256 static inline void spi_ll_dma_set_rx_eof_generation(spi_dev_t *hw, bool enable)
257 {
258     //This is not used in esp32
259 }
260 
261 /*------------------------------------------------------------------------------
262  * Buffer
263  *----------------------------------------------------------------------------*/
264 /**
265  * Write to SPI buffer.
266  *
267  * @param hw Beginning address of the peripheral registers.
268  * @param buffer_to_send Data address to copy to the buffer.
269  * @param bitlen Length to copy, in bits.
270  */
spi_ll_write_buffer(spi_dev_t * hw,const uint8_t * buffer_to_send,size_t bitlen)271 static inline void spi_ll_write_buffer(spi_dev_t *hw, const uint8_t *buffer_to_send, size_t bitlen)
272 {
273     for (size_t x = 0; x < bitlen; x += 32) {
274         //Use memcpy to get around alignment issues for txdata
275         uint32_t word;
276         memcpy(&word, &buffer_to_send[x / 8], 4);
277         hw->data_buf[(x / 32)] = word;
278     }
279 }
280 
281 /**
282  * Read from SPI buffer.
283  *
284  * @param hw Beginning address of the peripheral registers.
285  * @param buffer_to_rcv Address to copy buffer data to.
286  * @param bitlen Length to copy, in bits.
287  */
spi_ll_read_buffer(spi_dev_t * hw,uint8_t * buffer_to_rcv,size_t bitlen)288 static inline void spi_ll_read_buffer(spi_dev_t *hw, uint8_t *buffer_to_rcv, size_t bitlen)
289 {
290     for (size_t x = 0; x < bitlen; x += 32) {
291         //Do a memcpy to get around possible alignment issues in rx_buffer
292         uint32_t word = hw->data_buf[x / 32];
293         int len = bitlen - x;
294         if (len > 32) {
295             len = 32;
296         }
297         memcpy(&buffer_to_rcv[x / 8], &word, (len + 7) / 8);
298     }
299 }
300 
301 /*------------------------------------------------------------------------------
302  * Configs: mode
303  *----------------------------------------------------------------------------*/
304 /**
305  * Enable/disable the postive-cs feature.
306  *
307  * @param hw Beginning address of the peripheral registers.
308  * @param cs One of the CS (0-2) to enable/disable the feature.
309  * @param pos_cs true to enable the feature, otherwise disable (default).
310  */
spi_ll_master_set_pos_cs(spi_dev_t * hw,int cs,uint32_t pos_cs)311 static inline void spi_ll_master_set_pos_cs(spi_dev_t *hw, int cs, uint32_t pos_cs)
312 {
313     if (pos_cs) {
314         hw->pin.master_cs_pol |= (1 << cs);
315     } else {
316         hw->pin.master_cs_pol &= ~(1 << cs);
317     }
318 }
319 
320 /**
321  * Enable/disable the LSBFIRST feature for TX data.
322  *
323  * @param hw Beginning address of the peripheral registers.
324  * @param lsbfirst true if LSB of TX data to be sent first, otherwise MSB is sent first (default).
325  */
spi_ll_set_tx_lsbfirst(spi_dev_t * hw,bool lsbfirst)326 static inline void spi_ll_set_tx_lsbfirst(spi_dev_t *hw, bool lsbfirst)
327 {
328     hw->ctrl.wr_bit_order = lsbfirst;
329 }
330 
331 /**
332  * Enable/disable the LSBFIRST feature for RX data.
333  *
334  * @param hw Beginning address of the peripheral registers.
335  * @param lsbfirst true if first bit received as LSB, otherwise as MSB (default).
336  */
spi_ll_set_rx_lsbfirst(spi_dev_t * hw,bool lsbfirst)337 static inline void spi_ll_set_rx_lsbfirst(spi_dev_t *hw, bool lsbfirst)
338 {
339     hw->ctrl.rd_bit_order = lsbfirst;
340 }
341 
342 /**
343  * Set SPI mode for the peripheral as master.
344  *
345  * @param hw Beginning address of the peripheral registers.
346  * @param mode SPI mode to work at, 0-3.
347  */
spi_ll_master_set_mode(spi_dev_t * hw,uint8_t mode)348 static inline void spi_ll_master_set_mode(spi_dev_t *hw, uint8_t mode)
349 {
350     //Configure polarity
351     if (mode == 0) {
352         hw->pin.ck_idle_edge = 0;
353         hw->user.ck_out_edge = 0;
354     } else if (mode == 1) {
355         hw->pin.ck_idle_edge = 0;
356         hw->user.ck_out_edge = 1;
357     } else if (mode == 2) {
358         hw->pin.ck_idle_edge = 1;
359         hw->user.ck_out_edge = 1;
360     } else if (mode == 3) {
361         hw->pin.ck_idle_edge = 1;
362         hw->user.ck_out_edge = 0;
363     }
364 }
365 
366 /**
367  * Set SPI mode for the peripheral as slave.
368  *
369  * @param hw Beginning address of the peripheral registers.
370  * @param mode SPI mode to work at, 0-3.
371  */
spi_ll_slave_set_mode(spi_dev_t * hw,const int mode,bool dma_used)372 static inline void spi_ll_slave_set_mode(spi_dev_t *hw, const int mode, bool dma_used)
373 {
374     if (mode == 0) {
375         //The timing needs to be fixed to meet the requirements of DMA
376         hw->pin.ck_idle_edge = 1;
377         hw->user.ck_i_edge = 0;
378         hw->ctrl2.miso_delay_mode = 0;
379         hw->ctrl2.miso_delay_num = 0;
380         hw->ctrl2.mosi_delay_mode = 2;
381         hw->ctrl2.mosi_delay_num = 2;
382     } else if (mode == 1) {
383         hw->pin.ck_idle_edge = 1;
384         hw->user.ck_i_edge = 1;
385         hw->ctrl2.miso_delay_mode = 2;
386         hw->ctrl2.miso_delay_num = 0;
387         hw->ctrl2.mosi_delay_mode = 0;
388         hw->ctrl2.mosi_delay_num = 0;
389     } else if (mode == 2) {
390         //The timing needs to be fixed to meet the requirements of DMA
391         hw->pin.ck_idle_edge = 0;
392         hw->user.ck_i_edge = 1;
393         hw->ctrl2.miso_delay_mode = 0;
394         hw->ctrl2.miso_delay_num = 0;
395         hw->ctrl2.mosi_delay_mode = 1;
396         hw->ctrl2.mosi_delay_num = 2;
397     } else if (mode == 3) {
398         hw->pin.ck_idle_edge = 0;
399         hw->user.ck_i_edge = 0;
400         hw->ctrl2.miso_delay_mode = 1;
401         hw->ctrl2.miso_delay_num = 0;
402         hw->ctrl2.mosi_delay_mode = 0;
403         hw->ctrl2.mosi_delay_num = 0;
404     }
405 
406     /* Silicon issues exists in mode 0 and 2 with DMA, change clock phase to
407      * avoid dma issue. This will cause slave output to appear at most half a
408      * spi clock before
409      */
410     if (dma_used) {
411         if (mode == 0) {
412             hw->pin.ck_idle_edge = 0;
413             hw->user.ck_i_edge = 1;
414             hw->ctrl2.miso_delay_mode = 0;
415             hw->ctrl2.miso_delay_num = 2;
416             hw->ctrl2.mosi_delay_mode = 0;
417             hw->ctrl2.mosi_delay_num = 3;
418         } else if (mode == 2) {
419             hw->pin.ck_idle_edge = 1;
420             hw->user.ck_i_edge = 0;
421             hw->ctrl2.miso_delay_mode = 0;
422             hw->ctrl2.miso_delay_num = 2;
423             hw->ctrl2.mosi_delay_mode = 0;
424             hw->ctrl2.mosi_delay_num = 3;
425         }
426     }
427 }
428 
429 /**
430  * Set SPI to work in full duplex or half duplex mode.
431  *
432  * @param hw Beginning address of the peripheral registers.
433  * @param half_duplex true to work in half duplex mode, otherwise in full duplex mode.
434  */
spi_ll_set_half_duplex(spi_dev_t * hw,bool half_duplex)435 static inline void spi_ll_set_half_duplex(spi_dev_t *hw, bool half_duplex)
436 {
437     hw->user.doutdin = !half_duplex;
438 }
439 
440 /**
441  * Set SPI to work in SIO mode or not.
442  *
443  * SIO is a mode which MOSI and MISO share a line. The device MUST work in half-duplexmode.
444  *
445  * @param hw Beginning address of the peripheral registers.
446  * @param sio_mode true to work in SIO mode, otherwise false.
447  */
spi_ll_set_sio_mode(spi_dev_t * hw,int sio_mode)448 static inline void spi_ll_set_sio_mode(spi_dev_t *hw, int sio_mode)
449 {
450     hw->user.sio = sio_mode;
451 }
452 
453 /**
454  * Configure the SPI transaction line mode for the master to use.
455  *
456  * @param hw        Beginning address of the peripheral registers.
457  * @param line_mode SPI transaction line mode to use, see ``spi_line_mode_t``.
458  */
spi_ll_master_set_line_mode(spi_dev_t * hw,spi_line_mode_t line_mode)459 static inline void spi_ll_master_set_line_mode(spi_dev_t *hw, spi_line_mode_t line_mode)
460 {
461     hw->ctrl.val &= ~SPI_LL_ONE_LINE_CTRL_MASK;
462     hw->user.val &= ~SPI_LL_ONE_LINE_USER_MASK;
463     if (line_mode.cmd_lines > 1) {
464         HAL_ASSERT(false);
465     }
466     switch (line_mode.data_lines) {
467     case 2:
468         if (line_mode.addr_lines == 1) {
469             // 1-line-cmd + 1-line-addr + 2-line-data
470             hw->ctrl.fread_dual = 1;
471             hw->user.fwrite_dual = 1;
472         } else if (line_mode.addr_lines == 2) {
473             // 1-line-cmd + 2-line-addr + 2-line-data
474             hw->ctrl.fread_dio = 1;
475             hw->user.fwrite_dio = 1;
476         } else {
477             HAL_ASSERT(false);
478         }
479         hw->ctrl.fastrd_mode = 1;
480         break;
481     case 4:
482         if (line_mode.addr_lines == 1) {
483             // 1-line-cmd + 1-line-addr + 4-line-data
484             hw->ctrl.fread_quad = 1;
485             hw->user.fwrite_quad = 1;
486         } else if (line_mode.addr_lines == 4) {
487             // 1-line-cmd + 4-line-addr + 4-line-data
488             hw->ctrl.fread_qio = 1;
489             hw->user.fwrite_qio = 1;
490         } else {
491             HAL_ASSERT(false);
492         }
493         hw->ctrl.fastrd_mode = 1;
494         break;
495     default:
496         // 1-line-cmd + 1-line-addr + 1-line-data
497         break;
498     }
499 }
500 
501 /**
502  * Select one of the CS to use in current transaction.
503  *
504  * @param hw Beginning address of the peripheral registers.
505  * @param cs_id The cs to use, 0-2, otherwise none of them is used.
506  */
spi_ll_master_select_cs(spi_dev_t * hw,int cs_id)507 static inline void spi_ll_master_select_cs(spi_dev_t *hw, int cs_id)
508 {
509     hw->pin.cs0_dis = (cs_id == 0) ? 0 : 1;
510     hw->pin.cs1_dis = (cs_id == 1) ? 0 : 1;
511     hw->pin.cs2_dis = (cs_id == 2) ? 0 : 1;
512 }
513 
514 /**
515  * Keep Chip Select activated after the current transaction.
516  *
517  * @param hw Beginning address of the peripheral registers.
518  * @param keep_active if 0 don't keep CS activated, else keep CS activated
519  */
spi_ll_master_keep_cs(spi_dev_t * hw,int keep_active)520 static inline void spi_ll_master_keep_cs(spi_dev_t *hw, int keep_active)
521 {
522     hw->pin.cs_keep_active = (keep_active != 0) ? 1 : 0;
523 }
524 
525 /*------------------------------------------------------------------------------
526  * Configs: parameters
527  *----------------------------------------------------------------------------*/
528 /**
529  * Set the clock for master by stored value.
530  *
531  * @param hw Beginning address of the peripheral registers.
532  * @param val stored clock configuration calculated before (by ``spi_ll_cal_clock``).
533  */
spi_ll_master_set_clock_by_reg(spi_dev_t * hw,const spi_ll_clock_val_t * val)534 static inline void spi_ll_master_set_clock_by_reg(spi_dev_t *hw, const spi_ll_clock_val_t *val)
535 {
536     hw->clock.val = *(uint32_t *)val;
537 }
538 
539 /**
540  * Get the frequency of given dividers. Don't use in app.
541  *
542  * @param fapb APB clock of the system.
543  * @param pre Pre devider.
544  * @param n main divider.
545  *
546  * @return Frequency of given dividers.
547  */
spi_ll_freq_for_pre_n(int fapb,int pre,int n)548 static inline int spi_ll_freq_for_pre_n(int fapb, int pre, int n)
549 {
550     return (fapb / (pre * n));
551 }
552 
553 /**
554  * Calculate the nearest frequency avaliable for master.
555  *
556  * @param fapb APB clock of the system.
557  * @param hz Frequncy desired.
558  * @param duty_cycle Duty cycle desired.
559  * @param out_reg Output address to store the calculated clock configurations for the return frequency.
560  *
561  * @return Actual (nearest) frequency.
562  */
spi_ll_master_cal_clock(int fapb,int hz,int duty_cycle,spi_ll_clock_val_t * out_reg)563 static inline int spi_ll_master_cal_clock(int fapb, int hz, int duty_cycle, spi_ll_clock_val_t *out_reg)
564 {
565     typeof(SPI1.clock) reg;
566     int eff_clk;
567 
568     //In hw, n, h and l are 1-64, pre is 1-8K. Value written to register is one lower than used value.
569     if (hz > ((fapb / 4) * 3)) {
570         //Using Fapb directly will give us the best result here.
571         reg.clkcnt_l = 0;
572         reg.clkcnt_h = 0;
573         reg.clkcnt_n = 0;
574         reg.clkdiv_pre = 0;
575         reg.clk_equ_sysclk = 1;
576         eff_clk = fapb;
577     } else {
578         //For best duty cycle resolution, we want n to be as close to 32 as possible, but
579         //we also need a pre/n combo that gets us as close as possible to the intended freq.
580         //To do this, we bruteforce n and calculate the best pre to go along with that.
581         //If there's a choice between pre/n combos that give the same result, use the one
582         //with the higher n.
583         int pre, n, h, l;
584         int bestn = -1;
585         int bestpre = -1;
586         int besterr = 0;
587         int errval;
588         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.
589             //Effectively, this does pre=round((fapb/n)/hz).
590             pre = ((fapb / n) + (hz / 2)) / hz;
591             if (pre <= 0) {
592                 pre = 1;
593             }
594             if (pre > 8192) {
595                 pre = 8192;
596             }
597             errval = abs(spi_ll_freq_for_pre_n(fapb, pre, n) - hz);
598             if (bestn == -1 || errval <= besterr) {
599                 besterr = errval;
600                 bestn = n;
601                 bestpre = pre;
602             }
603         }
604 
605         n = bestn;
606         pre = bestpre;
607         l = n;
608         //This effectively does round((duty_cycle*n)/256)
609         h = (duty_cycle * n + 127) / 256;
610         if (h <= 0) {
611             h = 1;
612         }
613 
614         reg.clk_equ_sysclk = 0;
615         reg.clkcnt_n = n - 1;
616         reg.clkdiv_pre = pre - 1;
617         reg.clkcnt_h = h - 1;
618         reg.clkcnt_l = l - 1;
619         eff_clk = spi_ll_freq_for_pre_n(fapb, pre, n);
620     }
621     if (out_reg != NULL) {
622         *(uint32_t *)out_reg = reg.val;
623     }
624     return eff_clk;
625 }
626 
627 /**
628  * Calculate and set clock for SPI master according to desired parameters.
629  *
630  * This takes long, suggest to calculate the configuration during
631  * initialization by ``spi_ll_master_cal_clock`` and store the result, then
632  * configure the clock by stored value when used by
633  * ``spi_ll_msater_set_clock_by_reg``.
634  *
635  * @param hw Beginning address of the peripheral registers.
636  * @param fapb APB clock of the system.
637  * @param hz Frequncy desired.
638  * @param duty_cycle Duty cycle desired.
639  *
640  * @return Actual frequency that is used.
641  */
spi_ll_master_set_clock(spi_dev_t * hw,int fapb,int hz,int duty_cycle)642 static inline int spi_ll_master_set_clock(spi_dev_t *hw, int fapb, int hz, int duty_cycle)
643 {
644     spi_ll_clock_val_t reg_val;
645     int freq = spi_ll_master_cal_clock(fapb, hz, duty_cycle, &reg_val);
646     spi_ll_master_set_clock_by_reg(hw, &reg_val);
647     return freq;
648 }
649 
650 /**
651  * Enable/disable the CK sel feature for a CS pin.
652  *
653  * CK sel is a feature to toggle the CS line along with the clock.
654  *
655  * @param hw Beginning address of the peripheral registers.
656  * @param cs CS pin to enable/disable the feature, 0-2.
657  * @param cksel true to enable the feature, otherwise false.
658  */
spi_ll_master_set_cksel(spi_dev_t * hw,int cs,uint32_t cksel)659 static inline void spi_ll_master_set_cksel(spi_dev_t *hw, int cs, uint32_t cksel)
660 {
661     if (cksel) {
662         hw->pin.master_ck_sel |= (1 << cs);
663     } else {
664         hw->pin.master_ck_sel &= ~(1 << cs);
665     }
666 }
667 
668 /**
669  * Set the mosi delay after the output edge to the signal. (Preview)
670  *
671  * The delay mode/num is a Espressif conception, may change in the new chips.
672  *
673  * @param hw Beginning address of the peripheral registers.
674  * @param delay_mode Delay mode, see TRM.
675  * @param delay_num APB clocks to delay.
676  */
spi_ll_set_mosi_delay(spi_dev_t * hw,int delay_mode,int delay_num)677 static inline void spi_ll_set_mosi_delay(spi_dev_t *hw, int delay_mode, int delay_num)
678 {
679     hw->ctrl2.mosi_delay_mode = delay_mode;
680     hw->ctrl2.mosi_delay_num = delay_num;
681 }
682 
683 /**
684  * Set the miso delay applied to the input signal before the internal peripheral. (Preview)
685  *
686  * The delay mode/num is a Espressif conception, may change in the new chips.
687  *
688  * @param hw Beginning address of the peripheral registers.
689  * @param delay_mode Delay mode, see TRM.
690  * @param delay_num APB clocks to delay.
691  */
spi_ll_set_miso_delay(spi_dev_t * hw,int delay_mode,int delay_num)692 static inline void spi_ll_set_miso_delay(spi_dev_t *hw, int delay_mode, int delay_num)
693 {
694     hw->ctrl2.miso_delay_mode = delay_mode;
695     hw->ctrl2.miso_delay_num = delay_num;
696 }
697 
698 /**
699  * Set dummy clocks to output before RX phase (master), or clocks to skip
700  * before the data phase and after the address phase (slave).
701  *
702  * Note this phase is also used to compensate RX timing in half duplex mode.
703  *
704  * @param hw Beginning address of the peripheral registers.
705  * @param dummy_n Dummy cycles used. 0 to disable the dummy phase.
706  */
spi_ll_set_dummy(spi_dev_t * hw,int dummy_n)707 static inline void spi_ll_set_dummy(spi_dev_t *hw, int dummy_n)
708 {
709     hw->user.usr_dummy = dummy_n ? 1 : 0;
710     HAL_FORCE_MODIFY_U32_REG_FIELD(hw->user1, usr_dummy_cyclelen, dummy_n - 1);
711 }
712 
713 /**
714  * Set the delay of SPI clocks before the CS inactive edge after the last SPI clock.
715  *
716  * @param hw Beginning address of the peripheral registers.
717  * @param hold Delay of SPI clocks after the last clock, 0 to disable the hold phase.
718  */
spi_ll_master_set_cs_hold(spi_dev_t * hw,int hold)719 static inline void spi_ll_master_set_cs_hold(spi_dev_t *hw, int hold)
720 {
721     hw->ctrl2.hold_time = hold;
722     hw->user.cs_hold = hold ? 1 : 0;
723 }
724 
725 /**
726  * Set the delay of SPI clocks before the first SPI clock after the CS active edge.
727  *
728  * Note ESP32 doesn't support to use this feature when command/address phases
729  * are used in full duplex mode.
730  *
731  * @param hw Beginning address of the peripheral registers.
732  * @param setup Delay of SPI clocks after the CS active edge, 0 to disable the setup phase.
733  */
spi_ll_master_set_cs_setup(spi_dev_t * hw,uint8_t setup)734 static inline void spi_ll_master_set_cs_setup(spi_dev_t *hw, uint8_t setup)
735 {
736     hw->ctrl2.setup_time = setup - 1;
737     hw->user.cs_setup = setup ? 1 : 0;
738 }
739 
740 /*------------------------------------------------------------------------------
741  * Configs: data
742  *----------------------------------------------------------------------------*/
743 /**
744  * Set the input length (master).
745  *
746  * @param hw Beginning address of the peripheral registers.
747  * @param bitlen input length, in bits.
748  */
spi_ll_set_miso_bitlen(spi_dev_t * hw,size_t bitlen)749 static inline void spi_ll_set_miso_bitlen(spi_dev_t *hw, size_t bitlen)
750 {
751     hw->miso_dlen.usr_miso_dbitlen = bitlen - 1;
752 }
753 
754 /**
755  * Set the output length (master).
756  *
757  * @param hw Beginning address of the peripheral registers.
758  * @param bitlen output length, in bits.
759  */
spi_ll_set_mosi_bitlen(spi_dev_t * hw,size_t bitlen)760 static inline void spi_ll_set_mosi_bitlen(spi_dev_t *hw, size_t bitlen)
761 {
762     hw->mosi_dlen.usr_mosi_dbitlen = bitlen - 1;
763 }
764 
765 /**
766  * Set the maximum input length (slave).
767  *
768  * @param hw Beginning address of the peripheral registers.
769  * @param bitlen input length, in bits.
770  */
spi_ll_slave_set_rx_bitlen(spi_dev_t * hw,size_t bitlen)771 static inline void spi_ll_slave_set_rx_bitlen(spi_dev_t *hw, size_t bitlen)
772 {
773     hw->slv_rdbuf_dlen.bit_len = bitlen - 1;
774 }
775 
776 /**
777  * Set the maximum output length (slave).
778  *
779  * @param hw Beginning address of the peripheral registers.
780  * @param bitlen output length, in bits.
781  */
spi_ll_slave_set_tx_bitlen(spi_dev_t * hw,size_t bitlen)782 static inline void spi_ll_slave_set_tx_bitlen(spi_dev_t *hw, size_t bitlen)
783 {
784     hw->slv_wrbuf_dlen.bit_len = bitlen - 1;
785 }
786 
787 /**
788  * Set the length of command phase.
789  *
790  * When in 4-bit mode, the SPI cycles of the phase will be shorter. E.g. 16-bit
791  * command phases takes 4 cycles in 4-bit mode.
792  *
793  * @param hw Beginning address of the peripheral registers.
794  * @param bitlen Length of command phase, in bits. 0 to disable the command phase.
795  */
spi_ll_set_command_bitlen(spi_dev_t * hw,int bitlen)796 static inline void spi_ll_set_command_bitlen(spi_dev_t *hw, int bitlen)
797 {
798     hw->user2.usr_command_bitlen = bitlen - 1;
799     hw->user.usr_command = bitlen ? 1 : 0;
800 }
801 
802 /**
803  * Set the length of address phase.
804  *
805  * When in 4-bit mode, the SPI cycles of the phase will be shorter. E.g. 16-bit
806  * address phases takes 4 cycles in 4-bit mode.
807  *
808  * @param hw Beginning address of the peripheral registers.
809  * @param bitlen Length of address phase, in bits. 0 to disable the address phase.
810  */
spi_ll_set_addr_bitlen(spi_dev_t * hw,int bitlen)811 static inline void spi_ll_set_addr_bitlen(spi_dev_t *hw, int bitlen)
812 {
813     hw->user1.usr_addr_bitlen = bitlen - 1;
814     hw->user.usr_addr = bitlen ? 1 : 0;
815 }
816 
817 /**
818  * Set the address value in an intuitive way.
819  *
820  * The length and lsbfirst is required to shift and swap the address to the right place.
821  *
822  * @param hw Beginning address of the peripheral registers.
823  * @param address Address to set
824  * @param addrlen Length of the address phase
825  * @param lsbfirst whether the LSB first feature is enabled.
826  */
spi_ll_set_address(spi_dev_t * hw,uint64_t addr,int addrlen,uint32_t lsbfirst)827 static inline void spi_ll_set_address(spi_dev_t *hw, uint64_t addr, int addrlen, uint32_t lsbfirst)
828 {
829     if (lsbfirst) {
830         /* The output address start from the LSB of the highest byte, i.e.
831          * addr[24] -> addr[31]
832          * ...
833          * addr[0] -> addr[7]
834          * slv_wr_status[24] -> slv_wr_status[31]
835          * ...
836          * slv_wr_status[0] -> slv_wr_status[7]
837          * So swap the byte order to let the LSB sent first.
838          */
839         addr = HAL_SWAP64(addr);
840         hw->addr = addr >> 32;
841         hw->slv_wr_status = addr;
842     } else {
843         // shift the address to MSB of addr (and maybe slv_wr_status) register.
844         // output address will be sent from MSB to LSB of addr register, then comes the MSB to LSB of slv_wr_status register.
845         if (addrlen > 32) {
846             hw->addr = addr >> (addrlen - 32);
847             hw->slv_wr_status = addr << (64 - addrlen);
848         } else {
849             hw->addr = addr << (32 - addrlen);
850         }
851     }
852 }
853 
854 /**
855  * Set the command value in an intuitive way.
856  *
857  * The length and lsbfirst is required to shift and swap the command to the right place.
858  *
859  * @param hw Beginning command of the peripheral registers.
860  * @param command Command to set
861  * @param addrlen Length of the command phase
862  * @param lsbfirst whether the LSB first feature is enabled.
863  */
spi_ll_set_command(spi_dev_t * hw,uint16_t cmd,int cmdlen,bool lsbfirst)864 static inline void spi_ll_set_command(spi_dev_t *hw, uint16_t cmd, int cmdlen, bool lsbfirst)
865 {
866     if (lsbfirst) {
867         // The output command start from bit0 to bit 15, kept as is.
868         HAL_FORCE_MODIFY_U32_REG_FIELD(hw->user2, usr_command_value, cmd);
869     } else {
870         /* Output command will be sent from bit 7 to 0 of command_value, and
871          * then bit 15 to 8 of the same register field. Shift and swap to send
872          * more straightly.
873          */
874         HAL_FORCE_MODIFY_U32_REG_FIELD(hw->user2, usr_command_value, HAL_SPI_SWAP_DATA_TX(cmd, cmdlen));
875 
876     }
877 }
878 
879 /**
880  * Enable/disable the RX data phase.
881  *
882  * @param hw Beginning address of the peripheral registers.
883  * @param enable true if RX phase exist, otherwise false.
884  */
spi_ll_enable_miso(spi_dev_t * hw,int enable)885 static inline void spi_ll_enable_miso(spi_dev_t *hw, int enable)
886 {
887     hw->user.usr_miso = enable;
888 }
889 
890 /**
891  * Enable/disable the TX data phase.
892  *
893  * @param hw Beginning address of the peripheral registers.
894  * @param enable true if TX phase exist, otherwise false.
895  */
spi_ll_enable_mosi(spi_dev_t * hw,int enable)896 static inline void spi_ll_enable_mosi(spi_dev_t *hw, int enable)
897 {
898     hw->user.usr_mosi = enable;
899 }
900 
901 /**
902  * Reset the slave peripheral before next transaction.
903  *
904  * @param hw Beginning address of the peripheral registers.
905  */
spi_ll_slave_reset(spi_dev_t * hw)906 static inline void spi_ll_slave_reset(spi_dev_t *hw)
907 {
908     hw->slave.sync_reset = 1;
909     hw->slave.sync_reset = 0;
910 }
911 
912 /**
913  * Get the received bit length of the slave.
914  *
915  * @param hw Beginning address of the peripheral registers.
916  *
917  * @return Received bits of the slave.
918  */
spi_ll_slave_get_rcv_bitlen(spi_dev_t * hw)919 static inline uint32_t spi_ll_slave_get_rcv_bitlen(spi_dev_t *hw)
920 {
921     return hw->slv_rd_bit.slv_rdata_bit;
922 }
923 
924 /*------------------------------------------------------------------------------
925  * Interrupts
926  *----------------------------------------------------------------------------*/
927 /**
928  * Disable the trans_done interrupt.
929  *
930  * @param hw Beginning address of the peripheral registers.
931  */
spi_ll_disable_int(spi_dev_t * hw)932 static inline void spi_ll_disable_int(spi_dev_t *hw)
933 {
934     hw->slave.trans_inten = 0;
935 }
936 
937 /**
938  * Clear the trans_done interrupt.
939  *
940  * @param hw Beginning address of the peripheral registers.
941  */
spi_ll_clear_int_stat(spi_dev_t * hw)942 static inline void spi_ll_clear_int_stat(spi_dev_t *hw)
943 {
944     hw->slave.trans_done = 0;
945 }
946 
947 /**
948  * Set the trans_done interrupt.
949  *
950  * @param hw Beginning address of the peripheral registers.
951  */
spi_ll_set_int_stat(spi_dev_t * hw)952 static inline void spi_ll_set_int_stat(spi_dev_t *hw)
953 {
954     hw->slave.trans_done = 1;
955 }
956 
957 /**
958  * Enable the trans_done interrupt.
959  *
960  * @param hw Beginning address of the peripheral registers.
961  */
spi_ll_enable_int(spi_dev_t * hw)962 static inline void spi_ll_enable_int(spi_dev_t *hw)
963 {
964     hw->slave.trans_inten = 1;
965 }
966 
967 /*------------------------------------------------------------------------------
968  * DMA:
969  *      RX DMA (Peripherals->DMA->RAM)
970  *      TX DMA (RAM->DMA->Peripherals)
971  *----------------------------------------------------------------------------*/
972 /**
973  * Reset RX DMA which stores the data received from a peripheral into RAM.
974  *
975  * @param dma_in  Beginning address of the DMA peripheral registers which stores the data received from a peripheral into RAM.
976  * @param channel DMA channel, for chip version compatibility, not used.
977  */
spi_dma_ll_rx_reset(spi_dma_dev_t * dma_in,uint32_t channel)978 static inline void spi_dma_ll_rx_reset(spi_dma_dev_t *dma_in, uint32_t channel)
979 {
980     //Reset RX DMA peripheral
981     dma_in->dma_conf.in_rst = 1;
982     dma_in->dma_conf.in_rst = 0;
983 }
984 
985 /**
986  * Start RX DMA.
987  *
988  * @param dma_in  Beginning address of the DMA peripheral registers which stores the data received from a peripheral into RAM.
989  * @param channel DMA channel, for chip version compatibility, not used.
990  * @param addr    Address of the beginning DMA descriptor.
991  */
spi_dma_ll_rx_start(spi_dma_dev_t * dma_in,uint32_t channel,lldesc_t * addr)992 static inline void spi_dma_ll_rx_start(spi_dma_dev_t *dma_in, uint32_t channel, lldesc_t *addr)
993 {
994     dma_in->dma_in_link.addr = (int) addr & 0xFFFFF;
995     dma_in->dma_in_link.start = 1;
996 }
997 
998 /**
999  * Enable DMA RX channel burst for data
1000  *
1001  * @param dma_in  Beginning address of the DMA peripheral registers which stores the data received from a peripheral into RAM.
1002  * @param channel DMA channel, for chip version compatibility, not used.
1003  * @param enable  True to enable, false to disable
1004  */
spi_dma_ll_rx_enable_burst_data(spi_dma_dev_t * dma_in,uint32_t channel,bool enable)1005 static inline void spi_dma_ll_rx_enable_burst_data(spi_dma_dev_t *dma_in, uint32_t channel, bool enable)
1006 {
1007     //This is not supported in esp32
1008 }
1009 
1010 /**
1011  * Enable DMA RX channel burst for descriptor
1012  *
1013  * @param dma_in  Beginning address of the DMA peripheral registers which stores the data received from a peripheral into RAM.
1014  * @param channel DMA channel, for chip version compatibility, not used.
1015  * @param enable  True to enable, false to disable
1016  */
spi_dma_ll_rx_enable_burst_desc(spi_dma_dev_t * dma_in,uint32_t channel,bool enable)1017 static inline void spi_dma_ll_rx_enable_burst_desc(spi_dma_dev_t *dma_in, uint32_t channel, bool enable)
1018 {
1019     dma_in->dma_conf.indscr_burst_en = enable;
1020 }
1021 
1022 /**
1023  * Reset TX DMA which transmits the data from RAM to a peripheral.
1024  *
1025  * @param dma_out Beginning address of the DMA peripheral registers which transmits the data from RAM to a peripheral.
1026  * @param channel DMA channel, for chip version compatibility, not used.
1027  */
spi_dma_ll_tx_reset(spi_dma_dev_t * dma_out,uint32_t channel)1028 static inline void spi_dma_ll_tx_reset(spi_dma_dev_t *dma_out, uint32_t channel)
1029 {
1030     //Reset TX DMA peripheral
1031     dma_out->dma_conf.out_rst = 1;
1032     dma_out->dma_conf.out_rst = 0;
1033 }
1034 
1035 /**
1036  * Start TX DMA.
1037  *
1038  * @param dma_out Beginning address of the DMA peripheral registers which transmits the data from RAM to a peripheral.
1039  * @param channel DMA channel, for chip version compatibility, not used.
1040  * @param addr    Address of the beginning DMA descriptor.
1041  */
spi_dma_ll_tx_start(spi_dma_dev_t * dma_out,uint32_t channel,lldesc_t * addr)1042 static inline void spi_dma_ll_tx_start(spi_dma_dev_t *dma_out, uint32_t channel, lldesc_t *addr)
1043 {
1044     dma_out->dma_out_link.addr = (int) addr & 0xFFFFF;
1045     dma_out->dma_out_link.start = 1;
1046 }
1047 
1048 /**
1049  * Enable DMA TX channel burst for data
1050  *
1051  * @param dma_out Beginning address of the DMA peripheral registers which transmits the data from RAM to a peripheral.
1052  * @param channel DMA channel, for chip version compatibility, not used.
1053  * @param enable  True to enable, false to disable
1054  */
spi_dma_ll_tx_enable_burst_data(spi_dma_dev_t * dma_out,uint32_t channel,bool enable)1055 static inline void spi_dma_ll_tx_enable_burst_data(spi_dma_dev_t *dma_out, uint32_t channel, bool enable)
1056 {
1057     dma_out->dma_conf.out_data_burst_en = enable;
1058 }
1059 
1060 /**
1061  * Enable DMA TX channel burst for descriptor
1062  *
1063  * @param dma_out Beginning address of the DMA peripheral registers which transmits the data from RAM to a peripheral.
1064  * @param channel DMA channel, for chip version compatibility, not used.
1065  * @param enable  True to enable, false to disable
1066  */
spi_dma_ll_tx_enable_burst_desc(spi_dma_dev_t * dma_out,uint32_t channel,bool enable)1067 static inline void spi_dma_ll_tx_enable_burst_desc(spi_dma_dev_t *dma_out, uint32_t channel, bool enable)
1068 {
1069     dma_out->dma_conf.outdscr_burst_en = enable;
1070 }
1071 
1072 /**
1073  * Configuration of OUT EOF flag generation way
1074  *
1075  * @param dma_out Beginning address of the DMA peripheral registers which transmits the data from RAM to a peripheral.
1076  * @param channel DMA channel, for chip version compatibility, not used.
1077  * @param enable  1: when dma pop all data from fifo  0:when ahb push all data to fifo.
1078  */
spi_dma_ll_set_out_eof_generation(spi_dma_dev_t * dma_out,uint32_t channel,bool enable)1079 static inline void spi_dma_ll_set_out_eof_generation(spi_dma_dev_t *dma_out, uint32_t channel, bool enable)
1080 {
1081     dma_out->dma_conf.out_eof_mode = enable;
1082 }
1083 
1084 /**
1085  * Enable automatic outlink-writeback
1086  *
1087  * @param dma_out Beginning address of the DMA peripheral registers which transmits the data from RAM to a peripheral.
1088  * @param channel DMA channel, for chip version compatibility, not used.
1089  * @param enable  True to enable, false to disable
1090  */
spi_dma_ll_enable_out_auto_wrback(spi_dma_dev_t * dma_out,uint32_t channel,bool enable)1091 static inline void spi_dma_ll_enable_out_auto_wrback(spi_dma_dev_t *dma_out, uint32_t channel, bool enable)
1092 {
1093     //does not configure it in ESP32
1094 }
1095 
1096 /**
1097  * Get the spi communication command
1098  *
1099  * @param cmd_t           Base command value
1100  * @param line_mode       Line mode of SPI transaction phases: CMD, ADDR, DOUT/DIN.
1101  */
spi_ll_get_slave_hd_command(spi_command_t cmd_t,spi_line_mode_t line_mode)1102 static inline uint16_t spi_ll_get_slave_hd_command(spi_command_t cmd_t, spi_line_mode_t line_mode)
1103 {
1104     //This is not supported in esp32
1105     return 0;
1106 }
1107 
1108 /**
1109  * Get the dummy bits
1110  *
1111  * @param line_mode       Line mode of SPI transaction phases: CMD, ADDR, DOUT/DIN.
1112  */
spi_ll_get_slave_hd_dummy_bits(spi_line_mode_t line_mode)1113 static inline int spi_ll_get_slave_hd_dummy_bits(spi_line_mode_t line_mode)
1114 {
1115     //This is not supported in esp32
1116     return 0;
1117 }
1118 
1119 #undef SPI_LL_RST_MASK
1120 #undef SPI_LL_UNUSED_INT_MASK
1121 
1122 #ifdef __cplusplus
1123 }
1124 #endif
1125