1 /*
2 * Copyright (c) 2021 HPMicro
3 *
4 * SPDX-License-Identifier: BSD-3-Clause
5 *
6 */
7
8 #include "hpm_common.h"
9 #include "hpm_spi_drv.h"
10
11 #ifndef HPM_SPI_DRV_DEFAULT_RETRY_COUNT
12 /* the waiting time of timeout status is related to retry count and CPU frequency */
13 #define HPM_SPI_DRV_DEFAULT_RETRY_COUNT (5000U)
14 #endif
15
spi_wait_for_idle_status(SPI_Type * ptr)16 hpm_stat_t spi_wait_for_idle_status(SPI_Type *ptr)
17 {
18 uint32_t status;
19 uint32_t retry = 0;
20
21 do {
22 status = ptr->STATUS;
23 if (retry > HPM_SPI_DRV_DEFAULT_RETRY_COUNT) {
24 break;
25 }
26 retry++;
27 } while (status & SPI_STATUS_SPIACTIVE_MASK);
28
29 if (retry > HPM_SPI_DRV_DEFAULT_RETRY_COUNT) {
30 return status_timeout;
31 }
32
33 return status_success;
34 }
35
spi_wait_for_busy_status(SPI_Type * ptr)36 hpm_stat_t spi_wait_for_busy_status(SPI_Type *ptr)
37 {
38 uint32_t status;
39 uint32_t retry = 0;
40
41 do {
42 status = ptr->STATUS;
43 if (retry > HPM_SPI_DRV_DEFAULT_RETRY_COUNT) {
44 break;
45 }
46 retry++;
47 } while (!(status & SPI_STATUS_SPIACTIVE_MASK));
48
49 if (retry > HPM_SPI_DRV_DEFAULT_RETRY_COUNT) {
50 return status_timeout;
51 }
52
53 return status_success;
54 }
55
spi_write_command(SPI_Type * ptr,spi_mode_selection_t mode,spi_control_config_t * config,uint8_t * cmd)56 hpm_stat_t spi_write_command(SPI_Type *ptr, spi_mode_selection_t mode, spi_control_config_t *config, uint8_t *cmd)
57 {
58 if (mode == spi_master_mode) {
59 if (config->master_config.cmd_enable == true) {
60 if (cmd == NULL) {
61 return status_invalid_argument;
62 }
63 ptr->CMD = SPI_CMD_CMD_SET(*cmd);
64 } else {
65 ptr->CMD = SPI_CMD_CMD_SET(0xff); /* Write a dummy byte */
66 }
67 }
68
69 return status_success;
70 }
71
spi_read_command(SPI_Type * ptr,spi_mode_selection_t mode,spi_control_config_t * config,uint8_t * cmd)72 hpm_stat_t spi_read_command(SPI_Type *ptr, spi_mode_selection_t mode, spi_control_config_t *config, uint8_t *cmd)
73 {
74 if (mode == spi_slave_mode) {
75 if (config->slave_config.slave_data_only == false) {
76 if (cmd == NULL) {
77 return status_invalid_argument;
78 }
79 *cmd = (uint8_t)(ptr->CMD & SPI_CMD_CMD_MASK) >> SPI_CMD_CMD_SHIFT;
80 }
81 }
82
83 return status_success;
84 }
85
spi_write_address(SPI_Type * ptr,spi_mode_selection_t mode,spi_control_config_t * config,uint32_t * addr)86 hpm_stat_t spi_write_address(SPI_Type *ptr, spi_mode_selection_t mode, spi_control_config_t *config, uint32_t *addr)
87 {
88 if (mode == spi_master_mode) {
89 if (config->master_config.addr_enable == true) {
90 if (addr == NULL) {
91 return status_invalid_argument;
92 }
93 ptr->ADDR = SPI_ADDR_ADDR_SET(*addr);
94 }
95 }
96
97 return status_success;
98 }
99
spi_write_data(SPI_Type * ptr,uint8_t data_len_in_bytes,uint8_t * buff,uint32_t count)100 hpm_stat_t spi_write_data(SPI_Type *ptr, uint8_t data_len_in_bytes, uint8_t *buff, uint32_t count)
101 {
102 uint32_t status;
103 uint32_t transferred = 0;
104 uint32_t retry = 0;
105 uint32_t temp;
106
107 /* check parameter validity */
108 if (buff == NULL || count == 0) {
109 return status_invalid_argument;
110 }
111
112 if (data_len_in_bytes > 4 || data_len_in_bytes < 1) {
113 return status_invalid_argument;
114 }
115
116 /* data transfer */
117 while (transferred < count) {
118 status = ptr->STATUS;
119 if (!(status & SPI_STATUS_TXFULL_MASK)) {
120 /* write data into the txfifo */
121 temp = 0;
122 for (uint8_t i = 0; i < data_len_in_bytes; i++) {
123 temp += *(buff++) << i * 8;
124 }
125 ptr->DATA = temp;
126 /* transfer count increment */
127 transferred++;
128 retry = 0;
129 } else {
130 if (retry > HPM_SPI_DRV_DEFAULT_RETRY_COUNT) {
131 break;
132 }
133 retry++;
134 }
135 }
136
137 if (retry > HPM_SPI_DRV_DEFAULT_RETRY_COUNT) {
138 /* dummy state may triggers timeout if dummy count, retry count, spi rate and cpu frequency are inappropriate */
139 return status_timeout;
140 }
141
142 return status_success;
143 }
144
spi_read_data(SPI_Type * ptr,uint8_t data_len_in_bytes,uint8_t * buff,uint32_t count)145 hpm_stat_t spi_read_data(SPI_Type *ptr, uint8_t data_len_in_bytes, uint8_t *buff, uint32_t count)
146 {
147 uint32_t status;
148 uint32_t transferred = 0;
149 uint32_t retry = 0;
150 uint32_t temp;
151
152 /* check parameter validity */
153 if (buff == NULL || count == 0) {
154 return status_invalid_argument;
155 }
156
157 if (data_len_in_bytes > 4 || data_len_in_bytes < 1) {
158 return status_invalid_argument;
159 }
160
161 /* data transfer */
162 while (transferred < count) {
163 status = ptr->STATUS;
164 if (!(status & SPI_STATUS_RXEMPTY_MASK)) {
165 /* read data from the txfifo */
166 temp = ptr->DATA;
167 for (uint8_t i = 0; i < data_len_in_bytes; i++) {
168 *(buff++) = (uint8_t)(temp >> (i * 8));
169 }
170 /* transfer count increment */
171 transferred++;
172 retry = 0;
173 } else {
174 if (retry > HPM_SPI_DRV_DEFAULT_RETRY_COUNT) {
175 break;
176 }
177 retry++;
178 }
179 }
180
181 if (retry > HPM_SPI_DRV_DEFAULT_RETRY_COUNT) {
182 /* dummy state may triggers timeout if dummy count, retry count, spi rate and cpu frequency are inappropriate */
183 return status_timeout;
184 }
185
186 return status_success;
187 }
188
spi_write_read_data(SPI_Type * ptr,uint8_t data_len_in_bytes,uint8_t * wbuff,uint32_t wcount,uint8_t * rbuff,uint32_t rcount)189 hpm_stat_t spi_write_read_data(SPI_Type *ptr, uint8_t data_len_in_bytes, uint8_t *wbuff, uint32_t wcount, uint8_t *rbuff, uint32_t rcount)
190 {
191 uint32_t status;
192 uint32_t wtransferred = 0;
193 uint32_t rtransferred = 0;
194 uint32_t retry = 0;
195 uint32_t temp;
196
197 /* check parameter validity */
198 if (wbuff == NULL || wcount == 0 || rbuff == NULL || rcount == 0) {
199 return status_invalid_argument;
200 }
201
202 if (data_len_in_bytes > 4 || data_len_in_bytes < 1) {
203 return status_invalid_argument;
204 }
205
206 /* data transfer */
207 while (wtransferred < wcount || rtransferred < rcount) {
208 status = ptr->STATUS;
209
210 if (wtransferred < wcount) {
211 /* write data into the txfifo */
212 if (!(status & SPI_STATUS_TXFULL_MASK)) {
213 temp = 0;
214 for (uint8_t i = 0; i < data_len_in_bytes; i++) {
215 temp += *(wbuff++) << i * 8;
216 }
217 ptr->DATA = temp;
218 /* transfer count increment */
219 wtransferred++;
220 retry = 0;
221 } else {
222 if (retry > HPM_SPI_DRV_DEFAULT_RETRY_COUNT) {
223 break;
224 }
225 retry++;
226 }
227 }
228
229 if (rtransferred < rcount) {
230 /* read data from the txfifo */
231 if (!(status & SPI_STATUS_RXEMPTY_MASK)) {
232 temp = ptr->DATA;
233 for (uint8_t i = 0; i < data_len_in_bytes; i++) {
234 *(rbuff++) = (uint8_t)(temp >> (i * 8));
235 }
236 /* transfer count increment */
237 rtransferred++;
238 retry = 0;
239 } else {
240 if (retry > HPM_SPI_DRV_DEFAULT_RETRY_COUNT) {
241 break;
242 }
243 retry++;
244 }
245 }
246 }
247
248 if (retry > HPM_SPI_DRV_DEFAULT_RETRY_COUNT) {
249 /* dummy state may triggers timeout if dummy count, retry count, spi rate and cpu frequency are inappropriate */
250 return status_timeout;
251 }
252
253 return status_success;
254 }
255
spi_no_data(SPI_Type * ptr,spi_mode_selection_t mode,spi_control_config_t * config)256 static hpm_stat_t spi_no_data(SPI_Type *ptr, spi_mode_selection_t mode, spi_control_config_t *config)
257 {
258 (void) ptr;
259 if (mode == spi_master_mode) {
260 if (config->master_config.cmd_enable == false && config->master_config.addr_enable == false) {
261 return status_invalid_argument;
262 }
263 }
264 return status_success;
265 }
266
spi_master_get_default_timing_config(spi_timing_config_t * config)267 void spi_master_get_default_timing_config(spi_timing_config_t *config)
268 {
269 config->master_config.cs2sclk = spi_cs2sclk_half_sclk_4;
270 config->master_config.csht = spi_csht_half_sclk_12;
271 }
272
spi_master_get_default_format_config(spi_format_config_t * config)273 void spi_master_get_default_format_config(spi_format_config_t *config)
274 {
275 config->master_config.addr_len_in_bytes = 1;
276 config->common_config.data_len_in_bits = 32;
277 config->common_config.data_merge = false;
278 config->common_config.mosi_bidir = false;
279 config->common_config.lsb = false;
280 config->common_config.mode = spi_master_mode;
281 config->common_config.cpol = spi_sclk_high_idle;
282 config->common_config.cpha = spi_sclk_sampling_even_clk_edges;
283 }
284
spi_slave_get_default_format_config(spi_format_config_t * config)285 void spi_slave_get_default_format_config(spi_format_config_t *config)
286 {
287 config->common_config.data_len_in_bits = 32;
288 config->common_config.data_merge = false;
289 config->common_config.mosi_bidir = false;
290 config->common_config.lsb = false;
291 config->common_config.mode = spi_master_mode;
292 config->common_config.cpol = spi_sclk_high_idle;
293 config->common_config.cpha = spi_sclk_sampling_even_clk_edges;
294 }
295
spi_master_get_default_control_config(spi_control_config_t * config)296 void spi_master_get_default_control_config(spi_control_config_t *config)
297 {
298 config->master_config.cmd_enable = false;
299 config->master_config.addr_enable = false;
300 config->master_config.token_enable = false;
301 config->master_config.token_value = spi_token_value_0x00;
302 config->master_config.addr_phase_fmt = spi_address_phase_format_single_io_mode;
303 config->common_config.tx_dma_enable = false;
304 config->common_config.rx_dma_enable = false;
305 config->common_config.trans_mode = spi_trans_write_only;
306 config->common_config.data_phase_fmt = spi_single_io_mode;
307 config->common_config.dummy_cnt = spi_dummy_count_2;
308 #if defined(SPI_SOC_HAS_CS_SELECT) && (SPI_SOC_HAS_CS_SELECT == 1)
309 config->common_config.cs_index = spi_cs_0;
310 #endif
311 }
312
spi_slave_get_default_control_config(spi_control_config_t * config)313 void spi_slave_get_default_control_config(spi_control_config_t *config)
314 {
315 config->slave_config.slave_data_only = false;
316 config->common_config.tx_dma_enable = false;
317 config->common_config.rx_dma_enable = false;
318 config->common_config.trans_mode = spi_trans_read_only;
319 config->common_config.data_phase_fmt = spi_single_io_mode;
320 config->common_config.dummy_cnt = spi_dummy_count_2;
321 #if defined(SPI_SOC_HAS_CS_SELECT) && (SPI_SOC_HAS_CS_SELECT == 1)
322 config->common_config.cs_index = spi_cs_0;
323 #endif
324 }
325
spi_master_timing_init(SPI_Type * ptr,spi_timing_config_t * config)326 hpm_stat_t spi_master_timing_init(SPI_Type *ptr, spi_timing_config_t *config)
327 {
328 uint8_t sclk_div;
329 uint8_t div_remainder;
330 uint8_t div_integer;
331 if (config->master_config.sclk_freq_in_hz == 0) {
332 return status_invalid_argument;
333 }
334
335 if (config->master_config.clk_src_freq_in_hz > config->master_config.sclk_freq_in_hz) {
336 div_remainder = (config->master_config.clk_src_freq_in_hz % config->master_config.sclk_freq_in_hz);
337 div_integer = (config->master_config.clk_src_freq_in_hz / config->master_config.sclk_freq_in_hz);
338 if ((div_remainder != 0) || ((div_integer % 2) != 0)) {
339 return status_invalid_argument;
340 }
341 sclk_div = (div_integer / 2) - 1;
342 } else {
343 sclk_div = 0xff;
344 }
345
346 ptr->TIMING = SPI_TIMING_CS2SCLK_SET(config->master_config.cs2sclk) |
347 SPI_TIMING_CSHT_SET(config->master_config.csht) |
348 SPI_TIMING_SCLK_DIV_SET(sclk_div);
349
350 return status_success;
351 }
352
spi_format_init(SPI_Type * ptr,spi_format_config_t * config)353 void spi_format_init(SPI_Type *ptr, spi_format_config_t *config)
354 {
355 ptr->TRANSFMT = SPI_TRANSFMT_ADDRLEN_SET(config->master_config.addr_len_in_bytes - 1) |
356 SPI_TRANSFMT_DATALEN_SET(config->common_config.data_len_in_bits - 1) |
357 SPI_TRANSFMT_DATAMERGE_SET(config->common_config.data_merge) |
358 SPI_TRANSFMT_MOSIBIDIR_SET(config->common_config.mosi_bidir) |
359 SPI_TRANSFMT_LSB_SET(config->common_config.lsb) |
360 SPI_TRANSFMT_SLVMODE_SET(config->common_config.mode) |
361 SPI_TRANSFMT_CPOL_SET(config->common_config.cpol) |
362 SPI_TRANSFMT_CPHA_SET(config->common_config.cpha);
363 }
364
spi_control_init(SPI_Type * ptr,spi_control_config_t * config,uint32_t wcount,uint32_t rcount)365 hpm_stat_t spi_control_init(SPI_Type *ptr, spi_control_config_t *config, uint32_t wcount, uint32_t rcount)
366 {
367 if (wcount > SPI_SOC_TRANSFER_COUNT_MAX || rcount > SPI_SOC_TRANSFER_COUNT_MAX) {
368 return status_invalid_argument;
369 }
370
371 /* slave data only mode only works on write read together transfer mode */
372 if (config->slave_config.slave_data_only == true && config->common_config.trans_mode != spi_trans_write_read_together) {
373 return status_invalid_argument;
374 }
375
376 ptr->TRANSCTRL = SPI_TRANSCTRL_SLVDATAONLY_SET(config->slave_config.slave_data_only) |
377 SPI_TRANSCTRL_CMDEN_SET(config->master_config.cmd_enable) |
378 SPI_TRANSCTRL_ADDREN_SET(config->master_config.addr_enable) |
379 SPI_TRANSCTRL_ADDRFMT_SET(config->master_config.addr_phase_fmt) |
380 SPI_TRANSCTRL_TRANSMODE_SET(config->common_config.trans_mode) |
381 SPI_TRANSCTRL_DUALQUAD_SET(config->common_config.data_phase_fmt) |
382 SPI_TRANSCTRL_TOKENEN_SET(config->master_config.token_enable) |
383 SPI_TRANSCTRL_WRTRANCNT_SET(wcount - 1) |
384 SPI_TRANSCTRL_TOKENVALUE_SET(config->master_config.token_value) |
385 SPI_TRANSCTRL_DUMMYCNT_SET(config->common_config.dummy_cnt) |
386 SPI_TRANSCTRL_RDTRANCNT_SET(rcount - 1);
387
388 #if defined(SPI_SOC_HAS_CS_SELECT) && (SPI_SOC_HAS_CS_SELECT == 1)
389 ptr->CTRL = (ptr->CTRL & ~SPI_CTRL_CS_EN_MASK) | SPI_CTRL_CS_EN_SET(config->common_config.cs_index);
390 #endif
391
392 #if defined(SPI_SOC_HAS_NEW_TRANS_COUNT) && (SPI_SOC_HAS_NEW_TRANS_COUNT == 1)
393 ptr->WR_TRANS_CNT = wcount - 1;
394 ptr->RD_TRANS_CNT = rcount - 1;
395 #endif
396
397 /* reset txfifo, rxfifo and control */
398 ptr->CTRL |= SPI_CTRL_TXFIFORST_MASK | SPI_CTRL_RXFIFORST_MASK | SPI_CTRL_SPIRST_MASK;
399
400 return status_success;
401 }
402
spi_transfer(SPI_Type * ptr,spi_control_config_t * config,uint8_t * cmd,uint32_t * addr,uint8_t * wbuff,uint32_t wcount,uint8_t * rbuff,uint32_t rcount)403 hpm_stat_t spi_transfer(SPI_Type *ptr,
404 spi_control_config_t *config,
405 uint8_t *cmd, uint32_t *addr,
406 uint8_t *wbuff, uint32_t wcount, uint8_t *rbuff, uint32_t rcount)
407 {
408 hpm_stat_t stat = status_fail;
409 uint8_t mode, data_len_in_bytes, trans_mode;
410
411 stat = spi_control_init(ptr, config, wcount, rcount);
412 if (stat != status_success) {
413 return stat;
414 }
415
416 /* read data length */
417 data_len_in_bytes = spi_get_data_length_in_bytes(ptr);
418
419 /* read spi control mode */
420 mode = (ptr->TRANSFMT & SPI_TRANSFMT_SLVMODE_MASK) >> SPI_TRANSFMT_SLVMODE_SHIFT;
421
422 /* read spi transfer mode */
423 trans_mode = config->common_config.trans_mode;
424
425 /* write address on master mode */
426 stat = spi_write_address(ptr, mode, config, addr);
427 if (stat != status_success) {
428 return stat;
429 }
430
431 /* write command on master mode */
432 stat = spi_write_command(ptr, mode, config, cmd);
433 if (stat != status_success) {
434 return stat;
435 }
436
437 /* data phase */
438 if (trans_mode == spi_trans_write_read_together) {
439 stat = spi_write_read_data(ptr, data_len_in_bytes, wbuff, wcount, rbuff, rcount);
440 } else if (trans_mode == spi_trans_write_only || trans_mode == spi_trans_dummy_write) {
441 stat = spi_write_data(ptr, data_len_in_bytes, wbuff, wcount);
442 } else if (trans_mode == spi_trans_read_only || trans_mode == spi_trans_dummy_read) {
443 stat = spi_read_data(ptr, data_len_in_bytes, rbuff, rcount);
444 } else if (trans_mode == spi_trans_write_read || trans_mode == spi_trans_write_dummy_read) {
445 stat = spi_write_read_data(ptr, data_len_in_bytes, wbuff, wcount, rbuff, rcount);
446 } else if (trans_mode == spi_trans_read_write || trans_mode == spi_trans_read_dummy_write) {
447 stat = spi_write_read_data(ptr, data_len_in_bytes, wbuff, wcount, rbuff, rcount);
448 } else if (trans_mode == spi_trans_no_data) {
449 stat = spi_no_data(ptr, mode, config);
450 } else {
451 stat = status_invalid_argument;
452 }
453
454 if (stat != status_success) {
455 return stat;
456 }
457
458 /* read command on slave mode */
459 stat = spi_read_command(ptr, mode, config, cmd);
460 if (stat != status_success) {
461 return stat;
462 }
463 /* on the slave mode, if master keeps asserting the cs signal, it's maybe timeout */
464 stat = spi_wait_for_idle_status(ptr);
465 return stat;
466 }
467
spi_setup_dma_transfer(SPI_Type * ptr,spi_control_config_t * config,uint8_t * cmd,uint32_t * addr,uint32_t wcount,uint32_t rcount)468 hpm_stat_t spi_setup_dma_transfer(SPI_Type *ptr,
469 spi_control_config_t *config,
470 uint8_t *cmd, uint32_t *addr,
471 uint32_t wcount, uint32_t rcount)
472 {
473 hpm_stat_t stat = status_fail;
474 uint8_t mode;
475
476 stat = spi_control_init(ptr, config, wcount, rcount);
477 if (stat != status_success) {
478 return stat;
479 }
480
481 if (config->common_config.tx_dma_enable) {
482 ptr->CTRL |= SPI_CTRL_TXDMAEN_MASK;
483 }
484 if (config->common_config.rx_dma_enable) {
485 ptr->CTRL |= SPI_CTRL_RXDMAEN_MASK;
486 }
487
488 /* read spi control mode */
489 mode = (ptr->TRANSFMT & SPI_TRANSFMT_SLVMODE_MASK) >> SPI_TRANSFMT_SLVMODE_SHIFT;
490
491 /* address phase */
492 stat = spi_write_address(ptr, mode, config, addr);
493 if (stat != status_success) {
494 return stat;
495 }
496
497 /* command phase */
498 stat = spi_write_command(ptr, mode, config, cmd);
499 if (stat != status_success) {
500 return stat;
501 }
502
503 return stat;
504 }
505
506
507 #if defined(SPI_SOC_SUPPORT_DIRECTIO) && (SPI_SOC_SUPPORT_DIRECTIO == 1)
spi_directio_enable_output(SPI_Type * ptr,spi_directio_pin_t pin)508 hpm_stat_t spi_directio_enable_output(SPI_Type *ptr, spi_directio_pin_t pin)
509 {
510 hpm_stat_t stat = status_success;
511 switch (pin) {
512 case hold_pin:
513 ptr->DIRECTIO |= SPI_DIRECTIO_HOLD_OE_MASK;
514 break;
515 case wp_pin:
516 ptr->DIRECTIO |= SPI_DIRECTIO_WP_OE_MASK;
517 break;
518 case miso_pin:
519 ptr->DIRECTIO |= SPI_DIRECTIO_MISO_OE_MASK;
520 break;
521 case mosi_pin:
522 ptr->DIRECTIO |= SPI_DIRECTIO_MOSI_OE_MASK;
523 break;
524 case sclk_pin:
525 ptr->DIRECTIO |= SPI_DIRECTIO_SCLK_OE_MASK;
526 break;
527 case cs_pin:
528 ptr->DIRECTIO |= SPI_DIRECTIO_CS_OE_MASK;
529 break;
530 default:
531 stat = status_invalid_argument;
532 break;
533 }
534 return stat;
535 }
536
spi_directio_disable_output(SPI_Type * ptr,spi_directio_pin_t pin)537 hpm_stat_t spi_directio_disable_output(SPI_Type *ptr, spi_directio_pin_t pin)
538 {
539 hpm_stat_t stat = status_success;
540 switch (pin) {
541 case hold_pin:
542 ptr->DIRECTIO &= ~SPI_DIRECTIO_HOLD_OE_MASK;
543 break;
544 case wp_pin:
545 ptr->DIRECTIO &= ~SPI_DIRECTIO_WP_OE_MASK;
546 break;
547 case miso_pin:
548 ptr->DIRECTIO &= ~SPI_DIRECTIO_MISO_OE_MASK;
549 break;
550 case mosi_pin:
551 ptr->DIRECTIO &= ~SPI_DIRECTIO_MOSI_OE_MASK;
552 break;
553 case sclk_pin:
554 ptr->DIRECTIO &= ~SPI_DIRECTIO_SCLK_OE_MASK;
555 break;
556 case cs_pin:
557 ptr->DIRECTIO &= ~SPI_DIRECTIO_CS_OE_MASK;
558 break;
559 default:
560 stat = status_invalid_argument;
561 break;
562 }
563 return stat;
564 }
565
spi_directio_write(SPI_Type * ptr,spi_directio_pin_t pin,bool high)566 hpm_stat_t spi_directio_write(SPI_Type *ptr, spi_directio_pin_t pin, bool high)
567 {
568 hpm_stat_t stat = status_success;
569 switch (pin) {
570 case hold_pin:
571 (high == true) ? (ptr->DIRECTIO |= SPI_DIRECTIO_HOLD_O_MASK) : (ptr->DIRECTIO &= ~SPI_DIRECTIO_HOLD_O_MASK);
572 break;
573 case wp_pin:
574 (high == true) ? (ptr->DIRECTIO |= SPI_DIRECTIO_WP_O_MASK) : (ptr->DIRECTIO &= ~SPI_DIRECTIO_WP_O_MASK);
575 break;
576 case miso_pin:
577 (high == true) ? (ptr->DIRECTIO |= SPI_DIRECTIO_MISO_O_MASK) : (ptr->DIRECTIO &= ~SPI_DIRECTIO_MISO_O_MASK);
578 break;
579 case mosi_pin:
580 (high == true) ? (ptr->DIRECTIO |= SPI_DIRECTIO_MOSI_O_MASK) : (ptr->DIRECTIO &= ~SPI_DIRECTIO_MOSI_O_MASK);
581 break;
582 case sclk_pin:
583 (high == true) ? (ptr->DIRECTIO |= SPI_DIRECTIO_SCLK_O_MASK) : (ptr->DIRECTIO &= ~SPI_DIRECTIO_SCLK_O_MASK);
584 break;
585 case cs_pin:
586 (high == true) ? (ptr->DIRECTIO |= SPI_DIRECTIO_CS_O_MASK) : (ptr->DIRECTIO &= ~SPI_DIRECTIO_CS_O_MASK);
587 break;
588 default:
589 stat = status_invalid_argument;
590 break;
591 }
592 return stat;
593 }
594
spi_directio_read(SPI_Type * ptr,spi_directio_pin_t pin)595 uint8_t spi_directio_read(SPI_Type *ptr, spi_directio_pin_t pin)
596 {
597 uint8_t io_sta = 0;
598 switch (pin) {
599 case hold_pin:
600 io_sta = SPI_DIRECTIO_HOLD_I_GET(ptr->DIRECTIO);
601 break;
602 case wp_pin:
603 io_sta = SPI_DIRECTIO_WP_I_GET(ptr->DIRECTIO);
604 break;
605 case miso_pin:
606 io_sta = SPI_DIRECTIO_MISO_I_GET(ptr->DIRECTIO);
607 break;
608 case mosi_pin:
609 io_sta = SPI_DIRECTIO_MOSI_I_GET(ptr->DIRECTIO);
610 break;
611 case sclk_pin:
612 io_sta = SPI_DIRECTIO_SCLK_I_GET(ptr->DIRECTIO);
613 break;
614 case cs_pin:
615 io_sta = SPI_DIRECTIO_CS_I_GET(ptr->DIRECTIO);
616 break;
617 default:
618 break;
619 }
620 return io_sta;
621 }
622 #endif
623