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 transferred = 0;
148     uint32_t retry = 0;
149     uint32_t temp;
150     uint8_t rx_valid_size = 0;
151     uint8_t j = 0;
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         rx_valid_size = spi_get_rx_fifo_valid_data_size(ptr);
164         if (rx_valid_size > 0) {
165             for (j = 0; j < rx_valid_size; j++) {
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             }
171             /* transfer count increment */
172             transferred += rx_valid_size;
173             retry = 0;
174         } else {
175             if (retry > HPM_SPI_DRV_DEFAULT_RETRY_COUNT) {
176                 break;
177             }
178             retry++;
179         }
180     }
181 
182     if (retry > HPM_SPI_DRV_DEFAULT_RETRY_COUNT) {
183         /* dummy state may triggers timeout if dummy count, retry count, spi rate and cpu frequency are inappropriate */
184         return status_timeout;
185     }
186 
187     return status_success;
188 }
189 
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 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)
191 {
192     uint32_t status;
193     uint32_t wtransferred = 0;
194     uint32_t rtransferred = 0;
195     uint32_t retry = 0;
196     uint32_t temp;
197 
198     /* check parameter validity */
199     if (wbuff == NULL || wcount == 0 || rbuff == NULL || rcount == 0) {
200         return status_invalid_argument;
201     }
202 
203     if (data_len_in_bytes > 4 || data_len_in_bytes < 1) {
204         return status_invalid_argument;
205     }
206 
207     /* data transfer */
208     while (wtransferred < wcount || rtransferred < rcount) {
209         status = ptr->STATUS;
210 
211         if (wtransferred < wcount) {
212             /* write data into the txfifo */
213             if (!(status & SPI_STATUS_TXFULL_MASK)) {
214                 temp = 0;
215                 for (uint8_t i = 0; i < data_len_in_bytes; i++) {
216                     temp += *(wbuff++) << i * 8;
217                 }
218                 ptr->DATA = temp;
219                 /* transfer count increment */
220                 wtransferred++;
221                 retry = 0;
222             } else {
223                 if (retry > HPM_SPI_DRV_DEFAULT_RETRY_COUNT) {
224                     break;
225                 }
226                 retry++;
227             }
228         }
229 
230         if (rtransferred < rcount) {
231             /* read data from the txfifo */
232             if (!(status & SPI_STATUS_RXEMPTY_MASK)) {
233                 temp = ptr->DATA;
234                 for (uint8_t i = 0; i < data_len_in_bytes; i++) {
235                     *(rbuff++) = (uint8_t)(temp >> (i * 8));
236                 }
237                 /* transfer count increment */
238                 rtransferred++;
239                 retry = 0;
240             } else {
241                 if (retry > HPM_SPI_DRV_DEFAULT_RETRY_COUNT) {
242                     break;
243                 }
244                 retry++;
245             }
246         }
247     }
248 
249     if (retry > HPM_SPI_DRV_DEFAULT_RETRY_COUNT) {
250         /* dummy state may triggers timeout if dummy count, retry count, spi rate and cpu frequency are inappropriate */
251         return status_timeout;
252     }
253 
254     return status_success;
255 }
256 
spi_no_data(SPI_Type * ptr,spi_mode_selection_t mode,spi_control_config_t * config)257 static hpm_stat_t spi_no_data(SPI_Type *ptr, spi_mode_selection_t mode, spi_control_config_t *config)
258 {
259     (void) ptr;
260     if (mode == spi_master_mode) {
261         if (config->master_config.cmd_enable == false && config->master_config.addr_enable == false) {
262             return status_invalid_argument;
263         }
264     }
265     return status_success;
266 }
267 
spi_master_get_default_timing_config(spi_timing_config_t * config)268 void spi_master_get_default_timing_config(spi_timing_config_t *config)
269 {
270     config->master_config.cs2sclk = spi_cs2sclk_half_sclk_4;
271     config->master_config.csht = spi_csht_half_sclk_12;
272 }
273 
spi_master_get_default_format_config(spi_format_config_t * config)274 void spi_master_get_default_format_config(spi_format_config_t *config)
275 {
276     config->master_config.addr_len_in_bytes = 1;
277     config->common_config.data_len_in_bits = 32;
278     config->common_config.data_merge = false;
279     config->common_config.mosi_bidir = false;
280     config->common_config.lsb = false;
281     config->common_config.mode = spi_master_mode;
282     config->common_config.cpol = spi_sclk_high_idle;
283     config->common_config.cpha = spi_sclk_sampling_even_clk_edges;
284 }
285 
spi_slave_get_default_format_config(spi_format_config_t * config)286 void spi_slave_get_default_format_config(spi_format_config_t *config)
287 {
288     config->common_config.data_len_in_bits = 32;
289     config->common_config.data_merge = false;
290     config->common_config.mosi_bidir = false;
291     config->common_config.lsb = false;
292     config->common_config.mode = spi_master_mode;
293     config->common_config.cpol = spi_sclk_high_idle;
294     config->common_config.cpha = spi_sclk_sampling_even_clk_edges;
295 }
296 
spi_master_get_default_control_config(spi_control_config_t * config)297 void spi_master_get_default_control_config(spi_control_config_t *config)
298 {
299     config->master_config.cmd_enable = false;
300     config->master_config.addr_enable = false;
301     config->master_config.token_enable = false;
302     config->master_config.token_value = spi_token_value_0x00;
303     config->master_config.addr_phase_fmt = spi_address_phase_format_single_io_mode;
304     config->common_config.tx_dma_enable = false;
305     config->common_config.rx_dma_enable = false;
306     config->common_config.trans_mode = spi_trans_write_only;
307     config->common_config.data_phase_fmt = spi_single_io_mode;
308     config->common_config.dummy_cnt = spi_dummy_count_2;
309 #if defined(HPM_IP_FEATURE_SPI_CS_SELECT) && (HPM_IP_FEATURE_SPI_CS_SELECT == 1)
310     config->common_config.cs_index = spi_cs_0;
311 #endif
312 }
313 
spi_slave_get_default_control_config(spi_control_config_t * config)314 void spi_slave_get_default_control_config(spi_control_config_t *config)
315 {
316     config->slave_config.slave_data_only = false;
317     config->common_config.tx_dma_enable = false;
318     config->common_config.rx_dma_enable = false;
319     config->common_config.trans_mode = spi_trans_read_only;
320     config->common_config.data_phase_fmt = spi_single_io_mode;
321     config->common_config.dummy_cnt = spi_dummy_count_2;
322 #if defined(HPM_IP_FEATURE_SPI_CS_SELECT) && (HPM_IP_FEATURE_SPI_CS_SELECT == 1)
323     config->common_config.cs_index = spi_cs_0;
324 #endif
325 }
326 
spi_master_timing_init(SPI_Type * ptr,spi_timing_config_t * config)327 hpm_stat_t spi_master_timing_init(SPI_Type *ptr, spi_timing_config_t *config)
328 {
329     uint8_t sclk_div;
330     uint8_t div_remainder;
331     uint8_t div_integer;
332     if (config->master_config.sclk_freq_in_hz == 0) {
333         return status_invalid_argument;
334     }
335 
336     if (config->master_config.clk_src_freq_in_hz > config->master_config.sclk_freq_in_hz) {
337         div_remainder = (config->master_config.clk_src_freq_in_hz % config->master_config.sclk_freq_in_hz);
338         div_integer  = (config->master_config.clk_src_freq_in_hz / config->master_config.sclk_freq_in_hz);
339         if ((div_remainder != 0) || ((div_integer % 2) != 0)) {
340             return status_invalid_argument;
341         }
342         sclk_div = (div_integer / 2) - 1;
343     } else {
344         sclk_div = 0xff;
345     }
346 
347      ptr->TIMING = SPI_TIMING_CS2SCLK_SET(config->master_config.cs2sclk) |
348                    SPI_TIMING_CSHT_SET(config->master_config.csht) |
349                    SPI_TIMING_SCLK_DIV_SET(sclk_div);
350 
351     return status_success;
352 }
353 
spi_format_init(SPI_Type * ptr,spi_format_config_t * config)354 void spi_format_init(SPI_Type *ptr, spi_format_config_t *config)
355 {
356     ptr->TRANSFMT = SPI_TRANSFMT_ADDRLEN_SET(config->master_config.addr_len_in_bytes - 1) |
357                     SPI_TRANSFMT_DATALEN_SET(config->common_config.data_len_in_bits - 1) |
358                     SPI_TRANSFMT_DATAMERGE_SET(config->common_config.data_merge) |
359                     SPI_TRANSFMT_MOSIBIDIR_SET(config->common_config.mosi_bidir) |
360                     SPI_TRANSFMT_LSB_SET(config->common_config.lsb) |
361                     SPI_TRANSFMT_SLVMODE_SET(config->common_config.mode) |
362                     SPI_TRANSFMT_CPOL_SET(config->common_config.cpol) |
363                     SPI_TRANSFMT_CPHA_SET(config->common_config.cpha);
364 }
365 
spi_control_init(SPI_Type * ptr,spi_control_config_t * config,uint32_t wcount,uint32_t rcount)366 hpm_stat_t spi_control_init(SPI_Type *ptr, spi_control_config_t *config, uint32_t wcount, uint32_t rcount)
367 {
368 #if defined (SPI_SOC_TRANSFER_COUNT_MAX) && (SPI_SOC_TRANSFER_COUNT_MAX == 512)
369     if ((wcount > SPI_SOC_TRANSFER_COUNT_MAX) || (rcount > SPI_SOC_TRANSFER_COUNT_MAX)) {
370         return status_invalid_argument;
371     }
372 #endif
373     /* slave data only mode only works on write read together transfer mode */
374     if (config->slave_config.slave_data_only == true && config->common_config.trans_mode != spi_trans_write_read_together) {
375         return status_invalid_argument;
376     }
377 
378     ptr->TRANSCTRL = SPI_TRANSCTRL_SLVDATAONLY_SET(config->slave_config.slave_data_only) |
379                      SPI_TRANSCTRL_CMDEN_SET(config->master_config.cmd_enable) |
380                      SPI_TRANSCTRL_ADDREN_SET(config->master_config.addr_enable) |
381                      SPI_TRANSCTRL_ADDRFMT_SET(config->master_config.addr_phase_fmt) |
382                      SPI_TRANSCTRL_TRANSMODE_SET(config->common_config.trans_mode) |
383                      SPI_TRANSCTRL_DUALQUAD_SET(config->common_config.data_phase_fmt) |
384                      SPI_TRANSCTRL_TOKENEN_SET(config->master_config.token_enable) |
385                      SPI_TRANSCTRL_WRTRANCNT_SET(wcount - 1) |
386                      SPI_TRANSCTRL_TOKENVALUE_SET(config->master_config.token_value) |
387                      SPI_TRANSCTRL_DUMMYCNT_SET(config->common_config.dummy_cnt) |
388                      SPI_TRANSCTRL_RDTRANCNT_SET(rcount - 1);
389 
390 #if defined(HPM_IP_FEATURE_SPI_CS_SELECT) && (HPM_IP_FEATURE_SPI_CS_SELECT == 1)
391     ptr->CTRL = (ptr->CTRL & ~SPI_CTRL_CS_EN_MASK) | SPI_CTRL_CS_EN_SET(config->common_config.cs_index);
392 #endif
393 
394 #if defined(HPM_IP_FEATURE_SPI_NEW_TRANS_COUNT) && (HPM_IP_FEATURE_SPI_NEW_TRANS_COUNT == 1)
395     ptr->WR_TRANS_CNT = wcount - 1;
396     ptr->RD_TRANS_CNT = rcount - 1;
397 #endif
398 
399     /* reset txfifo, rxfifo and control */
400     ptr->CTRL |= SPI_CTRL_TXFIFORST_MASK | SPI_CTRL_RXFIFORST_MASK | SPI_CTRL_SPIRST_MASK;
401 
402     return status_success;
403 }
404 
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)405 hpm_stat_t spi_transfer(SPI_Type *ptr,
406                         spi_control_config_t *config,
407                         uint8_t *cmd, uint32_t *addr,
408                         uint8_t *wbuff, uint32_t wcount, uint8_t *rbuff, uint32_t rcount)
409 {
410     hpm_stat_t stat = status_fail;
411     uint8_t mode, data_len_in_bytes, trans_mode;
412 
413     stat = spi_control_init(ptr, config, wcount, rcount);
414     if (stat != status_success) {
415         return stat;
416     }
417 
418     /* read data length */
419     data_len_in_bytes = spi_get_data_length_in_bytes(ptr);
420 
421     /* read spi control mode */
422     mode = (ptr->TRANSFMT & SPI_TRANSFMT_SLVMODE_MASK) >> SPI_TRANSFMT_SLVMODE_SHIFT;
423 
424     /* read spi transfer mode */
425     trans_mode = config->common_config.trans_mode;
426 
427     /* write address on master mode */
428     stat = spi_write_address(ptr, mode, config, addr);
429     if (stat != status_success) {
430         return stat;
431     }
432 
433     /* write command on master mode */
434     stat = spi_write_command(ptr, mode, config, cmd);
435     if (stat != status_success) {
436         return stat;
437     }
438 
439     /* data phase */
440     if (trans_mode == spi_trans_write_read_together) {
441         stat = spi_write_read_data(ptr, data_len_in_bytes, wbuff, wcount, rbuff, rcount);
442     } else if (trans_mode == spi_trans_write_only || trans_mode == spi_trans_dummy_write) {
443         stat = spi_write_data(ptr, data_len_in_bytes, wbuff, wcount);
444     } else if (trans_mode == spi_trans_read_only || trans_mode == spi_trans_dummy_read) {
445         stat = spi_read_data(ptr, data_len_in_bytes, rbuff, rcount);
446     } else if (trans_mode == spi_trans_write_read || trans_mode == spi_trans_write_dummy_read) {
447         stat = spi_write_read_data(ptr, data_len_in_bytes, wbuff, wcount, rbuff, rcount);
448     } else if (trans_mode == spi_trans_read_write || trans_mode == spi_trans_read_dummy_write) {
449         stat = spi_write_read_data(ptr, data_len_in_bytes, wbuff, wcount, rbuff, rcount);
450     } else if (trans_mode == spi_trans_no_data) {
451         stat = spi_no_data(ptr, mode, config);
452     } else {
453         stat = status_invalid_argument;
454     }
455 
456     if (stat != status_success) {
457         return stat;
458     }
459 
460     /* read command on slave mode */
461     stat = spi_read_command(ptr, mode, config, cmd);
462     if (stat != status_success) {
463         return stat;
464     }
465     /* on the slave mode, if master keeps asserting the cs signal, it's maybe timeout */
466     stat = spi_wait_for_idle_status(ptr);
467     return stat;
468 }
469 
spi_setup_dma_transfer(SPI_Type * ptr,spi_control_config_t * config,uint8_t * cmd,uint32_t * addr,uint32_t wcount,uint32_t rcount)470 hpm_stat_t spi_setup_dma_transfer(SPI_Type *ptr,
471                         spi_control_config_t *config,
472                         uint8_t *cmd, uint32_t *addr,
473                         uint32_t wcount, uint32_t rcount)
474 {
475     hpm_stat_t stat = status_fail;
476     uint8_t mode;
477 
478     stat = spi_control_init(ptr, config, wcount, rcount);
479     if (stat != status_success) {
480         return stat;
481     }
482 
483     if (config->common_config.tx_dma_enable) {
484         ptr->CTRL |= SPI_CTRL_TXDMAEN_MASK;
485     }
486     if (config->common_config.rx_dma_enable) {
487         ptr->CTRL |= SPI_CTRL_RXDMAEN_MASK;
488     }
489 
490     /* read spi control mode */
491     mode = (ptr->TRANSFMT & SPI_TRANSFMT_SLVMODE_MASK) >> SPI_TRANSFMT_SLVMODE_SHIFT;
492 
493     /* address phase */
494     stat = spi_write_address(ptr, mode, config, addr);
495     if (stat != status_success) {
496         return stat;
497     }
498 
499     /* command phase */
500     stat = spi_write_command(ptr, mode, config, cmd);
501     if (stat != status_success) {
502         return stat;
503     }
504 
505     return stat;
506 }
507 
508 
509 #if defined(HPM_IP_FEATURE_SPI_SUPPORT_DIRECTIO) && (HPM_IP_FEATURE_SPI_SUPPORT_DIRECTIO == 1)
spi_directio_enable_output(SPI_Type * ptr,spi_directio_pin_t pin)510 hpm_stat_t spi_directio_enable_output(SPI_Type *ptr, spi_directio_pin_t pin)
511 {
512     hpm_stat_t stat = status_success;
513     switch (pin) {
514     case hold_pin:
515         ptr->DIRECTIO |= SPI_DIRECTIO_HOLD_OE_MASK;
516         break;
517     case wp_pin:
518         ptr->DIRECTIO |= SPI_DIRECTIO_WP_OE_MASK;
519         break;
520     case miso_pin:
521         ptr->DIRECTIO |= SPI_DIRECTIO_MISO_OE_MASK;
522         break;
523     case mosi_pin:
524         ptr->DIRECTIO |= SPI_DIRECTIO_MOSI_OE_MASK;
525         break;
526     case sclk_pin:
527         ptr->DIRECTIO |= SPI_DIRECTIO_SCLK_OE_MASK;
528         break;
529     case cs_pin:
530         ptr->DIRECTIO |= SPI_DIRECTIO_CS_OE_MASK;
531         break;
532     default:
533         stat = status_invalid_argument;
534         break;
535     }
536     return stat;
537 }
538 
spi_directio_disable_output(SPI_Type * ptr,spi_directio_pin_t pin)539 hpm_stat_t spi_directio_disable_output(SPI_Type *ptr, spi_directio_pin_t pin)
540 {
541     hpm_stat_t stat = status_success;
542     switch (pin) {
543     case hold_pin:
544         ptr->DIRECTIO &= ~SPI_DIRECTIO_HOLD_OE_MASK;
545         break;
546     case wp_pin:
547         ptr->DIRECTIO &= ~SPI_DIRECTIO_WP_OE_MASK;
548         break;
549     case miso_pin:
550         ptr->DIRECTIO &= ~SPI_DIRECTIO_MISO_OE_MASK;
551         break;
552     case mosi_pin:
553         ptr->DIRECTIO &= ~SPI_DIRECTIO_MOSI_OE_MASK;
554         break;
555     case sclk_pin:
556         ptr->DIRECTIO &= ~SPI_DIRECTIO_SCLK_OE_MASK;
557         break;
558     case cs_pin:
559         ptr->DIRECTIO &= ~SPI_DIRECTIO_CS_OE_MASK;
560         break;
561     default:
562         stat = status_invalid_argument;
563         break;
564     }
565     return stat;
566 }
567 
spi_directio_write(SPI_Type * ptr,spi_directio_pin_t pin,bool high)568 hpm_stat_t spi_directio_write(SPI_Type *ptr, spi_directio_pin_t pin, bool high)
569 {
570     hpm_stat_t stat = status_success;
571     switch (pin) {
572     case hold_pin:
573         (high == true) ? (ptr->DIRECTIO |= SPI_DIRECTIO_HOLD_O_MASK) : (ptr->DIRECTIO &= ~SPI_DIRECTIO_HOLD_O_MASK);
574         break;
575     case wp_pin:
576         (high == true) ? (ptr->DIRECTIO |= SPI_DIRECTIO_WP_O_MASK) : (ptr->DIRECTIO &= ~SPI_DIRECTIO_WP_O_MASK);
577         break;
578     case miso_pin:
579         (high == true) ? (ptr->DIRECTIO |= SPI_DIRECTIO_MISO_O_MASK) : (ptr->DIRECTIO &= ~SPI_DIRECTIO_MISO_O_MASK);
580         break;
581     case mosi_pin:
582         (high == true) ? (ptr->DIRECTIO |= SPI_DIRECTIO_MOSI_O_MASK) : (ptr->DIRECTIO &= ~SPI_DIRECTIO_MOSI_O_MASK);
583         break;
584     case sclk_pin:
585         (high == true) ? (ptr->DIRECTIO |= SPI_DIRECTIO_SCLK_O_MASK) : (ptr->DIRECTIO &= ~SPI_DIRECTIO_SCLK_O_MASK);
586         break;
587     case cs_pin:
588         (high == true) ? (ptr->DIRECTIO |= SPI_DIRECTIO_CS_O_MASK) : (ptr->DIRECTIO &= ~SPI_DIRECTIO_CS_O_MASK);
589         break;
590     default:
591         stat = status_invalid_argument;
592         break;
593     }
594     return stat;
595 }
596 
spi_directio_read(SPI_Type * ptr,spi_directio_pin_t pin)597 uint8_t spi_directio_read(SPI_Type *ptr, spi_directio_pin_t pin)
598 {
599     uint8_t io_sta = 0;
600     switch (pin) {
601     case hold_pin:
602         io_sta = SPI_DIRECTIO_HOLD_I_GET(ptr->DIRECTIO);
603         break;
604     case wp_pin:
605         io_sta = SPI_DIRECTIO_WP_I_GET(ptr->DIRECTIO);
606         break;
607     case miso_pin:
608         io_sta = SPI_DIRECTIO_MISO_I_GET(ptr->DIRECTIO);
609         break;
610     case mosi_pin:
611         io_sta = SPI_DIRECTIO_MOSI_I_GET(ptr->DIRECTIO);
612         break;
613     case sclk_pin:
614         io_sta = SPI_DIRECTIO_SCLK_I_GET(ptr->DIRECTIO);
615         break;
616     case cs_pin:
617         io_sta = SPI_DIRECTIO_CS_I_GET(ptr->DIRECTIO);
618         break;
619     default:
620         break;
621     }
622     return io_sta;
623 }
624 #endif
625 
626