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 SDIO slave (common part)
14 
15 // SDIO slave HAL usages:
16 
17 /*
18 Architecture:
19 
20 The whole SDIO slave peripheral consists of three parts: the registers (including the interrupt
21 control and shared registers), a send FIFO, and a receive FIFO. The document
22 ``esp_slave_protocol.rst`` describes the functionality of the peripheral in detail. An SDIO host
23 will only ever access one of the three parts at any one time, thus the hardware functionality of
24 the SDIO slave peripheral are completely independent. Likewise, this HAL is organized in such a
25 fashion as to correspond to the three independent parts.
26 
27 The shared registers are quite simple: the slave can directly access them from the internal data
28 bus, while the host can access them by CMD52/53 with the correct address. As for the interrupts:
29 when an SDIO host interrupts the SDIO slave peripheral (by writing a command), the corresponding
30 bit in the interrupt register will be set; when the SDIO slave peripheral needs to interrupt the
31 host, it write some register to cause the host interrupt bit being set, and the slave hardware
32 will output the interrupt signal on the DAT1 line.
33 
34 For the FIFOs, the peripheral provides counters as registers so that the host can always know whether the slave
35 is ready to send/receive data. The HAL resets the counters during initialization, and the host should somehow
36 inform the slave to reset the counters again if it should reboot (or lose the counter value for some reasons).
37 Then the host can read/write the FIFOs by CMD53 commands according to the counters.
38 
39 In order to avoid copying data to/from the FIFOs or memory buffers each time, the HAL layer
40 contains a descriptor queue (implemented as linked-list) that allows descriptors of memory
41 buffers to be queued for transmission/reception. Once a buffer is queued, the HAL takes ownership
42 of the buffer until some "finish" functions successfully return, indicating the
43 transmission/reception of that buffer is complete. The ISR is invoked multiple times to iterate
44 through the queued descriptors, and also to signal to the upper layer if a buffer has been
45 freed.
46 
47 The HAL is used as below:
48 
49 - Receiving part:
50 
51     1.  Call `sdio_slave_hal_recv_start` to start the receiving DMA.
52 
53         If there are already buffers loaded, the receiving will start from those buffers first.
54 
55     2.  Call `sdio_slave_hal_recv_init_desc` with a `sdio_slave_hal_recv_desc_t` and the buffer address to
56         associate the descriptor with the buffer.
57 
58         The HAL initialize this descriptors with the determined length and maybe some extra data.
59 
60     3.  Call `sdio_slave_hal_load_buf` with the initialized descriptor of the buffer to load a
61         receiving buffer to the HAL.
62 
63         When the DMA is started, the descriptors is loaded onto the DMA linked-list, and the
64         counter of receiving buffers is increased so that the host will know this by the
65         receiving interrupt. The hardware will automatically go through the linked list and write
66         data into the buffers loaded on the list.
67 
68     4.  (Optional, mandatory only when interrupt enabled) Call `sdio_slave_hal_recv_done` to check
69         and clear the receiving interrupt bits.
70 
71     5.  Call `sdio_slave_hal_recv_has_next_item` to check whether there are finished buffers.
72 
73     6.  Call `sdio_slave_hal_recv_unload_desc` for the same times as
74         `sdio_slave_hal_recv_has_next_item` successfully returns.
75 
76     7.  (Optional) Call `sdio_slave_hal_recv_reset_counter` to reset the counter to current loaded
77         but not used buffers if you want to reset the counter only. This is available only when
78         the DMA is stopped.
79 
80     8.  (Optional) Call `sdio_slave_hal_recv_flush_one_buffer` (recursively) if you want to
81         discard data of one (or more) buffers and load them again. This is available only when
82         the DMA is stopped.
83 
84     9.  (Optional when deinitialization) Call `sdio_slave_hal_recv_unload_desc` recursively to get
85         all the buffers loaded to the HAL, no matter they are used or not. Don't do this when the
86         DMA is not stopped.
87 
88 - Sending part:
89 
90     The sending driver is slightly different, since we are not using the re-start feature.
91     (TODO: re-write this part if the stitch mode is released)
92 
93     1.  Call `sdio_slave_hal_send_start` to start the sending DMA.
94 
95         If there is already any data queued, it will ne ready to be sent to host now.
96 
97     2.  Call `sdio_slave_hal_send_queue` to queue the data to send.
98 
99         If the interrupt is enabled, the ISR will be invoked.
100 
101     3.  (Required if interrupt enabled) Call `` to clear the interrupt bits used by the SW
102         invoking logic.
103 
104     4.  Call `sdio_slave_hal_send_new_packet_if_exist` to check and send new packet (if there is
105         data queued).
106 
107     5.  Call `sdio_slave_hal_send_eof_happened` to check whether the previous packet is done.
108 
109         It will also clear the interrupt status bit for this event.
110 
111     6.  Call `sdio_slave_hal_send_get_next_finished_arg` recursively to get the arguments for the
112         finished buffers.
113 
114     7.  (Optional when deinitialization) Call `sdio_slave_hal_send_flush_next_buffer` recursively
115         to get all buffers queued, regardless sent or not. Don't do this when the DMA is not stopped.
116 
117     8.  (Optional) Call `sdio_slave_hal_send_reset_counter` to reset the counter to current loaded
118         but not sent buffers if you want to reset the counter only. Don't do this when the DMA is not
119         stopped.
120 
121     Note a counter should be used when performing step 2 and 6, to make sure that the queue size
122     is enough.
123 
124 - Host part:
125 
126     1.  Call `sdio_slave_hal_hostint_set_ena` and `sdio_slave_hal_hostint_get_ena` to
127         enable/disable the interrupt sent to master. Note that the host can also modify the same
128         registers at the same time. Try to avoid using them outside the initialization process.
129 
130     2.  Call `sdio_slave_hal_hostint_send` and `sdio_slave_hal_hostint_clear` to trigger general
131         purpose interrupts or cancel all kinds of interrupts send to the host. These interrupts are
132         set/cleared in a concurrent-safe way, so the slave can call these functions safely.
133 
134     3.  Call `sdio_slave_hal_slvint_fetch_clear` to fetch the general purpose interrupts sent by
135         the host to the slave. These interrupts will also be cleared after the calls.
136 
137     4.  Call `sdio_slave_hal_host_get_reg` and `sdio_slave_hal_host_set_reg` to read/write the
138         general purpose shared between the host and slave. Note that these registers are also not
139         concurrent-safe. Try not to write to the same register from two directions at the same time.
140 */
141 
142 #pragma once
143 #include <esp_err.h>
144 #include "hal/sdio_slave_types.h"
145 #include "hal/sdio_slave_ll.h"
146 
147 /// Space used for each sending descriptor. Should initialize the sendbuf accoring to this size.
148 #define SDIO_SLAVE_SEND_DESC_SIZE   sizeof(sdio_slave_hal_send_desc_t)
149 
150 
151 /// Status of the sending part
152 typedef enum {
153     STATE_IDLE = 1,
154     STATE_WAIT_FOR_START = 2,
155     STATE_SENDING = 3,
156     STATE_GETTING_RESULT = 4,
157     STATE_GETTING_UNSENT_DESC = 5,
158 } send_state_t;
159 
160 typedef struct {
161     uint8_t* data;      ///< Address of the buffer
162     size_t  size;       ///< Size of the buffer, but can only queue (size/SDIO_SLAVE_SEND_DESC_SIZE)-1 descriptors
163     uint8_t* write_ptr;
164     uint8_t* read_ptr;
165     uint8_t* free_ptr;
166 } sdio_ringbuf_t;
167 
168 // Append two extra words to be used by the HAL.
169 // Should Initialize the member `data` of `send_desc_queue` of the HAL context
170 // with size of this desc * N.
171 
172 /// DMA descriptor with extra fields
173 typedef struct sdio_slave_hal_send_desc_s {
174     sdio_slave_ll_desc_t dma_desc;    ///< Used by Hardware, has pointer linking to next desc
175     uint32_t pkt_len;     ///< Accumulated length till this descriptor
176     void*   arg;          ///< Holding arguments indicating this buffer */
177 } sdio_slave_hal_send_desc_t;
178 
179 /// Descriptor used by the receiving part, call `sdio_slave_hal_recv_init_desc`
180 /// to initialize it before use.
181 typedef sdio_slave_ll_desc_t sdio_slave_hal_recv_desc_t;
182 #define sdio_slave_hal_recv_desc_s sdio_slave_ll_desc_s
183 typedef STAILQ_HEAD(recv_stailq_head_s, sdio_slave_hal_recv_desc_s) sdio_slave_hal_recv_stailq_t;
184 
185 
186 /** HAL context structure. Call `sdio_slave_hal_init` to initialize it and
187  * configure required members before actually use the HAL.
188  */
189 typedef struct {
190     /// Hardware registers for this SDIO slave peripheral, configured by
191     /// `sdio_slave_hal_init`
192     struct {
193         slc_dev_t*      slc;
194         host_dev_t*     host;
195         hinf_dev_t*     hinf;
196     };
197     sdio_slave_sending_mode_t sending_mode; /**< Sending mode, should be manually configured before using the HAL.
198                                              * see `sdio_slave_sending_mode_t`.
199                                              */
200     sdio_slave_timing_t timing;             /**< Timing mode (launch edge and latch edge settings). Should be manually
201                                              * configured before using the HAL. `SDIO_SLAVE_TIMING_PSEND_PSAMPLE` is
202                                              * recommended by default.
203                                              */
204     //some boolean flags
205     struct {
206         uint32_t no_highspeed: 1;           /**< Disable the highspeed support */
207     };
208     int                 send_queue_size;    /**< Max buffers that can be queued before sending. Should be manually
209                                              * configured before using the HAL.
210                                              */
211     size_t              recv_buffer_size;   /**< The size of each buffer. The host and slave should share a
212                                              * pre-negotiated value. Should be manually configured before using
213                                              * the HAL.
214                                              */
215     sdio_ringbuf_t      send_desc_queue;            /**< The ring buffer used to hold queued descriptors. Should be manually
216                                              * initialized before using the HAL.
217                                              */
218 
219     //Internal status, no need to touch.
220     send_state_t        send_state;         // Current state of sending part.
221     uint32_t            tail_pkt_len;       // The accumulated send length of the tail packet.
222     sdio_slave_hal_send_desc_t*         in_flight_head; // The head of linked list in-flight.
223     sdio_slave_hal_send_desc_t*         in_flight_end;  // The end of linked list in-flight.
224     sdio_slave_hal_send_desc_t*         in_flight_next; // The header of linked list to be sent next time.
225     sdio_slave_hal_send_desc_t*         returned_desc;  // The last returned descriptor
226 
227     sdio_slave_hal_recv_stailq_t            recv_link_list; // Linked list of buffers ready to hold data and the buffers already hold data.
228     volatile sdio_slave_hal_recv_desc_t*    recv_cur_ret;   // Next desc to return, NULL if all loaded descriptors are returned.
229 } sdio_slave_context_t ;
230 
231 /**
232  * Initialize the HAL, should provide buffers to the context and configure the
233  * members before this funciton is called.
234  *
235  * @param hal Context of the HAL layer.
236  */
237 void sdio_slave_hal_init(sdio_slave_context_t *hal);
238 
239 /**
240  * Initialize the SDIO slave peripheral hardware.
241  *
242  * @param hal Context of the HAL layer.
243  */
244 void sdio_slave_hal_hw_init(sdio_slave_context_t *hal);
245 
246 /**
247  * Set the IO ready for host to read.
248  *
249  * @param hal Context of the HAL layer.
250  * @param ready true to tell the host the slave is ready, otherwise false.
251  */
252 void sdio_slave_hal_set_ioready(sdio_slave_context_t *hal, bool ready);
253 
254 /*---------------------------------------------------------------------------
255  *                  Send
256  *--------------------------------------------------------------------------*/
257 
258 /**
259  * The hardware sending DMA starts. If there is existing data, send them.
260  *
261  * @param hal Context of the HAL layer.
262  */
263 esp_err_t sdio_slave_hal_send_start(sdio_slave_context_t *hal);
264 
265 /**
266  * Stops hardware sending DMA.
267  *
268  * @note The data in the queue, as well as the counter are not touched.
269  * @param hal Context of the HAL layer.
270  */
271 void sdio_slave_hal_send_stop(sdio_slave_context_t *hal);
272 
273 /**
274  * Put some data into the sending queue.
275  *
276  * @note The caller should keeps the buffer, until the `arg` is returned by
277  *       `sdio_slave_hal_send_get_next_finished_arg`.
278  * @note The caller should count to ensure there is enough space in the queue.
279  *       The initial queue size is sizeof(sendbuf.data)/sizeof(sdio_slave_hal_send_desc_t)-1,
280  *       Will decrease by one when this function successfully returns.
281  *       Released only by `sdio_slave_hal_send_get_next_finished_arg` or
282  *       `sdio_slave_hal_send_flush_next_buffer`.
283  *
284  * @note The HAL is not thread-safe. The caller should use a spinlock to ensure
285  *       the `sdio_slave_hal_send_queue` and ... are not called at the same time.
286  *
287  * @param hal Context of the HAL layer.
288  * @param addr Address of data in the memory to send.
289  * @param len Length of data to send.
290  * @param arg Argument indicating this sending.
291  * @return Always ESP_OK.
292  */
293 esp_err_t sdio_slave_hal_send_queue(sdio_slave_context_t *hal, uint8_t *addr, size_t len, void *arg);
294 
295 /**
296  * The ISR should call this, to handle the SW invoking event.
297  * @param hal Context of the HAL layer.
298  */
299 void sdio_slave_hal_send_handle_isr_invoke(sdio_slave_context_t *hal);
300 
301 /**
302  * Check whether there is no in-flight transactions, and send new packet if there
303  * is new packets queued.
304  *
305  * @param hal Context of the HAL layer.
306  * @return
307  *  - ESP_OK: The DMA starts to send a new packet.
308  *  - ESP_ERR_NOT_FOUND: No packet waiting to be sent.
309  *  - ESP_ERR_INVALID_STATE: There is packet in-flight.
310  */
311 esp_err_t sdio_slave_hal_send_new_packet_if_exist(sdio_slave_context_t *hal);
312 
313 /**
314  * Check whether the sending EOF has happened and clear the interrupt.
315  *
316  * Call `sdio_slave_hal_send_get_next_finished_arg` recursively to retrieve arguments of finished
317  * buffers.
318  *
319  * @param hal Context of the HAL layer.
320  * @return true if happened, otherwise false.
321  */
322 bool sdio_slave_hal_send_eof_happened(sdio_slave_context_t *hal);
323 
324 /**
325  * Get the arguments of finished packets. Call recursively until all finished
326  * arguments are all retrieved.
327  *
328  * @param hal Context of the HAL layer.
329  * @param out_arg Output argument of the finished buffer.
330  * @param out_returned_cnt Released queue size to be queued again.
331  * @return
332  *  - ESP_OK: if one argument retrieved.
333  *  - ESP_ERR_NOT_FOUND: All the arguments of the finished buffers are retrieved.
334  */
335 esp_err_t sdio_slave_hal_send_get_next_finished_arg(sdio_slave_context_t *hal, void **out_arg, uint32_t* out_returned_cnt);
336 
337 /**
338  * Flush one buffer in the queue, no matter sent, canceled or not sent yet.
339  *
340  * Call recursively to clear the whole queue before deinitialization.
341  *
342  * @note Only call when the DMA is stopped!
343  * @param hal Context of the HAL layer.
344  * @param out_arg Argument indiciating the buffer to send
345  * @param out_return_cnt Space in the queue released after this descriptor is flushed.
346  * @return
347  *  - ESP_ERR_INVALID_STATE: This function call be called only when the DMA is stopped.
348  *  - ESP_ERR_NOT_FOUND: if no buffer in the queue
349  *  - ESP_OK: if a buffer is successfully flushed and returned.
350  */
351 esp_err_t sdio_slave_hal_send_flush_next_buffer(sdio_slave_context_t *hal, void **out_arg, uint32_t *out_return_cnt);
352 
353 /**
354  * Walk through all the unsent buffers and reset the counter to the accumulated length of them. The data will be kept.
355  *
356  * @note Only call when the DMA is stopped!
357  * @param hal Context of the HAL layer.
358  * @return
359  *  - ESP_ERR_INVALID_STATE: this function call be called only when the DMA is stopped
360  *  - ESP_OK: if success
361  */
362 esp_err_t sdio_slave_hal_send_reset_counter(sdio_slave_context_t *hal);
363 
364 
365 /*---------------------------------------------------------------------------
366  *                  Receive
367  *--------------------------------------------------------------------------*/
368 /**
369  * Start the receiving DMA.
370  *
371  * @note If there are already some buffers loaded, will receive from them first.
372  * @param hal Context of the HAL layer.
373  */
374 void sdio_slave_hal_recv_start(sdio_slave_context_t *hal);
375 
376 /**
377  * Stop the receiving DMA.
378  *
379  * @note Data and the counter will not be touched. You can still call
380  *       `sdio_slave_hal_recv_has_next_item` to get the received buffer.
381  *       And unused buffers loaded to the HAL will still be in the `loaded`
382  *       state in the HAL, until returned by `sdio_slave_hal_recv_unload_desc`.
383  * @param hal Context of the HAL layer.
384  */
385 void sdio_slave_hal_recv_stop(sdio_slave_context_t* hal);
386 
387 /**
388  * Associate the buffer to the descriptor given. The descriptor may also be initialized with some
389  * other data.
390  *
391  * @param hal Context of the HAL layer.
392  * @param desc Descriptor to associate with the buffer
393  * @param start Start address of the buffer
394  */
395 void sdio_slave_hal_recv_init_desc(sdio_slave_context_t *hal, sdio_slave_hal_recv_desc_t *desc, uint8_t *start);
396 
397 /**
398  * Load the buffer to the HAL to be used to receive data.
399  *
400  * @note Loaded buffers will be returned to the upper layer only when:
401  *       1. Returned by `sdio_slave_hal_recv_has_next_item` when receiving to that buffer successfully
402  *       done.
403  *       2. Returned by `sdio_slave_hal_recv_unload_desc` unconditionally.
404  * @param hal Context of the HAL layer.
405  * @param desc Descriptor to load to the HAL to receive.
406  */
407 void sdio_slave_hal_load_buf(sdio_slave_context_t *hal, sdio_slave_hal_recv_desc_t *desc);
408 
409 /**
410  * Check and clear the interrupt indicating a buffer has finished receiving.
411  *
412  * @param hal Context of the HAL layer.
413  * @return true if interrupt triggered, otherwise false.
414  */
415 bool sdio_slave_hal_recv_done(sdio_slave_context_t* hal);
416 
417 /**
418  * Call this function recursively to check whether there is any buffer that has
419  * finished receiving.
420  *
421  * Will walk through the linked list to find a newer finished buffer. For each successful return,
422  * it means there is one finished buffer. You can one by `sdio_slave_hal_recv_unload_desc`. You can
423  * also call `sdio_slave_hal_recv_has_next_item` several times continuously before you call the
424  * `sdio_slave_hal_recv_unload_desc` for the same times.
425  *
426  * @param hal Context of the HAL layer.
427  * @return true if there is
428  */
429 bool sdio_slave_hal_recv_has_next_item(sdio_slave_context_t* hal);
430 
431 /**
432  * Unconditionally remove and return the first descriptor loaded to the HAL.
433  *
434  * Unless during de-initialization, `sdio_slave_hal_recv_has_next_item` should have succeed for the
435  * same times as this function is called, to ensure the returned descriptor has finished its
436  * receiving job.
437  *
438  * @param hal Context of the HAL layer.
439  * @return The removed descriptor, NULL means the linked-list is empty.
440  */
441 sdio_slave_hal_recv_desc_t *sdio_slave_hal_recv_unload_desc(sdio_slave_context_t *hal);
442 
443 /**
444  * Walk through all the unused buffers and reset the counter to the number of
445  * them.
446  *
447  * @note Only call when the DMA is stopped!
448  * @param hal Context of the HAL layer.
449  */
450 void sdio_slave_hal_recv_reset_counter(sdio_slave_context_t *hal);
451 
452 /**
453  * Walk through all the used buffers, clear the finished flag and appended them
454  * back to the end of the unused list, waiting to receive then.
455  *
456  * @note You will lose all the received data in the buffer.
457  * @note Only call when the DMA is stopped!
458  * @param hal Context of the HAL layer.
459  */
460 void sdio_slave_hal_recv_flush_one_buffer(sdio_slave_context_t *hal);
461 
462 
463 /*---------------------------------------------------------------------------
464  *                  Host
465  *--------------------------------------------------------------------------*/
466 
467 /**
468  * Enable some of the interrupts for the host.
469  *
470  * @note May have concurrency issue wit the host or other tasks, suggest only use it during
471  *       initialization.
472  * @param hal Context of the HAL layer.
473  * @param mask Bitwise mask for the interrupts to enable.
474  */
475 void sdio_slave_hal_hostint_set_ena(sdio_slave_context_t *hal, const sdio_slave_hostint_t *mask);
476 
477 /**
478  * Get the enabled interrupts.
479  *
480  * @param hal Context of the HAL layer.
481  * @param out_int_mask Output of the enabled interrupts
482  */
483 void sdio_slave_hal_hostint_get_ena(sdio_slave_context_t *hal, sdio_slave_hostint_t *out_int_mask);
484 
485 /**
486  * Send general purpose interrupt (slave send to host).
487  * @param hal Context of the HAL layer.
488  * @param mask Interrupts to send, only `SDIO_SLAVE_HOSTINT_BIT*` are allowed.
489  */
490 void sdio_slave_hal_hostint_send(sdio_slave_context_t *hal, const sdio_slave_hostint_t *mask);
491 
492 /**
493  * Cleared the specified interrupts for the host.
494  *
495  * @param hal Context of the HAL layer.
496  * @param mask Interrupts to clear.
497  */
498 void sdio_slave_hal_hostint_clear(sdio_slave_context_t *hal, const sdio_slave_hostint_t *mask);
499 
500 
501 /**
502  * Fetch the interrupt (host send to slave) status bits and clear all of them.
503  * @param hal Context of the HAL layer.
504  * @param out_int_mask Output interrupt status
505  */
506 void sdio_slave_hal_slvint_fetch_clear(sdio_slave_context_t *hal, sdio_slave_ll_slvint_t *out_int_mask);
507 
508 /**
509  * Get the value of a shared general purpose register.
510  *
511  * @param hal Context of the HAL layer.
512  * @param pos Position of the register, 4 bytes share a word. 0-63 except 24-27.
513  * @return The register value.
514  */
515 uint8_t sdio_slave_hal_host_get_reg(sdio_slave_context_t *hal, int pos);
516 
517 /**
518  * Set the value of shared general purpose register.
519  *
520  * @param hal Context of the HAL layer.
521  * @param pos Position of the register, 4 bytes share a word. 0-63 except 24-27.
522  * @param reg Value to set.
523  */
524 void sdio_slave_hal_host_set_reg(sdio_slave_context_t *hal, int pos, uint8_t reg);
525