1 // Copyright 2015-2016 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 #include "hal/spi_slave_hal.h"
16 #include "hal/spi_ll.h"
17 #include "soc/soc_caps.h"
18
19 //This GDMA related part will be introduced by GDMA dedicated APIs in the future. Here we temporarily use macros.
20 #if SOC_GDMA_SUPPORTED
21 #include "soc/gdma_struct.h"
22 #include "hal/gdma_ll.h"
23
24 #define spi_dma_ll_rx_reset(dev, chan) gdma_ll_rx_reset_channel(&GDMA, chan)
25 #define spi_dma_ll_tx_reset(dev, chan) gdma_ll_tx_reset_channel(&GDMA, chan);
26 #define spi_dma_ll_rx_start(dev, chan, addr) do {\
27 gdma_ll_rx_set_desc_addr(&GDMA, chan, (uint32_t)addr);\
28 gdma_ll_rx_start(&GDMA, chan);\
29 } while (0)
30 #define spi_dma_ll_tx_start(dev, chan, addr) do {\
31 gdma_ll_tx_set_desc_addr(&GDMA, chan, (uint32_t)addr);\
32 gdma_ll_tx_start(&GDMA, chan);\
33 } while (0)
34 #endif
35
spi_slave_hal_usr_is_done(spi_slave_hal_context_t * hal)36 bool spi_slave_hal_usr_is_done(spi_slave_hal_context_t* hal)
37 {
38 return spi_ll_usr_is_done(hal->hw);
39 }
40
spi_slave_hal_user_start(const spi_slave_hal_context_t * hal)41 void spi_slave_hal_user_start(const spi_slave_hal_context_t *hal)
42 {
43 spi_ll_clear_int_stat(hal->hw); //clear int bit
44 spi_ll_slave_user_start(hal->hw);
45 }
46
spi_slave_hal_prepare_data(const spi_slave_hal_context_t * hal)47 void spi_slave_hal_prepare_data(const spi_slave_hal_context_t *hal)
48 {
49 if (hal->use_dma) {
50
51 //Fill DMA descriptors
52 if (hal->rx_buffer) {
53 lldesc_setup_link(hal->dmadesc_rx, hal->rx_buffer, ((hal->bitlen + 7) / 8), true);
54
55 //reset dma inlink, this should be reset before spi related reset
56 spi_dma_ll_rx_reset(hal->dma_in, hal->rx_dma_chan);
57 spi_ll_dma_rx_fifo_reset(hal->dma_in);
58 spi_ll_slave_reset(hal->hw);
59 spi_ll_infifo_full_clr(hal->hw);
60
61 spi_ll_dma_rx_enable(hal->hw, 1);
62 spi_dma_ll_rx_start(hal->dma_in, hal->rx_dma_chan, &hal->dmadesc_rx[0]);
63 }
64 if (hal->tx_buffer) {
65 lldesc_setup_link(hal->dmadesc_tx, hal->tx_buffer, (hal->bitlen + 7) / 8, false);
66 //reset dma outlink, this should be reset before spi related reset
67 spi_dma_ll_tx_reset(hal->dma_out, hal->tx_dma_chan);
68 spi_ll_dma_tx_fifo_reset(hal->dma_out);
69 spi_ll_slave_reset(hal->hw);
70 spi_ll_outfifo_empty_clr(hal->hw);
71
72 spi_ll_dma_tx_enable(hal->hw, 1);
73 spi_dma_ll_tx_start(hal->dma_out, hal->tx_dma_chan, (&hal->dmadesc_tx[0]));
74 }
75 } else {
76 //No DMA. Turn off SPI and copy data to transmit buffers.
77 if (hal->tx_buffer) {
78 spi_ll_slave_reset(hal->hw);
79 spi_ll_write_buffer(hal->hw, hal->tx_buffer, hal->bitlen);
80 }
81
82 spi_ll_cpu_tx_fifo_reset(hal->hw);
83 }
84
85 spi_ll_slave_set_rx_bitlen(hal->hw, hal->bitlen);
86 spi_ll_slave_set_tx_bitlen(hal->hw, hal->bitlen);
87
88 spi_ll_enable_mosi(hal->hw, (hal->tx_buffer == NULL) ? 0 : 1);
89 spi_ll_enable_miso(hal->hw, (hal->rx_buffer == NULL) ? 0 : 1);
90 }
91
spi_slave_hal_store_result(spi_slave_hal_context_t * hal)92 void spi_slave_hal_store_result(spi_slave_hal_context_t *hal)
93 {
94 //when data of cur_trans->length are all sent, the slv_rdata_bit
95 //will be the length sent-1 (i.e. cur_trans->length-1 ), otherwise
96 //the length sent.
97 hal->rcv_bitlen = spi_ll_slave_get_rcv_bitlen(hal->hw);
98 if (hal->rcv_bitlen == hal->bitlen - 1) {
99 hal->rcv_bitlen++;
100 }
101 if (!hal->use_dma && hal->rx_buffer) {
102 //Copy result out
103 spi_ll_read_buffer(hal->hw, hal->rx_buffer, hal->bitlen);
104 }
105 }
106
spi_slave_hal_get_rcv_bitlen(spi_slave_hal_context_t * hal)107 uint32_t spi_slave_hal_get_rcv_bitlen(spi_slave_hal_context_t *hal)
108 {
109 return hal->rcv_bitlen;
110 }
111
spi_slave_hal_dma_need_reset(const spi_slave_hal_context_t * hal)112 bool spi_slave_hal_dma_need_reset(const spi_slave_hal_context_t *hal)
113 {
114 bool ret;
115 ret = false;
116 if (hal->use_dma && hal->rx_buffer) {
117 int i;
118 //In case CS goes high too soon, the transfer is aborted while the DMA channel still thinks it's going. This
119 //leads to issues later on, so in that case we need to reset the channel. The state can be detected because
120 //the DMA system doesn't give back the offending descriptor; the owner is still set to DMA.
121 for (i = 0; hal->dmadesc_rx[i].eof == 0 && hal->dmadesc_rx[i].owner == 0; i++) {}
122 if (hal->dmadesc_rx[i].owner) {
123 ret = true;
124 }
125 }
126 return ret;
127 }
128