1 // Copyright (C) 2022 Beken Corporation
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 <driver/dma.h>
16 #include <driver/gpio.h>
17 #include <driver/int.h>
18 #include <driver/spi.h>
19 #include "clock_driver.h"
20 #include "dma_hal.h"
21 #include "gpio_driver.h"
22 #include "icu_driver.h"
23 #include <common/bk_include.h>
24 #include <os/mem.h>
25 #include "power_driver.h"
26 #include <os/os.h>
27 #include "spi_driver.h"
28 #include "spi_hal.h"
29 #include "spi_statis.h"
30 #include "spi_config.h"
31 #include "sys_driver.h"
32
33 typedef struct {
34 spi_hal_t hal;
35 uint8_t id_init_bits;
36 uint8_t * tx_buf;
37 uint32_t tx_size;
38 uint8_t * rx_buf;
39 uint32_t rx_size;
40 volatile uint32_t rx_offset;
41 bool is_tx_blocked;
42 bool is_sw_tx_finished;
43 bool is_rx_blocked;
44 beken_semaphore_t tx_sema;
45 beken_semaphore_t rx_sema;
46 dma_id_t spi_tx_dma_chan;
47 dma_id_t spi_rx_dma_chan;
48 } spi_driver_t;
49
50 typedef struct {
51 spi_isr_t callback;
52 void *param;
53 } spi_callback_t;
54
55 #define SPI_RETURN_ON_NOT_INIT() do {\
56 if (!s_spi_driver_is_init) {\
57 SPI_LOGE("SPI driver not init\r\n");\
58 return BK_ERR_SPI_NOT_INIT;\
59 }\
60 } while(0)
61
62 #define SPI_RETURN_ON_ID_NOT_INIT(id) do {\
63 if (!s_spi[id].id_init_bits) {\
64 SPI_LOGE("SPI(%d) not init\r\n", id);\
65 return BK_ERR_SPI_ID_NOT_INIT;\
66 }\
67 } while(0)
68
69 #define SPI_RETURN_ON_INVALID_ID(id) do {\
70 if ((id) >= SOC_SPI_UNIT_NUM) {\
71 SPI_LOGE("SPI id number(%d) is invalid\r\n", (id));\
72 return BK_ERR_SPI_INVALID_ID;\
73 }\
74 } while(0)
75
76 #define SPI_SET_PIN(id) do {\
77 gpio_dev_unmap(SPI##id##_LL_CSN_PIN);\
78 gpio_dev_unmap(SPI##id##_LL_SCK_PIN);\
79 gpio_dev_unmap(SPI##id##_LL_MOSI_PIN);\
80 gpio_dev_unmap(SPI##id##_LL_MISO_PIN);\
81 gpio_dev_map(SPI##id##_LL_CSN_PIN, GPIO_DEV_SPI##id##_CSN);\
82 gpio_dev_map(SPI##id##_LL_SCK_PIN, GPIO_DEV_SPI##id##_SCK);\
83 gpio_dev_map(SPI##id##_LL_MOSI_PIN, GPIO_DEV_SPI##id##_MOSI);\
84 gpio_dev_map(SPI##id##_LL_MISO_PIN, GPIO_DEV_SPI##id##_MISO);\
85 bk_gpio_pull_up(SPI##id##_LL_CSN_PIN);\
86 bk_gpio_pull_up(SPI##id##_LL_SCK_PIN);\
87 } while(0)
88
89 static spi_driver_t s_spi[SOC_SPI_UNIT_NUM] = {0};
90 static bool s_spi_driver_is_init = false;
91 static volatile spi_id_t s_current_spi_dma_wr_id;
92 static volatile spi_id_t s_current_spi_dma_rd_id;
93 static spi_callback_t s_spi_rx_isr[SOC_SPI_UNIT_NUM] = {NULL};
94 static spi_callback_t s_spi_tx_finish_isr[SOC_SPI_UNIT_NUM] = {NULL};
95 static spi_callback_t s_spi_rx_finish_isr[SOC_SPI_UNIT_NUM] = {NULL};
96
97 static void spi_isr(void);
98 #if (SOC_SPI_UNIT_NUM > 1)
99 static void spi2_isr(void);
100 #endif
101 #if (SOC_SPI_UNIT_NUM > 2)
102 static void spi3_isr(void);
103 #endif
104
spi_init_gpio(spi_id_t id)105 static void spi_init_gpio(spi_id_t id)
106 {
107 switch (id) {
108 case SPI_ID_0:
109 SPI_SET_PIN(0);
110 break;
111 #if (SOC_SPI_UNIT_NUM > 1)
112 case SPI_ID_1:
113 SPI_SET_PIN(1);
114 break;
115 #endif
116 #if (SOC_SPI_UNIT_NUM > 2)
117 case SPI_ID_2:
118 SPI_SET_PIN(2);
119 break;
120 #endif
121 default:
122 break;
123 }
124 #if (!CONFIG_SYSTEM_CTRL)
125 gpio_spi_sel(GPIO_SPI_MAP_MODE1);
126 #endif
127 }
128
129 #if (CONFIG_SYSTEM_CTRL)
spi_clock_enable(spi_id_t id)130 static void spi_clock_enable(spi_id_t id)
131 {
132 switch(id)
133 {
134 case SPI_ID_0:
135 sys_drv_dev_clk_pwr_up(CLK_PWR_ID_SPI_1, CLK_PWR_CTRL_PWR_UP);
136 break;
137 #if (SOC_SPI_UNIT_NUM > 1)
138 case SPI_ID_1:
139 sys_drv_dev_clk_pwr_up(CLK_PWR_ID_SPI_2, CLK_PWR_CTRL_PWR_UP);
140 break;
141 #endif
142 default:
143 break;
144 }
145 }
146
spi_clock_disable(spi_id_t id)147 static void spi_clock_disable(spi_id_t id)
148 {
149 switch(id)
150 {
151 case SPI_ID_0:
152 sys_drv_dev_clk_pwr_up(CLK_PWR_ID_SPI_1, CLK_PWR_CTRL_PWR_DOWN);
153 break;
154 #if (SOC_SPI_UNIT_NUM > 1)
155 case SPI_ID_1:
156 sys_drv_dev_clk_pwr_up(CLK_PWR_ID_SPI_2, CLK_PWR_CTRL_PWR_DOWN);
157 break;
158 #endif
159 default:
160 break;
161 }
162 }
163
spi_interrupt_enable(spi_id_t id)164 static void spi_interrupt_enable(spi_id_t id)
165 {
166 switch(id)
167 {
168 case SPI_ID_0:
169 sys_drv_int_enable(SPI_INTERRUPT_CTRL_BIT);
170 break;
171 #if (SOC_SPI_UNIT_NUM > 1)
172 case SPI_ID_1:
173 sys_drv_int_enable(SPI1_INTERRUPT_CTRL_BIT);
174 break;
175 #endif
176 default:
177 break;
178 }
179 }
180
spi_interrupt_disable(spi_id_t id)181 static void spi_interrupt_disable(spi_id_t id)
182 {
183 switch(id)
184 {
185 case SPI_ID_0:
186 sys_drv_int_disable(SPI_INTERRUPT_CTRL_BIT);
187 break;
188 #if (SOC_SPI_UNIT_NUM > 1)
189 case SPI_ID_1:
190 sys_drv_int_disable(SPI1_INTERRUPT_CTRL_BIT);
191 break;
192 #endif
193 default:
194 break;
195 }
196 }
197 #endif
198
199 /* 1. power up spi
200 * 2. set clk
201 * 3. set gpio as spi
202 * 4. icu enable interrupt
203 */
spi_id_init_common(spi_id_t id)204 static bk_err_t spi_id_init_common(spi_id_t id)
205 {
206 int ret = 0;
207
208 #if (CONFIG_SYSTEM_CTRL)
209 spi_clock_enable(id);
210 spi_interrupt_enable(id);
211 #else
212 power_up_spi(id);
213 clk_set_spi_clk_26m(id);
214 icu_enable_spi_interrupt(id);
215 #endif
216 spi_init_gpio(id);
217
218 if (s_spi[id].tx_sema == NULL) {
219 ret = rtos_init_semaphore(&(s_spi[id].tx_sema), 1);
220 BK_ASSERT(kNoErr == ret);
221 }
222 if (s_spi[id].rx_sema == NULL) {
223 ret = rtos_init_semaphore(&(s_spi[id].rx_sema), 1);
224 BK_ASSERT(kNoErr == ret);
225 }
226 s_spi[id].is_tx_blocked = false;
227 s_spi[id].is_sw_tx_finished = true;
228 s_spi[id].is_rx_blocked = false;
229 s_spi[id].id_init_bits |= BIT(id);
230
231 return ret;
232 }
233
spi_id_deinit_common(spi_id_t id)234 static void spi_id_deinit_common(spi_id_t id)
235 {
236 spi_hal_stop_common(&s_spi[id].hal);
237
238 #if (CONFIG_SYSTEM_CTRL)
239 spi_clock_disable(id);
240 spi_interrupt_disable(id);
241 #else
242 icu_disable_spi_interrupt(id);
243 power_down_spi(id);
244 #endif
245 rtos_deinit_semaphore(&(s_spi[id].tx_sema));
246 rtos_deinit_semaphore(&(s_spi[id].rx_sema));
247 s_spi[id].id_init_bits &= ~BIT(id);
248 }
249
spi_id_write_bytes_common(spi_id_t id)250 static void spi_id_write_bytes_common(spi_id_t id)
251 {
252 for (int i = 0; i < s_spi[id].tx_size; i++) {
253 BK_WHILE (!spi_hal_is_tx_fifo_wr_ready(&s_spi[id].hal));
254 spi_hal_write_byte(&s_spi[id].hal, s_spi[id].tx_buf[i]);
255 }
256 }
257
spi_id_read_bytes_common(spi_id_t id)258 static uint32_t spi_id_read_bytes_common(spi_id_t id)
259 {
260 uint8_t data = 0;
261 uint32_t offset = s_spi[id].rx_offset;
262
263 while (spi_hal_read_byte(&s_spi[id].hal, &data) == BK_OK) {
264 if ((s_spi[id].rx_buf) && (offset < s_spi[id].rx_size)) {
265 s_spi[id].rx_buf[offset++] = data;
266 }
267 }
268 s_spi[id].rx_offset = offset;
269 SPI_LOGD("spi offset:%d\r\n", s_spi[id].rx_offset);
270 return offset;
271 }
272
273 #if CONFIG_SPI_DMA
274
spi_dma_tx_finish_handler(dma_id_t id)275 static void spi_dma_tx_finish_handler(dma_id_t id)
276 {
277 SPI_LOGI("[%s] spi_id:%d\r\n", __func__, s_current_spi_dma_wr_id);
278 }
279
spi_dma_rx_finish_handler(dma_id_t id)280 static void spi_dma_rx_finish_handler(dma_id_t id)
281 {
282 SPI_LOGI("[%s] spi_id:%d\r\n", __func__, s_current_spi_dma_rd_id);
283 if (s_spi_rx_finish_isr[s_current_spi_dma_rd_id].callback){
284 s_spi_rx_finish_isr[s_current_spi_dma_rd_id].callback(s_current_spi_dma_rd_id,s_spi_rx_finish_isr[s_current_spi_dma_rd_id].param);
285 }
286 if (s_spi[s_current_spi_dma_rd_id].is_rx_blocked) {
287 rtos_set_semaphore(&s_spi[s_current_spi_dma_rd_id].rx_sema);
288 s_spi[s_current_spi_dma_rd_id].is_rx_blocked = false;
289 }
290 }
291
spi_dma_tx_init(spi_id_t id,dma_id_t spi_tx_dma_chan)292 static void spi_dma_tx_init(spi_id_t id, dma_id_t spi_tx_dma_chan)
293 {
294 dma_config_t dma_config = {0};
295 spi_int_config_t int_cfg_table[] = SPI_INT_CONFIG_TABLE;
296
297 s_spi[id].spi_tx_dma_chan = spi_tx_dma_chan;
298
299 dma_config.mode = DMA_WORK_MODE_SINGLE;
300 dma_config.chan_prio = 0;
301 dma_config.src.dev = DMA_DEV_DTCM;
302 dma_config.src.width = DMA_DATA_WIDTH_32BITS;
303 dma_config.src.addr_inc_en = DMA_ADDR_INC_ENABLE;
304 dma_config.src.addr_loop_en = DMA_ADDR_LOOP_ENABLE;
305 dma_config.dst.width = DMA_DATA_WIDTH_8BITS;
306 dma_config.dst.start_addr = SPI_R_DATA(id);
307 dma_config.dst.dev = int_cfg_table[id].dma_dev;
308
309 BK_LOG_ON_ERR(bk_dma_init(spi_tx_dma_chan, &dma_config));
310 BK_LOG_ON_ERR(bk_dma_register_isr(spi_tx_dma_chan, NULL, spi_dma_tx_finish_handler));
311 BK_LOG_ON_ERR(bk_dma_enable_finish_interrupt(spi_tx_dma_chan));
312 }
313
spi_dma_rx_init(spi_id_t id,dma_id_t spi_rx_dma_chan)314 static void spi_dma_rx_init(spi_id_t id, dma_id_t spi_rx_dma_chan)
315 {
316 dma_config_t dma_config = {0};
317 spi_int_config_t int_cfg_table[] = SPI_INT_CONFIG_TABLE;
318
319 s_spi[id].spi_rx_dma_chan = spi_rx_dma_chan;
320
321 dma_config.mode = DMA_WORK_MODE_SINGLE;
322 dma_config.chan_prio = 0;
323 dma_config.src.dev = int_cfg_table[id].dma_dev;
324 dma_config.src.width = DMA_DATA_WIDTH_8BITS;
325 dma_config.src.start_addr = SPI_R_DATA(id);
326 dma_config.dst.dev = DMA_DEV_DTCM;
327 dma_config.dst.width = DMA_DATA_WIDTH_32BITS;
328 dma_config.dst.addr_inc_en = DMA_ADDR_INC_ENABLE;
329 dma_config.dst.addr_loop_en = DMA_ADDR_LOOP_ENABLE;
330
331 BK_LOG_ON_ERR(bk_dma_init(spi_rx_dma_chan, &dma_config));
332 BK_LOG_ON_ERR(bk_dma_register_isr(spi_rx_dma_chan, NULL, spi_dma_rx_finish_handler));
333 BK_LOG_ON_ERR(bk_dma_enable_finish_interrupt(spi_rx_dma_chan));
334 }
335
336 #endif /* CONFIG_SPI_DMA */
337
bk_spi_driver_init(void)338 bk_err_t bk_spi_driver_init(void)
339 {
340 if (s_spi_driver_is_init) {
341 return BK_OK;
342 }
343
344 spi_int_config_t int_config_table[] = SPI_INT_CONFIG_TABLE;
345
346 os_memset(&s_spi, 0, sizeof(s_spi));
347 os_memset(&s_spi_rx_isr, 0, sizeof(s_spi_rx_isr));
348 os_memset(&s_spi_tx_finish_isr, 0, sizeof(s_spi_tx_finish_isr));
349
350 for (int id = SPI_ID_0; id < SPI_ID_MAX; id++) {
351 spi_int_config_t *cur_int_cfg = &int_config_table[id];
352 bk_int_isr_register(cur_int_cfg->int_src, cur_int_cfg->isr, NULL);
353 s_spi[id].hal.id = id;
354 spi_hal_init(&s_spi[id].hal);
355 }
356 spi_statis_init();
357 s_spi_driver_is_init = true;
358
359 return BK_OK;
360 }
361
bk_spi_driver_deinit(void)362 bk_err_t bk_spi_driver_deinit(void)
363 {
364 if (!s_spi_driver_is_init) {
365 return BK_OK;
366 }
367 spi_int_config_t int_cfg_table[] = SPI_INT_CONFIG_TABLE;
368 for (int id = SPI_ID_0; id < SPI_ID_MAX; id++) {
369 spi_id_deinit_common(id);
370 bk_int_isr_unregister(int_cfg_table[id].int_src);
371 }
372 s_spi_driver_is_init = false;
373
374 return BK_OK;
375 }
376
bk_spi_init(spi_id_t id,const spi_config_t * config)377 bk_err_t bk_spi_init(spi_id_t id, const spi_config_t *config)
378 {
379 BK_RETURN_ON_NULL(config);
380 SPI_RETURN_ON_NOT_INIT();
381 SPI_RETURN_ON_INVALID_ID(id);
382
383 spi_id_init_common(id);
384 spi_hal_configure(&s_spi[id].hal, config);
385 spi_hal_start_common(&s_spi[id].hal);
386 #if (CONFIG_SPI_DMA)
387 if (config->dma_mode) {
388 #if (!CONFIG_SYSTEM_CTRL)
389 gpio_spi_sel(GPIO_SPI_MAP_MODE0);
390 #endif
391 spi_dma_tx_init(id, config->spi_tx_dma_chan);
392 spi_dma_rx_init(id, config->spi_rx_dma_chan);
393 }
394 #endif
395
396 return BK_OK;
397 }
398
399
bk_spi_deinit(spi_id_t id)400 bk_err_t bk_spi_deinit(spi_id_t id)
401 {
402 SPI_RETURN_ON_NOT_INIT();
403 SPI_RETURN_ON_INVALID_ID(id);
404 spi_id_deinit_common(id);
405 return BK_OK;
406 }
407
bk_spi_set_mode(spi_id_t id,spi_mode_t mode)408 bk_err_t bk_spi_set_mode(spi_id_t id, spi_mode_t mode)
409 {
410 SPI_RETURN_ON_NOT_INIT();
411 SPI_RETURN_ON_INVALID_ID(id);
412
413 spi_hal_t *hal = &s_spi[id].hal;
414 switch (mode) {
415 case SPI_POL_MODE_0:
416 spi_hal_set_cpol(hal, SPI_POLARITY_LOW);
417 spi_hal_set_cpha(hal, SPI_PHASE_1ST_EDGE);
418 break;
419 case SPI_POL_MODE_1:
420 spi_hal_set_cpol(hal, SPI_POLARITY_LOW);
421 spi_hal_set_cpha(hal, SPI_PHASE_2ND_EDGE);
422 break;
423 case SPI_POL_MODE_2:
424 spi_hal_set_cpol(hal, SPI_POLARITY_HIGH);
425 spi_hal_set_cpha(hal, SPI_PHASE_1ST_EDGE);
426 break;
427 case SPI_POL_MODE_3:
428 default:
429 spi_hal_set_cpol(hal, SPI_POLARITY_HIGH);
430 spi_hal_set_cpha(hal, SPI_PHASE_2ND_EDGE);
431 break;
432 }
433 return BK_OK;
434 }
435
bk_spi_set_bit_width(spi_id_t id,spi_bit_width_t bit_width)436 bk_err_t bk_spi_set_bit_width(spi_id_t id, spi_bit_width_t bit_width)
437 {
438 SPI_RETURN_ON_NOT_INIT();
439 SPI_RETURN_ON_INVALID_ID(id);
440 spi_hal_set_bit_width(&s_spi[id].hal, bit_width);
441 return BK_OK;
442 }
443
bk_spi_set_wire_mode(spi_id_t id,spi_wire_mode_t wire_mode)444 bk_err_t bk_spi_set_wire_mode(spi_id_t id, spi_wire_mode_t wire_mode)
445 {
446 SPI_RETURN_ON_NOT_INIT();
447 SPI_RETURN_ON_INVALID_ID(id);
448 spi_hal_set_wire_mode(&s_spi[id].hal, wire_mode);
449 return BK_OK;
450 }
451
bk_spi_set_baud_rate(spi_id_t id,uint32_t baud_rate)452 bk_err_t bk_spi_set_baud_rate(spi_id_t id, uint32_t baud_rate)
453 {
454 SPI_RETURN_ON_NOT_INIT();
455 SPI_RETURN_ON_INVALID_ID(id);
456 spi_hal_set_baud_rate(&s_spi[id].hal, baud_rate);
457 return BK_OK;
458 }
459
bk_spi_set_bit_order(spi_id_t id,spi_bit_order_t bit_order)460 bk_err_t bk_spi_set_bit_order(spi_id_t id, spi_bit_order_t bit_order)
461 {
462 SPI_RETURN_ON_NOT_INIT();
463 SPI_RETURN_ON_INVALID_ID(id);
464 spi_hal_set_first_bit(&s_spi[id].hal, bit_order);
465 return BK_OK;
466 }
467
bk_spi_register_rx_isr(spi_id_t id,spi_isr_t isr,void * param)468 bk_err_t bk_spi_register_rx_isr(spi_id_t id, spi_isr_t isr, void *param)
469 {
470 SPI_RETURN_ON_INVALID_ID(id);
471 uint32_t int_level = rtos_disable_int();
472 s_spi_rx_isr[id].callback = isr;
473 s_spi_rx_isr[id].param = param;
474 rtos_enable_int(int_level);
475 return BK_OK;
476 }
477
bk_spi_register_rx_finish_isr(spi_id_t id,spi_isr_t isr,void * param)478 bk_err_t bk_spi_register_rx_finish_isr(spi_id_t id, spi_isr_t isr, void *param)
479 {
480 SPI_RETURN_ON_INVALID_ID(id);
481 uint32_t int_level = rtos_disable_int();
482 s_spi_rx_finish_isr[id].callback = isr;
483 s_spi_rx_finish_isr[id].param = param;
484 rtos_enable_int(int_level);
485 return BK_OK;
486 }
487
488
bk_spi_register_tx_finish_isr(spi_id_t id,spi_isr_t isr,void * param)489 bk_err_t bk_spi_register_tx_finish_isr(spi_id_t id, spi_isr_t isr, void *param)
490 {
491 SPI_RETURN_ON_INVALID_ID(id);
492 uint32_t int_level = rtos_disable_int();
493 s_spi_tx_finish_isr[id].callback = isr;
494 s_spi_tx_finish_isr[id].param = param;
495 rtos_enable_int(int_level);
496 return BK_OK;
497 }
498
bk_spi_unregister_rx_isr(spi_id_t id)499 bk_err_t bk_spi_unregister_rx_isr(spi_id_t id)
500 {
501 SPI_RETURN_ON_INVALID_ID(id);
502 uint32_t int_level = rtos_disable_int();
503 s_spi_rx_isr[id].callback = NULL;
504 s_spi_rx_isr[id].param = NULL;
505 rtos_enable_int(int_level);
506 return BK_OK;
507 }
508
bk_spi_unregister_rx_finish_isr(spi_id_t id)509 bk_err_t bk_spi_unregister_rx_finish_isr(spi_id_t id)
510 {
511 SPI_RETURN_ON_INVALID_ID(id);
512 uint32_t int_level = rtos_disable_int();
513 s_spi_rx_finish_isr[id].callback = NULL;
514 s_spi_rx_finish_isr[id].param = NULL;
515 rtos_enable_int(int_level);
516 return BK_OK;
517 }
518
519
bk_spi_unregister_tx_finish_isr(spi_id_t id)520 bk_err_t bk_spi_unregister_tx_finish_isr(spi_id_t id)
521 {
522 SPI_RETURN_ON_INVALID_ID(id);
523 uint32_t int_level = rtos_disable_int();
524 s_spi_tx_finish_isr[id].callback = NULL;
525 s_spi_tx_finish_isr[id].param = NULL;
526 rtos_enable_int(int_level);
527 return BK_OK;
528 }
529
530
bk_spi_write_bytes(spi_id_t id,const void * data,uint32_t size)531 bk_err_t bk_spi_write_bytes(spi_id_t id, const void *data, uint32_t size)
532 {
533 SPI_RETURN_ON_NOT_INIT();
534 SPI_RETURN_ON_INVALID_ID(id);
535 SPI_RETURN_ON_ID_NOT_INIT(id);
536 BK_RETURN_ON_NULL(data);
537
538 uint32_t int_level = rtos_disable_int();
539 s_spi[id].tx_buf = (uint8_t *)data;
540 s_spi[id].tx_size = size;
541 s_spi[id].is_sw_tx_finished = false;
542 s_spi[id].is_tx_blocked = true;
543 s_spi[id].rx_size = size;
544 s_spi[id].rx_offset = 0;
545 spi_hal_clear_tx_fifo(&s_spi[id].hal);
546 spi_hal_set_tx_trans_len(&s_spi[id].hal, size);
547 #if CONFIG_SPI_SUPPORT_TX_FIFO_WR_READY
548 spi_hal_disable_tx_fifo_int(&s_spi[id].hal);
549 #else
550 spi_hal_enable_tx_fifo_int(&s_spi[id].hal);
551 #endif
552 spi_hal_enable_tx(&s_spi[id].hal);
553 rtos_enable_int(int_level);
554
555 #if CONFIG_SPI_SUPPORT_TX_FIFO_WR_READY
556 s_spi[id].is_sw_tx_finished = true;
557 spi_id_write_bytes_common(id); /* to solve slave write */
558 #endif
559
560 rtos_get_semaphore(&s_spi[id].tx_sema, BEKEN_NEVER_TIMEOUT);
561
562 int_level = rtos_disable_int();
563 spi_hal_disable_tx_fifo_int(&s_spi[id].hal);
564 spi_hal_disable_tx(&s_spi[id].hal);
565 rtos_enable_int(int_level);
566
567 return BK_OK;
568 }
569
bk_spi_read_bytes(spi_id_t id,void * data,uint32_t size)570 bk_err_t bk_spi_read_bytes(spi_id_t id, void *data, uint32_t size)
571 {
572 SPI_RETURN_ON_NOT_INIT();
573 SPI_RETURN_ON_INVALID_ID(id);
574 SPI_RETURN_ON_ID_NOT_INIT(id);
575 BK_RETURN_ON_NULL(data);
576
577 uint32_t int_level = rtos_disable_int();
578 s_spi[id].rx_size = size;
579 s_spi[id].rx_buf = (uint8_t *)data;
580 s_spi[id].rx_offset = 0;
581 s_spi[id].is_rx_blocked = true;
582 spi_hal_set_rx_trans_len(&s_spi[id].hal, size);
583 spi_hal_clear_rx_fifo(&s_spi[id].hal);
584 spi_hal_enable_rx_fifo_int(&s_spi[id].hal);
585 spi_hal_enable_rx_finish_int(&s_spi[id].hal);
586 spi_hal_enable_rx(&s_spi[id].hal);
587 #if !CONFIG_SPI_SUPPORT_TX_FIFO_WR_READY
588 /* special for bk7251, bk7251 need enable tx fifo int, otherwize spi_isr will not triggered */
589 spi_hal_enable_tx_fifo_int(&s_spi[id].hal);
590 #endif
591 rtos_enable_int(int_level);
592
593 rtos_get_semaphore(&(s_spi[id].rx_sema), BEKEN_NEVER_TIMEOUT);
594
595 int_level = rtos_disable_int();
596 spi_hal_disable_rx(&s_spi[id].hal);
597 spi_hal_disable_tx_fifo_int(&s_spi[id].hal);
598 spi_hal_disable_rx_fifo_int(&s_spi[id].hal);
599 s_spi[id].rx_size = 0;
600 s_spi[id].rx_offset = 0;
601 s_spi[id].rx_buf = NULL;
602 rtos_enable_int(int_level);
603
604 return BK_OK;
605 }
606
bk_spi_transmit(spi_id_t id,const void * tx_data,uint32_t tx_size,void * rx_data,uint32_t rx_size)607 bk_err_t bk_spi_transmit(spi_id_t id, const void *tx_data, uint32_t tx_size, void *rx_data, uint32_t rx_size)
608 {
609 SPI_RETURN_ON_INVALID_ID(id);
610 SPI_RETURN_ON_ID_NOT_INIT(id);
611
612 if (tx_size && tx_data) {
613 BK_LOG_ON_ERR(bk_spi_write_bytes(id, tx_data, tx_size));
614 }
615
616 if (rx_size && rx_data) {
617 BK_LOG_ON_ERR(bk_spi_read_bytes(id, rx_data, rx_size));
618 }
619
620 return BK_OK;
621 }
622
623
bk_spi_clr_tx(spi_id_t id)624 bk_err_t bk_spi_clr_tx(spi_id_t id)
625 {
626 spi_hal_disable_tx_fifo_int(&s_spi[id].hal);
627 spi_hal_disable_tx(&s_spi[id].hal);
628 return BK_OK;
629 }
630
bk_spi_clr_rx(spi_id_t id)631 bk_err_t bk_spi_clr_rx(spi_id_t id)
632 {
633 spi_hal_disable_rx(&s_spi[id].hal);
634 spi_hal_disable_tx_fifo_int(&s_spi[id].hal);
635 spi_hal_disable_rx_fifo_int(&s_spi[id].hal);
636 s_spi[id].rx_size = 0;
637 s_spi[id].rx_offset = 0;
638 s_spi[id].rx_buf = NULL;
639 return BK_OK;
640 }
641
642
bk_spi_write_bytes_async(spi_id_t id,const void * data,uint32_t size)643 bk_err_t bk_spi_write_bytes_async(spi_id_t id, const void *data, uint32_t size)
644 {
645 SPI_RETURN_ON_NOT_INIT();
646 SPI_RETURN_ON_INVALID_ID(id);
647 SPI_RETURN_ON_ID_NOT_INIT(id);
648 BK_RETURN_ON_NULL(data);
649
650 uint32_t int_level = rtos_disable_int();
651 s_spi[id].tx_buf = (uint8_t *)data;
652 s_spi[id].tx_size = size;
653 s_spi[id].is_sw_tx_finished = false;
654 s_spi[id].is_tx_blocked = false;
655 s_spi[id].rx_size = size;
656 s_spi[id].rx_offset = 0;
657 spi_hal_clear_tx_fifo(&s_spi[id].hal);
658 spi_hal_set_tx_trans_len(&s_spi[id].hal, size);
659 #if CONFIG_SPI_SUPPORT_TX_FIFO_WR_READY
660 spi_hal_disable_tx_fifo_int(&s_spi[id].hal);
661 #else
662 spi_hal_enable_tx_fifo_int(&s_spi[id].hal);
663 #endif
664 spi_hal_enable_tx(&s_spi[id].hal);
665 rtos_enable_int(int_level);
666
667 #if CONFIG_SPI_SUPPORT_TX_FIFO_WR_READY
668 s_spi[id].is_sw_tx_finished = true;
669 spi_id_write_bytes_common(id); /* to solve slave write */
670 #endif
671
672 return BK_OK;
673 }
674
bk_spi_read_bytes_async(spi_id_t id,void * data,uint32_t size)675 bk_err_t bk_spi_read_bytes_async(spi_id_t id, void *data, uint32_t size)
676 {
677 SPI_RETURN_ON_NOT_INIT();
678 SPI_RETURN_ON_INVALID_ID(id);
679 SPI_RETURN_ON_ID_NOT_INIT(id);
680 BK_RETURN_ON_NULL(data);
681
682 uint32_t int_level = rtos_disable_int();
683 s_spi[id].rx_size = size;
684 s_spi[id].rx_buf = (uint8_t *)data;
685 s_spi[id].rx_offset = 0;
686 s_spi[id].is_rx_blocked = false;
687 spi_hal_set_rx_trans_len(&s_spi[id].hal, size);
688 spi_hal_clear_rx_fifo(&s_spi[id].hal);
689 spi_hal_enable_rx_fifo_int(&s_spi[id].hal);
690 spi_hal_enable_rx_finish_int(&s_spi[id].hal);
691 spi_hal_enable_rx(&s_spi[id].hal);
692 #if !CONFIG_SPI_SUPPORT_TX_FIFO_WR_READY
693 /* special for bk7251, bk7251 need enable tx fifo int, otherwize spi_isr will not triggered */
694 spi_hal_enable_tx_fifo_int(&s_spi[id].hal);
695 #endif
696 rtos_enable_int(int_level);
697
698 return BK_OK;
699 }
700
701
702 #if CONFIG_SPI_DMA
703
bk_spi_dma_write_bytes(spi_id_t id,const void * data,uint32_t size)704 bk_err_t bk_spi_dma_write_bytes(spi_id_t id, const void *data, uint32_t size)
705 {
706 BK_RETURN_ON_NULL(data);
707 SPI_RETURN_ON_INVALID_ID(id);
708 SPI_RETURN_ON_ID_NOT_INIT(id);
709
710 uint32_t int_level = rtos_disable_int();
711 s_spi[id].is_tx_blocked = true;
712 s_current_spi_dma_wr_id = id;
713 spi_hal_set_tx_trans_len(&s_spi[id].hal, size);
714 spi_hal_enable_tx(&s_spi[id].hal);
715 rtos_enable_int(int_level);
716 bk_dma_write(s_spi[id].spi_tx_dma_chan, (uint8_t *)data, size);
717
718 rtos_get_semaphore(&s_spi[id].tx_sema, BEKEN_NEVER_TIMEOUT);
719
720 int_level = rtos_disable_int();
721 spi_hal_disable_tx(&s_spi[id].hal);
722 bk_dma_stop(s_spi[id].spi_tx_dma_chan);
723 rtos_enable_int(int_level);
724 return BK_OK;
725 }
726
bk_spi_dma_read_bytes(spi_id_t id,void * data,uint32_t size)727 bk_err_t bk_spi_dma_read_bytes(spi_id_t id, void *data, uint32_t size)
728 {
729 SPI_RETURN_ON_INVALID_ID(id);
730 SPI_RETURN_ON_ID_NOT_INIT(id);
731 BK_RETURN_ON_NULL(data);
732
733 uint32_t int_level = rtos_disable_int();
734 s_current_spi_dma_rd_id = id;
735 s_spi[id].is_rx_blocked = true;
736 spi_hal_set_rx_trans_len(&s_spi[id].hal, size);
737 spi_hal_clear_rx_fifo(&s_spi[id].hal);
738 spi_hal_disable_rx_fifo_int(&s_spi[id].hal);
739 spi_hal_enable_rx(&s_spi[id].hal);
740 rtos_enable_int(int_level);
741 bk_dma_read(s_spi[id].spi_rx_dma_chan, (uint8_t *)data, size);
742
743 rtos_get_semaphore(&s_spi[id].rx_sema, BEKEN_NEVER_TIMEOUT);
744
745 int_level = rtos_disable_int();
746 spi_hal_disable_rx(&s_spi[id].hal);
747 bk_dma_stop(s_spi[id].spi_rx_dma_chan);
748 rtos_enable_int(int_level);
749 return BK_OK;
750 }
751
bk_spi_dma_transmit(spi_id_t id,const void * tx_data,uint32_t tx_size,void * rx_data,uint32_t rx_size)752 bk_err_t bk_spi_dma_transmit(spi_id_t id, const void *tx_data, uint32_t tx_size, void *rx_data, uint32_t rx_size)
753 {
754 SPI_RETURN_ON_INVALID_ID(id);
755 SPI_RETURN_ON_ID_NOT_INIT(id);
756
757 if (tx_size && tx_data) {
758 BK_LOG_ON_ERR(bk_spi_dma_write_bytes(id, tx_data, tx_size));
759 }
760
761 if (rx_size && rx_data) {
762 BK_LOG_ON_ERR(bk_spi_dma_read_bytes(id, rx_data, rx_size));
763 }
764
765 return BK_OK;
766 }
767
768 #endif
769
spi_isr_common(spi_id_t id)770 static void spi_isr_common(spi_id_t id)
771 {
772 spi_hal_t *hal = &s_spi[id].hal;
773 uint8_t rd_data = 0;
774 uint32_t int_status = 0;
775 uint32_t rd_offset = s_spi[id].rx_offset;
776 SPI_STATIS_DEC();
777 SPI_STATIS_GET(spi_statis, id);
778
779 int_status = spi_hal_get_interrupt_status(hal);
780 spi_hal_clear_interrupt_status(hal, int_status);
781
782 SPI_LOGD("int_status:%x\r\n", int_status);
783
784 if (spi_hal_is_rx_fifo_int_triggered_with_status(hal, int_status)) {
785 SPI_STATIS_INC(spi_statis->rx_fifo_isr_cnt);
786 SPI_LOGD("rx fifo int triggered\r\n");
787 spi_id_read_bytes_common(id);
788 if (s_spi_rx_isr[id].callback) {
789 s_spi_rx_isr[id].callback(id, s_spi_rx_isr[id].param);
790 }
791 }
792
793 if (spi_hal_is_rx_finish_int_triggered(hal, int_status)) {
794 SPI_STATIS_INC(spi_statis->rx_finish_isr_cnt);
795 SPI_LOGD("rx fifo finish int triggered\r\n");
796 if (s_spi[id].rx_size && s_spi[id].rx_buf) {
797 while (spi_hal_read_byte(hal, &rd_data) == BK_OK) {
798 if (rd_offset < s_spi[id].rx_size) {
799 s_spi[id].rx_buf[rd_offset++] = rd_data;
800 }
801 }
802 s_spi[id].rx_offset = rd_offset;
803 }
804 bk_spi_clr_rx(id);
805 if (s_spi_rx_finish_isr[id].callback){
806 s_spi_rx_finish_isr[id].callback(s_current_spi_dma_rd_id,s_spi_rx_finish_isr[id].param);
807 }
808 if (s_spi[id].is_rx_blocked) {
809 rtos_set_semaphore(&s_spi[id].rx_sema);
810 s_spi[id].is_rx_blocked = false;
811 }
812 }
813
814 if (spi_hal_is_rx_overflow_int_triggered(hal, int_status)) {
815 SPI_STATIS_INC(spi_statis->rx_overflow_isr_cnt);
816 SPI_LOGW("rx overflow int triggered\r\n");
817 }
818
819 if (spi_hal_is_tx_fifo_int_triggered_with_status(hal, int_status)) {
820 SPI_STATIS_INC(spi_statis->tx_fifo_isr_cnt);
821 SPI_LOGD("tx fifo int triggered\r\n");
822 #if !CONFIG_SPI_SUPPORT_TX_FIFO_WR_READY
823 if ((!s_spi[id].is_sw_tx_finished) &&
824 s_spi[id].tx_size &&
825 s_spi[id].tx_buf) {
826 spi_id_write_bytes_common(id);
827 s_spi[id].is_sw_tx_finished = true;
828 }
829 for (int i = 0; (i < s_spi[id].rx_size) && s_spi[id].rx_buf; i++) {
830 /* bk7251 need spi_hal_write_byte when read byte,
831 * bk7251 master read data will not work without this operation */
832 if (spi_hal_is_master(hal)) {
833 spi_hal_write_byte(hal, 0xff);
834 }
835 if (spi_hal_read_byte(hal, &rd_data) == BK_OK) {
836 SPI_LOGD("tx fifo int read byte\r\n");
837 if (rd_offset < s_spi[id].rx_size) {
838 s_spi[id].rx_buf[rd_offset++] = rd_data;
839 }
840 } else {
841 break;
842 }
843 }
844 s_spi[id].rx_offset = rd_offset;
845 if (s_spi[id].is_sw_tx_finished) {
846 spi_hal_disable_tx_fifo_int(hal);
847 }
848 #endif
849 }
850
851 if (spi_hal_is_tx_finish_int_triggered(hal, int_status) &&
852 s_spi[id].is_sw_tx_finished) {
853 SPI_STATIS_INC(spi_statis->tx_finish_isr_cnt);
854 SPI_LOGD("tx finish int triggered\r\n");
855 if (spi_hal_is_master(hal)) {
856 if (s_spi[id].is_tx_blocked) {
857 rtos_set_semaphore(&s_spi[id].tx_sema);
858 s_spi[id].is_tx_blocked = false;
859 }
860 if (s_spi_tx_finish_isr[id].callback) {
861 s_spi_tx_finish_isr[id].callback(id, s_spi_tx_finish_isr[id].param);
862 }
863 bk_spi_clr_tx(id);
864 } else {
865 SPI_LOGW("tx finish int triggered, but current mode is spi_slave\r\n");
866 }
867 }
868
869 if (spi_hal_is_tx_underflow_int_triggered(hal, int_status)) {
870 SPI_STATIS_INC(spi_statis->tx_underflow_isr_cnt);
871 SPI_LOGW("tx underflow int triggered\r\n");
872 }
873
874 if (spi_hal_is_slave_release_int_triggered(hal, int_status)) {
875 SPI_STATIS_INC(spi_statis->slave_release_isr_cnt);
876 SPI_LOGD("slave cs up int triggered\r\n");
877 if (spi_hal_is_slave(hal)) {
878 if (s_spi[id].is_tx_blocked) {
879 rtos_set_semaphore(&s_spi[id].tx_sema);
880 s_spi[id].is_tx_blocked = false;
881 }
882 if (s_spi_tx_finish_isr[id].callback) {
883 s_spi_tx_finish_isr[id].callback(id, s_spi_tx_finish_isr[id].param);
884 }
885 }
886 if (s_spi[id].is_rx_blocked) {
887 rtos_set_semaphore(&s_spi[id].rx_sema);
888 s_spi[id].is_rx_blocked = false;
889 }
890 }
891 }
892
spi_isr(void)893 static void spi_isr(void)
894 {
895 SPI_STATIS_DEC();
896 SPI_STATIS_GET(spi_statis, SPI_ID_0);
897 SPI_STATIS_INC(spi_statis->spi_isr_cnt);
898 spi_isr_common(SPI_ID_0);
899 }
900
901 #if (SOC_SPI_UNIT_NUM > 1)
902
spi2_isr(void)903 static void spi2_isr(void)
904 {
905 SPI_STATIS_DEC();
906 SPI_STATIS_GET(spi_statis, SPI_ID_1);
907 SPI_STATIS_INC(spi_statis->spi_isr_cnt);
908 spi_isr_common(SPI_ID_1);
909 }
910
911 #endif
912
913 #if (SOC_SPI_UNIT_NUM > 2)
914
spi3_isr(void)915 static void spi3_isr(void)
916 {
917 SPI_STATIS_DEC();
918 SPI_STATIS_GET(spi_statis, SPI_ID_2);
919 SPI_STATIS_INC(spi_statis->spi_isr_cnt);
920 spi_isr_common(SPI_ID_2);
921 }
922
923 #endif
924
925