1 /*
2  * Copyright (c) 2006-2023, RT-Thread Development Team
3  *
4  * SPDX-License-Identifier: Apache-2.0
5  *
6  * Change Logs:
7  * Date           Author       Notes
8  * 2023-03-14     luobeihai    first version
9  * 2023-03-27     luobeihai    add APM32E1 series MCU support
10  */
11 
12 #ifndef _DRV_SDIO_H
13 #define _DRV_SDIO_H
14 #include <rtthread.h>
15 #include "rtdevice.h"
16 #include <rthw.h>
17 #include <string.h>
18 #include <drivers/dev_mmcsd_core.h>
19 #include <drivers/dev_sdio.h>
20 #include "drv_common.h"
21 #include "board.h"
22 
23 #define SDCARD_INSTANCE_TYPE              SDIO_T
24 
25 #define SDCARD_INSTANCE                   SDIO
26 
27 #define SDIO_BUFF_SIZE       4096
28 #define SDIO_ALIGN_LEN       32
29 
30 #ifndef SDIO_BASE_ADDRESS
31 #define SDIO_BASE_ADDRESS    (0x40012800U)
32 #endif
33 
34 #ifndef SDIO_CLOCK_FREQ
35 #define SDIO_CLOCK_FREQ      (48U * 1000 * 1000)
36 #endif
37 
38 #ifndef SDIO_BUFF_SIZE
39 #define SDIO_BUFF_SIZE       (4096)
40 #endif
41 
42 #ifndef SDIO_ALIGN_LEN
43 #define SDIO_ALIGN_LEN       (32)
44 #endif
45 
46 #ifndef SDIO_MAX_FREQ
47 #define SDIO_MAX_FREQ        (24 * 1000 * 1000)
48 #endif
49 
50 #define HW_SDIO_IT_CCRCFAIL                    (0x01U << 0)
51 #define HW_SDIO_IT_DCRCFAIL                    (0x01U << 1)
52 #define HW_SDIO_IT_CTIMEOUT                    (0x01U << 2)
53 #define HW_SDIO_IT_DTIMEOUT                    (0x01U << 3)
54 #define HW_SDIO_IT_TXUNDERR                    (0x01U << 4)
55 #define HW_SDIO_IT_RXOVERR                     (0x01U << 5)
56 #define HW_SDIO_IT_CMDREND                     (0x01U << 6)
57 #define HW_SDIO_IT_CMDSENT                     (0x01U << 7)
58 #define HW_SDIO_IT_DATAEND                     (0x01U << 8)
59 #define HW_SDIO_IT_STBITERR                    (0x01U << 9)
60 #define HW_SDIO_IT_DBCKEND                     (0x01U << 10)
61 #define HW_SDIO_IT_CMDACT                      (0x01U << 11)
62 #define HW_SDIO_IT_TXACT                       (0x01U << 12)
63 #define HW_SDIO_IT_RXACT                       (0x01U << 13)
64 #define HW_SDIO_IT_TXFIFOHE                    (0x01U << 14)
65 #define HW_SDIO_IT_RXFIFOHF                    (0x01U << 15)
66 #define HW_SDIO_IT_TXFIFOF                     (0x01U << 16)
67 #define HW_SDIO_IT_RXFIFOF                     (0x01U << 17)
68 #define HW_SDIO_IT_TXFIFOE                     (0x01U << 18)
69 #define HW_SDIO_IT_RXFIFOE                     (0x01U << 19)
70 #define HW_SDIO_IT_TXDAVL                      (0x01U << 20)
71 #define HW_SDIO_IT_RXDAVL                      (0x01U << 21)
72 #define HW_SDIO_IT_SDIOIT                      (0x01U << 22)
73 
74 #define HW_SDIO_ERRORS \
75     (HW_SDIO_IT_CCRCFAIL | HW_SDIO_IT_CTIMEOUT | \
76      HW_SDIO_IT_DCRCFAIL | HW_SDIO_IT_DTIMEOUT | \
77      HW_SDIO_IT_RXOVERR  | HW_SDIO_IT_TXUNDERR)
78 
79 #define HW_SDIO_POWER_OFF                      (0x00U)
80 #define HW_SDIO_POWER_UP                       (0x02U)
81 #define HW_SDIO_POWER_ON                       (0x03U)
82 
83 #define HW_SDIO_FLOW_ENABLE                    (0x01U << 14)
84 #define HW_SDIO_BUSWIDE_1B                     (0x00U << 11)
85 #define HW_SDIO_BUSWIDE_4B                     (0x01U << 11)
86 #define HW_SDIO_BUSWIDE_8B                     (0x02U << 11)
87 #define HW_SDIO_BYPASS_ENABLE                  (0x01U << 10)
88 #define HW_SDIO_IDLE_ENABLE                    (0x01U << 9)
89 #define HW_SDIO_CLK_ENABLE                     (0x01U << 8)
90 
91 #define HW_SDIO_SUSPEND_CMD                    (0x01U << 11)
92 #define HW_SDIO_CPSM_ENABLE                    (0x01U << 10)
93 #define HW_SDIO_WAIT_END                       (0x01U << 9)
94 #define HW_SDIO_WAIT_INT                       (0x01U << 8)
95 #define HW_SDIO_RESPONSE_NO                    (0x00U << 6)
96 #define HW_SDIO_RESPONSE_SHORT                 (0x01U << 6)
97 #define HW_SDIO_RESPONSE_LONG                  (0x03U << 6)
98 
99 #define HW_SDIO_DATA_LEN_MASK                  (0x01FFFFFFU)
100 
101 #define HW_SDIO_IO_ENABLE                      (0x01U << 11)
102 #define HW_SDIO_RWMOD_CK                       (0x01U << 10)
103 #define HW_SDIO_RWSTOP_ENABLE                  (0x01U << 9)
104 #define HW_SDIO_RWSTART_ENABLE                 (0x01U << 8)
105 #define HW_SDIO_DBLOCKSIZE_1                   (0x00U << 4)
106 #define HW_SDIO_DBLOCKSIZE_2                   (0x01U << 4)
107 #define HW_SDIO_DBLOCKSIZE_4                   (0x02U << 4)
108 #define HW_SDIO_DBLOCKSIZE_8                   (0x03U << 4)
109 #define HW_SDIO_DBLOCKSIZE_16                  (0x04U << 4)
110 #define HW_SDIO_DBLOCKSIZE_32                  (0x05U << 4)
111 #define HW_SDIO_DBLOCKSIZE_64                  (0x06U << 4)
112 #define HW_SDIO_DBLOCKSIZE_128                 (0x07U << 4)
113 #define HW_SDIO_DBLOCKSIZE_256                 (0x08U << 4)
114 #define HW_SDIO_DBLOCKSIZE_512                 (0x09U << 4)
115 #define HW_SDIO_DBLOCKSIZE_1024                (0x0AU << 4)
116 #define HW_SDIO_DBLOCKSIZE_2048                (0x0BU << 4)
117 #define HW_SDIO_DBLOCKSIZE_4096                (0x0CU << 4)
118 #define HW_SDIO_DBLOCKSIZE_8192                (0x0DU << 4)
119 #define HW_SDIO_DBLOCKSIZE_16384               (0x0EU << 4)
120 #define HW_SDIO_DMA_ENABLE                     (0x01U << 3)
121 #define HW_SDIO_STREAM_ENABLE                  (0x01U << 2)
122 #define HW_SDIO_TO_HOST                        (0x01U << 1)
123 #define HW_SDIO_DPSM_ENABLE                    (0x01U << 0)
124 
125 #define HW_SDIO_DATATIMEOUT                    (0xF0000000U)
126 
127 #if defined (SOC_SERIES_APM32F1) || defined (SOC_SERIES_APM32E1)
128 #define SDIO_BUS_CONFIG                                  \
129     {                                                    \
130         .Instance = SDIO,                                \
131         .dma_rx.dma_rcm = RCM_AHB_PERIPH_DMA2,           \
132         .dma_tx.dma_rcm = RCM_AHB_PERIPH_DMA2,           \
133         .dma_rx.Instance = DMA2_Channel4,                \
134         .dma_rx.dma_irq = DMA2_Channel4_5_IRQn,          \
135         .dma_tx.Instance = DMA2_Channel4,                \
136         .dma_tx.dma_irq = DMA2_Channel4_5_IRQn,          \
137     }
138 #elif defined (SOC_SERIES_APM32F4)
139 #define SDIO_BUS_CONFIG                                  \
140     {                                                    \
141         .Instance = SDIO,                                \
142         .dma_rx.dma_rcm = RCM_AHB1_PERIPH_DMA2,          \
143         .dma_tx.dma_rcm = RCM_AHB1_PERIPH_DMA2,          \
144         .dma_rx.Instance = DMA2_Stream3,                 \
145         .dma_rx.channel = DMA_CHANNEL_4,                 \
146         .dma_rx.dma_irq = DMA2_STR3_IRQn,                \
147         .dma_tx.Instance = DMA2_Stream6,                 \
148         .dma_tx.channel = DMA_CHANNEL_4,                 \
149         .dma_tx.dma_irq = DMA2_STR6_IRQn,                \
150     }
151 #endif /* SOC_SERIES_APM32F1 */
152 
153 #if defined (SOC_SERIES_APM32F1) || defined (SOC_SERIES_APM32E1)
154 #define DMA_INSTANCE_TYPE              DMA_Channel_T
155 #elif defined (SOC_SERIES_APM32F4)
156 #define DMA_INSTANCE_TYPE              DMA_Stream_T
157 #endif
158 
159 struct apm32_sdio
160 {
161     volatile rt_uint32_t power;
162     volatile rt_uint32_t clkcr;
163     volatile rt_uint32_t arg;
164     volatile rt_uint32_t cmd;
165     volatile rt_uint32_t respcmd;
166     volatile rt_uint32_t resp1;
167     volatile rt_uint32_t resp2;
168     volatile rt_uint32_t resp3;
169     volatile rt_uint32_t resp4;
170     volatile rt_uint32_t dtimer;
171     volatile rt_uint32_t dlen;
172     volatile rt_uint32_t dctrl;
173     volatile rt_uint32_t dcount;
174     volatile rt_uint32_t sta;
175     volatile rt_uint32_t icr;
176     volatile rt_uint32_t mask;
177     volatile rt_uint32_t reserved0[2];
178     volatile rt_uint32_t fifocnt;
179     volatile rt_uint32_t reserved1[13];
180     volatile rt_uint32_t fifo;
181 };
182 
183 typedef rt_err_t (*dma_txconfig)(rt_uint32_t *src, rt_uint32_t *dst, int size);
184 typedef rt_err_t (*dma_rxconfig)(rt_uint32_t *src, rt_uint32_t *dst, int size);
185 typedef rt_uint32_t (*sdio_clk_get)(struct apm32_sdio *hw_sdio);
186 
187 struct dma_config {
188     DMA_INSTANCE_TYPE *Instance;
189 #if defined (SOC_SERIES_APM32F4)
190     DMA_CHANNEL_T channel;
191 #endif
192     rt_uint32_t dma_rcm;
193     IRQn_Type dma_irq;
194 };
195 
196 struct apm32_sdio_des
197 {
198     struct apm32_sdio *hw_sdio;
199     dma_txconfig txconfig;
200     dma_rxconfig rxconfig;
201     sdio_clk_get clk_get;
202 };
203 
204 struct apm32_sdio_config
205 {
206     SDCARD_INSTANCE_TYPE *Instance;
207     struct dma_config dma_rx, dma_tx;
208 };
209 
210 /* apm32 sdio dirver class */
211 struct apm32_sdio_class
212 {
213     struct apm32_sdio_des *des;
214     const struct apm32_sdio_config *cfg;
215     struct rt_mmcsd_host host;
216     struct
217     {
218         DMA_INSTANCE_TYPE *handle_rx;
219         DMA_INSTANCE_TYPE *handle_tx;
220     } dma;
221 };
222 
223 extern void apm32_mmcsd_change(void);
224 
225 #endif
226