1 // Copyright 2015-2019 Espressif Systems (Shanghai) PTE LTD
2 //
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
6 //
7 // http://www.apache.org/licenses/LICENSE-2.0
8 //
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.
14
15
16 #include <string.h>
17 #include "sdkconfig.h"
18 #include "driver/spi_master.h"
19 #include "soc/spi_periph.h"
20 #include "esp_types.h"
21 #include "esp_attr.h"
22 #include "esp_log.h"
23 #include "esp_err.h"
24 #include "soc/soc.h"
25 #include "soc/soc_caps.h"
26 #include "soc/lldesc.h"
27 #include "driver/gpio.h"
28 #include "driver/periph_ctrl.h"
29 #include "esp_heap_caps.h"
30 #include "driver/spi_common_internal.h"
31 #include "stdatomic.h"
32 #include "hal/spi_hal.h"
33 #include "hal/gpio_hal.h"
34 #include "esp_rom_gpio.h"
35 #if CONFIG_IDF_TARGET_ESP32
36 #include "soc/dport_reg.h"
37 #endif
38 #if SOC_GDMA_SUPPORTED
39 #include "esp_private/gdma.h"
40 #endif
41
42 static const char *SPI_TAG = "spi";
43
44 #define SPI_CHECK(a, str, ret_val) do { \
45 if (!(a)) { \
46 ESP_LOGE(SPI_TAG,"%s(%d): %s", __FUNCTION__, __LINE__, str); \
47 return (ret_val); \
48 } \
49 } while(0)
50
51 #define SPI_CHECK_PIN(pin_num, pin_name, check_output) if (check_output) { \
52 SPI_CHECK(GPIO_IS_VALID_OUTPUT_GPIO(pin_num), pin_name" not valid", ESP_ERR_INVALID_ARG); \
53 } else { \
54 SPI_CHECK(GPIO_IS_VALID_GPIO(pin_num), pin_name" not valid", ESP_ERR_INVALID_ARG); \
55 }
56
57 #define SPI_MAIN_BUS_DEFAULT() { \
58 .host_id = 0, \
59 .bus_attr = { \
60 .tx_dma_chan = 0, \
61 .rx_dma_chan = 0, \
62 .max_transfer_sz = SOC_SPI_MAXIMUM_BUFFER_SIZE, \
63 .dma_desc_num= 0, \
64 }, \
65 }
66
67 #define FUNC_GPIO PIN_FUNC_GPIO
68
69
70 typedef struct {
71 int host_id;
72 spi_destroy_func_t destroy_func;
73 void* destroy_arg;
74 spi_bus_attr_t bus_attr;
75 #if SOC_GDMA_SUPPORTED
76 gdma_channel_handle_t tx_channel;
77 gdma_channel_handle_t rx_channel;
78 #endif
79 } spicommon_bus_context_t;
80
81 //Periph 1 is 'claimed' by SPI flash code.
82 static atomic_bool spi_periph_claimed[SOC_SPI_PERIPH_NUM] = { ATOMIC_VAR_INIT(true), ATOMIC_VAR_INIT(false),
83 #if (SOC_SPI_PERIPH_NUM >= 3)
84 ATOMIC_VAR_INIT(false),
85 #endif
86 #if (SOC_SPI_PERIPH_NUM >= 4)
87 ATOMIC_VAR_INIT(false),
88 #endif
89 };
90
91 static const char* spi_claiming_func[3] = {NULL, NULL, NULL};
92 static spicommon_bus_context_t s_mainbus = SPI_MAIN_BUS_DEFAULT();
93 static spicommon_bus_context_t* bus_ctx[SOC_SPI_PERIPH_NUM] = {&s_mainbus};
94
95 #if !SOC_GDMA_SUPPORTED
96 //Each bit stands for 1 dma channel, BIT(0) should be used for SPI1
97 static uint8_t spi_dma_chan_enabled = 0;
98 static portMUX_TYPE spi_dma_spinlock = portMUX_INITIALIZER_UNLOCKED;
99 #endif //#if !SOC_GDMA_SUPPORTED
100
101
is_valid_host(spi_host_device_t host)102 static inline bool is_valid_host(spi_host_device_t host)
103 {
104 #if (SOC_SPI_PERIPH_NUM == 2)
105 return host >= SPI1_HOST && host <= SPI2_HOST;
106 #elif (SOC_SPI_PERIPH_NUM == 3)
107 return host >= SPI1_HOST && host <= SPI3_HOST;
108 #endif
109 }
110
111 //----------------------------------------------------------alloc spi periph-------------------------------------------------------//
112 //Returns true if this peripheral is successfully claimed, false if otherwise.
spicommon_periph_claim(spi_host_device_t host,const char * source)113 bool spicommon_periph_claim(spi_host_device_t host, const char* source)
114 {
115 bool false_var = false;
116 bool ret = atomic_compare_exchange_strong(&spi_periph_claimed[host], &false_var, true);
117 if (ret) {
118 spi_claiming_func[host] = source;
119 periph_module_enable(spi_periph_signal[host].module);
120 } else {
121 ESP_EARLY_LOGE(SPI_TAG, "SPI%d already claimed by %s.", host+1, spi_claiming_func[host]);
122 }
123 return ret;
124 }
125
spicommon_periph_in_use(spi_host_device_t host)126 bool spicommon_periph_in_use(spi_host_device_t host)
127 {
128 return atomic_load(&spi_periph_claimed[host]);
129 }
130
131 //Returns true if this peripheral is successfully freed, false if otherwise.
spicommon_periph_free(spi_host_device_t host)132 bool spicommon_periph_free(spi_host_device_t host)
133 {
134 bool true_var = true;
135 bool ret = atomic_compare_exchange_strong(&spi_periph_claimed[host], &true_var, false);
136 if (ret) periph_module_disable(spi_periph_signal[host].module);
137 return ret;
138 }
139
spicommon_irqsource_for_host(spi_host_device_t host)140 int spicommon_irqsource_for_host(spi_host_device_t host)
141 {
142 return spi_periph_signal[host].irq;
143 }
144
spicommon_irqdma_source_for_host(spi_host_device_t host)145 int spicommon_irqdma_source_for_host(spi_host_device_t host)
146 {
147 return spi_periph_signal[host].irq_dma;
148 }
149
150 //----------------------------------------------------------alloc dma periph-------------------------------------------------------//
151 #if !SOC_GDMA_SUPPORTED
get_dma_periph(int dma_chan)152 static inline periph_module_t get_dma_periph(int dma_chan)
153 {
154 assert(dma_chan >= 1 && dma_chan <= SOC_SPI_DMA_CHAN_NUM);
155 #if CONFIG_IDF_TARGET_ESP32S2
156 if (dma_chan == 1) {
157 return PERIPH_SPI2_DMA_MODULE;
158 } else if (dma_chan == 2) {
159 return PERIPH_SPI3_DMA_MODULE;
160 } else {
161 abort();
162 }
163 #elif CONFIG_IDF_TARGET_ESP32
164 return PERIPH_SPI_DMA_MODULE;
165 #endif
166 }
167
spicommon_dma_chan_claim(int dma_chan,uint32_t * out_actual_dma_chan)168 static bool spicommon_dma_chan_claim(int dma_chan, uint32_t *out_actual_dma_chan)
169 {
170 bool ret = false;
171
172 portENTER_CRITICAL(&spi_dma_spinlock);
173 bool is_used = (BIT(dma_chan) & spi_dma_chan_enabled);
174 if (!is_used) {
175 spi_dma_chan_enabled |= BIT(dma_chan);
176 periph_module_enable(get_dma_periph(dma_chan));
177 *out_actual_dma_chan = dma_chan;
178 ret = true;
179 }
180 portEXIT_CRITICAL(&spi_dma_spinlock);
181
182 return ret;
183 }
184
spicommon_connect_spi_and_dma(spi_host_device_t host,int dma_chan)185 static void spicommon_connect_spi_and_dma(spi_host_device_t host, int dma_chan)
186 {
187 #if CONFIG_IDF_TARGET_ESP32
188 DPORT_SET_PERI_REG_BITS(DPORT_SPI_DMA_CHAN_SEL_REG, 3, dma_chan, (host * 2));
189 #elif CONFIG_IDF_TARGET_ESP32S2
190 //On ESP32S2, each SPI controller has its own DMA channel. So there is no need to connect them.
191 #endif
192 }
193
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)194 static 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)
195 {
196 assert(is_valid_host(host_id));
197 #if CONFIG_IDF_TARGET_ESP32
198 assert(dma_chan > SPI_DMA_DISABLED && dma_chan <= SPI_DMA_CH_AUTO);
199 #elif CONFIG_IDF_TARGET_ESP32S2
200 assert(dma_chan == (int)host_id || dma_chan == SPI_DMA_CH_AUTO);
201 #endif
202
203 esp_err_t ret = ESP_OK;
204 bool success = false;
205 uint32_t actual_dma_chan = 0;
206
207 if (dma_chan == SPI_DMA_CH_AUTO) {
208 #if CONFIG_IDF_TARGET_ESP32
209 for (int i = 1; i < SOC_SPI_DMA_CHAN_NUM+1; i++) {
210 success = spicommon_dma_chan_claim(i, &actual_dma_chan);
211 if (success) {
212 break;
213 }
214 }
215 #elif CONFIG_IDF_TARGET_ESP32S2
216 //On ESP32S2, each SPI controller has its own DMA channel
217 success = spicommon_dma_chan_claim(host_id, &actual_dma_chan);
218 #endif //#if CONFIG_IDF_TARGET_XXX
219 } else {
220 success = spicommon_dma_chan_claim((int)dma_chan, &actual_dma_chan);
221 }
222
223 //On ESP32 and ESP32S2, actual_tx_dma_chan and actual_rx_dma_chan are always same
224 *out_actual_tx_dma_chan = actual_dma_chan;
225 *out_actual_rx_dma_chan = actual_dma_chan;
226
227 if (!success) {
228 SPI_CHECK(false, "no available dma channel", ESP_ERR_NOT_FOUND);
229 }
230
231 spicommon_connect_spi_and_dma(host_id, *out_actual_tx_dma_chan);
232
233 return ret;
234 }
235
236 #else //SOC_GDMA_SUPPORTED
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)237 static 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)
238 {
239 assert(is_valid_host(host_id));
240 assert(dma_chan == SPI_DMA_CH_AUTO);
241
242 esp_err_t ret = ESP_OK;
243 spicommon_bus_context_t *ctx = bus_ctx[host_id];
244
245 if (dma_chan == SPI_DMA_CH_AUTO) {
246 gdma_channel_alloc_config_t tx_alloc_config = {
247 .flags.reserve_sibling = 1,
248 .direction = GDMA_CHANNEL_DIRECTION_TX,
249 };
250 ret = gdma_new_channel(&tx_alloc_config, &ctx->tx_channel);
251 if (ret != ESP_OK) {
252 return ret;
253 }
254
255 gdma_channel_alloc_config_t rx_alloc_config = {
256 .direction = GDMA_CHANNEL_DIRECTION_RX,
257 .sibling_chan = ctx->tx_channel,
258 };
259 ret = gdma_new_channel(&rx_alloc_config, &ctx->rx_channel);
260 if (ret != ESP_OK) {
261 return ret;
262 }
263
264 if (host_id == SPI2_HOST) {
265 gdma_connect(ctx->rx_channel, GDMA_MAKE_TRIGGER(GDMA_TRIG_PERIPH_SPI, 2));
266 gdma_connect(ctx->tx_channel, GDMA_MAKE_TRIGGER(GDMA_TRIG_PERIPH_SPI, 2));
267 }
268 #if (SOC_SPI_PERIPH_NUM >= 3)
269 else if (host_id == SPI3_HOST) {
270 gdma_connect(ctx->rx_channel, GDMA_MAKE_TRIGGER(GDMA_TRIG_PERIPH_SPI, 3));
271 gdma_connect(ctx->tx_channel, GDMA_MAKE_TRIGGER(GDMA_TRIG_PERIPH_SPI, 3));
272 }
273 #endif
274 gdma_get_channel_id(ctx->tx_channel, (int *)out_actual_tx_dma_chan);
275 gdma_get_channel_id(ctx->rx_channel, (int *)out_actual_rx_dma_chan);
276 }
277
278 return ret;
279 }
280 #endif //#if !SOC_GDMA_SUPPORTED
281
spicommon_slave_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)282 esp_err_t spicommon_slave_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)
283 {
284 assert(is_valid_host(host_id));
285 #if CONFIG_IDF_TARGET_ESP32
286 assert(dma_chan > SPI_DMA_DISABLED && dma_chan <= SPI_DMA_CH_AUTO);
287 #elif CONFIG_IDF_TARGET_ESP32S2
288 assert(dma_chan == (int)host_id || dma_chan == SPI_DMA_CH_AUTO);
289 #endif
290
291 esp_err_t ret = ESP_OK;
292 uint32_t actual_tx_dma_chan = 0;
293 uint32_t actual_rx_dma_chan = 0;
294 spicommon_bus_context_t *ctx = (spicommon_bus_context_t *)calloc(1, sizeof(spicommon_bus_context_t));
295 if (!ctx) {
296 ret = ESP_ERR_NO_MEM;
297 goto cleanup;
298 }
299 bus_ctx[host_id] = ctx;
300 ctx->host_id = host_id;
301
302 ret = spicommon_dma_chan_alloc(host_id, dma_chan, &actual_tx_dma_chan, &actual_rx_dma_chan);
303 if (ret != ESP_OK) {
304 goto cleanup;
305 }
306 ctx->bus_attr.tx_dma_chan = actual_tx_dma_chan;
307 ctx->bus_attr.rx_dma_chan = actual_rx_dma_chan;
308 *out_actual_tx_dma_chan = actual_tx_dma_chan;
309 *out_actual_rx_dma_chan = actual_rx_dma_chan;
310
311 return ret;
312
313 cleanup:
314 free(ctx);
315 ctx = NULL;
316 return ret;
317 }
318
319 //----------------------------------------------------------free dma periph-------------------------------------------------------//
spicommon_dma_chan_free(spi_host_device_t host_id)320 static esp_err_t spicommon_dma_chan_free(spi_host_device_t host_id)
321 {
322 assert(is_valid_host(host_id));
323
324 spicommon_bus_context_t *ctx = bus_ctx[host_id];
325 #if !SOC_GDMA_SUPPORTED
326 //On ESP32S2, each SPI controller has its own DMA channel
327 int dma_chan = ctx->bus_attr.tx_dma_chan;
328 assert(spi_dma_chan_enabled & BIT(dma_chan));
329
330 portENTER_CRITICAL(&spi_dma_spinlock);
331 spi_dma_chan_enabled &= ~BIT(dma_chan);
332 periph_module_disable(get_dma_periph(dma_chan));
333 portEXIT_CRITICAL(&spi_dma_spinlock);
334
335 #else //SOC_GDMA_SUPPORTED
336 if (ctx->rx_channel) {
337 gdma_disconnect(ctx->rx_channel);
338 gdma_del_channel(ctx->rx_channel);
339 }
340 if (ctx->tx_channel) {
341 gdma_disconnect(ctx->tx_channel);
342 gdma_del_channel(ctx->tx_channel);
343 }
344 #endif
345
346 return ESP_OK;
347 }
348
spicommon_slave_free_dma(spi_host_device_t host_id)349 esp_err_t spicommon_slave_free_dma(spi_host_device_t host_id)
350 {
351 assert(is_valid_host(host_id));
352
353 esp_err_t ret = spicommon_dma_chan_free(host_id);
354 free(bus_ctx[host_id]);
355 bus_ctx[host_id] = NULL;
356
357 return ret;
358 }
359
360 //----------------------------------------------------------IO general-------------------------------------------------------//
bus_uses_iomux_pins(spi_host_device_t host,const spi_bus_config_t * bus_config)361 static bool bus_uses_iomux_pins(spi_host_device_t host, const spi_bus_config_t* bus_config)
362 {
363 if (bus_config->sclk_io_num>=0 &&
364 bus_config->sclk_io_num != spi_periph_signal[host].spiclk_iomux_pin) {
365 return false;
366 }
367 if (bus_config->quadwp_io_num>=0 &&
368 bus_config->quadwp_io_num != spi_periph_signal[host].spiwp_iomux_pin) {
369 return false;
370 }
371 if (bus_config->quadhd_io_num>=0 &&
372 bus_config->quadhd_io_num != spi_periph_signal[host].spihd_iomux_pin) {
373 return false;
374 }
375 if (bus_config->mosi_io_num >= 0 &&
376 bus_config->mosi_io_num != spi_periph_signal[host].spid_iomux_pin) {
377 return false;
378 }
379 if (bus_config->miso_io_num>=0 &&
380 bus_config->miso_io_num != spi_periph_signal[host].spiq_iomux_pin) {
381 return false;
382 }
383
384 return true;
385 }
386
387 /*
388 Do the common stuff to hook up a SPI host to a bus defined by a bunch of GPIO pins. Feed it a host number and a
389 bus config struct and it'll set up the GPIO matrix and enable the device. If a pin is set to non-negative value,
390 it should be able to be initialized.
391 */
spicommon_bus_initialize_io(spi_host_device_t host,const spi_bus_config_t * bus_config,uint32_t flags,uint32_t * flags_o)392 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)
393 {
394 uint32_t temp_flag = 0;
395
396 bool miso_need_output;
397 bool mosi_need_output;
398 bool sclk_need_output;
399 if ((flags&SPICOMMON_BUSFLAG_MASTER) != 0) {
400 //initial for master
401 miso_need_output = ((flags&SPICOMMON_BUSFLAG_DUAL) != 0) ? true : false;
402 mosi_need_output = true;
403 sclk_need_output = true;
404 } else {
405 //initial for slave
406 miso_need_output = true;
407 mosi_need_output = ((flags&SPICOMMON_BUSFLAG_DUAL) != 0) ? true : false;
408 sclk_need_output = false;
409 }
410
411 const bool wp_need_output = true;
412 const bool hd_need_output = true;
413
414 //check pin capabilities
415 if (bus_config->sclk_io_num>=0) {
416 temp_flag |= SPICOMMON_BUSFLAG_SCLK;
417 SPI_CHECK_PIN(bus_config->sclk_io_num, "sclk", sclk_need_output);
418 }
419 if (bus_config->quadwp_io_num>=0) {
420 SPI_CHECK_PIN(bus_config->quadwp_io_num, "wp", wp_need_output);
421 }
422 if (bus_config->quadhd_io_num>=0) {
423 SPI_CHECK_PIN(bus_config->quadhd_io_num, "hd", hd_need_output);
424 }
425 //set flags for QUAD mode according to the existence of wp and hd
426 if (bus_config->quadhd_io_num >= 0 && bus_config->quadwp_io_num >= 0) temp_flag |= SPICOMMON_BUSFLAG_WPHD;
427 if (bus_config->mosi_io_num >= 0) {
428 temp_flag |= SPICOMMON_BUSFLAG_MOSI;
429 SPI_CHECK_PIN(bus_config->mosi_io_num, "mosi", mosi_need_output);
430 }
431 if (bus_config->miso_io_num>=0) {
432 temp_flag |= SPICOMMON_BUSFLAG_MISO;
433 SPI_CHECK_PIN(bus_config->miso_io_num, "miso", miso_need_output);
434 }
435 //set flags for DUAL mode according to output-capability of MOSI and MISO pins.
436 if ( (bus_config->mosi_io_num < 0 || GPIO_IS_VALID_OUTPUT_GPIO(bus_config->mosi_io_num)) &&
437 (bus_config->miso_io_num < 0 || GPIO_IS_VALID_OUTPUT_GPIO(bus_config->miso_io_num)) ) {
438 temp_flag |= SPICOMMON_BUSFLAG_DUAL;
439 }
440
441 //check if the selected pins correspond to the iomux pins of the peripheral
442 bool use_iomux = !(flags & SPICOMMON_BUSFLAG_GPIO_PINS) && bus_uses_iomux_pins(host, bus_config);
443 if (use_iomux) {
444 temp_flag |= SPICOMMON_BUSFLAG_IOMUX_PINS;
445 } else {
446 temp_flag |= SPICOMMON_BUSFLAG_GPIO_PINS;
447 }
448
449 uint32_t missing_flag = flags & ~temp_flag;
450 missing_flag &= ~SPICOMMON_BUSFLAG_MASTER;//don't check this flag
451
452 if (missing_flag != 0) {
453 //check pins existence
454 if (missing_flag & SPICOMMON_BUSFLAG_SCLK) ESP_LOGE(SPI_TAG, "sclk pin required.");
455 if (missing_flag & SPICOMMON_BUSFLAG_MOSI) ESP_LOGE(SPI_TAG, "mosi pin required.");
456 if (missing_flag & SPICOMMON_BUSFLAG_MISO) ESP_LOGE(SPI_TAG, "miso pin required.");
457 if (missing_flag & SPICOMMON_BUSFLAG_DUAL) ESP_LOGE(SPI_TAG, "not both mosi and miso output capable");
458 if (missing_flag & SPICOMMON_BUSFLAG_WPHD) ESP_LOGE(SPI_TAG, "both wp and hd required.");
459 if (missing_flag & SPICOMMON_BUSFLAG_IOMUX_PINS) ESP_LOGE(SPI_TAG, "not using iomux pins");
460 SPI_CHECK(missing_flag == 0, "not all required capabilities satisfied.", ESP_ERR_INVALID_ARG);
461 }
462
463 if (use_iomux) {
464 //All SPI iomux pin selections resolve to 1, so we put that here instead of trying to figure
465 //out which FUNC_GPIOx_xSPIxx to grab; they all are defined to 1 anyway.
466 ESP_LOGD(SPI_TAG, "SPI%d use iomux pins.", host+1);
467 if (bus_config->mosi_io_num >= 0) {
468 gpio_iomux_in(bus_config->mosi_io_num, spi_periph_signal[host].spid_in);
469 gpio_iomux_out(bus_config->mosi_io_num, spi_periph_signal[host].func, false);
470 }
471 if (bus_config->miso_io_num >= 0) {
472 gpio_iomux_in(bus_config->miso_io_num, spi_periph_signal[host].spiq_in);
473 gpio_iomux_out(bus_config->miso_io_num, spi_periph_signal[host].func, false);
474 }
475 if (bus_config->quadwp_io_num >= 0) {
476 gpio_iomux_in(bus_config->quadwp_io_num, spi_periph_signal[host].spiwp_in);
477 gpio_iomux_out(bus_config->quadwp_io_num, spi_periph_signal[host].func, false);
478 }
479 if (bus_config->quadhd_io_num >= 0) {
480 gpio_iomux_in(bus_config->quadhd_io_num, spi_periph_signal[host].spihd_in);
481 gpio_iomux_out(bus_config->quadhd_io_num, spi_periph_signal[host].func, false);
482 }
483 if (bus_config->sclk_io_num >= 0) {
484 gpio_iomux_in(bus_config->sclk_io_num, spi_periph_signal[host].spiclk_in);
485 gpio_iomux_out(bus_config->sclk_io_num, spi_periph_signal[host].func, false);
486 }
487 temp_flag |= SPICOMMON_BUSFLAG_IOMUX_PINS;
488 } else {
489 //Use GPIO matrix
490 ESP_LOGD(SPI_TAG, "SPI%d use gpio matrix.", host+1);
491 if (bus_config->mosi_io_num >= 0) {
492 if (mosi_need_output || (temp_flag&SPICOMMON_BUSFLAG_DUAL)) {
493 gpio_set_direction(bus_config->mosi_io_num, GPIO_MODE_INPUT_OUTPUT);
494 esp_rom_gpio_connect_out_signal(bus_config->mosi_io_num, spi_periph_signal[host].spid_out, false, false);
495 } else {
496 gpio_set_direction(bus_config->mosi_io_num, GPIO_MODE_INPUT);
497 }
498 esp_rom_gpio_connect_in_signal(bus_config->mosi_io_num, spi_periph_signal[host].spid_in, false);
499 #if CONFIG_IDF_TARGET_ESP32S2
500 PIN_INPUT_ENABLE(GPIO_PIN_MUX_REG[bus_config->mosi_io_num]);
501 #endif
502 gpio_hal_iomux_func_sel(GPIO_PIN_MUX_REG[bus_config->mosi_io_num], FUNC_GPIO);
503 }
504 if (bus_config->miso_io_num >= 0) {
505 if (miso_need_output || (temp_flag&SPICOMMON_BUSFLAG_DUAL)) {
506 gpio_set_direction(bus_config->miso_io_num, GPIO_MODE_INPUT_OUTPUT);
507 esp_rom_gpio_connect_out_signal(bus_config->miso_io_num, spi_periph_signal[host].spiq_out, false, false);
508 } else {
509 gpio_set_direction(bus_config->miso_io_num, GPIO_MODE_INPUT);
510 }
511 esp_rom_gpio_connect_in_signal(bus_config->miso_io_num, spi_periph_signal[host].spiq_in, false);
512 #if CONFIG_IDF_TARGET_ESP32S2
513 PIN_INPUT_ENABLE(GPIO_PIN_MUX_REG[bus_config->miso_io_num]);
514 #endif
515 gpio_hal_iomux_func_sel(GPIO_PIN_MUX_REG[bus_config->miso_io_num], FUNC_GPIO);
516 }
517 if (bus_config->quadwp_io_num >= 0) {
518 gpio_set_direction(bus_config->quadwp_io_num, GPIO_MODE_INPUT_OUTPUT);
519 esp_rom_gpio_connect_out_signal(bus_config->quadwp_io_num, spi_periph_signal[host].spiwp_out, false, false);
520 esp_rom_gpio_connect_in_signal(bus_config->quadwp_io_num, spi_periph_signal[host].spiwp_in, false);
521 #if CONFIG_IDF_TARGET_ESP32S2
522 PIN_INPUT_ENABLE(GPIO_PIN_MUX_REG[bus_config->quadwp_io_num]);
523 #endif
524 gpio_hal_iomux_func_sel(GPIO_PIN_MUX_REG[bus_config->quadwp_io_num], FUNC_GPIO);
525 }
526 if (bus_config->quadhd_io_num >= 0) {
527 gpio_set_direction(bus_config->quadhd_io_num, GPIO_MODE_INPUT_OUTPUT);
528 esp_rom_gpio_connect_out_signal(bus_config->quadhd_io_num, spi_periph_signal[host].spihd_out, false, false);
529 esp_rom_gpio_connect_in_signal(bus_config->quadhd_io_num, spi_periph_signal[host].spihd_in, false);
530 #if CONFIG_IDF_TARGET_ESP32S2
531 PIN_INPUT_ENABLE(GPIO_PIN_MUX_REG[bus_config->quadhd_io_num]);
532 #endif
533 gpio_hal_iomux_func_sel(GPIO_PIN_MUX_REG[bus_config->quadhd_io_num], FUNC_GPIO);
534 }
535 if (bus_config->sclk_io_num >= 0) {
536 if (sclk_need_output) {
537 gpio_set_direction(bus_config->sclk_io_num, GPIO_MODE_INPUT_OUTPUT);
538 esp_rom_gpio_connect_out_signal(bus_config->sclk_io_num, spi_periph_signal[host].spiclk_out, false, false);
539 } else {
540 gpio_set_direction(bus_config->sclk_io_num, GPIO_MODE_INPUT);
541 }
542 esp_rom_gpio_connect_in_signal(bus_config->sclk_io_num, spi_periph_signal[host].spiclk_in, false);
543 #if CONFIG_IDF_TARGET_ESP32S2
544 PIN_INPUT_ENABLE(GPIO_PIN_MUX_REG[bus_config->sclk_io_num]);
545 #endif
546 gpio_hal_iomux_func_sel(GPIO_PIN_MUX_REG[bus_config->sclk_io_num], FUNC_GPIO);
547 }
548 }
549
550 if (flags_o) *flags_o = temp_flag;
551 return ESP_OK;
552 }
553
spicommon_bus_free_io_cfg(const spi_bus_config_t * bus_cfg)554 esp_err_t spicommon_bus_free_io_cfg(const spi_bus_config_t *bus_cfg)
555 {
556 int pin_array[] = {
557 bus_cfg->mosi_io_num,
558 bus_cfg->miso_io_num,
559 bus_cfg->sclk_io_num,
560 bus_cfg->quadwp_io_num,
561 bus_cfg->quadhd_io_num,
562 };
563 for (int i = 0; i < sizeof(pin_array)/sizeof(int); i ++) {
564 const int io = pin_array[i];
565 if (io >= 0 && GPIO_IS_VALID_GPIO(io)) gpio_reset_pin(io);
566 }
567 return ESP_OK;
568 }
569
spicommon_cs_initialize(spi_host_device_t host,int cs_io_num,int cs_num,int force_gpio_matrix)570 void spicommon_cs_initialize(spi_host_device_t host, int cs_io_num, int cs_num, int force_gpio_matrix)
571 {
572 if (!force_gpio_matrix && cs_io_num == spi_periph_signal[host].spics0_iomux_pin && cs_num == 0) {
573 //The cs0s for all SPI peripherals map to pin mux source 1, so we use that instead of a define.
574 gpio_iomux_in(cs_io_num, spi_periph_signal[host].spics_in);
575 gpio_iomux_out(cs_io_num, spi_periph_signal[host].func, false);
576 } else {
577 //Use GPIO matrix
578 if (GPIO_IS_VALID_OUTPUT_GPIO(cs_io_num)) {
579 gpio_set_direction(cs_io_num, GPIO_MODE_INPUT_OUTPUT);
580 esp_rom_gpio_connect_out_signal(cs_io_num, spi_periph_signal[host].spics_out[cs_num], false, false);
581 } else {
582 gpio_set_direction(cs_io_num, GPIO_MODE_INPUT);
583 }
584 if (cs_num == 0) esp_rom_gpio_connect_in_signal(cs_io_num, spi_periph_signal[host].spics_in, false);
585 PIN_INPUT_ENABLE(GPIO_PIN_MUX_REG[cs_io_num]);
586 gpio_hal_iomux_func_sel(GPIO_PIN_MUX_REG[cs_io_num], FUNC_GPIO);
587 }
588 }
589
spicommon_cs_free_io(int cs_gpio_num)590 void spicommon_cs_free_io(int cs_gpio_num)
591 {
592 assert(cs_gpio_num>=0 && GPIO_IS_VALID_GPIO(cs_gpio_num));
593 gpio_reset_pin(cs_gpio_num);
594 }
595
spicommon_bus_using_iomux(spi_host_device_t host)596 bool spicommon_bus_using_iomux(spi_host_device_t host)
597 {
598 #define CHECK_IOMUX_PIN(HOST, PIN_NAME) if (GPIO.func_in_sel_cfg[spi_periph_signal[(HOST)].PIN_NAME##_in].sig_in_sel) return false
599
600 CHECK_IOMUX_PIN(host, spid);
601 CHECK_IOMUX_PIN(host, spiq);
602 CHECK_IOMUX_PIN(host, spiwp);
603 CHECK_IOMUX_PIN(host, spihd);
604 return true;
605 }
606
607
spi_bus_main_set_lock(spi_bus_lock_handle_t lock)608 void spi_bus_main_set_lock(spi_bus_lock_handle_t lock)
609 {
610 bus_ctx[0]->bus_attr.lock = lock;
611 }
612
spi_bus_lock_get_by_id(spi_host_device_t host_id)613 spi_bus_lock_handle_t spi_bus_lock_get_by_id(spi_host_device_t host_id)
614 {
615 return bus_ctx[host_id]->bus_attr.lock;
616 }
617
618 //----------------------------------------------------------master bus init-------------------------------------------------------//
spi_bus_initialize(spi_host_device_t host_id,const spi_bus_config_t * bus_config,spi_dma_chan_t dma_chan)619 esp_err_t spi_bus_initialize(spi_host_device_t host_id, const spi_bus_config_t *bus_config, spi_dma_chan_t dma_chan)
620 {
621 esp_err_t err = ESP_OK;
622 spicommon_bus_context_t *ctx = NULL;
623 spi_bus_attr_t *bus_attr = NULL;
624 uint32_t actual_tx_dma_chan = 0;
625 uint32_t actual_rx_dma_chan = 0;
626
627 SPI_CHECK(is_valid_host(host_id), "invalid host_id", ESP_ERR_INVALID_ARG);
628 SPI_CHECK(bus_ctx[host_id] == NULL, "SPI bus already initialized.", ESP_ERR_INVALID_STATE);
629 #ifdef CONFIG_IDF_TARGET_ESP32
630 SPI_CHECK(dma_chan >= SPI_DMA_DISABLED && dma_chan <= SPI_DMA_CH_AUTO, "invalid dma channel", ESP_ERR_INVALID_ARG );
631 #elif CONFIG_IDF_TARGET_ESP32S2
632 SPI_CHECK( dma_chan == SPI_DMA_DISABLED || dma_chan == (int)host_id || dma_chan == SPI_DMA_CH_AUTO, "invalid dma channel", ESP_ERR_INVALID_ARG );
633 #elif SOC_GDMA_SUPPORTED
634 SPI_CHECK( dma_chan == SPI_DMA_DISABLED || dma_chan == SPI_DMA_CH_AUTO, "invalid dma channel, chip only support spi dma channel auto-alloc", ESP_ERR_INVALID_ARG );
635 #endif
636 SPI_CHECK((bus_config->intr_flags & (ESP_INTR_FLAG_HIGH|ESP_INTR_FLAG_EDGE|ESP_INTR_FLAG_INTRDISABLED))==0, "intr flag not allowed", ESP_ERR_INVALID_ARG);
637 #ifndef CONFIG_SPI_MASTER_ISR_IN_IRAM
638 SPI_CHECK((bus_config->intr_flags & ESP_INTR_FLAG_IRAM)==0, "ESP_INTR_FLAG_IRAM should be disabled when CONFIG_SPI_MASTER_ISR_IN_IRAM is not set.", ESP_ERR_INVALID_ARG);
639 #endif
640
641 bool spi_chan_claimed = spicommon_periph_claim(host_id, "spi master");
642 SPI_CHECK(spi_chan_claimed, "host_id already in use", ESP_ERR_INVALID_STATE);
643
644 //clean and initialize the context
645 ctx = (spicommon_bus_context_t *)calloc(1, sizeof(spicommon_bus_context_t));
646 if (!ctx) {
647 err = ESP_ERR_NO_MEM;
648 goto cleanup;
649 }
650 bus_ctx[host_id] = ctx;
651 ctx->host_id = host_id;
652 bus_attr = &ctx->bus_attr;
653 bus_attr->bus_cfg = *bus_config;
654
655 if (dma_chan != SPI_DMA_DISABLED) {
656 bus_attr->dma_enabled = 1;
657
658 err = spicommon_dma_chan_alloc(host_id, dma_chan, &actual_tx_dma_chan, &actual_rx_dma_chan);
659 if (err != ESP_OK) {
660 goto cleanup;
661 }
662 bus_attr->tx_dma_chan = actual_tx_dma_chan;
663 bus_attr->rx_dma_chan = actual_rx_dma_chan;
664
665 int dma_desc_ct = lldesc_get_required_num(bus_config->max_transfer_sz);
666 if (dma_desc_ct == 0) dma_desc_ct = 1; //default to 4k when max is not given
667
668 bus_attr->max_transfer_sz = dma_desc_ct * LLDESC_MAX_NUM_PER_DESC;
669 bus_attr->dmadesc_tx = heap_caps_malloc(sizeof(lldesc_t) * dma_desc_ct, MALLOC_CAP_DMA);
670 bus_attr->dmadesc_rx = heap_caps_malloc(sizeof(lldesc_t) * dma_desc_ct, MALLOC_CAP_DMA);
671 if (bus_attr->dmadesc_tx == NULL || bus_attr->dmadesc_rx == NULL) {
672 err = ESP_ERR_NO_MEM;
673 goto cleanup;
674 }
675 bus_attr->dma_desc_num = dma_desc_ct;
676 } else {
677 bus_attr->dma_enabled = 0;
678 bus_attr->max_transfer_sz = SOC_SPI_MAXIMUM_BUFFER_SIZE;
679 bus_attr->dma_desc_num = 0;
680 }
681
682 spi_bus_lock_config_t lock_config = {
683 .host_id = host_id,
684 .cs_num = SOC_SPI_PERIPH_CS_NUM(host_id),
685 };
686 err = spi_bus_init_lock(&bus_attr->lock, &lock_config);
687 if (err != ESP_OK) {
688 goto cleanup;
689 }
690
691 #ifdef CONFIG_PM_ENABLE
692 err = esp_pm_lock_create(ESP_PM_APB_FREQ_MAX, 0, "spi_master",
693 &bus_attr->pm_lock);
694 if (err != ESP_OK) {
695 goto cleanup;
696 }
697 #endif //CONFIG_PM_ENABLE
698
699 err = spicommon_bus_initialize_io(host_id, bus_config, SPICOMMON_BUSFLAG_MASTER | bus_config->flags, &bus_attr->flags);
700 if (err != ESP_OK) {
701 goto cleanup;
702 }
703
704 return ESP_OK;
705
706 cleanup:
707 if (bus_attr) {
708 #ifdef CONFIG_PM_ENABLE
709 esp_pm_lock_delete(bus_attr->pm_lock);
710 #endif
711 if (bus_attr->lock) {
712 spi_bus_deinit_lock(bus_attr->lock);
713 }
714 free(bus_attr->dmadesc_tx);
715 free(bus_attr->dmadesc_rx);
716 bus_attr->dmadesc_tx = NULL;
717 bus_attr->dmadesc_rx = NULL;
718 if (bus_attr->dma_enabled) {
719 spicommon_dma_chan_free(host_id);
720 }
721 }
722 spicommon_periph_free(host_id);
723 free(bus_ctx[host_id]);
724 bus_ctx[host_id] = NULL;
725 return err;
726 }
727
spi_bus_get_attr(spi_host_device_t host_id)728 const spi_bus_attr_t* spi_bus_get_attr(spi_host_device_t host_id)
729 {
730 if (bus_ctx[host_id] == NULL) return NULL;
731
732 return &bus_ctx[host_id]->bus_attr;
733 }
734
spi_bus_free(spi_host_device_t host_id)735 esp_err_t spi_bus_free(spi_host_device_t host_id)
736 {
737 esp_err_t err = ESP_OK;
738 spicommon_bus_context_t* ctx = bus_ctx[host_id];
739 spi_bus_attr_t* bus_attr = &ctx->bus_attr;
740
741 if (ctx->destroy_func) {
742 err = ctx->destroy_func(ctx->destroy_arg);
743 }
744
745 spicommon_bus_free_io_cfg(&bus_attr->bus_cfg);
746
747 #ifdef CONFIG_PM_ENABLE
748 esp_pm_lock_delete(bus_attr->pm_lock);
749 #endif
750 spi_bus_deinit_lock(bus_attr->lock);
751 free(bus_attr->dmadesc_rx);
752 free(bus_attr->dmadesc_tx);
753 bus_attr->dmadesc_tx = NULL;
754 bus_attr->dmadesc_rx = NULL;
755 if (bus_attr->dma_enabled > 0) {
756 spicommon_dma_chan_free(host_id);
757 }
758 spicommon_periph_free(host_id);
759 free(ctx);
760 bus_ctx[host_id] = NULL;
761 return err;
762 }
763
spi_bus_register_destroy_func(spi_host_device_t host_id,spi_destroy_func_t f,void * arg)764 esp_err_t spi_bus_register_destroy_func(spi_host_device_t host_id,
765 spi_destroy_func_t f, void *arg)
766 {
767 bus_ctx[host_id]->destroy_func = f;
768 bus_ctx[host_id]->destroy_arg = arg;
769 return ESP_OK;
770 }
771
772
773 /*
774 Code for workaround for DMA issue in ESP32 v0/v1 silicon
775 */
776 #if CONFIG_IDF_TARGET_ESP32
777 static volatile int dmaworkaround_channels_busy[2] = {0, 0};
778 static dmaworkaround_cb_t dmaworkaround_cb;
779 static void *dmaworkaround_cb_arg;
780 static portMUX_TYPE dmaworkaround_mux = portMUX_INITIALIZER_UNLOCKED;
781 static int dmaworkaround_waiting_for_chan = 0;
782 #endif
783
spicommon_dmaworkaround_req_reset(int dmachan,dmaworkaround_cb_t cb,void * arg)784 bool IRAM_ATTR spicommon_dmaworkaround_req_reset(int dmachan, dmaworkaround_cb_t cb, void *arg)
785 {
786 #if CONFIG_IDF_TARGET_ESP32
787 int otherchan = (dmachan == 1) ? 2 : 1;
788 bool ret;
789 portENTER_CRITICAL_ISR(&dmaworkaround_mux);
790 if (dmaworkaround_channels_busy[otherchan-1]) {
791 //Other channel is busy. Call back when it's done.
792 dmaworkaround_cb = cb;
793 dmaworkaround_cb_arg = arg;
794 dmaworkaround_waiting_for_chan = otherchan;
795 ret = false;
796 } else {
797 //Reset DMA
798 periph_module_reset( PERIPH_SPI_DMA_MODULE );
799 ret = true;
800 }
801 portEXIT_CRITICAL_ISR(&dmaworkaround_mux);
802 return ret;
803 #else
804 //no need to reset
805 return true;
806 #endif
807 }
808
spicommon_dmaworkaround_reset_in_progress(void)809 bool IRAM_ATTR spicommon_dmaworkaround_reset_in_progress(void)
810 {
811 #if CONFIG_IDF_TARGET_ESP32
812 return (dmaworkaround_waiting_for_chan != 0);
813 #else
814 return false;
815 #endif
816 }
817
spicommon_dmaworkaround_idle(int dmachan)818 void IRAM_ATTR spicommon_dmaworkaround_idle(int dmachan)
819 {
820 #if CONFIG_IDF_TARGET_ESP32
821 portENTER_CRITICAL_ISR(&dmaworkaround_mux);
822 dmaworkaround_channels_busy[dmachan-1] = 0;
823 if (dmaworkaround_waiting_for_chan == dmachan) {
824 //Reset DMA
825 periph_module_reset( PERIPH_SPI_DMA_MODULE );
826 dmaworkaround_waiting_for_chan = 0;
827 //Call callback
828 dmaworkaround_cb(dmaworkaround_cb_arg);
829
830 }
831 portEXIT_CRITICAL_ISR(&dmaworkaround_mux);
832 #endif
833 }
834
spicommon_dmaworkaround_transfer_active(int dmachan)835 void IRAM_ATTR spicommon_dmaworkaround_transfer_active(int dmachan)
836 {
837 #if CONFIG_IDF_TARGET_ESP32
838 portENTER_CRITICAL_ISR(&dmaworkaround_mux);
839 dmaworkaround_channels_busy[dmachan-1] = 1;
840 portEXIT_CRITICAL_ISR(&dmaworkaround_mux);
841 #endif
842 }
843