1 /*
2  * SPDX-FileCopyrightText: 2010-2022 Espressif Systems (Shanghai) CO LTD
3  *
4  * SPDX-License-Identifier: Apache-2.0
5  */
6 
7 // Internal header, don't use it in the user code
8 
9 #pragma once
10 
11 #include <zephyr/kernel.h>
12 
13 #include "driver/spi_common.h"
14 #include "hal/spi_types.h"
15 #include "esp_pm.h"
16 #if SOC_GDMA_SUPPORTED
17 #include "esp_private/gdma.h"
18 #endif
19 
20 
21 #ifdef __cplusplus
22 extern "C"
23 {
24 #endif
25 
26 
27 #ifdef CONFIG_SPI_MASTER_ISR_IN_IRAM
28 #define SPI_MASTER_ISR_ATTR IRAM_ATTR
29 #else
30 #define SPI_MASTER_ISR_ATTR
31 #endif
32 
33 #ifdef CONFIG_SPI_MASTER_IN_IRAM
34 #define SPI_MASTER_ATTR IRAM_ATTR
35 #else
36 #define SPI_MASTER_ATTR
37 #endif
38 
39 
40 #define BUS_LOCK_DEBUG  0
41 
42 #if BUS_LOCK_DEBUG
43 #define BUS_LOCK_DEBUG_EXECUTE_CHECK(x)  assert(x)
44 #else
45 #define BUS_LOCK_DEBUG_EXECUTE_CHECK(x)
46 #endif
47 
48 
49 struct spi_bus_lock_t;
50 struct spi_bus_lock_dev_t;
51 /// Handle to the lock of an SPI bus
52 typedef struct spi_bus_lock_t* spi_bus_lock_handle_t;
53 /// Handle to lock of one of the device on an SPI bus
54 typedef struct spi_bus_lock_dev_t* spi_bus_lock_dev_handle_t;
55 
56 /// Background operation control function
57 typedef void (*bg_ctrl_func_t)(void*);
58 
59 typedef struct lldesc_s lldesc_t;
60 
61 /// Attributes of an SPI bus
62 typedef struct {
63     spi_bus_config_t bus_cfg;   ///< Config used to initialize the bus
64     uint32_t flags;             ///< Flags (attributes) of the bus
65     int max_transfer_sz;        ///< Maximum length of bytes available to send
66     bool dma_enabled;           ///< To enable DMA or not
67     int tx_dma_chan;            ///< TX DMA channel, on ESP32 and ESP32S2, tx_dma_chan and rx_dma_chan are same
68     int rx_dma_chan;            ///< RX DMA channel, on ESP32 and ESP32S2, tx_dma_chan and rx_dma_chan are same
69     int dma_desc_num;           ///< DMA descriptor number of dmadesc_tx or dmadesc_rx.
70     lldesc_t *dmadesc_tx;       ///< DMA descriptor array for TX
71     lldesc_t *dmadesc_rx;       ///< DMA descriptor array for RX
72     spi_bus_lock_handle_t lock;
73 #ifdef CONFIG_PM_ENABLE
74     esp_pm_lock_handle_t pm_lock;   ///< Power management lock
75 #endif
76 } spi_bus_attr_t;
77 
78 /// Destructor called when a bus is deinitialized.
79 typedef esp_err_t (*spi_destroy_func_t)(void*);
80 
81 
82 /**
83  * @brief Try to claim a SPI peripheral
84  *
85  * Call this if your driver wants to manage a SPI peripheral.
86  *
87  * @param host Peripheral to claim
88  * @param source The caller indentification string.
89  *
90  * @return True if peripheral is claimed successfully; false if peripheral already is claimed.
91  */
92 bool spicommon_periph_claim(spi_host_device_t host, const char* source);
93 
94 /**
95  * @brief Check whether the spi periph is in use.
96  *
97  * @param host Peripheral to check.
98  *
99  * @return True if in use, otherwise false.
100  */
101 bool spicommon_periph_in_use(spi_host_device_t host);
102 
103 /**
104  * @brief Return the SPI peripheral so another driver can claim it.
105  *
106  * @param host Peripheral to return
107  *
108  * @return True if peripheral is returned successfully; false if peripheral was free to claim already.
109  */
110 bool spicommon_periph_free(spi_host_device_t host);
111 
112 /**
113  * @brief Alloc DMA for SPI
114  *
115  * @param host_id                      SPI host ID
116  * @param dma_chan                     DMA channel to be used
117  * @param[out] out_actual_tx_dma_chan  Actual TX DMA channel (if you choose to assign a specific DMA channel, this will be the channel you assigned before)
118  * @param[out] out_actual_rx_dma_chan  Actual RX DMA channel (if you choose to assign a specific DMA channel, this will be the channel you assigned before)
119  *
120  * @return
121  *        - ESP_OK:                On success
122  *        - ESP_ERR_NO_MEM:        No enough memory
123  *        - ESP_ERR_NOT_FOUND:     There is no available DMA channel
124  */
125 esp_err_t spicommon_dma_chan_alloc(spi_host_device_t host_id, spi_dma_chan_t dma_chan, uint32_t *out_actual_tx_dma_chan, uint32_t *out_actual_rx_dma_chan);
126 
127 /**
128  * @brief Free DMA for SPI
129  *
130  * @param host_id  SPI host ID
131  *
132  * @return
133  *        - ESP_OK: On success
134  */
135 esp_err_t spicommon_dma_chan_free(spi_host_device_t host_id);
136 
137 #if SOC_GDMA_SUPPORTED
138 /**
139  * @brief Get SPI GDMA Handle for GMDA Supported Chip
140  *
141  * @param host_id           SPI host ID
142  * @param gdma_handle       GDMA Handle to Return
143  * @param gdma_direction    GDMA Channel Direction in Enum
144  *                          - GDMA_CHANNEL_DIRECTION_TX
145  *                          - GDMA_CHANNEL_DIRECTION_RX
146  *
147  * @return
148  *        - ESP_OK: On success
149  */
150 esp_err_t spicommon_gdma_get_handle(spi_host_device_t host_id, gdma_channel_handle_t *gdma_handle, gdma_channel_direction_t gdma_direction);
151 #endif
152 
153 /**
154  * @brief Connect a SPI peripheral to GPIO pins
155  *
156  * This routine is used to connect a SPI peripheral to the IO-pads and DMA channel given in
157  * the arguments. Depending on the IO-pads requested, the routing is done either using the
158  * IO_mux or using the GPIO matrix.
159  *
160  * @param host SPI peripheral to be routed
161  * @param bus_config Pointer to a spi_bus_config struct detailing the GPIO pins
162  * @param flags Combination of SPICOMMON_BUSFLAG_* flags, set to ensure the pins set are capable with some functions:
163  *              - ``SPICOMMON_BUSFLAG_MASTER``: Initialize I/O in master mode
164  *              - ``SPICOMMON_BUSFLAG_SLAVE``: Initialize I/O in slave mode
165  *              - ``SPICOMMON_BUSFLAG_IOMUX_PINS``: Pins set should match the iomux pins of the controller.
166  *              - ``SPICOMMON_BUSFLAG_SCLK``, ``SPICOMMON_BUSFLAG_MISO``, ``SPICOMMON_BUSFLAG_MOSI``:
167  *                  Make sure SCLK/MISO/MOSI is/are set to a valid GPIO. Also check output capability according to the mode.
168  *              - ``SPICOMMON_BUSFLAG_DUAL``: Make sure both MISO and MOSI are output capable so that DIO mode is capable.
169  *              - ``SPICOMMON_BUSFLAG_WPHD`` Make sure WP and HD are set to valid output GPIOs.
170  *              - ``SPICOMMON_BUSFLAG_QUAD``: Combination of ``SPICOMMON_BUSFLAG_DUAL`` and ``SPICOMMON_BUSFLAG_WPHD``.
171  *              - ``SPICOMMON_BUSFLAG_IO4_IO7``: Make sure spi data4 ~ spi data7 are set to valid output GPIOs.
172  *              - ``SPICOMMON_BUSFLAG_OCTAL``: Combination of ``SPICOMMON_BUSFLAG_QUAL`` and ``SPICOMMON_BUSFLAG_IO4_IO7``.
173  * @param[out] flags_o A SPICOMMON_BUSFLAG_* flag combination of bus abilities will be written to this address.
174  *              Leave to NULL if not needed.
175  *              - ``SPICOMMON_BUSFLAG_IOMUX_PINS``: The bus is connected to iomux pins.
176  *              - ``SPICOMMON_BUSFLAG_SCLK``, ``SPICOMMON_BUSFLAG_MISO``, ``SPICOMMON_BUSFLAG_MOSI``: The bus has
177  *                  CLK/MISO/MOSI connected.
178  *              - ``SPICOMMON_BUSFLAG_DUAL``: The bus is capable with DIO mode.
179  *              - ``SPICOMMON_BUSFLAG_WPHD`` The bus has WP and HD connected.
180  *              - ``SPICOMMON_BUSFLAG_QUAD``: Combination of ``SPICOMMON_BUSFLAG_DUAL`` and ``SPICOMMON_BUSFLAG_WPHD``.
181  *              - ``SPICOMMON_BUSFLAG_IO4_IO7``: The bus has spi data4 ~ spi data7 connected.
182  *              - ``SPICOMMON_BUSFLAG_OCTAL``: Combination of ``SPICOMMON_BUSFLAG_QUAL`` and ``SPICOMMON_BUSFLAG_IO4_IO7``.
183  * @return
184  *         - ESP_ERR_INVALID_ARG   if parameter is invalid
185  *         - ESP_OK                on success
186  */
187 esp_err_t spicommon_bus_initialize_io(spi_host_device_t host, const spi_bus_config_t *bus_config, uint32_t flags, uint32_t *flags_o);
188 
189 /**
190  * @brief Free the IO used by a SPI peripheral
191  *
192  * @param bus_cfg Bus config struct which defines which pins to be used.
193  *
194  * @return
195  *         - ESP_ERR_INVALID_ARG   if parameter is invalid
196  *         - ESP_OK                on success
197  */
198 esp_err_t spicommon_bus_free_io_cfg(const spi_bus_config_t *bus_cfg);
199 
200 /**
201  * @brief Initialize a Chip Select pin for a specific SPI peripheral
202  *
203  * @param host SPI peripheral
204  * @param cs_io_num GPIO pin to route
205  * @param cs_num CS id to route
206  * @param force_gpio_matrix If true, CS will always be routed through the GPIO matrix. If false,
207  *                          if the GPIO number allows it, the routing will happen through the IO_mux.
208  */
209 void spicommon_cs_initialize(spi_host_device_t host, int cs_io_num, int cs_num, int force_gpio_matrix);
210 
211 /**
212  * @brief Free a chip select line
213  *
214  * @param cs_gpio_num CS gpio num to free
215  */
216 void spicommon_cs_free_io(int cs_gpio_num);
217 
218 /**
219  * @brief Check whether all pins used by a host are through IOMUX.
220  *
221  * @param host SPI peripheral
222  *
223  * @return false if any pins are through the GPIO matrix, otherwise true.
224  */
225 bool spicommon_bus_using_iomux(spi_host_device_t host);
226 
227 /**
228  * @brief Get the IRQ source for a specific SPI host
229  *
230  * @param host The SPI host
231  *
232  * @return The hosts IRQ source
233  */
234 int spicommon_irqsource_for_host(spi_host_device_t host);
235 
236 /**
237  * @brief Get the IRQ source for a specific SPI DMA
238  *
239  * @param host The SPI host
240  *
241  * @return The hosts IRQ source
242  */
243 int spicommon_irqdma_source_for_host(spi_host_device_t host);
244 
245 /**
246  * Callback, to be called when a DMA engine reset is completed
247 */
248 typedef void(*dmaworkaround_cb_t)(void *arg);
249 
250 #if CONFIG_IDF_TARGET_ESP32
251 //This workaround is only for esp32
252 /**
253  * @brief Request a reset for a certain DMA channel
254  *
255  * @note In some (well-defined) cases in the ESP32 (at least rev v.0 and v.1), a SPI DMA channel will get confused. This can be remedied
256  * by resetting the SPI DMA hardware in case this happens. Unfortunately, the reset knob used for thsi will reset _both_ DMA channels, and
257  * as such can only done safely when both DMA channels are idle. These functions coordinate this.
258  *
259  * Essentially, when a reset is needed, a driver can request this using spicommon_dmaworkaround_req_reset. This is supposed to be called
260  * with an user-supplied function as an argument. If both DMA channels are idle, this call will reset the DMA subsystem and return true.
261  * If the other DMA channel is still busy, it will return false; as soon as the other DMA channel is done, however, it will reset the
262  * DMA subsystem and call the callback. The callback is then supposed to be used to continue the SPI drivers activity.
263  *
264  * @param dmachan DMA channel associated with the SPI host that needs a reset
265  * @param cb Callback to call in case DMA channel cannot be reset immediately
266  * @param arg Argument to the callback
267  *
268  * @return True when a DMA reset could be executed immediately. False when it could not; in this
269  *         case the callback will be called with the specified argument when the logic can execute
270  *         a reset, after that reset.
271  */
272 bool spicommon_dmaworkaround_req_reset(int dmachan, dmaworkaround_cb_t cb, void *arg);
273 
274 
275 /**
276  * @brief Check if a DMA reset is requested but has not completed yet
277  *
278  * @return True when a DMA reset is requested but hasn't completed yet. False otherwise.
279  */
280 bool spicommon_dmaworkaround_reset_in_progress(void);
281 
282 
283 /**
284  * @brief Mark a DMA channel as idle.
285  *
286  * A call to this function tells the workaround logic that this channel will
287  * not be affected by a global SPI DMA reset.
288  */
289 void spicommon_dmaworkaround_idle(int dmachan);
290 
291 /**
292  * @brief Mark a DMA channel as active.
293  *
294  * A call to this function tells the workaround logic that this channel will
295  * be affected by a global SPI DMA reset, and a reset like that should not be attempted.
296  */
297 void spicommon_dmaworkaround_transfer_active(int dmachan);
298 #endif  //#if CONFIG_IDF_TARGET_ESP32
299 
300 /*******************************************************************************
301  * Bus attributes
302  ******************************************************************************/
303 /**
304  * @brief Set bus lock for the main bus, called by startup code.
305  *
306  * @param lock The lock to be used by the main SPI bus.
307  */
308 void spi_bus_main_set_lock(spi_bus_lock_handle_t lock);
309 
310 /**
311  * @brief Get the attributes of a specified SPI bus.
312  *
313  * @param host_id The specified host to get attribute
314  * @return (Const) Pointer to the attributes
315  */
316 const spi_bus_attr_t* spi_bus_get_attr(spi_host_device_t host_id);
317 
318 /**
319  * @brief Register a function to a initialized bus to make it called when deinitializing the bus.
320  *
321  * @param host_id   The SPI bus to register the destructor.
322  * @param f         Destructor to register
323  * @param arg       The argument to call the destructor
324  * @return Always ESP_OK.
325  */
326 esp_err_t spi_bus_register_destroy_func(spi_host_device_t host_id,
327                                         spi_destroy_func_t f, void *arg);
328 
329 /*******************************************************************************
330  * SPI Bus Lock for arbitration among SPI master (intr, polling) trans, SPI flash operations and
331  * flash/psram cache access.
332  *
333  * NON-PUBLIC API. Don't use it directly in applications.
334  *
335  * There is the main lock corresponding to an SPI bus, of which several devices (holding child
336  * locks) attaching to it. Each of the device is STRONGLY RECOMMENDED to be used in only one task
337  * to avoid concurrency issues.
338  *
339  * Terms:
340  * - BG operations (BackGround operations) means some transaction that will not immediately /
341  *   explicitly be sent in the task. It can be some cache access, or interrupt transactions.
342  *
343  * - Operation: usage of the bus, for example, do SPI transactions.
344  *
345  * - Acquiring processor: the task or the ISR that is allowed to use the bus. No operations will be
346  *   performed if there is no acquiring processor. A processor becomes the acquiring processor if
347  *   it ask for that when no acquiring processor exist, otherwise it has to wait for the acquiring
348  *   processor to handle over the role to it. The acquiring processor will and will only assign one
349  *   acquiring processor in the waiting list (if not empty) when it finishes its operation.
350  *
351  * - Acquiring device: the only device allowed to use the bus. Operations can be performed in
352  *   either the BG or the task. When there's no acquiring device, only the ISR is allowed to be the
353  *   acquiring processor and perform operations on the bus.
354  *
355  * When a device wants to perform operations, it either:
356  * 1. Acquire the bus, and operate in the task (e.g. polling transactions of SPI master, and SPI flash
357  *    operations)
358  *
359  * 2. Request a BG operation. And the ISR will be enabled at proper time.
360  *
361  *    For example if a task wants to send an interrupt transaction, it prepares the data in the task,
362  *    call `spi_bus_lock_bg_request`, and handle sending in the ISR.
363  *
364  * 3. When a device has already acquired the bus, BG operations are also allowed. After the
365  *    `spi_bus_lock_bg_request` is called, call `spi_bus_lock_wait_bg_done` before operations in task
366  *    again to wait until BG operations are done.
367  *
368  * Any device may try to invoke the ISR (by `spi_bus_lock_bg_request`). The ISR will be invoked and
369  * become the acquiring processor immediately when the bus is not acquired by other processors. Any
370  * device may also try to acquire the bus (by `spi_bus_lock_acquire_start`). The device will become
371  * the acquiring processor immediately when the bus is not acquired and there is no request active.
372  *
373  * The acquiring processor must be aware of its acquiring role, and properly transfer the acquiring
374  * processor to other tasks or ISR when they have nothing else to do. Before picking a new
375  * acquiring processor, a new acquiring device must be picked first, if there are other devices,
376  * asking to be acquiring device. After that, the new acquiring processor is picked by the sequence
377  * below:
378  *
379  * 1. If there is an acquiring device:
380  *      1.1 The ISR, if acquiring device has active BG requests
381  *      1.2 The task of the device, if no active BG request for the device
382  * 2. The ISR, if there's no acquiring device, but any BG request is active
383  * 3. No one becomes the acquiring processor
384  *
385  * The API also helps on the arbitration of SPI cs lines. The bus is initialized with a cs_num
386  * argument. When attaching devices onto the bus with `spi_bus_lock_register_dev`, it will allocate
387  * devices with different device ID according to the flags given. If the ID is smaller than the
388  * cs_num given when bus is initialized, error will be returned.
389  *
390  * Usage:
391  * * Initialization:
392  * 1. Call `spi_bus_init_lock` to register a lock for a bus.
393  * 2. Call `spi_bus_lock_set_bg_control` to prepare BG enable/disable functions for
394  *    the lock.
395  * 3. Call `spi_bus_lock_register_dev` for each devices that may make use of the
396  *    bus, properly store the returned handle, representing those devices.
397  *
398  * * Acquiring:
399  * 1. Call `spi_bus_lock_acquire_start` when a device wants to use the bus
400  * 2. Call `spi_bus_lock_touch` to mark the bus as touched by this device. Also check if the bus
401  *    has been touched by other devices.
402  * 3. (optional) Do something on the bus...
403  * 4. (optional) Call `spi_bus_lock_bg_request` to inform and invoke the BG. See ISR below about
404  *    ISR operations.
405  * 5. (optional) If `spi_bus_lock_bg_request` is done, you have to call `spi_bus_lock_wait_bg_done`
406  *    before touching the bus again, or do the following steps.
407  * 6. Call `spi_bus_lock_acquire_end` to release the bus to other devices.
408  *
409  * * ISR:
410  * 1. Call `spi_bus_lock_bg_entry` when entering the ISR, run or skip the closure for the previous
411  *    operation according to the return value.
412  * 2. Call `spi_bus_lock_get_acquiring_dev` to get the acquiring device. If there is no acquiring
413  *    device, call `spi_bus_lock_bg_check_dev_acq` to check and update a new acquiring device.
414  * 3. Call `spi_bus_lock_bg_check_dev_req` to check for request of the desired device. If the
415  *    desired device is not requested, go to step 5.
416  * 4. Check, start operation for the desired device and go to step 6; otherwise if no operations
417  *    can be performed, call `spi_bus_lock_bg_clear_req` to clear the request for this device. If
418  *    `spi_bus_lock_bg_clear_req` is called and there is no BG requests active, goto step 6.
419  * 5. (optional) If the device is the acquiring device, go to step 6, otherwise
420  *    find another desired device, and go back to step 3.
421  * 6. Call `spi_bus_lock_bg_exit` to try quitting the ISR. If failed, go back to step 2 to look for
422  *    a new request again. Otherwise, quit the ISR.
423  *
424  * * Deinitialization (optional):
425  * 1. Call `spi_bus_lock_unregister_dev` for each device when they are no longer needed.
426  * 2. Call `spi_bus_deinit_lock` to release the resources occupied by the lock.
427  *
428  * Some technical details:
429  *
430  * The child-lock of each device will have its own Binary Semaphore, which allows the task serving
431  * this device (task A) being blocked when it fail to become the acquiring processor while it's
432  * calling `spi_bus_lock_acquire_start` or `spi_bus_lock_wait_bg_done`. If it is blocked, there
433  * must be an acquiring processor (either the ISR or another task (task B)), is doing transaction
434  * on the bus. After that, task A will get unblocked and become the acquiring processor when the
435  * ISR call `spi_bus_lock_bg_resume_acquired_dev`, or task B call `spi_bus_lock_acquire_end`.
436  *
437  * When the device wants to send ISR transaction, it should call `spi_bus_lock_bg_request` after
438  * the data is prepared. This function sets a request bit in the critical resource. The ISR will be
439  * invoked and become the new acquiring processor, when:
440  *
441  * 1. A task calls `spi_bus_lock_bg_request` while there is no acquiring processor;
442  * 2. A tasks calls `spi_bus_lock_bg_request` while the task is the acquiring processor. Then the
443  *    acquiring processor is handled over to the ISR;
444  * 3. A tasks who is the acquiring processor release the bus by calling `spi_bus_lock_acquire_end`,
445  *    and the ISR happens to be the next acquiring processor.
446  *
447  * The ISR will check (by `spi_bus_lock_bg_check_dev_req`) and clear a request bit (by
448  * `spi_bus_lock_bg_clear_req`) after it confirm that all the requests of the corresponding device
449  * are served. The request bit supports being written to recursively, which means, the task don't
450  * need to wait for `spi_bus_lock_bg_clear_req` before call another `spi_bus_lock_bg_request`. The
451  * API will handle the concurrency conflicts properly.
452  *
453  * The `spi_bus_lock_bg_exit` (together with `spi_bus_lock_bg_entry` called before)` is responsible
454  * to ensure ONE and ONLY ONE of the following will happen when the ISR try to give up its
455  * acquiring processor rule:
456  *
457  * 1. ISR quit, no any task unblocked while the interrupt disabled, and none of the BG bits is
458  *    active.
459  * 2. ISR quit, there is an acquiring device, and the acquiring processor is passed to the task
460  *    serving the acquiring device by unblocking the task.
461  * 3. The ISR failed to quit and have to try again.
462  ******************************************************************************/
463 
464 #define DEV_NUM_MAX 6     ///< Number of devices supported by this lock
465 
466 /// Lock configuration struct
467 typedef struct {
468     int host_id;    ///< SPI host id
469     int cs_num;     ///< Physical cs numbers of the host
470 } spi_bus_lock_config_t;
471 
472 /// Child-lock configuration struct
473 typedef struct {
474     uint32_t flags; ///< flags for the lock, OR-ed of `SPI_BUS_LOCK_DEV_*` flags.
475 #define SPI_BUS_LOCK_DEV_FLAG_CS_REQUIRED   BIT(0)  ///< The device needs a physical CS pin.
476 } spi_bus_lock_dev_config_t;
477 
478 /************* Common *********************/
479 /**
480  * Initialize a lock for an SPI bus.
481  *
482  * @param out_lock Output of the handle to the lock
483  * @return
484  *  - ESP_ERR_NO_MEM: if memory exhausted
485  *  - ESP_OK: if success
486  */
487 esp_err_t spi_bus_init_lock(spi_bus_lock_handle_t *out_lock, const spi_bus_lock_config_t *config);
488 
489 /**
490  * Free the resources used by an SPI bus lock.
491  *
492  * @note All attached devices should have been unregistered before calling this
493  *       funciton.
494  *
495  * @param lock Handle to the lock to free.
496  */
497 void spi_bus_deinit_lock(spi_bus_lock_handle_t lock);
498 
499 /**
500  * @brief Get the corresponding lock according to bus id.
501  *
502  * @param host_id The bus id to get the lock
503  * @return The lock handle
504  */
505 spi_bus_lock_handle_t spi_bus_lock_get_by_id(spi_host_device_t host_id);
506 
507 /**
508  * @brief Configure how the SPI bus lock enable the background operation.
509  *
510  * @note The lock will not try to stop the background operations, but wait for
511  *       The background operations finished indicated by `spi_bus_lock_bg_resume_acquired_dev`.
512  *
513  * @param lock Handle to the lock to set
514  * @param bg_enable The enabling function
515  * @param bg_disable The disabling function, set to NULL if not required
516  * @param arg Argument to pass to the enabling/disabling function.
517  */
518 void spi_bus_lock_set_bg_control(spi_bus_lock_handle_t lock, bg_ctrl_func_t bg_enable,
519                                  bg_ctrl_func_t bg_disable, void *arg);
520 
521 /**
522  * Attach a device onto an SPI bus lock. The returning handle is used to perform
523  * following requests for the attached device.
524  *
525  * @param lock SPI bus lock to attach
526  * @param out_dev_handle Output handle corresponding to the device
527  * @param flags requirement of the device, bitwise OR of SPI_BUS_LOCK_FLAG_* flags
528  *
529  * @return
530  *  - ESP_ERR_NOT_SUPPORTED: if there's no hardware resources for new devices.
531  *  - ESP_ERR_NO_MEM: if memory exhausted
532  *  - ESP_OK: if success
533  */
534 esp_err_t spi_bus_lock_register_dev(spi_bus_lock_handle_t lock,
535                                     spi_bus_lock_dev_config_t *config,
536                                     spi_bus_lock_dev_handle_t *out_dev_handle);
537 
538 /**
539  * Detach a device from its bus and free the resources used
540  *
541  * @param dev_handle Handle to the device.
542  */
543 void spi_bus_lock_unregister_dev(spi_bus_lock_dev_handle_t dev_handle);
544 
545 /**
546  * @brief Get the parent bus lock of the device
547  *
548  * @param dev_handle Handle to the device to get bus lock
549  * @return The bus lock handle
550  */
551 spi_bus_lock_handle_t spi_bus_lock_get_parent(spi_bus_lock_dev_handle_t dev_handle);
552 
553 /**
554  * @brief Get the device ID of a lock.
555  *
556  * The callers should allocate CS pins according to this ID.
557  *
558  * @param dev_handle Handle to the device to get ID
559  * @return ID of the device
560  */
561 int spi_bus_lock_get_dev_id(spi_bus_lock_dev_handle_t dev_handle);
562 
563 /**
564  * @brief The device request to touch bus registers. Can only be called by the acquiring processor.
565  *
566  * Also check if the registers has been touched by other devices.
567  *
568  * @param dev_handle Handle to the device to operate the registers
569  * @return true if there has been other devices touching SPI registers.
570  *     The caller may need to do a full-configuration. Otherwise return
571  *     false.
572  */
573 bool spi_bus_lock_touch(spi_bus_lock_dev_handle_t dev_handle);
574 
575 /************* Acquiring service *********************/
576 /**
577  * Acquiring the SPI bus for exclusive use. Will also wait for the BG to finish all requests of
578  * this device before it returns.
579  *
580  * After successfully return, the caller becomes the acquiring processor.
581  *
582  * @note For the main flash bus, `bg_disable` will be called to disable the cache.
583  *
584  * @param dev_handle Handle to the device request for acquiring.
585  * @param wait Time to wait until timeout or succeed, must be `portMAX_DELAY` for now.
586  * @return
587  *  - ESP_OK: on success
588  *  - ESP_ERR_INVALID_ARG: timeout is not portMAX_DELAY
589  */
590 esp_err_t spi_bus_lock_acquire_start(spi_bus_lock_dev_handle_t dev_handle, uint32_t wait);
591 
592 /**
593  * Release the bus acquired. Will pass the acquiring processor to other blocked
594  * processors (tasks or ISR), and cause them to be unblocked or invoked.
595  *
596  * The acquiring device may also become NULL if no device is asking for acquiring.
597  * In this case, the BG may be invoked if there is any BG requests.
598  *
599  * If the new acquiring device has BG requests, the BG will be invoked before the
600  * task is resumed later after the BG finishes all requests of the new acquiring
601  * device. Otherwise the task of the new acquiring device will be resumed immediately.
602  *
603  * @param dev_handle Handle to the device releasing the bus.
604  * @return
605  *  - ESP_OK: on success
606  *  - ESP_ERR_INVALID_STATE: the device hasn't acquired the lock yet
607  */
608 esp_err_t spi_bus_lock_acquire_end(spi_bus_lock_dev_handle_t dev_handle);
609 
610 /**
611  * Get the device acquiring the bus.
612  *
613  * @note Return value is not stable as the acquiring processor may change
614  *       when this function is called.
615  *
616  * @param lock Lock of SPI bus to get the acquiring device.
617  * @return The argument corresponding to the acquiring device, see
618  *         `spi_bus_lock_register_dev`.
619  */
620 spi_bus_lock_dev_handle_t spi_bus_lock_get_acquiring_dev(spi_bus_lock_handle_t lock);
621 
622 /************* BG (Background, for ISR or cache) service *********************/
623 /**
624  * Call by a device to request a BG operation.
625  *
626  * Depending on the bus lock state, the BG operations may be resumed by this
627  * call, or pending until BG operations allowed.
628  *
629  * Cleared by `spi_bus_lock_bg_clear_req` in the BG.
630  *
631  * @param dev_handle The device requesting BG operations.
632  * @return always ESP_OK
633  */
634 esp_err_t spi_bus_lock_bg_request(spi_bus_lock_dev_handle_t dev_handle);
635 
636 /**
637  * Wait until the ISR has finished all the BG operations for the acquiring device.
638  * If any `spi_bus_lock_bg_request` for this device has been called after
639  * `spi_bus_lock_acquire_start`, this function must be called before any operation
640  * in the task.
641  *
642  * @note Can only be called when bus acquired by this device.
643  *
644  * @param dev_handle Handle to the device acquiring the bus.
645  * @param wait Time to wait until timeout or succeed, must be `portMAX_DELAY` for now.
646  * @return
647  *  - ESP_OK: on success
648  *  - ESP_ERR_INVALID_STATE: The device is not the acquiring bus.
649  *  - ESP_ERR_INVALID_ARG: Timeout is not portMAX_DELAY.
650  */
651 esp_err_t spi_bus_lock_wait_bg_done(spi_bus_lock_dev_handle_t dev_handle, uint32_t wait);
652 
653 /**
654  * Handle interrupt and closure of last operation. Should be called at the beginning of the ISR,
655  * when the ISR is acting as the acquiring processor.
656  *
657  * @param lock The SPI bus lock
658  *
659  * @return false if the ISR has already touched the HW, should run closure of the
660  *         last operation first; otherwise true if the ISR just start operating
661  *         on the HW, closure should be skipped.
662  */
663 bool spi_bus_lock_bg_entry(spi_bus_lock_handle_t lock);
664 
665 /**
666  * Handle the scheduling of other acquiring devices, and control of HW operation
667  * status.
668  *
669  * If no BG request is found, call with `wip=false`. This function will return false,
670  * indicating there is incoming BG requests for the current acquiring device (or
671  * for all devices if there is no acquiring device) and the ISR needs retry.
672  * Otherwise may schedule a new acquiring processor (unblock the task) if there
673  * is, and return true.
674  *
675  * Otherwise if a BG request is started in this ISR, call with `wip=true` and the
676  * function will enable the interrupt to make the ISR be called again when the
677  * request is done.
678  *
679  * This function is safe and should still be called when the ISR just lost its acquiring processor
680  * role, but hasn't quit.
681  *
682  * @note This function will not change acquiring device. The ISR call
683  *       `spi_bus_lock_bg_update_acquiring` to check for new acquiring device,
684  *       when acquiring devices need to be served before other devices.
685  *
686  * @param lock The SPI bus lock.
687  * @param wip Whether an operation is being executed when quitting the ISR.
688  * @param do_yield[out] Not touched when no yielding required, otherwise set
689  *                      to pdTRUE.
690  * @return false if retry is required, indicating that there is pending BG request.
691  *         otherwise true and quit ISR is allowed.
692  */
693 bool spi_bus_lock_bg_exit(spi_bus_lock_handle_t lock, bool wip, int* do_yield);
694 
695 /**
696  * Check whether there is device asking for the acquiring device, and the desired
697  * device for the next operation is also recommended.
698  *
699  * @note Must be called when the ISR is acting as the acquiring processor, and
700  *        there is no acquiring device.
701  *
702  * @param lock The SPI bus lock.
703  * @param out_dev_lock The recommended device for hte next operation. It's the new
704  *        acquiring device when found, otherwise a device that has active BG request.
705  *
706  * @return true if the ISR need to quit (new acquiring device has no active BG
707  *         request, or no active BG requests for all devices when there is no
708  *         acquiring device), otherwise false.
709  */
710 bool spi_bus_lock_bg_check_dev_acq(spi_bus_lock_handle_t lock, spi_bus_lock_dev_handle_t *out_dev_lock);
711 
712 /**
713  * Check if the device has BG requests. Must be called when the ISR is acting as
714  * the acquiring processor.
715  *
716  * @note This is not stable, may become true again when a task request for BG
717  *       operation (by `spi_bus_lock_bg_request`).
718  *
719  * @param dev_lock The device to check.
720  * @return true if the device has BG requests, otherwise false.
721  */
722 bool spi_bus_lock_bg_check_dev_req(spi_bus_lock_dev_handle_t dev_lock);
723 
724 /**
725  * Clear the pending BG operation request of a device after served. Must be
726  * called when the ISR is acting as the acquiring processor.
727  *
728  * @note When the return value is true, the ISR will lost the acquiring processor role. Then
729  *       `spi_bus_lock_bg_exit` must be called and checked before calling all other functions that
730  *       require to be called when the ISR is the acquiring processor again.
731  *
732  * @param dev_handle The device whose request is served.
733  * @return True if no pending requests for the acquiring device, or for all devices
734  *         if there is no acquiring device. Otherwise false. When the return value is
735  *         true, the ISR is no longer the acquiring processor.
736  */
737 bool spi_bus_lock_bg_clear_req(spi_bus_lock_dev_handle_t dev_lock);
738 
739 /**
740  * Check if there is any active BG requests.
741  *
742  * @param lock The SPI bus lock.
743  * @return true if any device has active BG requst, otherwise false.
744  */
745 bool spi_bus_lock_bg_req_exist(spi_bus_lock_handle_t lock);
746 
747 /*******************************************************************************
748  * Variable and APIs for the OS to initialize the locks for the main chip
749  ******************************************************************************/
750 /// The lock for the main bus
751 extern const spi_bus_lock_handle_t g_main_spi_bus_lock;
752 
753 /**
754  * @brief Initialize the main SPI bus, called during chip startup.
755  *
756  * @return always ESP_OK
757  */
758 esp_err_t spi_bus_lock_init_main_bus(void);
759 
760 /// The lock for the main flash device
761 extern const spi_bus_lock_dev_handle_t g_spi_lock_main_flash_dev;
762 
763 /**
764  * @brief Initialize the main flash device, called during chip startup.
765  *
766  * @return
767  *      - ESP_OK: if success
768  *      - ESP_ERR_NO_MEM: memory exhausted
769  */
770 esp_err_t spi_bus_lock_init_main_dev(void);
771 
772 
773 #ifdef __cplusplus
774 }
775 #endif
776