summaryrefslogtreecommitdiff
path: root/components/drivers/sdio/host/sdio-dw.h
blob: 14dd05237bbf7a4cb62c1f8650b651a22e7dbfaa (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
/*
 * Copyright (c) 2006-2022, RT-Thread Development Team
 *
 * SPDX-License-Identifier: Apache-2.0
 *
 * Change Logs:
 * Date           Author       Notes
 * 2022-12-06     GuEe-GUI     first version
 */

#ifndef __SDIO_DW_H__
#define __SDIO_DW_H__

#include "../dev_sdio_dm.h"

#define SDIO_DW_CTRL                    0x000
#define SDIO_DW_PWREN                   0x004
#define SDIO_DW_CLKDIV                  0x008
#define SDIO_DW_CLKSRC                  0x00c
#define SDIO_DW_CLKENA                  0x010
#define SDIO_DW_TMOUT                   0x014
#define SDIO_DW_CTYPE                   0x018
#define SDIO_DW_BLKSIZ                  0x01c
#define SDIO_DW_BYTCNT                  0x020
#define SDIO_DW_INTMASK                 0x024
#define SDIO_DW_CMDARG                  0x028
#define SDIO_DW_CMD                     0x02c
#define SDIO_DW_RESP0                   0x030
#define SDIO_DW_RESP1                   0x034
#define SDIO_DW_RESP2                   0x038
#define SDIO_DW_RESP3                   0x03c
#define SDIO_DW_MINTSTS                 0x040
#define SDIO_DW_RINTSTS                 0x044
#define SDIO_DW_STATUS                  0x048
#define SDIO_DW_FIFOTH                  0x04c
#define SDIO_DW_CDETECT                 0x050
#define SDIO_DW_WRTPRT                  0x054
#define SDIO_DW_GPIO                    0x058
#define SDIO_DW_TCBCNT                  0x05c
#define SDIO_DW_TBBCNT                  0x060
#define SDIO_DW_DEBNCE                  0x064
#define SDIO_DW_USRID                   0x068
#define SDIO_DW_VERID                   0x06c
#define SDIO_DW_HCON                    0x070
#define SDIO_DW_UHS_REG                 0x074
#define SDIO_DW_RST_N                   0x078
#define SDIO_DW_BMOD                    0x080
#define SDIO_DW_PLDMND                  0x084
#define SDIO_DW_DBADDR                  0x088
#define SDIO_DW_IDSTS                   0x08c
#define SDIO_DW_IDINTEN                 0x090
#define SDIO_DW_DSCADDR                 0x094
#define SDIO_DW_BUFADDR                 0x098
#define SDIO_DW_CDTHRCTL                0x100
#define SDIO_DW_UHS_REG_EXT             0x108
#define SDIO_DW_DDR_REG                 0x10c
#define SDIO_DW_ENABLE_SHIFT            0x110
#define SDIO_DW_DATA(x)                 (x)
/*
 * Registers to support idmac 64-bit address mode
 */
#define SDIO_DW_DBADDRL                 0x088
#define SDIO_DW_DBADDRU                 0x08c
#define SDIO_DW_IDSTS64                 0x090
#define SDIO_DW_IDINTEN64               0x094
#define SDIO_DW_DSCADDRL                0x098
#define SDIO_DW_DSCADDRU                0x09c
#define SDIO_DW_BUFADDRL                0x0a0
#define SDIO_DW_BUFADDRU                0x0a4

/* Support for longer data read timeout */
#define SDIO_DW_QUIRK_EXTENDED_TMOUT    RT_BIT(0)

#define SDIO_DW_240A                    0x240a
#define SDIO_DW_280A                    0x280a

/*
 * Data offset is difference according to Version
 * Lower than 2.40a : data register offest is 0x100
 */
#define DATA_OFFSET                     0x100
#define DATA_240A_OFFSET                0x200

/* Control register defines */
#define SDIO_DW_CTRL_USE_IDMAC          RT_BIT(25)
#define SDIO_DW_CTRL_CEATA_INT_EN       RT_BIT(11)
#define SDIO_DW_CTRL_SEND_AS_CCSD       RT_BIT(10)
#define SDIO_DW_CTRL_SEND_CCSD          RT_BIT(9)
#define SDIO_DW_CTRL_ABRT_READ_DATA     RT_BIT(8)
#define SDIO_DW_CTRL_SEND_IRQ_RESP      RT_BIT(7)
#define SDIO_DW_CTRL_READ_WAIT          RT_BIT(6)
#define SDIO_DW_CTRL_DMA_ENABLE         RT_BIT(5)
#define SDIO_DW_CTRL_INT_ENABLE         RT_BIT(4)
#define SDIO_DW_CTRL_DMA_RESET          RT_BIT(2)
#define SDIO_DW_CTRL_FIFO_RESET         RT_BIT(1)
#define SDIO_DW_CTRL_RESET              RT_BIT(0)
/* Clock Enable register defines */
#define SDIO_DW_CLKEN_LOW_PWR           RT_BIT(16)
#define SDIO_DW_CLKEN_ENABLE            RT_BIT(0)
/* Time-out register defines */
#define SDIO_DW_TMOUT_DATA(n)           ((n) << 8)
#define SDIO_DW_TMOUT_DATA_MSK          0xffffff00
#define SDIO_DW_TMOUT_RESP(n)           ((n) & 0xff)
#define SDIO_DW_TMOUT_RESP_MSK          0xff
/* Card-type register defines */
#define SDIO_DW_CTYPE_8BIT              RT_BIT(16)
#define SDIO_DW_CTYPE_4BIT              RT_BIT(0)
#define SDIO_DW_CTYPE_1BIT              0
/* Interrupt status & mask register defines */
#define SDIO_DW_INT_SDIO(n)             RT_BIT(16 + (n))
#define SDIO_DW_INT_RAW_SDIO            RT_BIT(24)
#define SDIO_DW_INT_EBE                 RT_BIT(15)
#define SDIO_DW_INT_ACD                 RT_BIT(14)
#define SDIO_DW_INT_SBE                 RT_BIT(13)
#define SDIO_DW_INT_HLE                 RT_BIT(12)
#define SDIO_DW_INT_FRUN                RT_BIT(11)
#define SDIO_DW_INT_HTO                 RT_BIT(10)
#define SDIO_DW_INT_VOLT_SWITCH         RT_BIT(10)
#define SDIO_DW_INT_DRTO                RT_BIT(9)
#define SDIO_DW_INT_RTO                 RT_BIT(8)
#define SDIO_DW_INT_DCRC                RT_BIT(7)
#define SDIO_DW_INT_RCRC                RT_BIT(6)
#define SDIO_DW_INT_RXDR                RT_BIT(5)
#define SDIO_DW_INT_TXDR                RT_BIT(4)
#define SDIO_DW_INT_DATA_OVER           RT_BIT(3)
#define SDIO_DW_INT_CMD_DONE            RT_BIT(2)
#define SDIO_DW_INT_RESP_ERR            RT_BIT(1)
#define SDIO_DW_INT_CD                  RT_BIT(0)
#define SDIO_DW_INT_ERROR               0xbfc2
/* Command register defines */
#define SDIO_DW_CMD_START               RT_BIT(31)
#define SDIO_DW_CMD_USE_HOLD_REG        RT_BIT(29)
#define SDIO_DW_CMD_VOLT_SWITCH         RT_BIT(28)
#define SDIO_DW_CMD_CCS_EXP             RT_BIT(23)
#define SDIO_DW_CMD_CEATA_RD            RT_BIT(22)
#define SDIO_DW_CMD_UPD_CLK             RT_BIT(21)
#define SDIO_DW_CMD_INIT                RT_BIT(15)
#define SDIO_DW_CMD_STOP                RT_BIT(14)
#define SDIO_DW_CMD_PRV_DAT_WAIT        RT_BIT(13)
#define SDIO_DW_CMD_SEND_STOP           RT_BIT(12)
#define SDIO_DW_CMD_STRM_MODE           RT_BIT(11)
#define SDIO_DW_CMD_DAT_WR              RT_BIT(10)
#define SDIO_DW_CMD_DAT_EXP             RT_BIT(9)
#define SDIO_DW_CMD_RESP_CRC            RT_BIT(8)
#define SDIO_DW_CMD_RESP_LONG           RT_BIT(7)
#define SDIO_DW_CMD_RESP_EXP            RT_BIT(6)
#define SDIO_DW_CMD_INDX(n)             ((n) & 0x1f)
/* Status register defines */
#define SDIO_DW_GET_FCNT(x)             (((x) >> 17) & 0x1fff)
#define SDIO_DW_STATUS_DMA_REQ          RT_BIT(31)
#define SDIO_DW_STATUS_BUSY             RT_BIT(9)
/* FIFOTH register defines */
#define SDIO_DW_SET_FIFOTH(m, r, t)     (((m) & 0x7) << 28 | ((r) & 0xfff) << 16 | ((t) & 0xfff))
/* HCON register defines */
#define DMA_INTERFACE_IDMA              (0x0)
#define DMA_INTERFACE_DWDMA             (0x1)
#define DMA_INTERFACE_GDMA              (0x2)
#define DMA_INTERFACE_NODMA             (0x3)
#define SDIO_DW_GET_TRANS_MODE(x)       (((x) >> 16) & 0x3)
#define SDIO_DW_GET_SLOT_NUM(x)         ((((x) >> 1) & 0x1f) + 1)
#define SDIO_DW_GET_HDATA_WIDTH(x)      (((x) >> 7) & 0x7)
#define SDIO_DW_GET_ADDR_CONFIG(x)      (((x) >> 27) & 0x1)
/* Internal DMAC interrupt defines */
#define SDIO_DW_IDMAC_INT_AI            RT_BIT(9)
#define SDIO_DW_IDMAC_INT_NI            RT_BIT(8)
#define SDIO_DW_IDMAC_INT_CES           RT_BIT(5)
#define SDIO_DW_IDMAC_INT_DU            RT_BIT(4)
#define SDIO_DW_IDMAC_INT_FBE           RT_BIT(2)
#define SDIO_DW_IDMAC_INT_RI            RT_BIT(1)
#define SDIO_DW_IDMAC_INT_TI            RT_BIT(0)
/* Internal DMAC bus mode bits */
#define SDIO_DW_IDMAC_ENABLE            RT_BIT(7)
#define SDIO_DW_IDMAC_FB                RT_BIT(1)
#define SDIO_DW_IDMAC_SWRESET           RT_BIT(0)
/* H/W reset */
#define SDIO_DW_RST_HWACTIVE            0x1
/* Version ID register define */
#define SDIO_DW_GET_VERID(x)            ((x) & 0xffff)
/* Card read threshold */
#define SDIO_DW_SET_THLD(v, x)          (((v) & 0xfff) << 16 | (x))
#define SDIO_DW_CARD_WR_THR_EN          RT_BIT(2)
#define SDIO_DW_CARD_RD_THR_EN          RT_BIT(0)
/* UHS-1 register defines */
#define SDIO_DW_UHS_DDR                 RT_BIT(16)
#define SDIO_DW_UHS_18V                 RT_BIT(0)
/* DDR register defines */
#define SDIO_DW_DDR_HS400               RT_BIT(31)
/* Enable shift register defines */
#define SDIO_DW_ENABLE_PHASE            RT_BIT(0)
/* All ctrl reset bits */
#define SDIO_DW_CTRL_ALL_RESET_FLAGS    (SDIO_DW_CTRL_RESET | SDIO_DW_CTRL_FIFO_RESET | SDIO_DW_CTRL_DMA_RESET)

struct rt_dma_chan;

struct sdio_dw
{
    struct rt_device parent;
    struct rt_device *bus_dev;

    struct rt_workqueue *state_wq;
    struct rt_work state_work;

    void *base;
    void *fifo_base;
    rt_ubase_t base_phy;
    rt_uint32_t data_addr_override;
    rt_bool_t wm_aligned;

    int irq;
    int sdio_id0;
    rt_uint32_t verid;
    rt_uint32_t quirks;
    rt_uint32_t bus_hz;
    rt_bool_t fifo_mode;
    rt_uint32_t fifo_depth;
    rt_uint32_t fifoth_val;
    rt_uint32_t detect_delay_ms;
    rt_uint32_t current_speed;
    rt_uint32_t minimum_speed;
    void *priv;

    rt_uint32_t vqmmc_enabled;
    rt_uint32_t cmd_status;
    rt_uint32_t data_status;
    rt_uint32_t stop_cmdr;
    rt_uint32_t dir_status;
#define STATE_IDLE                  0
#define STATE_SENDING_CMD           1
#define STATE_SENDING_DATA          2
#define STATE_DATA_BUSY             3
#define STATE_SENDING_STOP          4
#define STATE_DATA_ERROR            5
#define STATE_SENDING_CMD11         6
#define STATE_WAITING_CMD11_DONE    7
    rt_uint32_t state;
#define EVENT_CMD_COMPLETE          0
#define EVENT_XFER_COMPLETE         1
#define EVENT_DATA_COMPLETE         2
#define EVENT_DATA_ERROR            3
    rt_bitmap_t pending_events;

    struct rt_mmcsd_req *req;
    struct rt_mmcsd_data *data;
    struct rt_mmcsd_cmd *cmd;
    struct rt_mmcsd_cmd stop_abort;
    rt_uint32_t prev_blksz;
    rt_uint8_t timing;

    struct rt_clk *biu_clk;
    struct rt_clk *ciu_clk;

    void *last_buf;
    rt_uint32_t last_remain;

    int data_shift;
    rt_uint8_t part_buf_start;
    rt_uint8_t part_buf_count;
    union
    {
        rt_uint64_t part_buf;
        rt_uint16_t part_buf16;
        rt_uint32_t part_buf32;
        rt_uint64_t part_buf64;
    };
    void (*push_data)(struct sdio_dw *sd, void *buf, int cnt);
    void (*pull_data)(struct sdio_dw *sd, void *buf, int cnt);

    /* DMA interface members */
#define TRANS_MODE_PIO      0
#define TRANS_MODE_IDMAC    1
#define TRANS_MODE_EDMAC    2
    rt_bool_t use_dma;
    rt_bool_t using_dma;
    rt_bool_t dma_64bit_address;
    rt_size_t ring_size;
    void *dma_buf;
    rt_ubase_t dma_buf_phy;
    struct rt_dma_chan *edma_chan;
    const struct sdio_dw_dma_ops *dma_ops;

    struct rt_timer cmd11_timer;
    struct rt_timer cto_timer;
    struct rt_timer dto_timer;

    struct rt_reset_control *rstc;

    struct sdio_dw_slot *slot;
    const struct sdio_dw_drv_data *drv_data;

    struct rt_spinlock lock, irq_lock;
};

/* DMA ops for Internal/External DMAC interface */
struct sdio_dw_dma_ops
{
    rt_err_t (*init)(struct sdio_dw *sd);
    rt_err_t (*start)(struct sdio_dw *sd);
    rt_err_t (*complete)(struct sdio_dw *sd);
    rt_err_t (*stop)(struct sdio_dw *sd);
    rt_err_t (*cleanup)(struct sdio_dw *sd);
    rt_err_t (*exit)(struct sdio_dw *sd);
};

struct sdio_dw_slot
{
    struct rt_mmcsd_host *host;
    struct sdio_dw *sd;

    rt_uint32_t ctype;

    struct rt_mmcsd_req *req;

    rt_uint32_t clock;
    rt_uint32_t clk_old;

#define DW_MMC_CARD_PRESENT     0
#define DW_MMC_CARD_NEED_INIT   1
#define DW_MMC_CARD_NO_LOW_PWR  2
#define DW_MMC_CARD_NO_USE_HOLD 3
#define DW_MMC_CARD_NEEDS_POLL  4
    rt_bitmap_t flags;

    int id;
    int sdio_id;
};

struct sdio_dw_drv_data
{
    rt_ubase_t *caps;
    rt_uint32_t num_caps;
    rt_uint32_t common_caps;

    rt_err_t    (*init)(struct sdio_dw *sd);
    rt_err_t    (*set_iocfg)(struct sdio_dw *sd, struct rt_mmcsd_io_cfg *ios);
    rt_err_t    (*parse_ofw)(struct sdio_dw *sd);
    rt_err_t    (*execute_tuning)(struct sdio_dw_slot *slot, rt_uint32_t opcode);
    rt_err_t    (*prepare_hs400_tuning)(struct sdio_dw *sd, struct rt_mmcsd_io_cfg *ios);
    rt_err_t    (*switch_voltage)(struct rt_mmcsd_host *host, struct rt_mmcsd_io_cfg *ios);
    rt_err_t    (*set_data_timeout)(struct sdio_dw *sd, rt_uint32_t timeout_ns);
    rt_uint32_t (*get_drto_clks)(struct sdio_dw *sd);
};

#define sdio_dw_writel(sd, reg, val)    HWREG32((sd)->base + SDIO_DW_##reg) = (val)
#define sdio_dw_writew(sd, reg, val)    HWREG16((sd)->base + SDIO_DW_##reg) = (val)
#define sdio_dw_writeb(sd, reg, val)    HWREG8((sd)->base + SDIO_DW_##reg) = (val)

#define sdio_dw_readl(sd, reg)          HWREG32((sd)->base + SDIO_DW_##reg)
#define sdio_dw_readw(sd, reg)          HWREG16((sd)->base + SDIO_DW_##reg)
#define sdio_dw_readb(sd, reg)          HWREG8((sd)->base + SDIO_DW_##reg)

#define sdio_dw_fifo_writew(sd, val)    HWREG16((sd)->fifo_base) = (val)
#define sdio_dw_fifo_writel(sd, val)    HWREG32((sd)->fifo_base) = (val)
#define sdio_dw_fifo_writeq(sd, val)    HWREG64((sd)->fifo_base) = (val)

#define sdio_dw_fifo_readw(sd)          HWREG16((sd)->fifo_base)
#define sdio_dw_fifo_readl(sd)          HWREG32((sd)->fifo_base)
#define sdio_dw_fifo_readq(sd)          HWREG64((sd)->fifo_base)

rt_err_t sdio_dw_probe(struct sdio_dw *sd);
rt_err_t sdio_dw_remove(struct sdio_dw *sd);

#endif /* __SDIO_DW_H__ */