1 /*
2  * Copyright (c) 2021-2024 HPMicro
3  *
4  * SPDX-License-Identifier: BSD-3-Clause
5  *
6  */
7 
8 #ifndef HPM_SDXC_SOC_DRV_H
9 #define HPM_SDXC_SOC_DRV_H
10 
11 #include "hpm_soc.h"
12 #include "hpm_sdxc_regs.h"
13 
14 #if defined(__cplusplus)
15 extern "C" {
16 #endif
17 
18 /**
19  * @brief Enable TMCLK (for Data timeout detection)
20 */
sdxc_enable_tm_clock(SDXC_Type * base)21 static inline void sdxc_enable_tm_clock(SDXC_Type *base)
22 {
23     volatile uint32_t *reg = (base == HPM_SDXC0) ? &HPM_CONCTL->CTRL4 : &HPM_CONCTL->CTRL5;
24     (*reg) |= (1UL << 10);
25 }
26 
27 /**
28  * @brief Wait at least 74 clocks until card is ready to receive the first command
29  */
sdxc_wait_card_active(SDXC_Type * base)30 static inline void sdxc_wait_card_active(SDXC_Type *base)
31 {
32     base->SYS_CTRL |= SDXC_SYS_CTRL_SD_CLK_EN_MASK;
33 
34     while (!IS_HPM_BITMASK_SET(base->SYS_CTRL, SDXC_SYS_CTRL_SD_CLK_EN_MASK)) {
35     }
36     /*
37      * Assume that the BUS clock is 200MHz, while in the identification state, the SD clock is 400KHz.
38      *  - Reading the register costs about 5ns in best case, hence the loop should be (74 / 400KHz) * 1000000000 / 5
39      *  - For robustness, use 50000 here
40      */
41     for (volatile uint32_t i = 0; i < 50000U; i++) {
42         (void) base->CAPABILITIES1;
43     }
44 }
45 
sdxc_enable_inverse_clock(SDXC_Type * base,bool enable)46 static inline void sdxc_enable_inverse_clock(SDXC_Type *base, bool enable)
47 {
48     volatile uint32_t *reg = (base == HPM_SDXC0) ? &HPM_CONCTL->CTRL4 : &HPM_CONCTL->CTRL5;
49     if (enable) {
50         *reg |= (1UL << 28);
51     } else {
52         *reg &= ~(1UL << 28);
53     }
54 }
55 
sdxc_is_inverse_clock_enabled(SDXC_Type * base)56 static inline bool sdxc_is_inverse_clock_enabled(SDXC_Type *base)
57 {
58     volatile uint32_t *reg = (base == HPM_SDXC0) ? &HPM_CONCTL->CTRL4 : &HPM_CONCTL->CTRL5;
59     return ((*reg) & (1UL << 28)) != 0U;
60 }
61 
sdxc_select_cardclk_delay_source(SDXC_Type * base,bool delay_from_pad)62 static inline void sdxc_select_cardclk_delay_source(SDXC_Type *base, bool delay_from_pad)
63 {
64     (void) base;
65     (void) delay_from_pad;
66 }
67 
sdxc_set_cardclk_delay_chain(SDXC_Type * base,uint32_t delay_chain)68 static inline void sdxc_set_cardclk_delay_chain(SDXC_Type *base, uint32_t delay_chain)
69 {
70     (void) base;
71     volatile uint32_t *reg = (base == HPM_SDXC0) ? &HPM_CONCTL->CTRL4 : &HPM_CONCTL->CTRL5;
72     *reg = (*reg & ~CONCTL_CTRL4_SDXC0_GPR_TUNING_CARD_CLK_SEL_MASK) |
73            CONCTL_CTRL4_SDXC0_GPR_TUNING_CARD_CLK_SEL_SET(delay_chain);
74 }
75 
sdxc_set_data_strobe_delay(SDXC_Type * base,uint32_t num_delaycells)76 static inline void sdxc_set_data_strobe_delay(SDXC_Type *base, uint32_t num_delaycells)
77 {
78     (void) base;
79     volatile uint32_t *reg = (base == HPM_SDXC0) ? &HPM_CONCTL->CTRL4 : &HPM_CONCTL->CTRL5;
80     *reg = (*reg & ~CONCTL_CTRL4_SDXC0_GPR_TUNING_STROBE_SEL_MASK) |
81            CONCTL_CTRL4_SDXC0_GPR_TUNING_STROBE_SEL_SET(num_delaycells);
82     *reg |= CONCTL_CTRL4_SDXC0_GPR_STROBE_IN_ENABLE_MASK;
83 }
84 
85 
sdxc_get_default_strobe_delay(SDXC_Type * base)86 static inline uint32_t sdxc_get_default_strobe_delay(SDXC_Type *base)
87 {
88     (void) base;
89     return 0;
90 }
91 
sdxc_set_rxclk_delay_chain(SDXC_Type * base,uint32_t num_delaycells)92 static inline void sdxc_set_rxclk_delay_chain(SDXC_Type *base, uint32_t num_delaycells)
93 {
94     volatile uint32_t *reg = (base == HPM_SDXC0) ? &HPM_CONCTL->CTRL4 : &HPM_CONCTL->CTRL5;
95     *reg = (*reg & ~CONCTL_CTRL4_SDXC0_GPR_CCLK_RX_DLY_SW_SEL_MASK) |
96            CONCTL_CTRL4_SDXC0_GPR_CCLK_RX_DLY_SW_SEL_SET(num_delaycells);
97 
98     *reg |= CONCTL_CTRL4_SDXC0_GPR_CCLK_RX_DLY_SW_FORCE_MASK;
99 }
100 
sdxc_get_default_cardclk_delay_chain(SDXC_Type * base,uint32_t clock_freq)101 static inline uint32_t sdxc_get_default_cardclk_delay_chain(SDXC_Type *base, uint32_t clock_freq)
102 {
103     (void) base;
104     uint32_t num_delaycells = 1;
105     if (clock_freq <= 52000000) {
106         num_delaycells = 13;
107     }
108     return num_delaycells;
109 }
110 
sdxc_is_ddr50_supported(SDXC_Type * base)111 static inline bool sdxc_is_ddr50_supported(SDXC_Type *base)
112 {
113     (void) base;
114     return false;
115 }
116 
117 #if defined(__cplusplus)
118 }
119 #endif
120 
121 
122 #endif /* HPM_SDXC_SOC_DRV_H  */
123