/ components / kendryte_sdk / src / sipeed_spi.c
sipeed_spi.c
  1  #include <stdio.h>
  2  #include <fpioa.h>
  3  #include <spi.h>
  4  #include <sipeed_spi.h>
  5  #include <sysctl.h>
  6  #include <utils.h>
  7  
  8  void sipeed_spi_init(
  9              sipeed_spi_device_num_t spi_num,
 10              sipeed_spi_device_num_t work_mode,
 11              sipeed_spi_device_num_t frame_format,
 12              sipeed_size_t data_bit_length,
 13              sipeed_uint32_t endian)
 14  {
 15      spi_init(spi_num, work_mode, frame_format, data_bit_length, endian);
 16  }
 17  
 18  void sipeed_spi_init_non_standard(sipeed_spi_device_num_t spi_num, sipeed_uint32_t instruction_length, sipeed_uint32_t address_length,
 19                             sipeed_uint32_t wait_cycles, sipeed_spi_instruction_address_trans_mode_t instruction_address_trans_mode)
 20  {
 21      spi_init_non_standard(spi_num,instruction_length,address_length,wait_cycles, instruction_address_trans_mode);
 22  }
 23  
 24  void sipeed_spi_send_data_standard(sipeed_spi_device_num_t spi_num, sipeed_spi_chip_select_t chip_select, const sipeed_uint8_t *cmd_buff,
 25                              sipeed_size_t cmd_len, const sipeed_uint8_t *tx_buff, sipeed_size_t tx_len)
 26  {
 27      spi_send_data_standard( spi_num,chip_select,cmd_buff,cmd_len,tx_buff,tx_len);
 28  }
 29  void sipeed_spi_receive_data_standard(sipeed_spi_device_num_t spi_num, sipeed_spi_chip_select_t chip_select, const sipeed_uint8_t *cmd_buff,
 30                                 sipeed_size_t cmd_len, sipeed_uint8_t *rx_buff, sipeed_size_t rx_len)
 31  {
 32      spi_receive_data_standard(spi_num,chip_select,cmd_buff,cmd_len,rx_buff,rx_len);
 33  
 34  }
 35  void sipeed_spi_receive_data_multiple(sipeed_spi_device_num_t spi_num, sipeed_spi_chip_select_t chip_select, const sipeed_uint32_t *cmd_buff,
 36                                 sipeed_size_t cmd_len, sipeed_uint8_t *rx_buff, sipeed_size_t rx_len)
 37  {
 38      spi_receive_data_multiple( spi_num,chip_select,cmd_buff,cmd_len,rx_buff,rx_len);
 39  }
 40  
 41  void sipeed_spi_send_data_multiple(sipeed_spi_device_num_t spi_num, sipeed_spi_chip_select_t chip_select, const sipeed_uint32_t *cmd_buff,
 42                              sipeed_size_t cmd_len, const sipeed_uint8_t *tx_buff, sipeed_size_t tx_len)
 43  {
 44      spi_send_data_multiple( spi_num,  chip_select,cmd_buff,cmd_len, tx_buff, tx_len);
 45  }
 46  
 47  void sipeed_spi_send_data_standard_dma(sipeed_dmac_channel_number_t channel_num, sipeed_spi_device_num_t spi_num,
 48                                  sipeed_spi_chip_select_t chip_select,
 49                                  const sipeed_uint8_t *cmd_buff, sipeed_size_t cmd_len, const sipeed_uint8_t *tx_buff, sipeed_size_t tx_len)
 50  {
 51      spi_send_data_standard_dma(channel_num, spi_num, chip_select, cmd_buff, cmd_len, tx_buff, tx_len);
 52  }
 53  
 54  void sipeed_spi_receive_data_standard_dma(sipeed_dmac_channel_number_t dma_send_channel_num,
 55                                     sipeed_dmac_channel_number_t dma_receive_channel_num,
 56                                     sipeed_spi_device_num_t spi_num, sipeed_spi_chip_select_t chip_select, const sipeed_uint8_t *cmd_buff,
 57                                     sipeed_size_t cmd_len, sipeed_uint8_t *rx_buff, sipeed_size_t rx_len)
 58  {
 59      spi_receive_data_standard_dma(dma_send_channel_num, dma_receive_channel_num, spi_num, chip_select, cmd_buff, cmd_len, rx_buff, rx_len);
 60  }
 61  
 62  void sipeed_spi_send_data_multiple_dma(sipeed_dmac_channel_number_t channel_num, sipeed_spi_device_num_t spi_num,
 63                                  sipeed_spi_chip_select_t chip_select,
 64                                  const sipeed_uint32_t *cmd_buff, sipeed_size_t cmd_len, const sipeed_uint8_t *tx_buff, sipeed_size_t tx_len)
 65  {
 66      spi_send_data_multiple_dma(channel_num, spi_num,chip_select,cmd_buff,cmd_len,tx_buff,tx_len);
 67  
 68  }
 69  
 70  void sipeed_spi_receive_data_multiple_dma(sipeed_dmac_channel_number_t dma_send_channel_num,
 71                                     sipeed_dmac_channel_number_t dma_receive_channel_num,
 72                                     sipeed_spi_device_num_t spi_num, sipeed_spi_chip_select_t chip_select, const sipeed_uint32_t *cmd_buff,
 73                                     sipeed_size_t cmd_len, sipeed_uint8_t *rx_buff, sipeed_size_t rx_len)
 74  {
 75      spi_receive_data_multiple_dma( dma_send_channel_num, dma_receive_channel_num,
 76                                      spi_num,  chip_select, cmd_buff,
 77                                      cmd_len, rx_buff, rx_len);
 78  }
 79  
 80  void sipeed_spi_fill_data_dma(sipeed_dmac_channel_number_t channel_num, sipeed_spi_device_num_t spi_num, sipeed_spi_chip_select_t chip_select,
 81                         const sipeed_uint32_t *tx_buff, sipeed_size_t tx_len)
 82  {
 83      spi_fill_data_dma( channel_num,  spi_num,  chip_select, tx_buff, tx_len);
 84  }
 85  
 86  void sipeed_spi_send_data_normal_dma(sipeed_dmac_channel_number_t channel_num, sipeed_spi_device_num_t spi_num,
 87                                sipeed_spi_chip_select_t chip_select,
 88                                const void *tx_buff, sipeed_size_t tx_len, sipeed_spi_transfer_width_t spi_transfer_width)
 89  {
 90      spi_send_data_normal_dma( channel_num,  spi_num,
 91                                 chip_select, tx_buff, tx_len, spi_transfer_width);
 92  
 93  }
 94  
 95  sipeed_uint32_t sipeed_spi_set_clk_rate(sipeed_spi_device_num_t spi_num, sipeed_uint32_t spi_clk)
 96  {
 97      return spi_set_clk_rate( spi_num, spi_clk);
 98  }
 99  
