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 data length in bit
42 */
43 typedef enum {
44 spi_data_length_8_bits = 7,
45 spi_data_length_16_bits = 15,
46 spi_data_length_31_bits = 30
47 } spi_data_length_in_bits_t;
48
49 /**
50 * @brief spi mode selection
51 */
52 typedef enum {
53 spi_master_mode = 0,
54 spi_slave_mode
55 } spi_mode_selection_t;
56
57 /**
58 * @brief spi clock polarity
59 */
60 typedef enum {
61 spi_sclk_low_idle = 0,
62 spi_sclk_high_idle
63 } spi_sclk_idle_state_t;
64
65 /**
66 * @brief spi clock phase
67 */
68 typedef enum {
69 spi_sclk_sampling_odd_clk_edges = 0,
70 spi_sclk_sampling_even_clk_edges
71 } spi_sclk_sampling_clk_edges_t;
72
73 /**
74 * @brief spi cs to sclk edge duration
75 */
76 typedef enum {
77 spi_cs2sclk_half_sclk_1 = 0,
78 spi_cs2sclk_half_sclk_2,
79 spi_cs2sclk_half_sclk_3,
80 spi_cs2sclk_half_sclk_4
81 } spi_cs2sclk_duration_t;
82
83 /**
84 * @brief spi cs high level duration
85 */
86 typedef enum {
87 spi_csht_half_sclk_1 = 0,
88 spi_csht_half_sclk_2,
89 spi_csht_half_sclk_3,
90 spi_csht_half_sclk_4,
91 spi_csht_half_sclk_5,
92 spi_csht_half_sclk_6,
93 spi_csht_half_sclk_7,
94 spi_csht_half_sclk_8,
95 spi_csht_half_sclk_9,
96 spi_csht_half_sclk_10,
97 spi_csht_half_sclk_11,
98 spi_csht_half_sclk_12,
99 spi_csht_half_sclk_13,
100 spi_csht_half_sclk_14,
101 spi_csht_half_sclk_15,
102 spi_csht_half_sclk_16,
103 } spi_csht_duration_t;
104
105 /**
106 * @brief spi address phase format
107 */
108 typedef enum {
109 spi_address_phase_format_single_io_mode = 0,
110 spi_address_phase_format_dualquad_io_mode
111 } spi_addr_phase_format_t;
112
113 /**
114 * @brief spi transfer mode
115 */
116 typedef enum {
117 spi_trans_write_read_together = 0,
118 spi_trans_write_only,
119 spi_trans_read_only,
120 spi_trans_write_read,
121 spi_trans_read_write,
122 spi_trans_write_dummy_read,
123 spi_trans_read_dummy_write,
124 spi_trans_no_data,
125 spi_trans_dummy_write,
126 spi_trans_dummy_read
127 } spi_trans_mode_t;
128
129 /**
130 * @brief spi data phase format
131 */
132 typedef enum {
133 spi_single_io_mode = 0,
134 spi_dual_io_mode,
135 spi_quad_io_mode,
136 } spi_data_phase_format_t;
137
138 /**
139 * @brief spi token value
140 */
141 typedef enum {
142 spi_token_value_0x00 = 0,
143 spi_token_value_0x69
144 } spi_token_value_t;
145
146 /**
147 * @brief spi dummy count
148 */
149 typedef enum {
150 spi_dummy_count_1 = 0,
151 spi_dummy_count_2,
152 spi_dummy_count_3,
153 spi_dummy_count_4
154 } spi_dummy_count_t;
155
156 /**
157 * @brief spi master interface timing config structure
158 */
159 typedef struct {
160 uint32_t clk_src_freq_in_hz;
161 uint32_t sclk_freq_in_hz;
162 uint8_t cs2sclk;
163 uint8_t csht;
164 } spi_master_timing_config_t;
165
166 /**
167 * @brief spi interface timing config structure
168 */
169 typedef struct {
170 spi_master_timing_config_t master_config;
171 } spi_timing_config_t;
172
173 /**
174 * @brief spi master transfer format config structure
175 */
176 typedef struct {
177 uint8_t addr_len_in_bytes;
178 } spi_master_format_config_t;
179
180 /**
181 * @brief spi common format config structure
182 */
183 typedef struct {
184 uint8_t data_len_in_bits;
185 bool data_merge;
186 bool mosi_bidir;
187 bool lsb;
188 uint8_t mode;
189 uint8_t cpol;
190 uint8_t cpha;
191 } spi_common_format_config_t;
192
193 /**
194 * @brief spi format config structure
195 */
196 typedef struct {
197 spi_master_format_config_t master_config;
198 spi_common_format_config_t common_config;
199 } spi_format_config_t;
200
201 /**
202 * @brief spi master transfer control config structure
203 */
204 typedef struct {
205 bool cmd_enable;
206 bool addr_enable;
207 uint8_t addr_phase_fmt;
208 bool token_enable;
209 uint8_t token_value;
210 } spi_master_control_config_t;
211
212 /**
213 * @brief spi slave transfer control config structure
214 */
215 typedef struct {
216 bool slave_data_only;
217 } spi_slave_control_config_t;
218
219 /**
220 * @brief spi common transfer control config structure
221 */
222 typedef struct {
223 bool tx_dma_enable;
224 bool rx_dma_enable;
225 uint8_t trans_mode;
226 uint8_t data_phase_fmt;
227 uint8_t dummy_cnt;
228 } spi_common_control_config_t;
229
230 /**
231 * @brief spi control config structure
232 */
233 typedef struct {
234 spi_master_control_config_t master_config;
235 spi_slave_control_config_t slave_config;
236 spi_common_control_config_t common_config;
237 } spi_control_config_t;
238
239 #if defined(__cplusplus)
240 extern "C" {
241 #endif /* __cplusplus */
242
243 /**
244 * @brief spi master get default timing config
245 *
246 * @param [out] config spi_timing_config_t
247 */
248 void spi_master_get_default_timing_config(spi_timing_config_t *config);
249
250 /**
251 * @brief spi master get default format config
252 *
253 * @param [out] config spi_format_config_t
254 */
255 void spi_master_get_default_format_config(spi_format_config_t *config);
256
257 /**
258 * @brief spi master get default control config
259 *
260 * @param [out] config spi_control_config_t
261 */
262 void spi_master_get_default_control_config(spi_control_config_t *config);
263
264 /**
265 * @brief spi slave get default format config
266 *
267 * @param [out] config spi_format_config_t
268 */
269 void spi_slave_get_default_format_config(spi_format_config_t *config);
270
271 /**
272 * @brief spi slave get default control config
273 *
274 * @param [out] config spi_control_config_t
275 */
276 void spi_slave_get_default_control_config(spi_control_config_t *config);
277
278 /**
279 * @brief spi master timing initialization
280 *
281 * @param [in] ptr SPI base address
282 * @param [in] config spi_timing_config_t
283 * @retval hpm_stat_t status_invalid_argument or status_success
284 */
285 hpm_stat_t spi_master_timing_init(SPI_Type *ptr, spi_timing_config_t *config);
286
287 /**
288 * @brief spi format initialization
289 *
290 * @param [in] ptr SPI base address
291 * @param [in] config spi_format_config_t
292 */
293 void spi_format_init(SPI_Type *ptr, spi_format_config_t *config);
294
295 /**
296 * @brief spi transfer
297 *
298 * @param [in] ptr SPI base address
299 * @param [in] config spi_control_config_t
300 * @param [in] cmd spi transfer mode
301 * @param [in] addr spi transfer target address
302 * @param [in] wbuff spi sent data buff address
303 * @param [in] wcount spi sent data count, not greater than SPI_SOC_TRANSFER_COUNT_MAX
304 * @param [in] rbuff spi receive data buff address
305 * @param [in] rcount spi receive data count, not greater than SPI_SOC_TRANSFER_COUNT_MAX
306 * @retval hpm_stat_t status_success if spi transfer without any error
307 */
308 hpm_stat_t spi_transfer(SPI_Type *ptr,
309 spi_control_config_t *config,
310 uint8_t *cmd, uint32_t *addr,
311 uint8_t *wbuff, uint32_t wcount, uint8_t *rbuff, uint32_t rcount);
312
313 /**
314 * @brief spi setup dma transfer
315 *
316 * @param [in] ptr SPI base address
317 * @param [in] config spi_control_config_t
318 * @param [in] cmd spi transfer mode
319 * @param [in] addr spi transfer target address
320 * @param [in] wcount spi sent data count, not greater than SPI_SOC_TRANSFER_COUNT_MAX
321 * @param [in] rcount spi receive data count, not greater than SPI_SOC_TRANSFER_COUNT_MAX
322 * @retval hpm_stat_t status_success if spi setup dma transfer without any error
323 */
324 hpm_stat_t spi_setup_dma_transfer(SPI_Type *ptr,
325 spi_control_config_t *config,
326 uint8_t *cmd, uint32_t *addr,
327 uint32_t wcount, uint32_t rcount);
328
329 /**
330 * @brief spi wait for idle status
331 *
332 * @param [in] ptr SPI base address
333 * @retval hpm_stat_t status_success if spi in idle status
334 */
335 hpm_stat_t spi_wait_for_idle_status(SPI_Type *ptr);
336
337 /**
338 * @brief spi wait for busy status
339 *
340 * @param [in] ptr SPI base address
341 * @retval hpm_stat_t status_success if spi in busy status
342 */
343 hpm_stat_t spi_wait_for_busy_status(SPI_Type *ptr);
344
345 /**
346 * @brief Enables the SPI DMA request.
347 *
348 * This function configures the Rx and Tx DMA mask of the SPI. The parameters are base and a DMA mask.
349 *
350 * @param base SPI base address.
351 * @param mask The dma enable mask; Use the spi_dma_enable_t.
352 */
spi_enable_dma(SPI_Type * ptr,uint32_t mask)353 static inline void spi_enable_dma(SPI_Type *ptr, uint32_t mask)
354 {
355 ptr->CTRL |= mask;
356 }
357
358 /*!
359 * @brief Disables the SPI DMA request.
360 *
361 * This function configures the Rx and Tx DMA mask of the SPI. The parameters are base and a DMA mask.
362 *
363 * @param base SPI base address.
364 * @param mask The dma enable mask; Use the spi_dma_enable_t.
365 */
spi_disable_dma(SPI_Type * ptr,uint32_t mask)366 static inline void spi_disable_dma(SPI_Type *ptr, uint32_t mask)
367 {
368 ptr->CTRL &= ~mask;
369 }
370
371 /**
372 * @brief Get the SPI interrupt status.
373 *
374 * This function gets interrupt status of the SPI.
375 *
376 * @param base SPI base address.
377 * @retval SPI interrupt status register value
378 */
spi_get_interrupt_status(SPI_Type * ptr)379 static inline uint32_t spi_get_interrupt_status(SPI_Type *ptr)
380 {
381 return ptr->INTRST;
382 }
383
384 /**
385 * @brief Clear the SPI interrupt status.
386 *
387 * This function clears interrupt status of the SPI.
388 *
389 * @param base SPI base address.
390 * @param mask The interrupt mask; Use the spi_interrupt_t.
391 *
392 */
spi_clear_interrupt_status(SPI_Type * ptr,uint32_t mask)393 static inline void spi_clear_interrupt_status(SPI_Type *ptr, uint32_t mask)
394 {
395 /* write 1 to clear */
396 ptr->INTRST |= mask;
397 }
398
399 /**
400 * @brief Enables the SPI interrupt.
401 *
402 * This function configures interrupt of the SPI. The parameters are base and a interrupt mask.
403 *
404 * @param base SPI base address.
405 * @param mask The interrupt mask; Use the spi_interrupt_t.
406 */
spi_enable_interrupt(SPI_Type * ptr,uint32_t mask)407 static inline void spi_enable_interrupt(SPI_Type *ptr, uint32_t mask)
408 {
409 ptr->INTREN |= mask;
410 }
411
412 /*!
413 * @brief Disables the SPI interrupt.
414 *
415 * This function configures interrupt of the SPI. The parameters are base and a interrupt mask.
416 *
417 * @param base SPI base address.
418 * @param mask The interrupt mask; Use the spi_interrupt_t.
419 */
spi_disable_interrupt(SPI_Type * ptr,uint32_t mask)420 static inline void spi_disable_interrupt(SPI_Type *ptr, uint32_t mask)
421 {
422 ptr->INTREN &= ~mask;
423 }
424
425 /**
426 * @brief spi write and read data
427 *
428 * @note Call this function after SPI CONTROL is configured by spi_control_init.
429 * The order of reading and writing is controlled by spi_control_init.
430 *
431 * @param [in] ptr SPI base address
432 * @param [in] datalen data length in bit, use the spi_data_length_in_bits_t
433 * @param [in] wbuff spi sent data buff address
434 * @param [in] wcount spi sent data count, not greater than SPI_SOC_TRANSFER_COUNT_MAX
435 * @param [in] rbuff spi receive data buff address
436 * @param [in] rcount spi receive data count, not greater than SPI_SOC_TRANSFER_COUNT_MAX
437 * @retval hpm_stat_t status_success if spi transfer without any error
438 */
439 hpm_stat_t spi_write_read_data(SPI_Type *ptr, uint8_t datalen, uint8_t *wbuff, uint32_t wcount, uint8_t *rbuff, uint32_t rcount);
440
441 /**
442 * @brief spi read data
443 *
444 * @note Call this function after SPI CONTROL is configured by spi_control_init.
445 *
446 * @param [in] ptr SPI base address
447 * @param [in] datalen data length in bit, use the spi_data_length_in_bits_t
448 * @param [in] buff spi receive data buff address
449 * @param [in] count spi receive data count, not greater than SPI_SOC_TRANSFER_COUNT_MAX
450 * @retval hpm_stat_t status_success if spi transfer without any error
451 */
452 hpm_stat_t spi_read_data(SPI_Type *ptr, uint8_t datalen, uint8_t *buff, uint32_t count);
453
454 /**
455 * @brief spi write data
456 *
457 * @note Call this function after SPI CONTROL is configured by spi_control_init.
458 *
459 * @param [in] ptr SPI base address
460 * @param [in] datalen data length in bit, use the spi_data_length_in_bits_t
461 * @param [in] buff spi sent data buff address
462 * @param [in] count spi sent data count, not greater than SPI_SOC_TRANSFER_COUNT_MAX
463 * @retval hpm_stat_t status_success if spi transfer without any error
464 */
465 hpm_stat_t spi_write_data(SPI_Type *ptr, uint8_t datalen, uint8_t *buff, uint32_t count);
466
467 /**
468 * @brief spi write command
469 *
470 * @note Call this function after SPI CONTROL is configured by spi_control_init.
471 *
472 * @param [in] ptr SPI base address
473 * @param [in] mode spi mode, use the spi_mode_selection_t
474 * @param [in] config point to spi_control_config_t
475 * @param [in] cmd command data address
476 * @retval hpm_stat_t status_success if spi transfer without any error
477 */
478 hpm_stat_t spi_write_command(SPI_Type *ptr, spi_mode_selection_t mode, spi_control_config_t *config, uint8_t *cmd);
479
480 /**
481 * @brief spi control initialization
482 *
483 * @param [in] ptr SPI base address
484 * @param [in] config point to spi_control_config_t
485 * @param [in] wcount spi sent data count, not greater than SPI_SOC_TRANSFER_COUNT_MAX
486 * @param [in] rcount spi receive count, not greater than SPI_SOC_TRANSFER_COUNT_MAX
487 * @retval hpm_stat_t status_success if spi transfer without any error
488 */
489 hpm_stat_t spi_control_init(SPI_Type *ptr, spi_control_config_t *config, uint32_t wcount, uint32_t rcount);
490
491 /**
492 * @}
493 */
494
495 #if defined(__cplusplus)
496 }
497 #endif /* __cplusplus */
498 #endif /* HPM_SPI_DRV_H */
499