1 // Copyright 2010-2017 Espressif Systems (Shanghai) PTE LTD
3 // Licensed under the Apache License, Version 2.0 (the "License");
4 // you may not use this file except in compliance with the License.
5 // You may obtain a copy of the License at
7 // http://www.apache.org/licenses/LICENSE-2.0
9 // Unless required by applicable law or agreed to in writing, software
10 // distributed under the License is distributed on an "AS IS" BASIS,
11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 // See the License for the specific language governing permissions and
13 // limitations under the License.
16 #ifndef _DRIVER_SPI_COMMON_H_
17 #define _DRIVER_SPI_COMMON_H_
22 #include "soc/spi_struct.h"
23 #include "rom/lldesc.h"
32 //Maximum amount of bytes that can be put in one DMA descriptor
33 #define SPI_MAX_DMA_LEN (4096-4)
37 * @brief Enum with the three SPI peripherals that are software-accessible in it
40 SPI_HOST=0, ///< SPI1, SPI
41 HSPI_HOST=1, ///< SPI2, HSPI
42 VSPI_HOST=2 ///< SPI3, VSPI
46 * @brief This is a configuration structure for a SPI bus.
48 * You can use this structure to specify the GPIO pins of the bus. Normally, the driver will use the
49 * GPIO matrix to route the signals. An exception is made when all signals either can be routed through
50 * the IO_MUX or are -1. In that case, the IO_MUX is used, allowing for >40MHz speeds.
52 * @note Be advised that the slave driver does not use the quadwp/quadhd lines and fields in spi_bus_config_t refering to these lines will be ignored and can thus safely be left uninitialized.
55 int mosi_io_num; ///< GPIO pin for Master Out Slave In (=spi_d) signal, or -1 if not used.
56 int miso_io_num; ///< GPIO pin for Master In Slave Out (=spi_q) signal, or -1 if not used.
57 int sclk_io_num; ///< GPIO pin for Spi CLocK signal, or -1 if not used.
58 int quadwp_io_num; ///< GPIO pin for WP (Write Protect) signal which is used as D2 in 4-bit communication modes, or -1 if not used.
59 int quadhd_io_num; ///< GPIO pin for HD (HolD) signal which is used as D3 in 4-bit communication modes, or -1 if not used.
60 int max_transfer_sz; ///< Maximum transfer size, in bytes. Defaults to 4094 if 0.
61 uint32_t flags; ///< Abilities of bus to be checked by the driver. Or-ed value of ``SPICOMMON_BUSFLAG_*`` flags.
66 * @brief Try to claim a SPI peripheral
68 * Call this if your driver wants to manage a SPI peripheral.
70 * @param host Peripheral to claim
71 * @return True if peripheral is claimed successfully; false if peripheral already is claimed.
73 bool spicommon_periph_claim(spi_host_device_t host);
76 * @brief Return the SPI peripheral so another driver can claim it.
78 * @param host Peripheral to return
79 * @return True if peripheral is returned successfully; false if peripheral was free to claim already.
81 bool spicommon_periph_free(spi_host_device_t host);
84 * @brief Try to claim a SPI DMA channel
86 * Call this if your driver wants to use SPI with a DMA channnel.
88 * @param dma_chan channel to claim
90 * @return True if success; false otherwise.
92 bool spicommon_dma_chan_claim(int dma_chan);
95 * @brief Return the SPI DMA channel so other driver can claim it, or just to power down DMA.
97 * @param dma_chan channel to return
99 * @return True if success; false otherwise.
101 bool spicommon_dma_chan_free(int dma_chan);
103 #define SPICOMMON_BUSFLAG_SLAVE 0 ///< Initialize I/O in slave mode
104 #define SPICOMMON_BUSFLAG_MASTER (1<<0) ///< Initialize I/O in master mode
105 #define SPICOMMON_BUSFLAG_NATIVE_PINS (1<<1) ///< Check using iomux pins. Or indicates the pins are configured through the IO mux rather than GPIO matrix.
106 #define SPICOMMON_BUSFLAG_SCLK (1<<2) ///< Check existing of SCLK pin. Or indicates CLK line initialized.
107 #define SPICOMMON_BUSFLAG_MISO (1<<3) ///< Check existing of MISO pin. Or indicates MISO line initialized.
108 #define SPICOMMON_BUSFLAG_MOSI (1<<4) ///< Check existing of MOSI pin. Or indicates CLK line initialized.
109 #define SPICOMMON_BUSFLAG_DUAL (1<<5) ///< Check MOSI and MISO pins can output. Or indicates bus able to work under DIO mode.
110 #define SPICOMMON_BUSFLAG_WPHD (1<<6) ///< Check existing of WP and HD pins. Or indicates WP & HD pins initialized.
111 #define SPICOMMON_BUSFLAG_QUAD (SPICOMMON_BUSFLAG_DUAL|SPICOMMON_BUSFLAG_WPHD) ///< Check existing of MOSI/MISO/WP/HD pins as output. Or indicates bus able to work under QIO mode.
114 * @brief Connect a SPI peripheral to GPIO pins
116 * This routine is used to connect a SPI peripheral to the IO-pads and DMA channel given in
117 * the arguments. Depending on the IO-pads requested, the routing is done either using the
118 * IO_mux or using the GPIO matrix.
120 * @param host SPI peripheral to be routed
121 * @param bus_config Pointer to a spi_bus_config struct detailing the GPIO pins
122 * @param dma_chan DMA-channel (1 or 2) to use, or 0 for no DMA.
123 * @param flags Combination of SPICOMMON_BUSFLAG_* flags, set to ensure the pins set are capable with some functions:
124 * - ``SPICOMMON_BUSFLAG_MASTER``: Initialize I/O in master mode
125 * - ``SPICOMMON_BUSFLAG_SLAVE``: Initialize I/O in slave mode
126 * - ``SPICOMMON_BUSFLAG_NATIVE_PINS``: Pins set should match the iomux pins of the controller.
127 * - ``SPICOMMON_BUSFLAG_SCLK``, ``SPICOMMON_BUSFLAG_MISO``, ``SPICOMMON_BUSFLAG_MOSI``:
128 * Make sure SCLK/MISO/MOSI is/are set to a valid GPIO. Also check output capability according to the mode.
129 * - ``SPICOMMON_BUSFLAG_DUAL``: Make sure both MISO and MOSI are output capable so that DIO mode is capable.
130 * - ``SPICOMMON_BUSFLAG_WPHD`` Make sure WP and HD are set to valid output GPIOs.
131 * - ``SPICOMMON_BUSFLAG_QUAD``: Combination of ``SPICOMMON_BUSFLAG_DUAL`` and ``SPICOMMON_BUSFLAG_WPHD``.
132 * @param[out] flags_o A SPICOMMON_BUSFLAG_* flag combination of bus abilities will be written to this address.
133 * Leave to NULL if not needed.
134 * - ``SPICOMMON_BUSFLAG_NATIVE_PINS``: The bus is connected to iomux pins.
135 * - ``SPICOMMON_BUSFLAG_SCLK``, ``SPICOMMON_BUSFLAG_MISO``, ``SPICOMMON_BUSFLAG_MOSI``: The bus has
136 * CLK/MISO/MOSI connected.
137 * - ``SPICOMMON_BUSFLAG_DUAL``: The bus is capable with DIO mode.
138 * - ``SPICOMMON_BUSFLAG_WPHD`` The bus has WP and HD connected.
139 * - ``SPICOMMON_BUSFLAG_QUAD``: Combination of ``SPICOMMON_BUSFLAG_DUAL`` and ``SPICOMMON_BUSFLAG_WPHD``.
141 * - ESP_ERR_INVALID_ARG if parameter is invalid
142 * - ESP_OK on success
144 esp_err_t spicommon_bus_initialize_io(spi_host_device_t host, const spi_bus_config_t *bus_config, int dma_chan, uint32_t flags, uint32_t *flags_o);
147 * @brief Free the IO used by a SPI peripheral
149 * @param host SPI peripheral to be freed
151 * - ESP_ERR_INVALID_ARG if parameter is invalid
152 * - ESP_OK on success
155 esp_err_t spicommon_bus_free_io(spi_host_device_t host);
158 * @brief Initialize a Chip Select pin for a specific SPI peripheral
161 * @param host SPI peripheral
162 * @param cs_io_num GPIO pin to route
163 * @param cs_num CS id to route
164 * @param force_gpio_matrix If true, CS will always be routed through the GPIO matrix. If false,
165 * if the GPIO number allows it, the routing will happen through the IO_mux.
168 void spicommon_cs_initialize(spi_host_device_t host, int cs_io_num, int cs_num, int force_gpio_matrix);
171 * @brief Free a chip select line
173 * @param host SPI peripheral
174 * @param cs_num CS id to free
176 void spicommon_cs_free(spi_host_device_t host, int cs_num);
180 * @brief Setup a DMA link chain
182 * This routine will set up a chain of linked DMA descriptors in the array pointed to by
183 * ``dmadesc``. Enough DMA descriptors will be used to fit the buffer of ``len`` bytes in, and the
184 * descriptors will point to the corresponding positions in ``buffer`` and linked together. The
185 * end result is that feeding ``dmadesc[0]`` into DMA hardware results in the entirety ``len`` bytes
186 * of ``data`` being read or written.
188 * @param dmadesc Pointer to array of DMA descriptors big enough to be able to convey ``len`` bytes
189 * @param len Length of buffer
190 * @param data Data buffer to use for DMA transfer
191 * @param isrx True if data is to be written into ``data``, false if it's to be read from ``data``.
193 void spicommon_setup_dma_desc_links(lldesc_t *dmadesc, int len, const uint8_t *data, bool isrx);
196 * @brief Get the position of the hardware registers for a specific SPI host
198 * @param host The SPI host
200 * @return A register descriptor stuct pointer, pointed at the hardware registers
202 spi_dev_t *spicommon_hw_for_host(spi_host_device_t host);
205 * @brief Get the IRQ source for a specific SPI host
207 * @param host The SPI host
209 * @return The hosts IRQ source
211 int spicommon_irqsource_for_host(spi_host_device_t host);
214 * Callback, to be called when a DMA engine reset is completed
216 typedef void(*dmaworkaround_cb_t)(void *arg);
220 * @brief Request a reset for a certain DMA channel
222 * @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
223 * by resetting the SPI DMA hardware in case this happens. Unfortunately, the reset knob used for thsi will reset _both_ DMA channels, and
224 * as such can only done safely when both DMA channels are idle. These functions coordinate this.
226 * Essentially, when a reset is needed, a driver can request this using spicommon_dmaworkaround_req_reset. This is supposed to be called
227 * with an user-supplied function as an argument. If both DMA channels are idle, this call will reset the DMA subsystem and return true.
228 * 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
229 * DMA subsystem and call the callback. The callback is then supposed to be used to continue the SPI drivers activity.
231 * @param dmachan DMA channel associated with the SPI host that needs a reset
232 * @param cb Callback to call in case DMA channel cannot be reset immediately
233 * @param arg Argument to the callback
235 * @return True when a DMA reset could be executed immediately. False when it could not; in this
236 * case the callback will be called with the specified argument when the logic can execute
237 * a reset, after that reset.
239 bool spicommon_dmaworkaround_req_reset(int dmachan, dmaworkaround_cb_t cb, void *arg);
243 * @brief Check if a DMA reset is requested but has not completed yet
245 * @return True when a DMA reset is requested but hasn't completed yet. False otherwise.
247 bool spicommon_dmaworkaround_reset_in_progress();
251 * @brief Mark a DMA channel as idle.
253 * A call to this function tells the workaround logic that this channel will
254 * not be affected by a global SPI DMA reset.
256 void spicommon_dmaworkaround_idle(int dmachan);
259 * @brief Mark a DMA channel as active.
261 * A call to this function tells the workaround logic that this channel will
262 * be affected by a global SPI DMA reset, and a reset like that should not be attempted.
264 void spicommon_dmaworkaround_transfer_active(int dmachan);