100  
101  static spi_transfer_width_t sipeed_spi_get_frame_size(size_t data_bit_length)
102  {
103      if (data_bit_length < 8)
104          return SPI_TRANS_CHAR;
105      else if (data_bit_length < 16)
106          return SPI_TRANS_SHORT;
107      return SPI_TRANS_INT;
108  }
109  
110  static void sipeed_spi_set_tmod(uint8_t spi_num, uint32_t tmod)
111  {
112      configASSERT(spi_num < SPI_DEVICE_MAX && spi_num != 2);
113      volatile spi_t *spi_handle = spi[spi_num];
114      uint8_t tmod_offset = 0;
115      switch(spi_num)
116      {
117          case 0:
118          case 1:
119              tmod_offset = 8;
120              break;
121          case 2:
122              configASSERT(!"Spi Bus 2 Not Support!");
123              break;
124          case 3:
125          default:
126              tmod_offset = 10;
127              break;
128      }
129      set_bit(&spi_handle->ctrlr0, 3 << tmod_offset, tmod << tmod_offset);
130  }
131  
132  void sipeed_spi_transfer_data_standard(spi_device_num_t spi_num, spi_chip_select_t chip_select, const uint8_t *tx_buff,uint8_t *rx_buff,  size_t tx_len, size_t rx_len)
133  {
134      configASSERT(spi_num < SPI_DEVICE_MAX && spi_num != 2);
135      configASSERT(tx_len > 0 && tx_len >= rx_len);
136      size_t index, fifo_len;
137      sipeed_spi_set_tmod(spi_num, SPI_TMOD_TRANS_RECV);
138  
139      volatile spi_t *spi_handle = spi[spi_num];
140  
141      uint8_t dfs_offset;
142      switch(spi_num){
143          case 0:
144          case 1:
145              dfs_offset = 16;
146              break;
147          case 2:
148              configASSERT(!"Spi Bus 2 Not Support!");
149              break;
150          case 3:
151          default:
152              dfs_offset = 0;
153              break;
154      }
155      uint32_t data_bit_length = (spi_handle->ctrlr0 >> dfs_offset) & 0x1F;
156      spi_transfer_width_t frame_width = sipeed_spi_get_frame_size(data_bit_length);
157      spi_handle->ctrlr1 = (uint32_t)(tx_len/frame_width - 1);
158      spi_handle->ssienr = 0x01;
159      spi_handle->ser = 1U << chip_select;
160      uint32_t index_tx = 0, index_rx = 0;
161      while (tx_len)
162      {
163          fifo_len = 32 - spi_handle->txflr;
164          fifo_len = fifo_len < tx_len ? fifo_len : tx_len;
165          switch(frame_width)
166          {
167              case SPI_TRANS_INT:
168                  fifo_len = fifo_len / 4 * 4;
169                  for (index = 0; index < fifo_len / 4; index++)
170                      spi_handle->dr[0] = ((uint32_t *)tx_buff)[index_tx++];
171                  break;
172              case SPI_TRANS_SHORT:
173                  fifo_len = fifo_len / 2 * 2;
174                  for (index = 0; index < fifo_len / 2; index++)
175                      spi_handle->dr[0] = ((uint16_t *)tx_buff)[index_tx++];
176                  break;
177              default:
178                  for (index = 0; index < fifo_len; index++)
179                      spi_handle->dr[0] = tx_buff[index_tx++];
180                  break;
181          }
182          tx_len -= fifo_len;
183          while(rx_len)
184          {
185              fifo_len = spi_handle->rxflr;
186              if(fifo_len==0)
187              {
188                  if(index_tx - index_rx < 32)
189                      break;
190              }
191              fifo_len = fifo_len < rx_len ? fifo_len : rx_len;
192              switch(frame_width)
193              {
194                  case SPI_TRANS_INT:
195                      fifo_len = fifo_len / 4 * 4;
196                      for (index = 0; index < fifo_len / 4; index++)
197                      ((uint32_t *)rx_buff)[index_rx++] = spi_handle->dr[0];
198                      break;
199                  case SPI_TRANS_SHORT:
200                      fifo_len = fifo_len / 2 * 2;
201                      for (index = 0; index < fifo_len / 2; index++)
202                      ((uint16_t *)rx_buff)[index_rx++] = (uint16_t)spi_handle->dr[0];
203                      break;
204                  default:
205                      for (index = 0; index < fifo_len; index++)
206                          rx_buff[index_rx++] = (uint8_t)spi_handle->dr[0];
207                      break;
208              }
209  
210              rx_len -= fifo_len;
211              
212          }
213      }
214  
215      while ((spi_handle->sr & 0x05) != 0x04)
216          ;
217      while (rx_len)
218      {
219          fifo_len = spi_handle->rxflr;
220          fifo_len = fifo_len < rx_len ? fifo_len : rx_len;
221          switch(frame_width)
222          {
223              case SPI_TRANS_INT:
224                  fifo_len = fifo_len / 4 * 4;
225                  for (index = 0; index < fifo_len / 4; index++)
226                    ((uint32_t *)rx_buff)[index_rx++] = spi_handle->dr[0];
227                  break;
228              case SPI_TRANS_SHORT:
229                  fifo_len = fifo_len / 2 * 2;
230                  for (index = 0; index < fifo_len / 2; index++)
231                    ((uint16_t *)rx_buff)[index_rx++] = (uint16_t)spi_handle->dr[0];
232                   break;
233              default:
234                    for (index = 0; index < fifo_len; index++)
235                        rx_buff[index_rx++] = (uint8_t)spi_handle->dr[0];
236                  break;
237          }
238  
239          rx_len -= fifo_len;
240      }
241      spi_handle->ser = 0x00;
242      spi_handle->ssienr = 0x00;
243  }
244  
245  void sipeed_spi_deinit(spi_device_num_t spi_num)
246  {
247      volatile spi_t *spi_handle = spi[spi_num];
248      spi_handle->ssienr = 0x00;
249      sysctl_clock_disable(SYSCTL_CLOCK_SPI0 + spi_num);
250  }
251