1 /*
2 * Copyright (c) 2022 Winner Microelectronics Co., Ltd. All rights reserved.
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 /**
17 * @file wm_hostspi.c
18 *
19 * @brief host spi Driver Module
20 *
21 * @author dave
22 *
23 * Copyright (c) 2015 Winner Microelectronics Co., Ltd.
24 */
25 #include <stdio.h>
26 #include <string.h>
27 #include <stdlib.h>
28 #include "wm_regs.h"
29 #include "wm_irq.h"
30 #include "wm_gpio.h"
31 #include "wm_dma.h"
32 #include "wm_dbg.h"
33 #include "wm_mem.h"
34 #include "wm_cpu.h"
35 #include "wm_spi_hal.h"
36 #include "wm_wl_task.h"
37 #include "tls_common.h"
38 #include "core_804.h"
39 #include "wm_pmu.h"
40 #include "wm_hostspi.h"
41
42 static struct tls_spi_port *spi_port = NULL;
43
44 #define MSG_QUEUE_SIZE (8)
45
46 #define SPI_SCHEDULER_STK_SIZE (256)
47 #if TLS_OS_FREERTOS
48 static u32 *spi_scheduler_stk = NULL;
49 #endif
50 void tls_spi_queue_send(u32 msg);
51
52 #define SPI_SCHED_MSG_START_ENGINE (1)
53 #define SPI_SCHED_MSG_TX_FIFO_READY (2)
54 #define SPI_SCHED_MSG_RX_FIFO_READY (3)
55 #define SPI_SCHED_MSG_TRANSFER_COMPLETE (4)
56 #define SPI_SCHED_MSG_EXIT (5)
57 #define SPI_SCHED_MSG_END (6)
58 static void spi_start_transfer(u32 transfer_bytes);
59
60 int tls_spi_async(struct tls_spi_message *message);
61 int tls_spi_sync(struct tls_spi_message *message);
62
63 #ifdef SPI_USE_DMA
64 unsigned char *SPI_DMA_CMD_ADDR = NULL;
65 unsigned char *SPI_DMA_BUF_ADDR = NULL;
66
SpiMasterInit(u8 mode,u8 cs_active,u32 fclk)67 static void SpiMasterInit(u8 mode, u8 cs_active, u32 fclk)
68 {
69 tls_sys_clk sysclk;
70
71 SPIM_CHCFG_REG = SPI_CLEAR_FIFOS;
72 while (SPIM_CHCFG_REG & SPI_CLEAR_FIFOS);
73
74 tls_sys_clk_get(&sysclk);
75
76 SPIM_CLKCFG_REG = sysclk.apbclk*UNIT_MHZ/(fclk*2) - 1;
77 SPIM_SPICFG_REG = 0;
78 SPIM_SPICFG_REG = SPI_FRAME_FORMAT_MOTO | SPI_SET_MASTER_SLAVE(SPI_MASTER) | mode;
79 SPIM_INTEN_REG = 0xff; /* Disable INT */
80
81 if (SPI_DMA_CMD_ADDR == NULL) {
82 SPI_DMA_CMD_ADDR = tls_mem_alloc(SPI_DMA_CMD_MAX_SIZE);
83 if (SPI_DMA_CMD_ADDR == NULL) {
84 return;
85 }
86 }
87
88 if (SPI_DMA_BUF_ADDR == NULL) {
89 SPI_DMA_BUF_ADDR = tls_mem_alloc(SPI_DMA_BUF_MAX_SIZE);
90 if (SPI_DMA_BUF_ADDR == NULL) {
91 tls_mem_free(SPI_DMA_CMD_ADDR);
92 SPI_DMA_CMD_ADDR = NULL;
93 return;
94 }
95 }
96
97 tls_dma_init();
98 }
99
spiWaitIdle(void)100 int spiWaitIdle(void)
101 {
102 unsigned long regVal;
103 unsigned long timeout = 0;
104
105 do {
106 timeout++;
107 if (timeout > 0x4FFFFF) // 5s
108 return TLS_SPI_STATUS_EBUSY;
109 regVal = SPIM_SPISTATUS_REG;
110 }
111 while (regVal & (1 << 12));
112
113 return TLS_SPI_STATUS_OK;
114 }
115
SpiDmaBlockWrite(u8 * data,u32 len,u8 ifusecmd,u32 cmd)116 static int SpiDmaBlockWrite(u8 * data, u32 len, u8 ifusecmd, u32 cmd)
117 {
118 struct tls_dma_descriptor DmaDesc;
119 u32 txlen, txlenbk;
120 u32 i, blocknum, blocksize = 0;
121 int ret = TLS_SPI_STATUS_OK;
122 int txcmdover = 0;
123
124 if (data == NULL) {
125 return TLS_SPI_STATUS_EINVAL;
126 }
127 if (spiWaitIdle())
128 return TLS_SPI_STATUS_EBUSY;
129 SPIM_CHCFG_REG = SPI_CLEAR_FIFOS;
130 while (SPIM_CHCFG_REG & SPI_CLEAR_FIFOS);
131
132 if (ifusecmd)
133 SPIM_TXDATA_REG = cmd;
134
135 if (len % 4) {
136 txlen = len & 0xfffffffc;
137 } else {
138 txlen = len;
139 }
140
141 txlenbk = txlen;
142 if (txlen > 0) {
143 blocknum = txlen / SPI_DMA_MAX_TRANS_SIZE;
144
145 /* Request DMA Channel */
146 unsigned char dmaCh = tls_dma_request(1, TLS_DMA_FLAGS_CHANNEL_SEL(TLS_DMA_SEL_LSSPI_TX) |
147 TLS_DMA_FLAGS_HARD_MODE);
148 for (i = 0; i <= blocknum; i++) {
149 DmaDesc.src_addr = (int) (data + i * SPI_DMA_MAX_TRANS_SIZE);
150 DmaDesc.dest_addr = HR_SPI_TXDATA_REG;
151 blocksize = (txlen > SPI_DMA_MAX_TRANS_SIZE) ? SPI_DMA_MAX_TRANS_SIZE : txlen;
152
153 if (blocksize == 0)
154 break;
155 DmaDesc.dma_ctrl = TLS_DMA_DESC_CTRL_SRC_ADD_INC |
156 TLS_DMA_DESC_CTRL_DATA_SIZE_WORD |
157 TLS_DMA_DESC_CTRL_TOTAL_BYTES(blocksize);
158 DmaDesc.valid = TLS_DMA_DESC_VALID;
159 DmaDesc.next = NULL;
160 tls_dma_start(dmaCh, &DmaDesc, 0);
161 /* Enable SPI TX DMA */
162 SPIM_MODECFG_REG = SPI_RX_TRIGGER_LEVEL(0) | SPI_TX_TRIGGER_LEVEL(0) | SPI_TX_DMA_ON;
163 SPIM_SPITIMEOUT_REG = SPI_TIMER_EN | SPI_TIME_OUT((u32) 0xffff);
164
165 if (ifusecmd && i == 0) {
166 SPIM_CHCFG_REG = SPI_FORCE_SPI_CS_OUT | SPI_TX_CHANNEL_ON |
167 SPI_CONTINUE_MODE | SPI_START |
168 SPI_VALID_CLKS_NUM(((blocksize + 4) * 8));
169 txcmdover = 1;
170 } else
171 SPIM_CHCFG_REG = SPI_FORCE_SPI_CS_OUT | SPI_TX_CHANNEL_ON | SPI_CONTINUE_MODE |
172 SPI_START | SPI_VALID_CLKS_NUM((blocksize * 8));
173
174 if (spiWaitIdle()) {
175 ret = TLS_SPI_STATUS_EBUSY;
176 break;
177 }
178 /* Wait Dma Channel Complete and Free Dma channel */
179 if (tls_dma_wait_complt(dmaCh)) {
180 ret = TLS_SPI_STATUS_EBUSY;
181 break;
182 }
183 txlen -= blocksize;
184 }
185 tls_dma_free(dmaCh);
186 }
187
188 if (len > txlenbk) {
189 u32 word32 = 0;
190 int temp = 0;
191 for (i = 0; i < (len - txlenbk); i++) {
192 word32 |= (data[txlenbk + i] << (i * 8));
193 }
194 SPIM_TXDATA_REG = word32;
195 SPIM_MODECFG_REG = SPI_RX_TRIGGER_LEVEL(0) | SPI_TX_TRIGGER_LEVEL(0);
196 SPIM_SPITIMEOUT_REG = SPI_TIMER_EN | SPI_TIME_OUT((u32) 0xffff);
197 if (ifusecmd && txcmdover == 0)
198 temp = 4;
199 SPIM_CHCFG_REG = SPI_FORCE_SPI_CS_OUT | SPI_TX_CHANNEL_ON | SPI_CONTINUE_MODE |
200 SPI_START | SPI_VALID_CLKS_NUM(((temp + len - txlenbk) * 8));
201 if (spiWaitIdle()) {
202 ret = TLS_SPI_STATUS_EBUSY;
203 }
204 }
205 SPIM_CHCFG_REG = 0x00000000;
206 SPIM_MODECFG_REG = 0x00000000;
207 SPIM_SPITIMEOUT_REG = 0x00000000;
208
209 return ret;
210 }
211
SpiDmaBlockRead(u8 * data,u32 len,u8 * txdata,u8 txlen)212 static int SpiDmaBlockRead(u8 * data, u32 len, u8 * txdata, u8 txlen)
213 {
214 unsigned char dmaCh = 0;
215 struct tls_dma_descriptor DmaDesc;
216 u32 word32 = 0;
217 u32 i;
218 u32 rxlen, rxlenbk;
219 u8 blocknum;
220 u32 blocksize = 0;
221 int ret = TLS_SPI_STATUS_OK;
222 if (data == NULL) {
223 return TLS_SPI_STATUS_EINVAL;
224 }
225 if (spiWaitIdle()) {
226 return TLS_SPI_STATUS_EBUSY;
227 }
228
229 SPIM_CHCFG_REG = SPI_CLEAR_FIFOS;
230 while (SPIM_CHCFG_REG & SPI_CLEAR_FIFOS);
231
232 if (len % 4) {
233 rxlen = len & 0xfffffffc;
234 } else {
235 rxlen = len;
236 }
237 rxlenbk = rxlen;
238 blocknum = rxlen / SPI_DMA_MAX_TRANS_SIZE;
239
240 if (txlen > 0 && txlen <= 32) {
241 for (i = 0; i < txlen; i++) {
242 if ((i > 0) && (i % 4 == 0)) {
243 SPIM_TXDATA_REG = word32;
244 word32 = 0;
245 }
246 word32 |= (txdata[i] << ((i % 4) * 8));
247 }
248 SPIM_TXDATA_REG = word32;
249 }
250
251 /* Request DMA Channel */
252 dmaCh = tls_dma_request(1, TLS_DMA_FLAGS_CHANNEL_SEL(TLS_DMA_SEL_LSSPI_RX) |
253 TLS_DMA_FLAGS_HARD_MODE);
254 DmaDesc.src_addr = HR_SPI_RXDATA_REG;
255 for (i = 0; i <= blocknum; i++) {
256 if (rxlenbk > 0) {
257 DmaDesc.dest_addr = (int) (data + i * SPI_DMA_MAX_TRANS_SIZE);
258 blocksize = (rxlen > SPI_DMA_MAX_TRANS_SIZE) ? SPI_DMA_MAX_TRANS_SIZE : rxlen;
259 if (blocksize == 0) {
260 break;
261 }
262 DmaDesc.dma_ctrl =
263 TLS_DMA_DESC_CTRL_DEST_ADD_INC | TLS_DMA_DESC_CTRL_BURST_SIZE1 |
264 TLS_DMA_DESC_CTRL_DATA_SIZE_WORD |
265 TLS_DMA_DESC_CTRL_TOTAL_BYTES(blocksize);
266 DmaDesc.valid = TLS_DMA_DESC_VALID;
267 DmaDesc.next = NULL;
268 tls_dma_start(dmaCh, &DmaDesc, 0);
269 /* Enable SPI RX DMA */
270 SPIM_MODECFG_REG = SPI_RX_TRIGGER_LEVEL(0) | SPI_TX_TRIGGER_LEVEL(0) |
271 SPI_RX_DMA_ON;
272 } else {
273 SPIM_MODECFG_REG = SPI_RX_TRIGGER_LEVEL(0) | SPI_TX_TRIGGER_LEVEL(0);
274 }
275 SPIM_SPITIMEOUT_REG = SPI_TIMER_EN | SPI_TIME_OUT((u32) 0xffff);
276 if (blocknum == 0) {
277 SPIM_CHCFG_REG =
278 SPI_FORCE_SPI_CS_OUT | SPI_RX_CHANNEL_ON | SPI_TX_CHANNEL_ON |
279 SPI_CONTINUE_MODE | SPI_START |
280 SPI_VALID_CLKS_NUM(((len + txlen) * 8)) | SPI_RX_INVALID_BITS(txlen *8);
281 } else {
282 if (i == 0) {
283 SPIM_CHCFG_REG =
284 SPI_FORCE_SPI_CS_OUT | SPI_RX_CHANNEL_ON | SPI_TX_CHANNEL_ON
285 | SPI_CONTINUE_MODE | SPI_START |
286 SPI_VALID_CLKS_NUM(((blocksize + txlen) *8)) | SPI_RX_INVALID_BITS(txlen * 8);
287 } else if (i == blocknum) {
288 SPIM_CHCFG_REG =
289 SPI_FORCE_SPI_CS_OUT | SPI_RX_CHANNEL_ON | SPI_CONTINUE_MODE
290 | SPI_START | SPI_VALID_CLKS_NUM((blocksize + len - rxlenbk) * 8);
291 } else {
292 SPIM_CHCFG_REG =
293 SPI_FORCE_SPI_CS_OUT | SPI_RX_CHANNEL_ON | SPI_CONTINUE_MODE
294 | SPI_START | SPI_VALID_CLKS_NUM(blocksize * 8);
295 }
296 }
297 if (spiWaitIdle()) {
298 ret = TLS_SPI_STATUS_EBUSY;
299 break;
300 }
301
302 /* Wait Dma Channel Complete and Free Dma channel */
303 if (tls_dma_wait_complt(dmaCh)) {
304 ret = TLS_SPI_STATUS_EBUSY;
305 break;
306 }
307 rxlen -= blocksize;
308 }
309 tls_dma_free(dmaCh);
310
311 if (len > rxlenbk) {
312 word32 = SPIM_RXDATA_REG;
313 *((int *) data + rxlenbk / 4) = word32;
314 }
315 SPIM_CHCFG_REG = 0x00000000;
316 SPIM_MODECFG_REG = 0x00000000;
317 SPIM_SPITIMEOUT_REG = 0x00000000;
318 return ret;
319 }
320 #endif
321
322 /**
323 * @brief This function is used to set SPI transfer mode.
324 *
325 * @param[in] type is the transfer type.
326 * type == SPI_BYTE_TRANSFER byte transfer
327 * type == SPI_WORD_TRANSFER word transfer
328 * type == SPI_USE_DMA_TRANSFER DMA transfer
329 *
330 * @return None
331 *
332 * @note None
333 */
tls_spi_trans_type(u8 type)334 void tls_spi_trans_type(u8 type)
335 {
336 spi_port->transtype = type;
337 if (SPI_WORD_TRANSFER == type) {
338 spi_set_endian(0);
339 } else if (SPI_USE_DMA_TRANSFER == type) {
340 #ifdef SPI_USE_DMA
341 SpiMasterInit(spi_port->mode, TLS_SPI_CS_LOW, spi_port->speed_hz);
342 #endif
343 }
344 }
345
spi_message_init(struct tls_spi_message * m)346 static void spi_message_init(struct tls_spi_message *m)
347 {
348 memset_s(m, sizeof(m), 0, sizeof(*m));
349 dl_list_init(&m->transfers);
350 }
351
spi_complete(void * arg)352 static void spi_complete(void *arg)
353 {
354 tls_os_sem_t *sem;
355
356 sem = (tls_os_sem_t *) arg;
357 tls_os_sem_release(sem);
358 }
359
spi_fill_txfifo(struct tls_spi_transfer * current_transfer,u32 current_remaining_bytes)360 static u32 spi_fill_txfifo(struct tls_spi_transfer *current_transfer,
361 u32 current_remaining_bytes)
362 {
363 u8 fifo_level;
364 u16 rw_words;
365 u16 rw_bytes;
366 u8 data8;
367 u8 i;
368 u32 data32 = 0;
369 u32 tx_remaining_bytes;
370 if ((current_transfer == NULL) || (current_remaining_bytes == 0))
371 return 0;
372
373 tx_remaining_bytes = current_remaining_bytes;
374 spi_get_status(NULL, NULL, &fifo_level);
375 rw_words =
376 ((fifo_level > tx_remaining_bytes) ? tx_remaining_bytes : fifo_level) / 4;
377 rw_bytes =
378 ((fifo_level > tx_remaining_bytes) ? tx_remaining_bytes : fifo_level) % 4;
379
380 for (i = 0; i < rw_words; i++) {
381 if (current_transfer->tx_buf) {
382 if (SPI_BYTE_TRANSFER == spi_port->transtype) {
383 data32 = 0;
384 data32 |= ((u8 *) current_transfer->tx_buf +
385 (current_transfer->len - tx_remaining_bytes))[0] << 24;
386 data32 |= ((u8 *) current_transfer->tx_buf +
387 (current_transfer->len - tx_remaining_bytes))[1] << 16;
388 data32 |= ((u8 *) current_transfer->tx_buf +
389 (current_transfer->len - tx_remaining_bytes))[2] << 8;
390 data32 |= ((u8 *) current_transfer->tx_buf +
391 (current_transfer->len - tx_remaining_bytes))[3] << 0;
392 } else if (SPI_WORD_TRANSFER == spi_port->transtype) {
393 data32 = *((u32 *) ((u8 *) current_transfer->tx_buf +
394 current_transfer->len - tx_remaining_bytes));
395 }
396 } else {
397 data32 = 0xffffffff;
398 }
399 TLS_DBGPRT_SPI_INFO("spi fifo[%d]: 0x%x.\n", i, data32);
400 spi_data_put(data32);
401 tx_remaining_bytes -= 4;
402 }
403
404 if (rw_bytes) {
405 data32 = 0;
406 for (i = 0; i < rw_bytes; i++) {
407 if (current_transfer->tx_buf) {
408 data8 = ((u8 *) current_transfer->tx_buf)[current_transfer->len -
409 tx_remaining_bytes];
410 } else {
411 data8 = 0xff;
412 }
413 if (SPI_BYTE_TRANSFER == spi_port->transtype)
414 data32 |= data8 << ((3 - i) * 8);
415 else if (SPI_WORD_TRANSFER == spi_port->transtype) {
416 data32 |= data8 << (i * 8);
417 }
418 tx_remaining_bytes -= 1;
419 }
420 TLS_DBGPRT_SPI_INFO("spi_fifo: 0x%x.\n", data32);
421 spi_data_put(data32);
422 }
423
424 return (current_remaining_bytes - tx_remaining_bytes);
425 }
426
spi_get_rxfifo(struct tls_spi_transfer * current_transfer,u32 current_remaining_bytes)427 static u32 spi_get_rxfifo(struct tls_spi_transfer *current_transfer,
428 u32 current_remaining_bytes)
429 {
430 u8 fifo_level;
431 u8 rw_words;
432 u8 rw_bytes;
433 u8 data8 = 0;
434 u8 i;
435 u32 data32;
436 u32 rx_remaining_bytes;
437
438 if ((current_transfer == NULL) || (current_remaining_bytes == 0))
439 return 0;
440
441 rx_remaining_bytes = current_remaining_bytes;
442 spi_get_status(NULL, &fifo_level, NULL);
443
444 rw_words = fifo_level / 4;
445 rw_bytes = fifo_level % 4;
446
447 for (i = 0; i < rw_words; i++) {
448 data32 = spi_data_get();
449 if (current_transfer->rx_buf) {
450 if (SPI_BYTE_TRANSFER == spi_port->transtype) {
451 data32 = swap_32(data32);
452 (((u8 *) current_transfer->rx_buf +
453 (current_transfer->len - rx_remaining_bytes)))[0] = (u8) data32;
454 (((u8 *) current_transfer->rx_buf +
455 (current_transfer->len - rx_remaining_bytes)))[1] = (u8) (data32 >> 8);
456 (((u8 *) current_transfer->rx_buf +
457 (current_transfer->len - rx_remaining_bytes)))[2] = (u8) (data32 >> 16);
458 (((u8 *) current_transfer->rx_buf +
459 (current_transfer->len - rx_remaining_bytes)))[3] = (u8) (data32 >> 24);
460 } else if (SPI_WORD_TRANSFER == spi_port->transtype) {
461 *((u32 *) ((u8 *) current_transfer->rx_buf +
462 current_transfer->len - rx_remaining_bytes)) = data32;
463 }
464 }
465 rx_remaining_bytes -= 4;
466 }
467
468 if (rw_bytes) {
469 data32 = spi_data_get();
470 if (current_transfer->rx_buf) {
471 for (i = 0; i < rw_bytes; i++) {
472 if (SPI_BYTE_TRANSFER == spi_port->transtype)
473 data8 = (u8) (data32 >> ((3 - i) * 8));
474 else if (SPI_WORD_TRANSFER == spi_port->transtype)
475 data8 = (u8) (data32 >> (i * 8));
476 ((u8 *) current_transfer->rx_buf)[current_transfer->len -rx_remaining_bytes] = data8;
477 rx_remaining_bytes -= 1;
478 }
479 } else {
480 rx_remaining_bytes -= rw_bytes;
481 }
482 }
483
484 return (current_remaining_bytes - rx_remaining_bytes);
485 }
486
spi_next_transfer(struct tls_spi_message * current_message)487 static struct tls_spi_transfer *spi_next_transfer(struct tls_spi_message
488 *current_message)
489 {
490 if (current_message == NULL) {
491 return NULL;
492 }
493
494 return dl_list_first(¤t_message->transfers, struct tls_spi_transfer, transfer_list);
495 }
496
spi_next_message(void)497 static struct tls_spi_message *spi_next_message(void)
498 {
499 struct tls_spi_message *current_message;
500
501 current_message =
502 dl_list_first(&spi_port->wait_queue, struct tls_spi_message, queue);
503 if (current_message == NULL) {
504 return NULL;
505 }
506
507 spi_port->current_transfer = spi_next_transfer(current_message);
508 current_message->status = SPI_MESSAGE_STATUS_INPROGRESS;
509
510 return current_message;
511 }
512
513 int gSpiCsFlag = 0;
spi_start_transfer(u32 transfer_bytes)514 static void spi_start_transfer(u32 transfer_bytes)
515 {
516 if (spi_port->reconfig) {
517 TLS_DBGPRT_SPI_INFO("reconfig the spi master controller.\n");
518 spi_set_mode(spi_port->mode);
519 spi_set_chipselect_mode(spi_port->cs_active);
520 spi_set_sclk(spi_port->speed_hz);
521
522 spi_port->reconfig = 0;
523 }
524
525 spi_set_sclk_length(transfer_bytes * 8, 0);
526 {
527 spi_set_chipselect_mode(SPI_CS_ACTIVE_MODE);
528 }
529 spi_sclk_start();
530 }
531
spi_continue_transfer(void)532 static void spi_continue_transfer(void)
533 {
534 struct tls_spi_message *current_message;
535 struct tls_spi_transfer *current_transfer;
536 u32 transfer_bytes;
537
538 current_message = spi_port->current_message;
539 current_transfer = spi_port->current_transfer;
540 if ((current_message == NULL) || (current_transfer == NULL)) {
541 return;
542 }
543 transfer_bytes =
544 spi_get_rxfifo(current_transfer, spi_port->current_remaining_bytes);
545
546 spi_port->current_remaining_bytes -= transfer_bytes;
547 if (spi_port->current_remaining_bytes == 0) {
548 tls_os_sem_acquire(spi_port->lock, 0);
549
550 dl_list_del(¤t_transfer->transfer_list);
551 spi_port->current_transfer =
552 spi_next_transfer(spi_port->current_message);
553 if (spi_port->current_transfer == NULL) {
554 spi_set_chipselect_mode(SPI_CS_INACTIVE_MODE);
555 current_message->status = SPI_MESSAGE_STATUS_DONE;
556 dl_list_del(¤t_message->queue);
557 spi_port->current_message = spi_next_message();
558 }
559
560 tls_os_sem_release(spi_port->lock);
561 current_transfer = spi_port->current_transfer;
562 if (current_transfer != NULL) {
563 spi_port->current_remaining_bytes = current_transfer->len;
564 }
565 }
566
567 transfer_bytes =
568 spi_fill_txfifo(current_transfer, spi_port->current_remaining_bytes);
569 if (transfer_bytes) {
570 spi_start_transfer(transfer_bytes);
571 }
572
573 if (current_message->status == SPI_MESSAGE_STATUS_DONE) {
574 current_message->complete(current_message->context);
575 }
576 }
577
spi_scheduler(void * data)578 static void spi_scheduler(void *data)
579 {
580 u8 err;
581 u32 msg;
582 u32 transfer_bytes;
583 struct tls_spi_transfer *current_transfer;
584
585 while (1) {
586 err = tls_os_queue_receive(spi_port->msg_queue, (void **) &msg, 4, 0);
587 if (err == TLS_OS_SUCCESS) {
588 switch (msg) {
589 case SPI_SCHED_MSG_START_ENGINE:
590 if (spi_port->current_message) {
591 TLS_DBGPRT_WARNING("spi transaction scheduler is running now!\n");
592 break;
593 }
594
595 TLS_DBGPRT_SPI_INFO("acquire the first transaction message in waiting queue.\n");
596 tls_os_sem_acquire(spi_port->lock, 0);
597
598 spi_port->current_message = spi_next_message();
599
600 tls_os_sem_release(spi_port->lock);
601 current_transfer = spi_port->current_transfer;
602 if (current_transfer == NULL) {
603 break;
604 }
605 spi_port->current_remaining_bytes = current_transfer->len;
606
607 TLS_DBGPRT_SPI_INFO("fill the tx fifo.\n");
608 transfer_bytes = spi_fill_txfifo(current_transfer, spi_port->current_remaining_bytes);
609 TLS_DBGPRT_SPI_INFO("start the spi transfer - %d.\n", transfer_bytes);
610 spi_start_transfer(transfer_bytes);
611
612 break;
613
614 case SPI_SCHED_MSG_TX_FIFO_READY:
615 TLS_DBGPRT_SPI_INFO("process SPI_SCHED_MSG_TX_FIFO_READY.\n");
616 break;
617
618 case SPI_SCHED_MSG_RX_FIFO_READY:
619 TLS_DBGPRT_SPI_INFO("process SPI_SCHED_MSG_RX_FIFO_READY.\n");
620 break;
621
622 case SPI_SCHED_MSG_TRANSFER_COMPLETE:
623 spi_continue_transfer();
624 break;
625
626 case SPI_SCHED_MSG_EXIT:
627 break;
628
629 default:
630 break;
631 }
632 }
633 }
634 }
635
SPI_LS_IRQHandler(void)636 ATTRIBUTE_ISR void SPI_LS_IRQHandler(void)
637 {
638 u32 int_status;
639 u32 int_mask;
640 csi_kernel_intrpt_enter();
641 int_status = spi_get_int_status();
642 spi_clear_int_status(int_status);
643
644 int_mask = spi_int_mask();
645 int_status &= ~int_mask;
646
647 if (int_status & SPI_INT_TX_FIFO_RDY) {
648 tls_spi_queue_send(SPI_SCHED_MSG_TX_FIFO_READY);
649 }
650
651 if (int_status & SPI_INT_RX_FIFO_RDY) {
652 tls_spi_queue_send(SPI_SCHED_MSG_RX_FIFO_READY);
653 }
654
655 if (int_status & SPI_INT_TRANSFER_DONE) {
656 if (SPI_WORD_TRANSFER == spi_port->transtype) {
657 spi_continue_transfer();
658 } else {
659 tls_spi_queue_send(SPI_SCHED_MSG_TRANSFER_COMPLETE);
660 }
661 }
662 csi_kernel_intrpt_exit();
663 }
664
665 /**
666 * @brief This function is used to setup the spi CPOL,CPHA,cs signal and clock.
667 *
668 * @param[in] mode is CPOL and CPHA type defined in TLS_SPI_MODE_0 to TLS_SPI_MODE_3
669 * @param[in] cs_active is cs mode, defined as TLS_SPI_CS_LOW or TLS_SPI_CS_HIGH
670 * @param[in] fclk is spi clock,the unit is HZ.
671 *
672 * @retval TLS_SPI_STATUS_OK if setup success
673 * @retval TLS_SPI_STATUS_EMODENOSUPPORT if mode is not support
674 * @retval TLS_SPI_STATUS_EINVAL if cs_active is not support
675 * @retval TLS_SPI_STATUS_ECLKNOSUPPORT if fclk is not support
676 *
677 * @note None
678 */
tls_spi_setup(u8 mode,u8 cs_active,u32 fclk)679 int tls_spi_setup(u8 mode, u8 cs_active, u32 fclk)
680 {
681 tls_sys_clk sysclk;
682
683 if ((spi_port->mode == mode) && (spi_port->cs_active == cs_active)
684 && (spi_port->speed_hz == fclk)) {
685 TLS_DBGPRT_WARNING("@mode, @cs_activer, @fclk is the same as settings of the current spi master driver!\n");
686 return TLS_SPI_STATUS_OK;
687 }
688
689 switch (mode) {
690 case TLS_SPI_MODE_0:
691 case TLS_SPI_MODE_1:
692 case TLS_SPI_MODE_2:
693 case TLS_SPI_MODE_3:
694 spi_port->mode = mode;
695 break;
696
697 default:
698 TLS_DBGPRT_ERR("@mode is invalid!\n");
699 return TLS_SPI_STATUS_EMODENOSUPPORT;
700 }
701
702 if ((cs_active != TLS_SPI_CS_HIGH) && (cs_active != TLS_SPI_CS_LOW)) {
703 TLS_DBGPRT_ERR("@cs_active is invalid!\n");
704 return TLS_SPI_STATUS_EINVAL;
705 } else {
706 spi_port->cs_active = cs_active;
707 }
708
709 tls_sys_clk_get(&sysclk);
710
711 if ((fclk < TLS_SPI_FCLK_MIN) || (fclk > sysclk.apbclk * UNIT_MHZ / 2)) { // 2:TLS_SPI_FCLK_MAX
712 TLS_DBGPRT_ERR("@fclk is invalid!\n");
713 return TLS_SPI_STATUS_ECLKNOSUPPORT;
714 } else {
715 spi_port->speed_hz = fclk;
716 }
717
718 #ifdef SPI_USE_DMA
719 if (SPI_USE_DMA_TRANSFER == spi_port->transtype) {
720 SpiMasterInit(mode, TLS_SPI_CS_LOW, fclk);
721 return TLS_SPI_STATUS_OK;
722 }
723 #endif
724
725 spi_port->reconfig = 1;
726
727 return TLS_SPI_STATUS_OK;
728 }
729
730 /**
731 * @brief This function is used to synchronous write command then read data by SPI.
732 *
733 * @param[in] txbuf is the write data buffer.
734 * @param[in] n_tx is the write data length.
735 * @param[in] rxbuf is the read data buffer.
736 * @param[in] n_rx is the read data length.
737 *
738 * @retval TLS_SPI_STATUS_OK if write success.
739 * @retval TLS_SPI_STATUS_EINVAL if argument is invalid.
740 * @retval TLS_SPI_STATUS_ENOMEM if there is no enough memory.
741 * @retval TLS_SPI_STATUS_ESHUTDOWN if SPI driver does not installed.
742 *
743 * @note None
744 */
tls_spi_read_with_cmd(const u8 * txbuf,u32 n_tx,u8 * rxbuf,u32 n_rx)745 int tls_spi_read_with_cmd(const u8 * txbuf, u32 n_tx, u8 * rxbuf, u32 n_rx)
746 {
747 int status;
748 struct tls_spi_message message;
749 struct tls_spi_transfer x[2];
750
751 if ((txbuf == NULL) || (n_tx == 0) || (rxbuf == NULL) || (n_rx == 0)) {
752 return TLS_SPI_STATUS_EINVAL;
753 }
754
755 #ifdef SPI_USE_DMA
756 if (SPI_USE_DMA_TRANSFER == spi_port->transtype) {
757 if (n_rx > SPI_DMA_BUF_MAX_SIZE || n_tx > SPI_DMA_CMD_MAX_SIZE) {
758 TLS_DBGPRT_ERR("\nread length too long\n");
759 return TLS_SPI_STATUS_EINVAL;
760 }
761 tls_os_sem_acquire(spi_port->lock, 0);
762 tls_open_peripheral_clock(TLS_PERIPHERAL_TYPE_LSPI);
763 if (SPI_DMA_CMD_ADDR && SPI_DMA_BUF_ADDR) {
764 MEMCPY((u8 *) SPI_DMA_CMD_ADDR, txbuf, n_tx);
765 SpiDmaBlockRead((u8 *) SPI_DMA_BUF_ADDR, n_rx, (u8 *) SPI_DMA_CMD_ADDR,
766 n_tx);
767 MEMCPY(rxbuf, (u8 *) SPI_DMA_BUF_ADDR, n_rx);
768 status = TLS_SPI_STATUS_OK;
769 } else {
770 status = TLS_SPI_STATUS_ENOMEM;
771 }
772
773 tls_close_peripheral_clock(TLS_PERIPHERAL_TYPE_LSPI);
774 tls_os_sem_release(spi_port->lock);
775 return status;
776 }
777 #endif
778
779 spi_message_init(&message);
780
781 memset_s(x, sizeof(x), 0, sizeof(x));
782 if (n_tx) {
783 x[0].len = n_tx;
784 x[0].tx_buf = txbuf;
785 dl_list_add_tail(&message.transfers, &x[0].transfer_list);
786 }
787 if (n_rx) {
788 x[1].len = n_rx;
789 x[1].rx_buf = rxbuf;
790 dl_list_add_tail(&message.transfers, &x[1].transfer_list);
791 }
792
793 /* do the i/o. */
794 status = tls_spi_sync(&message);
795
796 return status;
797 }
798
799 /**
800 * @brief This function is used to synchronous read data by SPI.
801 *
802 * @param[in] buf is the buffer for saving SPI data.
803 * @param[in] len is the data length.
804 *
805 * @retval TLS_SPI_STATUS_OK if write success.
806 * @retval TLS_SPI_STATUS_EINVAL if argument is invalid.
807 * @retval TLS_SPI_STATUS_ENOMEM if there is no enough memory.
808 * @retval TLS_SPI_STATUS_ESHUTDOWN if SPI driver does not installed.
809 *
810 * @note None
811 */
tls_spi_read(u8 * buf,u32 len)812 int tls_spi_read(u8 * buf, u32 len)
813 {
814 struct tls_spi_transfer t;
815 struct tls_spi_message m;
816
817 if ((buf == NULL) || (len == 0)) {
818 return TLS_SPI_STATUS_EINVAL;
819 }
820
821 #ifdef SPI_USE_DMA
822 if (SPI_USE_DMA_TRANSFER == spi_port->transtype) {
823 u32 data32 = 0;
824 u16 rxBitLen;
825 u32 rdval1 = 0;
826 u32 i;
827 tls_os_sem_acquire(spi_port->lock, 0);
828 tls_open_peripheral_clock(TLS_PERIPHERAL_TYPE_LSPI);
829
830 if (len <= 4) {
831 SPIM_CHCFG_REG = SPI_CLEAR_FIFOS;
832 while (SPIM_CHCFG_REG & SPI_CLEAR_FIFOS);
833
834 rxBitLen = 8 * len;
835 rdval1 =
836 SPI_FORCE_SPI_CS_OUT | SPI_CS_LOW | SPI_TX_CHANNEL_ON |
837 SPI_RX_CHANNEL_ON | SPI_CONTINUE_MODE | SPI_START |
838 SPI_VALID_CLKS_NUM(rxBitLen);
839 SPIM_CHCFG_REG = rdval1;
840 spiWaitIdle();
841 SPIM_CHCFG_REG |= SPI_CS_HIGH;
842
843 data32 = SPIM_RXDATA_REG;
844
845 for (i = 0; i < len; i++) {
846 *(buf + i) = (u8) (data32 >> (i * 8));
847 }
848 SPIM_CHCFG_REG = 0x00000000;
849 SPIM_MODECFG_REG = 0x00000000;
850 } else {
851 if (len > SPI_DMA_BUF_MAX_SIZE) {
852 TLS_DBGPRT_ERR("\nread len too long\n");
853 tls_close_peripheral_clock(TLS_PERIPHERAL_TYPE_LSPI);
854 tls_os_sem_release(spi_port->lock);
855 return TLS_SPI_STATUS_EINVAL;
856 }
857 if (SPI_DMA_BUF_ADDR) {
858 SpiDmaBlockRead((u8 *) SPI_DMA_BUF_ADDR, len, NULL, 0);
859 MEMCPY(buf, (u8 *) SPI_DMA_BUF_ADDR, len);
860 } else {
861 tls_close_peripheral_clock(TLS_PERIPHERAL_TYPE_LSPI);
862 tls_os_sem_release(spi_port->lock);
863 return TLS_SPI_STATUS_ENOMEM;
864 }
865 }
866 tls_close_peripheral_clock(TLS_PERIPHERAL_TYPE_LSPI);
867 tls_os_sem_release(spi_port->lock);
868 return TLS_SPI_STATUS_OK;
869 }
870 #endif
871
872 memset_s(&t, sizeof(t), 0, sizeof(t));
873 t.rx_buf = buf;
874 t.len = len;
875
876 spi_message_init(&m);
877
878 dl_list_add_tail(&m.transfers, &t.transfer_list);
879
880 return tls_spi_sync(&m);
881 }
882
883 /**
884 * @brief This function is used to synchronous write data by SPI.
885 *
886 * @param[in] buf is the user data.
887 * @param[in] len is the data length.
888 *
889 * @retval TLS_SPI_STATUS_OK if write success.
890 * @retval TLS_SPI_STATUS_EINVAL if argument is invalid.
891 * @retval TLS_SPI_STATUS_ENOMEM if there is no enough memory.
892 * @retval TLS_SPI_STATUS_ESHUTDOWN if SPI driver does not installed.
893 *
894 * @note None
895 */
tls_spi_write(const u8 * buf,u32 len)896 int tls_spi_write(const u8 * buf, u32 len)
897 {
898 struct tls_spi_transfer t;
899 struct tls_spi_message m;
900
901 if ((buf == NULL) || (len == 0)) {
902 return TLS_SPI_STATUS_EINVAL;
903 }
904
905 #ifdef SPI_USE_DMA
906 if (SPI_USE_DMA_TRANSFER == spi_port->transtype) {
907 u32 data32 = 0;
908 u16 txBitLen;
909 u32 rdval1 = 0;
910 u32 i;
911 tls_os_sem_acquire(spi_port->lock, 0);
912 tls_open_peripheral_clock(TLS_PERIPHERAL_TYPE_LSPI);
913 if (len <= 4) {
914 SPIM_CHCFG_REG = SPI_CLEAR_FIFOS;
915 while (SPIM_CHCFG_REG & SPI_CLEAR_FIFOS);
916 for (i = 0; i < len; i++) {
917 data32 |= (((u8) (buf[i])) << (i * 8));
918 }
919 SPIM_TXDATA_REG = data32;
920 txBitLen = 8 * len;
921 rdval1 =
922 SPI_FORCE_SPI_CS_OUT | SPI_CS_LOW | SPI_TX_CHANNEL_ON |
923 SPI_RX_CHANNEL_ON | SPI_CONTINUE_MODE | SPI_START |
924 SPI_VALID_CLKS_NUM(txBitLen);
925 SPIM_CHCFG_REG = rdval1;
926 spiWaitIdle();
927 SPIM_CHCFG_REG |= SPI_CS_HIGH;
928
929 SPIM_CHCFG_REG = 0x00000000;
930 SPIM_MODECFG_REG = 0x00000000;
931 } else {
932 if (len > SPI_DMA_BUF_MAX_SIZE) {
933 TLS_DBGPRT_ERR("\nwrite len too long\n");
934 tls_close_peripheral_clock(TLS_PERIPHERAL_TYPE_LSPI);
935 tls_os_sem_release(spi_port->lock);
936 return TLS_SPI_STATUS_EINVAL;
937 }
938 if (SPI_DMA_BUF_ADDR) {
939 MEMCPY((u8 *) SPI_DMA_BUF_ADDR, buf, len);
940 SpiDmaBlockWrite((u8 *) SPI_DMA_BUF_ADDR, len, 0, 0);
941 } else {
942 tls_close_peripheral_clock(TLS_PERIPHERAL_TYPE_LSPI);
943 tls_os_sem_release(spi_port->lock);
944 return TLS_SPI_STATUS_ENOMEM;
945 }
946 }
947 tls_close_peripheral_clock(TLS_PERIPHERAL_TYPE_LSPI);
948 tls_os_sem_release(spi_port->lock);
949 return TLS_SPI_STATUS_OK;
950 }
951
952 #endif
953 memset_s(&t, sizeof(t), 0, sizeof(t));
954 t.tx_buf = buf;
955 t.len = len;
956
957 spi_message_init(&m);
958
959 dl_list_add_tail(&m.transfers, &t.transfer_list);
960
961 return tls_spi_sync(&m);
962 }
963
964 /**
965 * @brief This function is used to synchronous write 32bit command then write data by SPI.
966 *
967 * @param[in] cmd is the command data.
968 * @param[in] n_cmd is the command len,can not bigger than four
969 * @param[in] txbuf is the write data buffer.
970 * @param[in] n_tx is the write data length.
971 *
972 * @retval TLS_SPI_STATUS_OK if write success.
973 * @retval TLS_SPI_STATUS_EINVAL if argument is invalid.
974 * @retval TLS_SPI_STATUS_ENOMEM if there is no enough memory.
975 * @retval TLS_SPI_STATUS_ESHUTDOWN if SPI driver does not installed.
976 *
977 * @note None
978 */
tls_spi_write_with_cmd(const u8 * cmd,u32 n_cmd,const u8 * txbuf,u32 n_tx)979 int tls_spi_write_with_cmd(const u8 * cmd, u32 n_cmd, const u8 * txbuf,
980 u32 n_tx)
981 {
982 int status;
983 struct tls_spi_message message;
984 struct tls_spi_transfer x[2];
985
986 if ((cmd == NULL) || (n_cmd == 0) || (txbuf == NULL) || (n_tx == 0)) {
987 return TLS_SPI_STATUS_EINVAL;
988 }
989
990 #ifdef SPI_USE_DMA
991 if (SPI_USE_DMA_TRANSFER == spi_port->transtype) {
992 if (n_tx > SPI_DMA_BUF_MAX_SIZE) {
993 TLS_DBGPRT_ERR("\nwriten len too long\n");
994 return TLS_SPI_STATUS_EINVAL;
995 }
996 tls_os_sem_acquire(spi_port->lock, 0);
997 tls_open_peripheral_clock(TLS_PERIPHERAL_TYPE_LSPI);
998 if (SPI_DMA_BUF_ADDR) {
999 MEMCPY((u8 *) SPI_DMA_BUF_ADDR, (u8 *) cmd, n_cmd);
1000 MEMCPY((u8 *) (SPI_DMA_BUF_ADDR + n_cmd), txbuf, n_tx);
1001 SpiDmaBlockWrite((u8 *) SPI_DMA_BUF_ADDR, (n_cmd + n_tx), 0, 0);
1002 status = TLS_SPI_STATUS_OK;
1003 } else {
1004 status = TLS_SPI_STATUS_ENOMEM;
1005 }
1006 tls_close_peripheral_clock(TLS_PERIPHERAL_TYPE_LSPI);
1007 tls_os_sem_release(spi_port->lock);
1008 return status;
1009 }
1010 #endif
1011
1012 spi_message_init(&message);
1013
1014 memset_s(x, sizeof(x), 0, sizeof(x));
1015 if (n_cmd) {
1016 x[0].len = n_cmd;
1017 x[0].tx_buf = (const void *) cmd;
1018 dl_list_add_tail(&message.transfers, &x[0].transfer_list);
1019 }
1020 if (n_tx) {
1021 x[1].len = n_tx;
1022 x[1].tx_buf = txbuf;
1023 dl_list_add_tail(&message.transfers, &x[1].transfer_list);
1024 }
1025
1026 /* do the i/o. */
1027 status = tls_spi_sync(&message);
1028
1029 return status;
1030 }
1031
1032 /**
1033 * @brief
1034 *
1035 * @param message
1036 *
1037 * @return
1038 */
tls_spi_sync(struct tls_spi_message * message)1039 int tls_spi_sync(struct tls_spi_message *message)
1040 {
1041 int status;
1042 u8 err;
1043 tls_os_sem_t *sem;
1044
1045 err = tls_os_sem_create(&sem, 0);
1046 if (err != TLS_OS_SUCCESS) {
1047 TLS_DBGPRT_ERR("create spi transaction synchronizing semaphore fail!\n");
1048 return TLS_SPI_STATUS_ENOMEM;
1049 }
1050
1051 message->context = (void *) sem;
1052 message->complete = spi_complete;
1053
1054 tls_open_peripheral_clock(TLS_PERIPHERAL_TYPE_LSPI);
1055 status = tls_spi_async(message);
1056 if (status == TLS_SPI_STATUS_OK) {
1057 TLS_DBGPRT_SPI_INFO("waiting spi transaction finishing!\n");
1058 tls_os_sem_acquire(sem, 0);
1059 }
1060 tls_close_peripheral_clock(TLS_PERIPHERAL_TYPE_LSPI);
1061
1062 tls_os_sem_delete(sem);
1063 message->context = NULL;
1064 message->complete = NULL;
1065
1066 return status;
1067 }
1068
1069 /**
1070 * @brief
1071 *
1072 * @param message
1073 *
1074 * @return
1075 */
tls_spi_async(struct tls_spi_message * message)1076 int tls_spi_async(struct tls_spi_message *message)
1077 {
1078 u8 need_sched;
1079 struct tls_spi_transfer *transfer;
1080
1081 if (spi_port == NULL) {
1082 TLS_DBGPRT_ERR("spi master driver module not beed installed!\n");
1083 return TLS_SPI_STATUS_ESHUTDOWN;
1084 }
1085
1086 if ((message == NULL) || (dl_list_empty(&message->transfers))) {
1087 TLS_DBGPRT_ERR("@message is NULL or @message->transfers is empty!\n");
1088 return TLS_SPI_STATUS_EINVAL;
1089 }
1090
1091 dl_list_for_each(transfer, &message->transfers, struct tls_spi_transfer,
1092 transfer_list)
1093 {
1094 if (transfer->len == 0) {
1095 TLS_DBGPRT_ERR("\"@transfer->len\" belong to @message is 0!\n");
1096 return TLS_SPI_STATUS_EINVAL;
1097 }
1098 }
1099
1100 tls_os_sem_acquire(spi_port->lock, 0);
1101
1102 if (dl_list_empty(&spi_port->wait_queue)) {
1103 need_sched = 1;
1104 } else {
1105 need_sched = 0;
1106 }
1107 message->status = SPI_MESSAGE_STATUS_IDLE;
1108 dl_list_add_tail(&spi_port->wait_queue, &message->queue);
1109
1110 tls_os_sem_release(spi_port->lock);
1111
1112 if (need_sched == 1) {
1113 tls_spi_queue_send(SPI_SCHED_MSG_START_ENGINE);
1114 }
1115
1116 return TLS_SPI_STATUS_OK;
1117 }
1118
1119 /**
1120 * @brief This function is used to initialize the SPI master driver.
1121 *
1122 * @param[in] None
1123 *
1124 * @retval TLS_SPI_STATUS_OK if initialize success
1125 * @retval TLS_SPI_STATUS_EBUSY if SPI is already initialized
1126 * @retval TLS_SPI_STATUS_ENOMEM if malloc SPI memory fail
1127 *
1128 * @note None
1129 */
tls_spi_init(void)1130 int tls_spi_init(void)
1131 {
1132 u8 err;
1133 struct tls_spi_port *port;
1134
1135 if (spi_port != NULL) {
1136 TLS_DBGPRT_ERR("spi driver module has been installed!\n");
1137 return TLS_SPI_STATUS_EBUSY;
1138 }
1139
1140 TLS_DBGPRT_SPI_INFO("initialize spi master driver module.\n");
1141
1142 port = (struct tls_spi_port *) tls_mem_alloc(sizeof(struct tls_spi_port));
1143 if (port == NULL) {
1144 TLS_DBGPRT_ERR("allocate \"struct tls_spi_port\" fail!\n");
1145 return TLS_SPI_STATUS_ENOMEM;
1146 }
1147 memset_s(port, sizeof(port), 0, sizeof(struct tls_spi_port));
1148 err = tls_os_sem_create(&port->lock, 1);
1149 if (err != TLS_OS_SUCCESS) {
1150 TLS_DBGPRT_ERR("create semaphore @spi_port->lock fail!\n");
1151 tls_mem_free(port);
1152 return TLS_SPI_STATUS_ENOMEM;
1153 }
1154
1155 port->speed_hz = SPI_DEFAULT_SPEED;
1156 port->cs_active = SPI_CS_ACTIVE_MODE;
1157 port->mode = SPI_DEFAULT_MODE; /* CPHA = 0,CPOL = 0 */
1158 port->reconfig = 0;
1159
1160 dl_list_init(&port->wait_queue);
1161
1162 port->current_message = NULL;
1163 port->current_remaining_transfer = 0;
1164 port->current_transfer = NULL;
1165 port->current_remaining_bytes = 0;
1166
1167 spi_port = port;
1168
1169 TLS_DBGPRT_SPI_INFO("initialize spi master controller.\n");
1170 tls_open_peripheral_clock(TLS_PERIPHERAL_TYPE_LSPI);
1171
1172 spi_clear_fifo();
1173 spi_set_endian(1);
1174 tls_spi_trans_type(SPI_BYTE_TRANSFER);
1175 spi_set_mode(spi_port->mode);
1176 spi_set_chipselect_mode(SPI_CS_INACTIVE_MODE);
1177 spi_force_cs_out(1);
1178 spi_set_sclk(spi_port->speed_hz);
1179
1180 spi_set_tx_trigger_level(0);
1181 spi_set_rx_trigger_level(7);
1182
1183 spi_set_rx_channel(1);
1184 spi_set_tx_channel(1);
1185 spi_unmask_int(SPI_INT_TRANSFER_DONE);
1186 tls_close_peripheral_clock(TLS_PERIPHERAL_TYPE_LSPI);
1187
1188 TLS_DBGPRT_SPI_INFO("register spi master interrupt handler.\n");
1189 tls_irq_enable(SPI_LS_IRQn);
1190
1191 TLS_DBGPRT_SPI_INFO("spi master driver module initialization finish.\n");
1192
1193 return TLS_SPI_STATUS_OK;
1194 }
1195
tls_spi_task_init(void)1196 int tls_spi_task_init(void)
1197 {
1198 u8 err;
1199 if (spi_port == NULL) {
1200 return TLS_SPI_STATUS_ENOMEM;
1201 }
1202
1203 if (spi_port->msg_queue) {
1204 return TLS_SPI_STATUS_OK;
1205 }
1206
1207 err = tls_os_queue_create(&spi_port->msg_queue, MSG_QUEUE_SIZE);
1208 if (err != TLS_OS_SUCCESS) {
1209 TLS_DBGPRT_ERR("create message queue @spi_port->msg_queue fail!\n");
1210 return TLS_SPI_STATUS_ENOMEM;
1211 }
1212 #if TLS_OS_LITEOS
1213 err = tls_os_task_create(NULL, "hostspi",
1214 spi_scheduler,
1215 (void *) spi_port,
1216 (void *) NULL,
1217 SPI_SCHEDULER_STK_SIZE * sizeof(u32),
1218 TLS_SPI_SCHEDULER_TASK_PRIO, 0);
1219 if (err != TLS_OS_SUCCESS) {
1220 TLS_DBGPRT_ERR("create spi master driver scheduler task fail!\n");
1221 tls_os_queue_delete(spi_port->msg_queue);
1222 return TLS_SPI_STATUS_ENOMEM;
1223 }
1224 #else
1225 spi_scheduler_stk = tls_mem_alloc(SPI_SCHEDULER_STK_SIZE * sizeof(u32));
1226 if (spi_scheduler_stk == NULL) {
1227 tls_os_queue_delete(spi_port->msg_queue);
1228 TLS_DBGPRT_ERR("spi_scheduler_stk allocated fail!\n");
1229 return TLS_SPI_STATUS_ENOMEM;
1230 }
1231 err = tls_os_task_create(NULL, "hostspi",
1232 spi_scheduler,
1233 (void *) spi_port,
1234 (void *) spi_scheduler_stk,
1235 SPI_SCHEDULER_STK_SIZE * sizeof(u32),
1236 TLS_SPI_SCHEDULER_TASK_PRIO, 0);
1237 if (err != TLS_OS_SUCCESS) {
1238 TLS_DBGPRT_ERR("create spi master driver scheduler task fail!\n");
1239 tls_os_queue_delete(spi_port->msg_queue);
1240 tls_mem_free(spi_scheduler_stk);
1241 spi_scheduler_stk = NULL;
1242 return TLS_SPI_STATUS_ENOMEM;
1243 }
1244 #endif
1245
1246 return TLS_SPI_STATUS_OK;
1247 }
1248
tls_spi_queue_send(u32 msg)1249 void tls_spi_queue_send(u32 msg)
1250 {
1251 if (TLS_SPI_STATUS_OK == tls_spi_task_init()) {
1252 tls_os_queue_send(spi_port->msg_queue, (void *) msg, 4); // 4:msg_size
1253 }
1254 }
1255
1256 /**
1257 * @brief
1258 *
1259 * @return
1260 */
tls_spi_exit(void)1261 int tls_spi_exit(void)
1262 {
1263 TLS_DBGPRT_SPI_INFO("Not support spi master driver module uninstalled!\n");
1264 return TLS_SPI_STATUS_EPERM;
1265 }
1266
1267 /**********************************************************************************************************
1268 * Description: This function is used to select SPI slave type.
1269 *
1270 * Arguments : slave is the slave type,defined as follow:
1271 * slave == SPI_SLAVE_FLASH :flash
1272 * slave == SPI_SLAVE_CARD : sd card
1273 *
1274 * Returns : Before communicate with different SPI device, must call the function.
1275 **********************************************************************************************************/
tls_spi_slave_sel(u16 slave)1276 void tls_spi_slave_sel(u16 slave)
1277 {
1278 tls_gpio_cfg((enum tls_io_name) SPI_SLAVE_CONTROL_PIN, WM_GPIO_DIR_OUTPUT,
1279 WM_GPIO_ATTR_FLOATING);
1280 if (SPI_SLAVE_FLASH == slave) {
1281 tls_gpio_write((enum tls_io_name) SPI_SLAVE_CONTROL_PIN, 0);
1282 } else if (SPI_SLAVE_CARD == slave) {
1283 tls_gpio_write((enum tls_io_name) SPI_SLAVE_CONTROL_PIN, 1);
1284 }
1285 }
1286
1287 /**********************************************************************************************************
1288 * Description: This function is used to spi data tx/rx without irq.
1289 *
1290 * Arguments : data_out-------data to be sent to slave
1291 * data_in -------data to be received from slave
1292 * num_out -------number to be sent to slave unit:byte
1293 * num_in -------number to be received from slave unit:byte
1294 * Returns : Before communicate with different SPI device, must call the function.
1295 **********************************************************************************************************/
tls_spi_xfer(const void * data_out,void * data_in,uint32_t num_out,uint32_t num_in)1296 int32_t tls_spi_xfer(const void *data_out, void *data_in, uint32_t num_out, uint32_t num_in)
1297 {
1298 int ret = 0;
1299 uint32_t length = 0;
1300 uint32_t remain_length ;
1301 uint32_t int_status;
1302 struct tls_spi_transfer tls_transfer;
1303 uint32_t tot_num = 0;
1304
1305 if (data_in == NULL || num_out == 0 || num_in == 0 || data_out == NULL) {
1306 return -1;
1307 }
1308 tls_open_peripheral_clock(TLS_PERIPHERAL_TYPE_LSPI);
1309 tls_transfer.tx_buf = data_out;
1310 tls_transfer.rx_buf = data_in;
1311
1312 tot_num = (num_out > num_in) ? num_out : num_in;
1313 remain_length = tot_num;
1314 tls_transfer.len = tot_num;
1315 tls_irq_disable(SPI_LS_IRQn);
1316 length = spi_fill_txfifo(&tls_transfer, remain_length);
1317 spi_set_sclk_length(length * 8, 0);
1318 spi_sclk_start();
1319
1320 while (remain_length > 0) {
1321 while (spi_get_busy_status() == 1);
1322 length = spi_get_rxfifo(&tls_transfer, remain_length);
1323 remain_length -= length;
1324
1325 if (remain_length == 0) {
1326 while (spi_get_busy_status() == 1);
1327 break;
1328 }
1329 while (spi_get_busy_status() == 1);
1330 length = spi_fill_txfifo(&tls_transfer, remain_length);
1331 if (length) {
1332 spi_set_sclk_length(length * 8, 0);
1333 spi_sclk_start();
1334 }
1335 }
1336
1337 while (spi_get_busy_status() == 1);
1338 int_status = spi_get_int_status();
1339 spi_clear_int_status(int_status);
1340 tls_irq_enable(SPI_LS_IRQn);
1341 tls_close_peripheral_clock(TLS_PERIPHERAL_TYPE_LSPI);
1342
1343 return (ret == TLS_SPI_STATUS_OK) ? 0 : -1;
1344 }