1 /*
2  * Copyright (c) 2006-2021, RT-Thread Development Team
3  *
4  * SPDX-License-Identifier: Apache-2.0
5  *
6  * Change Logs:
7  * Date           Author       Notes
8  */
9 
10 #include <rtthread.h>
11 #include <rthw.h>
12 #include <drivers/dev_mmcsd_core.h>
13 #include <drivers/dev_sdio.h>
14 
15 #include "stm32l4xx.h"
16 
17 #ifdef BSP_USING_STM32_SDIO
18 
19 #include <stm32_sdio.h>
20 
21 static DMA_HandleTypeDef SDTxDMAHandler;
22 static DMA_HandleTypeDef SDRxDMAHandler;
23 
24 static struct rt_mmcsd_host *host;
25 
SDMMC1_IRQHandler(void)26 void SDMMC1_IRQHandler(void)
27 {
28     /* enter interrupt */
29     rt_interrupt_enter();
30 
31     /* Process All SDIO Interrupt Sources */
32     rthw_sdio_irq_process(host);
33 
34     /* leave interrupt */
35     rt_interrupt_leave();
36 }
37 
38 /**
39   * @brief  Configures the DMA2 Channel4 for SDIO Tx request.
40   * @param  BufferSRC: pointer to the source buffer
41   * @param  BufferSize: buffer size
42   * @retval None
43   */
SD_LowLevel_DMA_TxConfig(uint32_t * src,uint32_t * dst,uint32_t BufferSize)44 void SD_LowLevel_DMA_TxConfig(uint32_t *src, uint32_t *dst, uint32_t BufferSize)
45 {
46     DMA2_Channel4->CCR &= ~0x00000001;
47 
48     DMA2->IFCR = DMA_ISR_GIF1 << 4;
49 
50     DMA2_CSELR->CSELR &= ~(0xf << (3 * 4));   // channel 4
51     DMA2_CSELR->CSELR |= (uint32_t) (0x07 << (3 * 4));
52 
53     DMA2_Channel4->CCR   = DMA_MEMORY_TO_PERIPH | DMA_PINC_DISABLE | DMA_MINC_ENABLE | \
54                            DMA_PDATAALIGN_WORD | DMA_MDATAALIGN_WORD | DMA_NORMAL | DMA_PRIORITY_MEDIUM;
55     DMA2_Channel4->CNDTR = BufferSize;
56     DMA2_Channel4->CPAR  = (uint32_t)dst;
57     DMA2_Channel4->CMAR = (uint32_t)src;
58 
59     DMA2_Channel4->CCR  |= 0x00000001;
60 
61 //    HAL_DMA_Start(&SDTxDMAHandler, (uint32_t)src, (uint32_t)dst, BufferSize);
62 }
63 
64 /**
65   * @brief  Configures the DMA2 Channel4 for SDIO Rx request.
66   * @param  BufferDST: pointer to the destination buffer
67   * @param  BufferSize: buffer size
68   * @retval None
69   */
SD_LowLevel_DMA_RxConfig(uint32_t * src,uint32_t * dst,uint32_t BufferSize)70 void SD_LowLevel_DMA_RxConfig(uint32_t *src, uint32_t *dst, uint32_t BufferSize)
71 {
72 
73     DMA2_Channel4->CCR &= ~0x00000001;
74 
75     DMA2->IFCR = DMA_ISR_GIF1 << 4;
76 
77     DMA2_CSELR->CSELR &= ~(0xf << (3 * 4));   // channel 4
78     DMA2_CSELR->CSELR |= (uint32_t) (0x07 << (3 * 4));
79 
80     DMA2_Channel4->CCR   = DMA_PERIPH_TO_MEMORY | DMA_PINC_DISABLE | DMA_MINC_ENABLE | \
81                            DMA_PDATAALIGN_WORD | DMA_MDATAALIGN_WORD | DMA_NORMAL | DMA_PRIORITY_MEDIUM;
82     DMA2_Channel4->CNDTR = BufferSize;
83     DMA2_Channel4->CPAR  = (uint32_t)src;
84     DMA2_Channel4->CMAR = (uint32_t)dst;
85 
86     DMA2_Channel4->CCR  |= 0x00000001;
87 }
88 
SD_LowLevel_Init(void)89 void SD_LowLevel_Init(void)
90 {
91     {
92         // clock enable
93         __HAL_RCC_GPIOB_CLK_ENABLE();
94         __HAL_RCC_GPIOC_CLK_ENABLE();
95         __HAL_RCC_GPIOD_CLK_ENABLE();
96         __HAL_RCC_DMA2_CLK_ENABLE();
97         __HAL_RCC_SDMMC1_CLK_ENABLE();
98     }
99 
100     {
101         HAL_NVIC_EnableIRQ(SDMMC1_IRQn);
102     }
103 
104     {
105         // init sdio hardware
106         GPIO_InitTypeDef GPIO_InitStruct;
107 
108         /*Configure GPIO pin Output Level */
109         HAL_GPIO_WritePin(GPIOD, GPIO_PIN_1, GPIO_PIN_RESET);
110         GPIO_InitStruct.Pin = GPIO_PIN_1;
111         GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP;
112         GPIO_InitStruct.Pull = GPIO_NOPULL;
113         GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW;
114         HAL_GPIO_Init(GPIOD, &GPIO_InitStruct);
115         rt_thread_delay(1);
116         HAL_GPIO_WritePin(GPIOD, GPIO_PIN_1, GPIO_PIN_SET);
117 
118         /* Setup GPIO pins for SDIO data & clock */
119         /**SDMMC1 GPIO Configuration
120         PC8     ------> SDMMC1_D0
121         PC9     ------> SDMMC1_D1
122         PC10     ------> SDMMC1_D2
123         PC11     ------> SDMMC1_D3
124         PC12     ------> SDMMC1_CK
125         PD2     ------> SDMMC1_CMD
126         */
127         GPIO_InitStruct.Pin = GPIO_PIN_9;
128         GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;
129         GPIO_InitStruct.Pull = GPIO_PULLUP;
130         GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_VERY_HIGH;
131         GPIO_InitStruct.Alternate = GPIO_AF12_SDMMC1;
132         HAL_GPIO_Init(GPIOC, &GPIO_InitStruct);
133 
134         GPIO_InitStruct.Pin = GPIO_PIN_8 | GPIO_PIN_10 | GPIO_PIN_11
135                               | GPIO_PIN_12;
136         GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;
137         GPIO_InitStruct.Pull = GPIO_PULLUP;
138         GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_VERY_HIGH;
139         GPIO_InitStruct.Alternate = GPIO_AF12_SDMMC1;
140         HAL_GPIO_Init(GPIOC, &GPIO_InitStruct);
141 
142         GPIO_InitStruct.Pin = GPIO_PIN_2;
143         GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;
144         GPIO_InitStruct.Pull = GPIO_PULLUP;
145         GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_VERY_HIGH;
146         GPIO_InitStruct.Alternate = GPIO_AF12_SDMMC1;
147 
148         HAL_GPIO_Init(GPIOD, &GPIO_InitStruct);
149     }
150 
151     {
152     }
153 }
154 
stm32_sdio_clock_get(struct stm32_sdio * hw_sdio)155 static rt_uint32_t stm32_sdio_clock_get(struct stm32_sdio *hw_sdio)
156 {
157     return HAL_RCCEx_GetPeriphCLKFreq(RCC_PERIPHCLK_SDMMC1);
158 }
159 
DMA_TxConfig(rt_uint32_t * src,rt_uint32_t * dst,int Size)160 static rt_err_t DMA_TxConfig(rt_uint32_t *src, rt_uint32_t *dst, int Size)
161 {
162     SD_LowLevel_DMA_TxConfig((uint32_t *)src, (uint32_t *)dst, Size / 4);
163     return RT_EOK;
164 }
165 
DMA_RxConfig(rt_uint32_t * src,rt_uint32_t * dst,int Size)166 static rt_err_t DMA_RxConfig(rt_uint32_t *src, rt_uint32_t *dst, int Size)
167 {
168     SD_LowLevel_DMA_RxConfig((uint32_t *)src, (uint32_t *)dst, Size / 4);
169     return RT_EOK;
170 }
171 
stm32f4xx_sdio_init(void)172 int stm32f4xx_sdio_init(void)
173 {
174     struct stm32_sdio_des sdio_des;
175 
176     SD_LowLevel_Init();
177 
178     sdio_des.clk_get = stm32_sdio_clock_get;
179     sdio_des.hw_sdio = (struct stm32_sdio *)0x40012800U;
180     sdio_des.rxconfig = DMA_RxConfig;
181     sdio_des.txconfig = DMA_TxConfig;
182 
183     host = sdio_host_create(&sdio_des);
184     if (host == RT_NULL)
185     {
186         rt_kprintf("%s host create fail\n");
187         return -1;
188     }
189 
190     return 0;
191 }
192 INIT_DEVICE_EXPORT(stm32f4xx_sdio_init);
193 
194 #endif
195