• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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