1 /*
2  * SPDX-FileCopyrightText: 2015-2022 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 HAL layer for SPI master (common part)
14 
15 // SPI HAL usages:
16 // 1. initialize the bus
17 // 2. initialize the DMA descriptors if DMA used
18 // 3. setup the clock speed (since this takes long time)
19 // 4. call setup_device to update parameters for the specific device
20 // 5. call setup_trans to update parameters for the specific transaction
21 // 6. prepare data to send, and prepare the receiving buffer
22 // 7. trigger user defined SPI transaction to start
23 // 8. wait until the user transaction is done
24 // 9. fetch the received data
25 // Parameter to be updated only during ``setup_device`` will be highlighted in the
26 // field comments.
27 
28 #pragma once
29 #include "hal/spi_ll.h"
30 #include <esp_err.h>
31 #include "soc/lldesc.h"
32 #include "soc/soc_caps.h"
33 #include "hal/spi_types.h"
34 
35 /**
36  * Input parameters to the ``spi_hal_cal_clock_conf`` to calculate the timing configuration
37  */
38 typedef struct {
39     uint32_t clk_src_hz;                ///< Selected SPI clock source speed in Hz
40     uint32_t half_duplex;               ///< Whether half duplex mode is used, device specific
41     uint32_t no_compensate;             ///< No need to add dummy to compensate the timing, device specific
42     uint32_t expected_freq;             ///< Expected frequency in Hz.
43     uint32_t duty_cycle;                ///< Expected duty cycle of SPI clock
44     uint32_t input_delay_ns;            /**< Maximum delay between SPI launch clock and the data to be valid.
45                                          *   This is used to compensate/calculate the maximum frequency allowed.
46                                          *   Left 0 if not known.
47                                          */
48     bool use_gpio;                      ///< True if the GPIO matrix is used, otherwise false
49 } spi_hal_timing_param_t;
50 
51 /**
52  * Timing configuration structure that should be calculated by
53  * ``spi_hal_cal_clock_conf`` at initialization and hold. Filled into the
54  * ``timing_conf`` member of the context of HAL before setup a device.
55  */
56 typedef struct {
57     spi_ll_clock_val_t clock_reg;       ///< Register value used by the LL layer
58     spi_clock_source_t clock_source;    ///< Clock source of each device used by LL layer
59     int timing_dummy;                   ///< Extra dummy needed to compensate the timing
60     int timing_miso_delay;              ///< Extra miso delay clocks to compensate the timing
61 } spi_hal_timing_conf_t;
62 
63 /**
64  * DMA configuration structure
65  * Should be set by driver at initialization
66  */
67 typedef struct {
68     spi_dma_dev_t *dma_in;              ///< Input  DMA(DMA -> RAM) peripheral register address
69     spi_dma_dev_t *dma_out;             ///< Output DMA(RAM -> DMA) peripheral register address
70     bool dma_enabled;                   ///< Whether the DMA is enabled, do not update after initialization
71     lldesc_t  *dmadesc_tx;              /**< Array of DMA descriptor used by the TX DMA.
72                                          *   The amount should be larger than dmadesc_n. The driver should ensure that
73                                          *   the data to be sent is shorter than the descriptors can hold.
74                                          */
75     lldesc_t *dmadesc_rx;               /**< Array of DMA descriptor used by the RX DMA.
76                                          *   The amount should be larger than dmadesc_n. The driver should ensure that
77                                          *   the data to be sent is shorter than the descriptors can hold.
78                                          */
79     uint32_t tx_dma_chan;               ///< TX DMA channel
80     uint32_t rx_dma_chan;               ///< RX DMA channel
81     int dmadesc_n;                      ///< The amount of descriptors of both ``dmadesc_tx`` and ``dmadesc_rx`` that the HAL can use.
82 } spi_hal_config_t;
83 
84 /**
85  * Transaction configuration structure, this should be assigned by driver each time.
86  * All these parameters will be updated to the peripheral every transaction.
87  */
88 typedef struct {
89     uint16_t cmd;                       ///< Command value to be sent
90     int cmd_bits;                       ///< Length (in bits) of the command phase
91     int addr_bits;                      ///< Length (in bits) of the address phase
92     int dummy_bits;                     ///< Base length (in bits) of the dummy phase. Note when the compensation is enabled, some extra dummy bits may be appended.
93     int tx_bitlen;                      ///< TX length, in bits
94     int rx_bitlen;                      ///< RX length, in bits
95     uint64_t addr;                      ///< Address value to be sent
96     uint8_t *send_buffer;               ///< Data to be sent
97     uint8_t *rcv_buffer;                ///< Buffer to hold the receive data.
98     spi_line_mode_t line_mode;          ///< SPI line mode of this transaction
99     int cs_keep_active;                 ///< Keep CS active after transaction
100 } spi_hal_trans_config_t;
101 
102 /**
103  * Context that should be maintained by both the driver and the HAL.
104  */
105 typedef struct {
106     /* These two need to be malloced by the driver first */
107     lldesc_t  *dmadesc_tx;              /**< Array of DMA descriptor used by the TX DMA.
108                                          *   The amount should be larger than dmadesc_n. The driver should ensure that
109                                          *   the data to be sent is shorter than the descriptors can hold.
110                                          */
111     lldesc_t *dmadesc_rx;               /**< Array of DMA descriptor used by the RX DMA.
112                                          *   The amount should be larger than dmadesc_n. The driver should ensure that
113                                          *   the data to be sent is shorter than the descriptors can hold.
114                                          */
115 
116     /* Configured by driver at initialization, don't touch */
117     spi_dev_t     *hw;                  ///< Beginning address of the peripheral registers.
118     spi_dma_dev_t *dma_in;              ///< Address of the DMA peripheral registers which stores the data received from a peripheral into RAM (DMA -> RAM).
119     spi_dma_dev_t *dma_out;             ///< Address of the DMA peripheral registers which transmits the data from RAM to a peripheral (RAM -> DMA).
120     bool  dma_enabled;                  ///< Whether the DMA is enabled, do not update after initialization
121     uint32_t tx_dma_chan;               ///< TX DMA channel
122     uint32_t rx_dma_chan;               ///< RX DMA channel
123     int dmadesc_n;                      ///< The amount of descriptors of both ``dmadesc_tx`` and ``dmadesc_rx`` that the HAL can use.
124 
125     /* Internal parameters, don't touch */
126     spi_hal_trans_config_t trans_config; ///< Transaction configuration
127 } spi_hal_context_t;
128 
129 /**
130  * Device configuration structure, this should be initialised by driver based on different devices respectively.
131  * All these parameters will be updated to the peripheral only when ``spi_hal_setup_device``.
132  * They may not get updated when ``spi_hal_setup_trans``.
133  */
134 typedef struct {
135     int mode;                           ///< SPI mode, device specific
136     int cs_setup;                       ///< Setup time of CS active edge before the first SPI clock, device specific
137     int cs_hold;                        ///< Hold time of CS inactive edge after the last SPI clock, device specific
138     int cs_pin_id;                      ///< CS pin to use, 0-2, otherwise all the CS pins are not used. Device specific
139     spi_hal_timing_conf_t timing_conf;  /**< This structure holds the pre-calculated timing configuration for the device
140                                          *   at initialization, device specific
141                                          */
142     struct {
143         uint32_t sio : 1;               ///< Whether to use SIO mode, device specific
144         uint32_t half_duplex : 1;       ///< Whether half duplex mode is used, device specific
145         uint32_t tx_lsbfirst : 1;       ///< Whether LSB is sent first for TX data, device specific
146         uint32_t rx_lsbfirst : 1;       ///< Whether LSB is received first for RX data, device specific
147         uint32_t no_compensate : 1;     ///< No need to add dummy to compensate the timing, device specific
148 #if SOC_SPI_AS_CS_SUPPORTED
149         uint32_t as_cs  : 1;            ///< Whether to toggle the CS while the clock toggles, device specific
150 #endif
151         uint32_t positive_cs : 1;       ///< Whether the postive CS feature is abled, device specific
152     };//boolean configurations
153 } spi_hal_dev_config_t;
154 
155 /**
156  * Init the peripheral and the context.
157  *
158  * @param hal        Context of the HAL layer.
159  * @param host_id    Index of the SPI peripheral. 0 for SPI1, 1 for SPI2 and 2 for SPI3.
160  * @param hal_config Configuration of the hal defined by the upper layer.
161  */
162 void spi_hal_init(spi_hal_context_t *hal, uint32_t host_id, const spi_hal_config_t *hal_config);
163 
164 /**
165  * Deinit the peripheral (and the context if needed).
166  *
167  * @param hal Context of the HAL layer.
168  */
169 void spi_hal_deinit(spi_hal_context_t *hal);
170 
171 /**
172  * Setup device-related configurations according to the settings in the context.
173  *
174  * @param hal       Context of the HAL layer.
175  * @param hal_dev   Device configuration
176  */
177 void spi_hal_setup_device(spi_hal_context_t *hal, const spi_hal_dev_config_t *hal_dev);
178 
179 /**
180  * Setup transaction related configurations according to the settings in the context.
181  *
182  * @param hal       Context of the HAL layer.
183  * @param hal_dev   Device configuration
184  * @param hal_trans Transaction configuration
185  */
186 void spi_hal_setup_trans(spi_hal_context_t *hal, const spi_hal_dev_config_t *hal_dev, const spi_hal_trans_config_t *hal_trans);
187 
188 /**
189  * Prepare the data for the current transaction.
190  *
191  * @param hal            Context of the HAL layer.
192  * @param hal_dev        Device configuration
193  * @param hal_trans      Transaction configuration
194  */
195 void spi_hal_prepare_data(spi_hal_context_t *hal, const spi_hal_dev_config_t *hal_dev, const spi_hal_trans_config_t *hal_trans);
196 
197 /**
198  * Trigger start a user-defined transaction.
199  *
200  * @param hal Context of the HAL layer.
201  */
202 void spi_hal_user_start(const spi_hal_context_t *hal);
203 
204 /**
205  * Check whether the transaction is done (trans_done is set).
206  *
207  * @param hal Context of the HAL layer.
208  */
209 bool spi_hal_usr_is_done(const spi_hal_context_t *hal);
210 
211 /**
212  * Post transaction operations, mainly fetch data from the buffer.
213  *
214  * @param hal       Context of the HAL layer.
215  */
216 void spi_hal_fetch_result(const spi_hal_context_t *hal);
217 
218 /*----------------------------------------------------------
219  * Utils
220  * ---------------------------------------------------------*/
221 /**
222  * Calculate the configuration of clock and timing. The configuration will be used when ``spi_hal_setup_device``.
223  *
224  * It is highly suggested to do this at initialization, since it takes long time.
225  *
226  * @param timing_param   Input parameters to calculate timing configuration
227  * @param out_freq       Output of the actual frequency, left NULL if not required.
228  * @param timing_conf    Output of the timing configuration.
229  *
230  * @return ESP_OK if desired is available, otherwise fail.
231  */
232 esp_err_t spi_hal_cal_clock_conf(const spi_hal_timing_param_t *timing_param, int *out_freq, spi_hal_timing_conf_t *timing_conf);
233 
234 /**
235  * Get the frequency actual used.
236  *
237  * @param hal            Context of the HAL layer.
238  * @param fapb           APB clock frequency.
239  * @param hz             Desired frequencyc.
240  * @param duty_cycle     Desired duty cycle.
241  */
242 int spi_hal_master_cal_clock(int fapb, int hz, int duty_cycle);
243 
244 /**
245  * Get the timing configuration for given parameters.
246  *
247  * @param source_freq_hz Clock freq of selected clock source for SPI in Hz.
248  * @param eff_clk        Actual SPI clock frequency
249  * @param gpio_is_used   true if the GPIO matrix is used, otherwise false.
250  * @param input_delay_ns Maximum delay between SPI launch clock and the data to
251  *                       be valid. This is used to compensate/calculate the maximum frequency
252  *                       allowed. Left 0 if not known.
253  * @param dummy_n        Dummy cycles required to correctly read the data.
254  * @param miso_delay_n   suggested delay on the MISO line, in APB clocks.
255  */
256 void spi_hal_cal_timing(int source_freq_hz, int eff_clk, bool gpio_is_used, int input_delay_ns, int *dummy_n, int *miso_delay_n);
257 
258 /**
259  * Get the maximum frequency allowed to read if no compensation is used.
260  *
261  * @param gpio_is_used   true if the GPIO matrix is used, otherwise false.
262  * @param input_delay_ns Maximum delay between SPI launch clock and the data to
263  *                       be valid. This is used to compensate/calculate the maximum frequency
264  *                       allowed. Left 0 if not known.
265  */
266 int spi_hal_get_freq_limit(bool gpio_is_used, int input_delay_ns);
267