1 /*
2 * Copyright (c) 2021 HPMicro
3 *
4 * SPDX-License-Identifier: BSD-3-Clause
5 *
6 */
7
8 #ifndef HPM_SPI_DRV_H
9 #define HPM_SPI_DRV_H
10 #include "hpm_spi_regs.h"
11 #include "hpm_soc_feature.h"
12
13 /**
14 * @brief SPI driver APIs
15 * @defgroup spi_interface SPI driver APIs
16 * @ingroup io_interfaces
17 * @{
18 */
19
20 /**
21 * @brief spi dma enable
22 */
23 typedef enum {
24 spi_tx_dma_enable = SPI_CTRL_TXDMAEN_MASK,
25 spi_rx_dma_enable = SPI_CTRL_RXDMAEN_MASK
26 } spi_dma_enable_t;
27
28 /**
29 * @brief spi interrupt mask
30 */
31 typedef enum {
32 spi_rx_fifo_overflow_int = SPI_INTREN_RXFIFOORINTEN_MASK,
33 spi_tx_fifo_underflow_int = SPI_INTREN_TXFIFOURINTEN_MASK,
34 spi_rx_fifo_threshold_int = SPI_INTREN_RXFIFOINTEN_MASK,
35 spi_tx_fifo_threshold_int = SPI_INTREN_TXFIFOINTEN_MASK,
36 spi_end_int = SPI_INTREN_ENDINTEN_MASK,
37 spi_slave_cmd_int = SPI_INTREN_SLVCMDEN_MASK,
38 } spi_interrupt_t;
39
40 /**
41 * @brief spi mode selection
42 */
43 typedef enum {
44 spi_master_mode = 0,
45 spi_slave_mode
46 } spi_mode_selection_t;
47
48 /**
49 * @brief spi clock polarity
50 */
51 typedef enum {
52 spi_sclk_low_idle = 0,
53 spi_sclk_high_idle
54 } spi_sclk_idle_state_t;
55
56 /**
57 * @brief spi clock phase
58 */
59 typedef enum {
60 spi_sclk_sampling_odd_clk_edges = 0,
61 spi_sclk_sampling_even_clk_edges
62 } spi_sclk_sampling_clk_edges_t;
63
64 /**
65 * @brief spi cs to sclk edge duration
66 */
67 typedef enum {
68 spi_cs2sclk_half_sclk_1 = 0,
69 spi_cs2sclk_half_sclk_2,
70 spi_cs2sclk_half_sclk_3,
71 spi_cs2sclk_half_sclk_4
72 } spi_cs2sclk_duration_t;
73
74 /**
75 * @brief spi cs high level duration
76 */
77 typedef enum {
78 spi_csht_half_sclk_1 = 0,
79 spi_csht_half_sclk_2,
80 spi_csht_half_sclk_3,
81 spi_csht_half_sclk_4,
82 spi_csht_half_sclk_5,
83 spi_csht_half_sclk_6,
84 spi_csht_half_sclk_7,
85 spi_csht_half_sclk_8,
86 spi_csht_half_sclk_9,
87 spi_csht_half_sclk_10,
88 spi_csht_half_sclk_11,
89 spi_csht_half_sclk_12,
90 spi_csht_half_sclk_13,
91 spi_csht_half_sclk_14,
92 spi_csht_half_sclk_15,
93 spi_csht_half_sclk_16,
94 } spi_csht_duration_t;
95
96 /**
97 * @brief spi address phase format
98 */
99 typedef enum {
100 spi_address_phase_format_single_io_mode = 0,
101 spi_address_phase_format_dualquad_io_mode
102 } spi_addr_phase_format_t;
103
104 /**
105 * @brief spi transfer mode
106 */
107 typedef enum {
108 spi_trans_write_read_together = 0,
109 spi_trans_write_only,
110 spi_trans_read_only,
111 spi_trans_write_read,
112 spi_trans_read_write,
113 spi_trans_write_dummy_read,
114 spi_trans_read_dummy_write,
115 spi_trans_no_data,
116 spi_trans_dummy_write,
117 spi_trans_dummy_read
118 } spi_trans_mode_t;
119
120 /**
121 * @brief spi data phase format
122 */
123 typedef enum {
124 spi_single_io_mode = 0,
125 spi_dual_io_mode,
126 spi_quad_io_mode,
127 } spi_data_phase_format_t;
128
129 /**
130 * @brief spi token value
131 */
132 typedef enum {
133 spi_token_value_0x00 = 0,
134 spi_token_value_0x69
135 } spi_token_value_t;
136
137 /**
138 * @brief spi dummy count
139 */
140 typedef enum {
141 spi_dummy_count_1 = 0,
142 spi_dummy_count_2,
143 spi_dummy_count_3,
144 spi_dummy_count_4
145 } spi_dummy_count_t;
146
147 typedef enum {
148 msb_first = 0,
149 lsb_first,
150 } spi_shift_direction_t;
151
152 /**
153 * @brief spi master interface timing config structure
154 */
155 typedef struct {
156 uint32_t clk_src_freq_in_hz;
157 uint32_t sclk_freq_in_hz;
158 uint8_t cs2sclk;
159 uint8_t csht;
160 } spi_master_timing_config_t;
161
162 /**
163 * @brief spi interface timing config structure
164 */
165 typedef struct {
166 spi_master_timing_config_t master_config;
167 } spi_timing_config_t;
168
169 /**
170 * @brief spi master transfer format config structure
171 */
172 typedef struct {
173 uint8_t addr_len_in_bytes;
174 } spi_master_format_config_t;
175
176 /**
177 * @brief spi common format config structure
178 */
179 typedef struct {
180 uint8_t data_len_in_bits;
181 bool data_merge;
182 bool mosi_bidir;
183 bool lsb;
184 uint8_t mode;
185 uint8_t cpol;
186 uint8_t cpha;
187 } spi_common_format_config_t;
188
189 /**
190 * @brief spi format config structure
191 */
192 typedef struct {
193 spi_master_format_config_t master_config;
194 spi_common_format_config_t common_config;
195 } spi_format_config_t;
196
197 /**
198 * @brief spi master transfer control config structure
199 */
200 typedef struct {
201 bool cmd_enable;
202 bool addr_enable;
203 uint8_t addr_phase_fmt;
204 bool token_enable;
205 uint8_t token_value;
206 } spi_master_control_config_t;
207
208 /**
209 * @brief spi slave transfer control config structure
210 */
211 typedef struct {
212 bool slave_data_only;
213 } spi_slave_control_config_t;
214
215 /**
216 * @brief spi common transfer control config structure
217 */
218 typedef struct {
219 bool tx_dma_enable;
220 bool rx_dma_enable;
221 uint8_t trans_mode;
222 uint8_t data_phase_fmt;
223 uint8_t dummy_cnt;
224 #if defined(HPM_IP_FEATURE_SPI_CS_SELECT) && (HPM_IP_FEATURE_SPI_CS_SELECT == 1)
225 uint8_t cs_index;
226 #endif
227 } spi_common_control_config_t; /*!< value in spi_cs_index_t */
228
229 /**
230 * @brief spi control config structure
231 */
232 typedef struct {
233 spi_master_control_config_t master_config;
234 spi_slave_control_config_t slave_config;
235 spi_common_control_config_t common_config;
236 } spi_control_config_t;
237
238 #if defined(HPM_IP_FEATURE_SPI_CS_SELECT) && (HPM_IP_FEATURE_SPI_CS_SELECT == 1)
239 typedef enum {
240 spi_cs_0 = 1,
241 spi_cs_1 = 2,
242 spi_cs_2 = 4,
243 spi_cs_3 = 8,
244 } spi_cs_index_t;
245 #endif
246
247 typedef enum {
248 addrlen_8bit = 0,
249 addrlen_16bit,
250 addrlen_24bit,
251 addrlen_32bit
252 } spi_address_len_t;
253
254 #if defined(HPM_IP_FEATURE_SPI_SUPPORT_DIRECTIO) && (HPM_IP_FEATURE_SPI_SUPPORT_DIRECTIO == 1)
255 typedef enum {
256 hold_pin = 0,
257 wp_pin,
258 miso_pin,
259 mosi_pin,
260 sclk_pin,
261 cs_pin
262 } spi_directio_pin_t;
263
264 #endif
265
266
267
268 #if defined(__cplusplus)
269 extern "C" {
270 #endif /* __cplusplus */
271
272 /**
273 * @brief spi master get default timing config
274 *
275 * @param [out] config spi_timing_config_t
276 */
277 void spi_master_get_default_timing_config(spi_timing_config_t *config);
278
279 /**
280 * @brief spi master get default format config
281 *
282 * @param [out] config spi_format_config_t
283 */
284 void spi_master_get_default_format_config(spi_format_config_t *config);
285
286 /**
287 * @brief spi master get default control config
288 *
289 * @param [out] config spi_control_config_t
290 */
291 void spi_master_get_default_control_config(spi_control_config_t *config);
292
293 /**
294 * @brief spi slave get default format config
295 *
296 * @param [out] config spi_format_config_t
297 */
298 void spi_slave_get_default_format_config(spi_format_config_t *config);
299
300 /**
301 * @brief spi slave get default control config
302 *
303 * @param [out] config spi_control_config_t
304 */
305 void spi_slave_get_default_control_config(spi_control_config_t *config);
306
307 /**
308 * @brief spi master timing initialization
309 *
310 * @param [in] ptr SPI base address
311 * @param [in] config spi_timing_config_t
312 * @retval hpm_stat_t status_invalid_argument or status_success
313 */
314 hpm_stat_t spi_master_timing_init(SPI_Type *ptr, spi_timing_config_t *config);
315
316 /**
317 * @brief spi format initialization
318 *
319 * @param [in] ptr SPI base address
320 * @param [in] config spi_format_config_t
321 */
322 void spi_format_init(SPI_Type *ptr, spi_format_config_t *config);
323
324 /**
325 * @brief spi transfer
326 *
327 * @param [in] ptr SPI base address
328 * @param [in] config spi_control_config_t
329 * @param [in,out] cmd spi transfer command address
330 * @param [in] addr spi transfer target address
331 * @param [in] wbuff spi sent data buff address
332 * @param [in] wcount spi sent data count, not greater than SPI_SOC_TRANSFER_COUNT_MAX
333 * @param [out] rbuff spi receive data buff address
334 * @param [in] rcount spi receive data count, not greater than SPI_SOC_TRANSFER_COUNT_MAX
335 * @retval hpm_stat_t status_success if spi transfer without any error
336 */
337 hpm_stat_t spi_transfer(SPI_Type *ptr,
338 spi_control_config_t *config,
339 uint8_t *cmd, uint32_t *addr,
340 uint8_t *wbuff, uint32_t wcount, uint8_t *rbuff, uint32_t rcount);
341
342 /**
343 * @brief spi setup dma transfer
344 *
345 * @param [in] ptr SPI base address
346 * @param [in] config spi_control_config_t
347 * @param [in] cmd spi transfer command address
348 * @param [in] addr spi transfer target address
349 * @param [in] wcount spi sent data count, not greater than SPI_SOC_TRANSFER_COUNT_MAX
350 * @param [in] rcount spi receive data count, not greater than SPI_SOC_TRANSFER_COUNT_MAX
351 * @retval hpm_stat_t status_success if spi setup dma transfer without any error
352 */
353 hpm_stat_t spi_setup_dma_transfer(SPI_Type *ptr,
354 spi_control_config_t *config,
355 uint8_t *cmd, uint32_t *addr,
356 uint32_t wcount, uint32_t rcount);
357
358 /**
359 * @brief spi wait for idle status
360 *
361 * @note on slave mode, if CS signal is asserted, take it as busy; if SPI CS signal is de-asserted, take it as idle.
362 *
363 * @param [in] ptr SPI base address
364 * @retval hpm_stat_t status_success if spi in idle status
365 */
366 hpm_stat_t spi_wait_for_idle_status(SPI_Type *ptr);
367
368 /**
369 * @brief spi wait for busy status
370 *
371 * @note on slave mode, if CS signal is asserted, take it as busy; if SPI CS signal is de-asserted, take it as idle.
372 *
373 * @param [in] ptr SPI base address
374 * @retval hpm_stat_t status_success if spi in busy status
375 */
376 hpm_stat_t spi_wait_for_busy_status(SPI_Type *ptr);
377
378 /**
379 * @brief SPI set TX FIFO threshold
380 *
381 * This function configures SPI TX FIFO threshold.
382 *
383 * @param ptr SPI base address.
384 * @param threshold The FIFO threshold value, the value should not greater than FIFO size.
385 */
spi_set_tx_fifo_threshold(SPI_Type * ptr,uint32_t threshold)386 static inline void spi_set_tx_fifo_threshold(SPI_Type *ptr, uint32_t threshold)
387 {
388 ptr->CTRL = (ptr->CTRL & ~SPI_CTRL_TXTHRES_MASK) | SPI_CTRL_TXTHRES_SET(threshold);
389 }
390
391 /**
392 * @brief SPI set RX FIFO threshold
393 *
394 * This function configures SPI RX FIFO threshold.
395 *
396 * @param ptr SPI base address.
397 * @param threshold The FIFO threshold value, the value should not greater than FIFO size.
398 */
spi_set_rx_fifo_threshold(SPI_Type * ptr,uint32_t threshold)399 static inline void spi_set_rx_fifo_threshold(SPI_Type *ptr, uint32_t threshold)
400 {
401 ptr->CTRL = (ptr->CTRL & ~SPI_CTRL_RXTHRES_MASK) | SPI_CTRL_RXTHRES_SET(threshold);
402 }
403
404 /**
405 * @brief Enables the SPI DMA request.
406 *
407 * This function configures the Rx and Tx DMA mask of the SPI. The parameters are base and a DMA mask.
408 *
409 * @param ptr SPI base address.
410 * @param mask The dma enable mask; Use the spi_dma_enable_t.
411 */
spi_enable_dma(SPI_Type * ptr,uint32_t mask)412 static inline void spi_enable_dma(SPI_Type *ptr, uint32_t mask)
413 {
414 ptr->CTRL |= mask;
415 }
416
417 /*!
418 * @brief Disables the SPI DMA request.
419 *
420 * This function configures the Rx and Tx DMA mask of the SPI. The parameters are base and a DMA mask.
421 *
422 * @param ptr SPI base address.
423 * @param mask The dma enable mask; Use the spi_dma_enable_t.
424 */
spi_disable_dma(SPI_Type * ptr,uint32_t mask)425 static inline void spi_disable_dma(SPI_Type *ptr, uint32_t mask)
426 {
427 ptr->CTRL &= ~mask;
428 }
429
430 /**
431 * @brief Get the SPI interrupt status.
432 *
433 * This function gets interrupt status of the SPI.
434 *
435 * @param ptr SPI base address.
436 * @retval SPI interrupt status register value
437 */
spi_get_interrupt_status(SPI_Type * ptr)438 static inline uint32_t spi_get_interrupt_status(SPI_Type *ptr)
439 {
440 return ptr->INTRST;
441 }
442
443 /**
444 * @brief Clear the SPI interrupt status.
445 *
446 * This function clears interrupt status of the SPI.
447 *
448 * @param ptr SPI base address.
449 * @param mask The interrupt mask; Use the spi_interrupt_t.
450 *
451 */
spi_clear_interrupt_status(SPI_Type * ptr,uint32_t mask)452 static inline void spi_clear_interrupt_status(SPI_Type *ptr, uint32_t mask)
453 {
454 /* write 1 to clear */
455 ptr->INTRST = mask;
456 }
457
458 /**
459 * @brief Enables the SPI interrupt.
460 *
461 * This function configures interrupt of the SPI. The parameters are base and a interrupt mask.
462 *
463 * @param ptr SPI base address.
464 * @param mask The interrupt mask; Use the spi_interrupt_t.
465 */
spi_enable_interrupt(SPI_Type * ptr,uint32_t mask)466 static inline void spi_enable_interrupt(SPI_Type *ptr, uint32_t mask)
467 {
468 ptr->INTREN |= mask;
469 }
470
471 /*!
472 * @brief Disables the SPI interrupt.
473 *
474 * This function configures interrupt of the SPI. The parameters are base and a interrupt mask.
475 *
476 * @param ptr SPI base address.
477 * @param mask The interrupt mask; Use the spi_interrupt_t.
478 */
spi_disable_interrupt(SPI_Type * ptr,uint32_t mask)479 static inline void spi_disable_interrupt(SPI_Type *ptr, uint32_t mask)
480 {
481 ptr->INTREN &= ~mask;
482 }
483
484 /**
485 * @brief spi write and read data
486 *
487 * @note Call this function after SPI CONTROL is configured by spi_control_init.
488 * The order of reading and writing is controlled by spi_control_init.
489 *
490 * @param [in] ptr SPI base address
491 * @param [in] data_len_in_bytes data length in bytes
492 * @param [in] wbuff spi sent data buff address
493 * @param [in] wcount spi sent data count, not greater than SPI_SOC_TRANSFER_COUNT_MAX
494 * @param [out] rbuff spi receive data buff address
495 * @param [in] rcount spi receive data count, not greater than SPI_SOC_TRANSFER_COUNT_MAX
496 * @retval hpm_stat_t status_success if spi transfer without any error
497 */
498 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);
499
500 /**
501 * @brief spi read data
502 *
503 * @note Call this function after SPI CONTROL is configured by spi_control_init.
504 *
505 * @param [in] ptr SPI base address
506 * @param [in] data_len_in_bytes data length in bytes
507 * @param [out] buff spi receive data buff address
508 * @param [in] count spi receive data count, not greater than SPI_SOC_TRANSFER_COUNT_MAX
509 * @retval hpm_stat_t status_success if spi transfer without any error
510 */
511 hpm_stat_t spi_read_data(SPI_Type *ptr, uint8_t data_len_in_bytes, uint8_t *buff, uint32_t count);
512
513 /**
514 * @brief spi write data
515 *
516 * @note Call this function after SPI CONTROL is configured by spi_control_init.
517 *
518 * @param [in] ptr SPI base address
519 * @param [in] data_len_in_bytes data length in bytes
520 * @param [in] buff spi sent data buff address
521 * @param [in] count spi sent data count, not greater than SPI_SOC_TRANSFER_COUNT_MAX
522 * @retval hpm_stat_t status_success if spi transfer without any error
523 */
524 hpm_stat_t spi_write_data(SPI_Type *ptr, uint8_t data_len_in_bytes, uint8_t *buff, uint32_t count);
525
526 /**
527 * @brief spi write command
528 *
529 * Writing operations on this register will trigger SPI transfers, call this function on master mode.
530 *
531 * @param [in] ptr SPI base address
532 * @param [in] mode spi mode, use the spi_mode_selection_t
533 * @param [in] config point to spi_control_config_t
534 * @param [in] cmd command data address
535 * @retval hpm_stat_t status_success if spi transfer without any error
536 */
537 hpm_stat_t spi_write_command(SPI_Type *ptr, spi_mode_selection_t mode, spi_control_config_t *config, uint8_t *cmd);
538
539 /**
540 * @brief spi read command
541 *
542 * On slave mode, the command field of the last received SPI transaction is stored in this SPI Command Register
543 *
544 * @param [in] ptr SPI base address
545 * @param [in] mode spi mode, use the spi_mode_selection_t
546 * @param [in] config point to spi_control_config_t
547 * @param [out] cmd command data address
548 * @retval hpm_stat_t status_success if spi transfer without any error
549 */
550 hpm_stat_t spi_read_command(SPI_Type *ptr, spi_mode_selection_t mode, spi_control_config_t *config, uint8_t *cmd);
551
552 /**
553 * @brief spi write address
554 *
555 * @note Call this function on master mode.
556 *
557 * @param [in] ptr SPI base address
558 * @param [in] mode spi mode, use the spi_mode_selection_t
559 * @param [in] config point to spi_control_config_t
560 * @param [in] addr point to address
561 * @retval hpm_stat_t status_success if spi transfer without any error
562 */
563 hpm_stat_t spi_write_address(SPI_Type *ptr, spi_mode_selection_t mode, spi_control_config_t *config, uint32_t *addr);
564
565 /**
566 * @brief spi control initialization
567 *
568 * @param [in] ptr SPI base address
569 * @param [in] config point to spi_control_config_t
570 * @param [in] wcount spi sent data count, not greater than SPI_SOC_TRANSFER_COUNT_MAX
571 * @param [in] rcount spi receive count, not greater than SPI_SOC_TRANSFER_COUNT_MAX
572 * @retval hpm_stat_t status_success if spi transfer without any error
573 */
574 hpm_stat_t spi_control_init(SPI_Type *ptr, spi_control_config_t *config, uint32_t wcount, uint32_t rcount);
575
576 /**
577 * @brief Get the SPI data length in bits.
578 *
579 * @param ptr SPI base address.
580 * @retval SPI data length in bits
581 */
spi_get_data_length_in_bits(SPI_Type * ptr)582 static inline uint8_t spi_get_data_length_in_bits(SPI_Type *ptr)
583 {
584 return ((ptr->TRANSFMT & SPI_TRANSFMT_DATALEN_MASK) >> SPI_TRANSFMT_DATALEN_SHIFT) + 1;
585 }
586
587 /**
588 * @brief Get the SPI data length in bytes.
589 *
590 * @param ptr SPI base address.
591 * @retval SPI data length in bytes
592 */
spi_get_data_length_in_bytes(SPI_Type * ptr)593 static inline uint8_t spi_get_data_length_in_bytes(SPI_Type *ptr)
594 {
595 return ((spi_get_data_length_in_bits(ptr) + 7U) / 8U);
596 }
597
598 /**
599 * @brief SPI get active status.
600 *
601 * @param ptr SPI base address.
602 * @retval bool true for active, false for inactive
603 */
spi_is_active(SPI_Type * ptr)604 static inline bool spi_is_active(SPI_Type *ptr)
605 {
606 return ((ptr->STATUS & SPI_STATUS_SPIACTIVE_MASK) == SPI_STATUS_SPIACTIVE_MASK) ? true : false;
607 }
608
609 /**
610 * @brief SPI enable tx dma
611 *
612 * @param ptr SPI base address
613 */
spi_enable_tx_dma(SPI_Type * ptr)614 static inline void spi_enable_tx_dma(SPI_Type *ptr)
615 {
616 ptr->CTRL |= SPI_CTRL_TXDMAEN_MASK;
617 }
618
619 /**
620 * @brief SPI disable tx dma
621 *
622 * @param ptr SPI base address
623 */
spi_disable_tx_dma(SPI_Type * ptr)624 static inline void spi_disable_tx_dma(SPI_Type *ptr)
625 {
626 ptr->CTRL &= ~SPI_CTRL_TXDMAEN_MASK;
627 }
628
629 /**
630 * @brief SPI enable rx dma
631 *
632 * @param ptr SPI base address
633 */
spi_enable_rx_dma(SPI_Type * ptr)634 static inline void spi_enable_rx_dma(SPI_Type *ptr)
635 {
636 ptr->CTRL |= SPI_CTRL_RXDMAEN_MASK;
637 }
638
639 /**
640 * @brief SPI disable rx dma
641 *
642 * @param ptr SPI base address
643 */
spi_disable_rx_dma(SPI_Type * ptr)644 static inline void spi_disable_rx_dma(SPI_Type *ptr)
645 {
646 ptr->CTRL &= ~SPI_CTRL_RXDMAEN_MASK;
647 }
648
649 /**
650 * @brief SPI slave get sent data count
651 *
652 * @param ptr SPI base address
653 * @retval uint32_t data count
654 */
spi_slave_get_sent_data_count(SPI_Type * ptr)655 static inline uint32_t spi_slave_get_sent_data_count(SPI_Type *ptr)
656 {
657 #if defined(HPM_IP_FEATURE_SPI_NEW_TRANS_COUNT) && (HPM_IP_FEATURE_SPI_NEW_TRANS_COUNT == 1)
658 return ptr->SLVDATAWCNT;
659 #else
660 return SPI_SLVDATACNT_WCNT_GET(ptr->SLVDATACNT);
661 #endif
662 }
663
664 /**
665 * @brief SPI slave get received data count
666 *
667 * @param ptr SPI base address
668 * @retval uint32_t data count
669 */
spi_slave_get_received_data_count(SPI_Type * ptr)670 static inline uint32_t spi_slave_get_received_data_count(SPI_Type *ptr)
671 {
672 #if defined(HPM_IP_FEATURE_SPI_NEW_TRANS_COUNT) && (HPM_IP_FEATURE_SPI_NEW_TRANS_COUNT == 1)
673 return ptr->SLVDATARCNT;
674 #else
675 return SPI_SLVDATACNT_RCNT_GET(ptr->SLVDATACNT);
676 #endif
677 }
678
679 /**
680 * @brief set spi clock phase
681 *
682 * @param [in] ptr SPI base address
683 * @param [in] clock_phase clock phase enum
684 */
spi_set_clock_phase(SPI_Type * ptr,spi_sclk_sampling_clk_edges_t clock_phase)685 static inline void spi_set_clock_phase(SPI_Type *ptr, spi_sclk_sampling_clk_edges_t clock_phase)
686 {
687 ptr->TRANSFMT = (ptr->TRANSFMT & ~SPI_TRANSFMT_CPHA_MASK) | SPI_TRANSFMT_CPHA_SET(clock_phase);
688 }
689
690 /**
691 * @brief get spi clock phase
692 *
693 * @param [in] ptr SPI base address
694 * @retval spi_sclk_sampling_clk_edges_t spi_sclk_sampling_odd_clk_edges if CPHA is 0
695 */
spi_get_clock_phase(SPI_Type * ptr)696 static inline spi_sclk_sampling_clk_edges_t spi_get_clock_phase(SPI_Type *ptr)
697 {
698 return (spi_sclk_sampling_clk_edges_t)SPI_TRANSFMT_CPHA_GET(ptr->TRANSFMT);
699 }
700
701 /**
702 * @brief set spi clock polarity
703 *
704 * @param [in] ptr SPI base address
705 * @param [in] clock_polarity clock polarity enum
706 */
spi_set_clock_polarity(SPI_Type * ptr,spi_sclk_idle_state_t clock_polarity)707 static inline void spi_set_clock_polarity(SPI_Type *ptr, spi_sclk_idle_state_t clock_polarity)
708 {
709 ptr->TRANSFMT = (ptr->TRANSFMT & ~SPI_TRANSFMT_CPOL_MASK) | SPI_TRANSFMT_CPOL_SET(clock_polarity);
710 }
711
712 /**
713 * @brief get spi clock phase
714 *
715 * @param [in] ptr SPI base address
716 * @retval spi_sclk_idle_state_t spi_sclk_low_idle if CPOL is 0
717 */
spi_get_clock_polarity(SPI_Type * ptr)718 static inline spi_sclk_idle_state_t spi_get_clock_polarity(SPI_Type *ptr)
719 {
720 return (spi_sclk_idle_state_t)SPI_TRANSFMT_CPOL_GET(ptr->TRANSFMT);
721 }
722
723 /**
724 * @brief set spi the length of each data unit in bits
725 *
726 * @param [in] ptr SPI base address
727 * @param [in] nbits the actual bits number of a data
728 * @retval hpm_stat_t status_success if spi transfer without any error
729 */
spi_set_data_bits(SPI_Type * ptr,uint8_t nbits)730 static inline hpm_stat_t spi_set_data_bits(SPI_Type *ptr, uint8_t nbits)
731 {
732 if (nbits > 32) {
733 return status_invalid_argument;
734 } else {
735 ptr->TRANSFMT = (ptr->TRANSFMT & ~SPI_TRANSFMT_DATALEN_MASK) | SPI_TRANSFMT_DATALEN_SET(nbits - 1);
736 return status_success;
737 }
738 }
739
740 /**
741 * @brief SPI transmit fifo reset
742 *
743 * @param ptr SPI base address
744 */
spi_transmit_fifo_reset(SPI_Type * ptr)745 static inline void spi_transmit_fifo_reset(SPI_Type *ptr)
746 {
747 ptr->CTRL |= SPI_CTRL_TXFIFORST_MASK;
748 }
749
750 /**
751 * @brief SPI receive fifo reset
752 *
753 * @param ptr SPI base address
754 */
spi_receive_fifo_reset(SPI_Type * ptr)755 static inline void spi_receive_fifo_reset(SPI_Type *ptr)
756 {
757 ptr->CTRL |= SPI_CTRL_RXFIFORST_MASK;
758 }
759
760 /**
761 * @brief SPI reset
762 *
763 * @param ptr SPI base address
764 */
spi_reset(SPI_Type * ptr)765 static inline void spi_reset(SPI_Type *ptr)
766 {
767 ptr->CTRL |= SPI_CTRL_SPIRST_MASK;
768 }
769
770 /**
771 * @brief set spi the length of address
772 *
773 * @param [in] ptr SPI base address
774 * @param [in] addrlen address lenth enum
775 */
spi_set_address_len(SPI_Type * ptr,spi_address_len_t addrlen)776 static inline void spi_set_address_len(SPI_Type *ptr, spi_address_len_t addrlen)
777 {
778 ptr->TRANSFMT = (ptr->TRANSFMT & ~SPI_TRANSFMT_ADDRLEN_MASK) | SPI_TRANSFMT_ADDRLEN_SET(addrlen);
779 }
780
781 /**
782 * @brief Enable SPI data merge
783 *
784 * @param [in] ptr SPI base address
785 */
spi_enable_data_merge(SPI_Type * ptr)786 static inline void spi_enable_data_merge(SPI_Type *ptr)
787 {
788 ptr->TRANSFMT |= SPI_TRANSFMT_DATAMERGE_MASK;
789 }
790
791 /**
792 * @brief Disable SPI data merge
793 *
794 * @param [in] ptr SPI base address
795 */
spi_disable_data_merge(SPI_Type * ptr)796 static inline void spi_disable_data_merge(SPI_Type *ptr)
797 {
798 ptr->TRANSFMT &= ~SPI_TRANSFMT_DATAMERGE_MASK;
799 }
800
801 #if defined(HPM_IP_FEATURE_SPI_SUPPORT_DIRECTIO) && (HPM_IP_FEATURE_SPI_SUPPORT_DIRECTIO == 1)
802 /**
803 * @brief enable specific pin output for spi directio
804 *
805 * @note must be used spi_enable_directio API before enable output function
806 *
807 * @param [in] ptr SPI base address
808 * @param [in] pin spi_directio_pin_t enum
809 */
810 hpm_stat_t spi_directio_enable_output(SPI_Type *ptr, spi_directio_pin_t pin);
811
812 /**
813 * @brief disable specific pin output for spi directio
814 *
815 * @param [in] ptr SPI base address
816 * @param [in] pin spi_directio_pin_t enum
817 */
818 hpm_stat_t spi_directio_disable_output(SPI_Type *ptr, spi_directio_pin_t pin);
819
820 /**
821 * @brief write specified pin level for spi directio
822 *
823 * @param [in] ptr SPI base address
824 * @param [in] pin spi_directio_pin_t enum
825 * @param [in] high Pin level set to high when it is set to true
826 */
827 hpm_stat_t spi_directio_write(SPI_Type *ptr, spi_directio_pin_t pin, bool high);
828
829 /**
830 * @brief Read specified pin level for spi directio
831 *
832 * @param [in] ptr SPI base address
833 * @param pin spi_directio_pin_t enum
834 *
835 * @return Pin status
836 */
837 uint8_t spi_directio_read(SPI_Type *ptr, spi_directio_pin_t pin);
838
839 /**
840 * @brief Enable SPI directIO control function
841 *
842 * @note if SPI transmission is required, the function must be disable
843 *
844 * @param [in] ptr SPI base address
845 */
spi_enable_directio(SPI_Type * ptr)846 static inline void spi_enable_directio(SPI_Type *ptr)
847 {
848 ptr->DIRECTIO |= SPI_DIRECTIO_DIRECTIOEN_MASK;
849 }
850
851 /**
852 * @brief Disable SPI directIO control function
853 *
854 * @param [in] ptr SPI base address
855 */
spi_disable_directio(SPI_Type * ptr)856 static inline void spi_disable_directio(SPI_Type *ptr)
857 {
858 ptr->DIRECTIO &= ~SPI_DIRECTIO_DIRECTIOEN_MASK;
859 }
860
861 /**
862 * @brief get whether spi directio function is enabled
863 *
864 * @param [in] ptr SPI base address
865 *
866 * @return if pi directio function is enable, it will return 1
867 */
spi_get_directio_enable_status(SPI_Type * ptr)868 static inline uint8_t spi_get_directio_enable_status(SPI_Type *ptr)
869 {
870 return SPI_DIRECTIO_DIRECTIOEN_GET(ptr->DIRECTIO);
871 }
872
873 #endif
874
875 /**
876 * @brief Get valid data size in receive FIFO
877 *
878 * @param [in] ptr SPI base address
879 *
880 * @return rx fifo valid data size
881 */
spi_get_rx_fifo_valid_data_size(SPI_Type * ptr)882 static inline uint8_t spi_get_rx_fifo_valid_data_size(SPI_Type *ptr)
883 {
884 return ((SPI_STATUS_RXNUM_7_6_GET(ptr->STATUS) << 5) | SPI_STATUS_RXNUM_5_0_GET(ptr->STATUS));
885 }
886
887 /**
888 * @brief Get valid data size in transmit FIFO
889 *
890 * @param [in] ptr SPI base address
891 *
892 * @return tx fifo valid data size
893 */
spi_get_tx_fifo_valid_data_size(SPI_Type * ptr)894 static inline uint8_t spi_get_tx_fifo_valid_data_size(SPI_Type *ptr)
895 {
896 return ((SPI_STATUS_TXNUM_7_6_GET(ptr->STATUS) << 5) | SPI_STATUS_TXNUM_5_0_GET(ptr->STATUS));
897 }
898
899 /**
900 * @brief Get SPI RXFIFO size
901 *
902 * @param [in] ptr SPI base address
903 *
904 * @return RXFIFO size, the unit is word
905 */
spi_get_rx_fifo_size(SPI_Type * ptr)906 static inline uint8_t spi_get_rx_fifo_size(SPI_Type *ptr)
907 {
908 uint8_t size = SPI_CONFIG_RXFIFOSIZE_GET(ptr->CONFIG);
909 return (2 << size);
910 }
911
912 /**
913 * @brief Get SPI TXFIFO size
914 *
915 * @param [in] ptr SPI base address
916 *
917 * @return TXFIFO size, the unit is word
918 */
spi_get_tx_fifo_size(SPI_Type * ptr)919 static inline uint8_t spi_get_tx_fifo_size(SPI_Type *ptr)
920 {
921 uint8_t size = SPI_CONFIG_TXFIFOSIZE_GET(ptr->CONFIG);
922 return (2 << size);
923 }
924
925 /**
926 * @brief SPI slave enable only date mode
927 *
928 * @note This mode only works in the uni-directional regular (single) mode
929 * @param [in] ptr SPI base address
930 */
spi_slave_enable_data_only(SPI_Type * ptr)931 static inline void spi_slave_enable_data_only(SPI_Type *ptr)
932 {
933 ptr->TRANSCTRL |= SPI_TRANSCTRL_SLVDATAONLY_MASK;
934 }
935
936 /**
937 * @brief SPI slave disable only date mode
938 *
939 * @param [in] ptr SPI base address
940 */
spi_slave_disable_data_only(SPI_Type * ptr)941 static inline void spi_slave_disable_data_only(SPI_Type *ptr)
942 {
943 ptr->TRANSCTRL &= ~SPI_TRANSCTRL_SLVDATAONLY_MASK;
944 }
945
946 /**
947 * @brief SPI master enable command phase
948 *
949 * @param [in] ptr SPI base address
950 */
spi_master_enable_command_phase(SPI_Type * ptr)951 static inline void spi_master_enable_command_phase(SPI_Type *ptr)
952 {
953 ptr->TRANSCTRL |= SPI_TRANSCTRL_CMDEN_MASK;
954 }
955
956 /**
957 * @brief SPI master disable command phase
958 *
959 * @param [in] ptr SPI base address
960 */
spi_master_disable_command_phase(SPI_Type * ptr)961 static inline void spi_master_disable_command_phase(SPI_Type *ptr)
962 {
963 ptr->TRANSCTRL &= ~SPI_TRANSCTRL_CMDEN_MASK;
964 }
965
966 /**
967 * @brief SPI master enable address phase
968 *
969 * @param [in] ptr SPI base address
970 */
spi_master_enable_address_phase(SPI_Type * ptr)971 static inline void spi_master_enable_address_phase(SPI_Type *ptr)
972 {
973 ptr->TRANSCTRL |= SPI_TRANSCTRL_ADDREN_MASK;
974 }
975
976 /**
977 * @brief SPI master disable address phase
978 *
979 * @param [in] ptr SPI base address
980 */
spi_master_disable_address_phase(SPI_Type * ptr)981 static inline void spi_master_disable_address_phase(SPI_Type *ptr)
982 {
983 ptr->TRANSCTRL &= ~SPI_TRANSCTRL_ADDREN_MASK;
984 }
985
986 /**
987 * @brief SPI master set address phase format
988 *
989 * @param [in] ptr SPI base address
990 * @param [in] format spi_addr_phase_format_t enum
991 */
spi_master_set_address_phase_format(SPI_Type * ptr,spi_addr_phase_format_t format)992 static inline void spi_master_set_address_phase_format(SPI_Type *ptr, spi_addr_phase_format_t format)
993 {
994 ptr->TRANSCTRL = (ptr->TRANSCTRL & ~SPI_TRANSCTRL_ADDRFMT_MASK) | SPI_TRANSCTRL_ADDRFMT_SET(format);
995 }
996
997 /**
998 * @brief SPI master set transfer mode
999 *
1000 * @param [in] ptr SPI base address
1001 * @param [in] mode spi_trans_mode_t enum
1002 */
spi_set_transfer_mode(SPI_Type * ptr,spi_trans_mode_t mode)1003 static inline void spi_set_transfer_mode(SPI_Type *ptr, spi_trans_mode_t mode)
1004 {
1005 ptr->TRANSCTRL = (ptr->TRANSCTRL & ~SPI_TRANSCTRL_TRANSMODE_MASK) | SPI_TRANSCTRL_TRANSMODE_SET(mode);
1006 }
1007
1008 /**
1009 * @brief SPI master enable token transfer
1010 *
1011 * @param [in] ptr SPI base address
1012 */
spi_master_enable_token_transfer(SPI_Type * ptr)1013 static inline void spi_master_enable_token_transfer(SPI_Type *ptr)
1014 {
1015 ptr->TRANSCTRL |= SPI_TRANSCTRL_TOKENEN_MASK;
1016 }
1017
1018 /**
1019 * @brief SPI master disable token transfer
1020 *
1021 * @param [in] ptr SPI base address
1022 */
spi_master_disable_token_transfer(SPI_Type * ptr)1023 static inline void spi_master_disable_token_transfer(SPI_Type *ptr)
1024 {
1025 ptr->TRANSCTRL &= ~SPI_TRANSCTRL_TOKENEN_MASK;
1026 }
1027
1028 /**
1029 * @brief SPI master set transfer count for write data
1030 *
1031 * @param [in] ptr SPI base address
1032 * @param [in] count the number of units of data to be transmitted to the SPI bus from the Data
1033 */
spi_set_write_data_count(SPI_Type * ptr,uint32_t count)1034 static inline void spi_set_write_data_count(SPI_Type *ptr, uint32_t count)
1035 {
1036 #if defined(HPM_IP_FEATURE_SPI_NEW_TRANS_COUNT) && (HPM_IP_FEATURE_SPI_NEW_TRANS_COUNT == 1)
1037 ptr->WR_TRANS_CNT = (count - 1);
1038 #else
1039 ptr->TRANSCTRL = (ptr->TRANSCTRL & ~SPI_TRANSCTRL_WRTRANCNT_MASK) | SPI_TRANSCTRL_WRTRANCNT_SET(count - 1);
1040 #endif
1041 }
1042
1043 /**
1044 * @brief SPI master set transfer count for read data
1045 *
1046 * @param [in] ptr SPI base address
1047 * @param [in] count the number of units of data to be received from SPI bus and stored to the Data
1048 */
spi_set_read_data_count(SPI_Type * ptr,uint32_t count)1049 static inline void spi_set_read_data_count(SPI_Type *ptr, uint32_t count)
1050 {
1051 #if defined(HPM_IP_FEATURE_SPI_NEW_TRANS_COUNT) && (HPM_IP_FEATURE_SPI_NEW_TRANS_COUNT == 1)
1052 ptr->RD_TRANS_CNT = (count - 1);
1053 #else
1054 ptr->TRANSCTRL = (ptr->TRANSCTRL & ~SPI_TRANSCTRL_RDTRANCNT_MASK) | SPI_TRANSCTRL_RDTRANCNT_SET(count - 1);
1055 #endif
1056 }
1057
1058 /**
1059 * @brief SPI master set the value of the one-byte special token following the address phase for SPI read transfers
1060 *
1061 * @param [in] ptr SPI base address
1062 * @param [in] value spi_token_value_t enum
1063 */
spi_master_set_token_value(SPI_Type * ptr,spi_token_value_t value)1064 static inline void spi_master_set_token_value(SPI_Type *ptr, spi_token_value_t value)
1065 {
1066 ptr->TRANSCTRL = (ptr->TRANSCTRL & ~SPI_TRANSCTRL_TOKENVALUE_MASK) | SPI_TRANSCTRL_TOKENVALUE_SET(value);
1067 }
1068
1069 /**
1070 * @brief SPI master set dummy data count
1071 *
1072 * @param [in] ptr SPI base address
1073 * @param [in] count spi_dummy_count_t enum
1074 */
spi_set_dummy_count(SPI_Type * ptr,spi_dummy_count_t count)1075 static inline void spi_set_dummy_count(SPI_Type *ptr, spi_dummy_count_t count)
1076 {
1077 ptr->TRANSCTRL = (ptr->TRANSCTRL & ~SPI_TRANSCTRL_DUMMYCNT_MASK) | SPI_TRANSCTRL_DUMMYCNT_SET(count);
1078 }
1079
1080 /**
1081 * @brief SPI master set the minimum time between the edges of SPI CS and the edges of SCLK
1082 *
1083 * @param [in] ptr SPI base address
1084 * @param [in] duration spi_cs2sclk_duration_t enum
1085 */
spi_master_set_cs2sclk_timing(SPI_Type * ptr,spi_cs2sclk_duration_t duration)1086 static inline void spi_master_set_cs2sclk_timing(SPI_Type *ptr, spi_cs2sclk_duration_t duration)
1087 {
1088 ptr->TIMING = (ptr->TIMING & ~SPI_TIMING_CS2SCLK_MASK) | SPI_TIMING_CS2SCLK_SET(duration);
1089 }
1090
1091 /**
1092 * @brief SPI master get the minimum time between the edges of SPI CS and the edges of SCLK
1093 *
1094 * @param [in] ptr SPI base address
1095 * @retval spi_cs2sclk_duration_t enum
1096 */
spi_master_get_cs2sclk_timing(SPI_Type * ptr)1097 static inline spi_cs2sclk_duration_t spi_master_get_cs2sclk_timing(SPI_Type *ptr)
1098 {
1099 return (spi_cs2sclk_duration_t)SPI_TIMING_CS2SCLK_GET(ptr->TIMING);
1100 }
1101
1102 /**
1103 * @brief SPI master set the minimum time that SPI CS should stay HIGH.
1104 *
1105 * @param [in] ptr SPI base address
1106 * @param [in] duration spi_csht_duration_t enum
1107 */
spi_master_set_csht_timing(SPI_Type * ptr,spi_csht_duration_t duration)1108 static inline void spi_master_set_csht_timing(SPI_Type *ptr, spi_csht_duration_t duration)
1109 {
1110 ptr->TIMING = (ptr->TIMING & ~SPI_TIMING_CSHT_MASK) | SPI_TIMING_CSHT_SET(duration);
1111 }
1112
1113 /**
1114 * @brief SPI master get the minimum time that SPI CS should stay HIGH.
1115 *
1116 * @param [in] ptr SPI base address
1117 * @retval spi_csht_duration_t enum
1118 */
spi_master_get_csht_timing(SPI_Type * ptr)1119 static inline spi_csht_duration_t spi_master_get_csht_timing(SPI_Type *ptr)
1120 {
1121 return (spi_csht_duration_t)SPI_TIMING_CSHT_GET(ptr->TIMING);
1122 }
1123
1124 /**
1125 * @brief SPI master set the clock frequency ratio between the clock source and SPI SCLK
1126 *
1127 * @param [in] ptr SPI base address
1128 * @param [in] div the frequency ratio value
1129 */
spi_master_set_sclk_div(SPI_Type * ptr,uint8_t div)1130 static inline void spi_master_set_sclk_div(SPI_Type *ptr, uint8_t div)
1131 {
1132 ptr->TIMING = (ptr->TIMING & ~SPI_TIMING_SCLK_DIV_MASK) | SPI_TIMING_SCLK_DIV_SET(div);
1133 }
1134
1135 /**
1136 * @brief SPI master get the clock frequency ratio between the clock source and SPI SCLK
1137 *
1138 * @param [in] ptr SPI base address
1139 *
1140 * @retval return the frequency ratio value
1141 */
spi_master_get_sclk_div(SPI_Type * ptr)1142 static inline uint8_t spi_master_get_sclk_div(SPI_Type *ptr)
1143 {
1144 return SPI_TIMING_SCLK_DIV_GET(ptr->TIMING);
1145 }
1146
1147 /**
1148 * @brief SPI slave set the user defined status flags
1149 *
1150 * @note in Non-SlvDataOnly, the command is read status command, such as 0x05\0x15\0x25 command
1151 *
1152 * @param [in] ptr SPI base address
1153 * @param [in] user_status user status value
1154 */
spi_slave_set_user_status(SPI_Type * ptr,uint16_t user_status)1155 static inline void spi_slave_set_user_status(SPI_Type *ptr, uint16_t user_status)
1156 {
1157 ptr->SLVST = (ptr->SLVST & ~SPI_SLVST_USR_STATUS_MASK) | SPI_SLVST_USR_STATUS_SET(user_status);
1158 }
1159
1160 /**
1161 * @brief SPI master set data phase format
1162 *
1163 * @param [in] ptr SPI base address
1164 * @param [in] format spi_data_phase_format_t enum
1165 */
spi_master_set_data_phase_format(SPI_Type * ptr,spi_data_phase_format_t format)1166 static inline void spi_master_set_data_phase_format(SPI_Type *ptr, spi_data_phase_format_t format)
1167 {
1168 ptr->TRANSCTRL = (ptr->TRANSCTRL & ~SPI_TRANSCTRL_DUALQUAD_MASK) | SPI_TRANSCTRL_DUALQUAD_SET(format);
1169 }
1170
1171 /**
1172 * @brief SPI master get data phase format
1173 *
1174 * @param [in] ptr SPI base address
1175 *
1176 * @retval return the data phase format
1177 */
spi_master_get_data_phase_format(SPI_Type * ptr)1178 static inline spi_data_phase_format_t spi_master_get_data_phase_format(SPI_Type *ptr)
1179 {
1180 return (spi_data_phase_format_t)SPI_TRANSCTRL_DUALQUAD_GET(ptr->TRANSCTRL);
1181 }
1182
1183 /**
1184 * @brief set spi shift direction
1185 *
1186 * @param [in] ptr SPI base address
1187 * @param [in] shift_direction shift direction enum
1188 */
spi_set_shift_direction(SPI_Type * ptr,spi_shift_direction_t shift_direction)1189 static inline void spi_set_shift_direction(SPI_Type *ptr, spi_shift_direction_t shift_direction)
1190 {
1191 ptr->TRANSFMT = (ptr->TRANSFMT & ~SPI_TRANSFMT_LSB_MASK) | SPI_TRANSFMT_LSB_SET(shift_direction);
1192 }
1193
1194 /**
1195 * @brief get spi shift direction
1196 *
1197 * @param [in] ptr SPI base address
1198 * @retval spi_shift_direction_t msb_first if frist MSB
1199 */
spi_get_shift_direction(SPI_Type * ptr)1200 static inline spi_shift_direction_t spi_get_shift_direction(SPI_Type *ptr)
1201 {
1202 return (spi_shift_direction_t)SPI_TRANSFMT_LSB_GET(ptr->TRANSFMT);
1203 }
1204
1205 /**
1206 * @}
1207 */
1208
1209 #if defined(__cplusplus)
1210 }
1211 #endif /* __cplusplus */
1212 #endif /* HPM_SPI_DRV_H */
1213