hc
2024-05-10 23fa18eaa71266feff7ba8d83022d9e1cc83c65a
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
/*
 * ARM PrimeCell MultiMedia Card Interface - PL180
 *
 * Copyright (C) ST-Ericsson SA 2010
 *
 * Author: Ulf Hansson <ulf.hansson@stericsson.com>
 * Author: Martin Lundholm <martin.xa.lundholm@stericsson.com>
 * Ported to drivers/mmc/ by: Matt Waddel <matt.waddel@linaro.org>
 *
 * SPDX-License-Identifier:    GPL-2.0+
 */
 
#ifndef __ARM_PL180_MMCI_H__
#define __ARM_PL180_MMCI_H__
 
/* need definition of struct mmc_config */
#include <mmc.h>
 
#define COMMAND_REG_DELAY    300
#define DATA_REG_DELAY        1000
#define CLK_CHANGE_DELAY    2000
 
#define INIT_PWR        0xBF /* Power on, full power, not open drain */
#define ARM_MCLK        (100*1000*1000)
 
/* SDI Power Control register bits */
#define SDI_PWR_PWRCTRL_MASK    0x00000003
#define SDI_PWR_PWRCTRL_ON    0x00000003
#define SDI_PWR_PWRCTRL_OFF    0x00000000
#define SDI_PWR_DAT2DIREN    0x00000004
#define SDI_PWR_CMDDIREN    0x00000008
#define SDI_PWR_DAT0DIREN    0x00000010
#define SDI_PWR_DAT31DIREN    0x00000020
#define SDI_PWR_OPD        0x00000040
#define SDI_PWR_FBCLKEN        0x00000080
#define SDI_PWR_DAT74DIREN    0x00000100
#define SDI_PWR_RSTEN        0x00000200
 
#define VOLTAGE_WINDOW_MMC    0x00FF8080
#define VOLTAGE_WINDOW_SD    0x80010000
 
/* SDI clock control register bits */
#define SDI_CLKCR_CLKDIV_MASK    0x000000FF
#define SDI_CLKCR_CLKEN        0x00000100
#define SDI_CLKCR_PWRSAV    0x00000200
#define SDI_CLKCR_BYPASS    0x00000400
#define SDI_CLKCR_WIDBUS_MASK    0x00001800
#define SDI_CLKCR_WIDBUS_1    0x00000000
#define SDI_CLKCR_WIDBUS_4    0x00000800
/* V2 only */
#define SDI_CLKCR_WIDBUS_8    0x00001000
#define SDI_CLKCR_NEDGE        0x00002000
#define SDI_CLKCR_HWFC_EN    0x00004000
 
#define SDI_CLKCR_CLKDIV_INIT_V1 0x000000C6 /* MCLK/(2*(0xC6+1)) => 505KHz */
#define SDI_CLKCR_CLKDIV_INIT_V2 0x000000FD
 
/* SDI command register bits */
#define SDI_CMD_CMDINDEX_MASK    0x000000FF
#define SDI_CMD_WAITRESP    0x00000040
#define SDI_CMD_LONGRESP    0x00000080
#define SDI_CMD_WAITINT        0x00000100
#define SDI_CMD_WAITPEND    0x00000200
#define SDI_CMD_CPSMEN        0x00000400
#define SDI_CMD_SDIOSUSPEND    0x00000800
#define SDI_CMD_ENDCMDCOMPL    0x00001000
#define SDI_CMD_NIEN        0x00002000
#define SDI_CMD_CE_ATACMD    0x00004000
#define SDI_CMD_CBOOTMODEEN    0x00008000
 
#define SDI_DTIMER_DEFAULT    0xFFFF0000
 
/* SDI Status register bits */
#define SDI_STA_CCRCFAIL    0x00000001
#define SDI_STA_DCRCFAIL    0x00000002
#define SDI_STA_CTIMEOUT    0x00000004
#define SDI_STA_DTIMEOUT    0x00000008
#define SDI_STA_TXUNDERR    0x00000010
#define SDI_STA_RXOVERR        0x00000020
#define SDI_STA_CMDREND        0x00000040
#define SDI_STA_CMDSENT        0x00000080
#define SDI_STA_DATAEND        0x00000100
#define SDI_STA_STBITERR    0x00000200
#define SDI_STA_DBCKEND        0x00000400
#define SDI_STA_CMDACT        0x00000800
#define SDI_STA_TXACT        0x00001000
#define SDI_STA_RXACT        0x00002000
#define SDI_STA_TXFIFOBW    0x00004000
#define SDI_STA_RXFIFOBR    0x00008000
#define SDI_STA_TXFIFOF        0x00010000
#define SDI_STA_RXFIFOF        0x00020000
#define SDI_STA_TXFIFOE        0x00040000
#define SDI_STA_RXFIFOE        0x00080000
#define SDI_STA_TXDAVL        0x00100000
#define SDI_STA_RXDAVL        0x00200000
#define SDI_STA_SDIOIT        0x00400000
#define SDI_STA_CEATAEND    0x00800000
#define SDI_STA_CARDBUSY    0x01000000
#define SDI_STA_BOOTMODE    0x02000000
#define SDI_STA_BOOTACKERR    0x04000000
#define SDI_STA_BOOTACKTIMEOUT    0x08000000
#define SDI_STA_RSTNEND        0x10000000
 
/* SDI Interrupt Clear register bits */
#define SDI_ICR_MASK        0x1DC007FF
#define SDI_ICR_CCRCFAILC    0x00000001
#define SDI_ICR_DCRCFAILC    0x00000002
#define SDI_ICR_CTIMEOUTC    0x00000004
#define SDI_ICR_DTIMEOUTC    0x00000008
#define SDI_ICR_TXUNDERRC    0x00000010
#define SDI_ICR_RXOVERRC    0x00000020
#define SDI_ICR_CMDRENDC    0x00000040
#define SDI_ICR_CMDSENTC    0x00000080
#define SDI_ICR_DATAENDC    0x00000100
#define SDI_ICR_STBITERRC    0x00000200
#define SDI_ICR_DBCKENDC    0x00000400
#define SDI_ICR_SDIOITC        0x00400000
#define SDI_ICR_CEATAENDC    0x00800000
#define SDI_ICR_BUSYENDC    0x01000000
#define SDI_ICR_BOOTACKERRC    0x04000000
#define SDI_ICR_BOOTACKTIMEOUTC    0x08000000
#define SDI_ICR_RSTNENDC    0x10000000
 
#define SDI_MASK0_MASK        0x1FFFFFFF
 
/* SDI Data control register bits */
#define SDI_DCTRL_DTEN        0x00000001
#define SDI_DCTRL_DTDIR_IN    0x00000002
#define SDI_DCTRL_DTMODE_STREAM    0x00000004
#define SDI_DCTRL_DMAEN        0x00000008
#define SDI_DCTRL_DBLKSIZE_MASK    0x000000F0
#define SDI_DCTRL_RWSTART    0x00000100
#define SDI_DCTRL_RWSTOP    0x00000200
#define SDI_DCTRL_RWMOD        0x00000200
#define SDI_DCTRL_SDIOEN    0x00000800
#define SDI_DCTRL_DMAREQCTL    0x00001000
#define SDI_DCTRL_DBOOTMODEEN    0x00002000
#define SDI_DCTRL_BUSYMODE    0x00004000
#define SDI_DCTRL_DDR_MODE    0x00008000
#define SDI_DCTRL_DBLOCKSIZE_V2_MASK   0x7fff0000
#define SDI_DCTRL_DBLOCKSIZE_V2_SHIFT  16
 
#define SDI_FIFO_BURST_SIZE    8
 
struct sdi_registers {
   u32 power;        /* 0x00*/
   u32 clock;        /* 0x04*/
   u32 argument;        /* 0x08*/
   u32 command;        /* 0x0c*/
   u32 respcommand;    /* 0x10*/
   u32 response0;        /* 0x14*/
   u32 response1;        /* 0x18*/
   u32 response2;        /* 0x1c*/
   u32 response3;        /* 0x20*/
   u32 datatimer;        /* 0x24*/
   u32 datalength;        /* 0x28*/
   u32 datactrl;        /* 0x2c*/
   u32 datacount;        /* 0x30*/
   u32 status;        /* 0x34*/
   u32 status_clear;    /* 0x38*/
   u32 mask0;        /* 0x3c*/
   u32 mask1;        /* 0x40*/
   u32 card_select;    /* 0x44*/
   u32 fifo_count;        /* 0x48*/
   u32 padding1[(0x80-0x4C)>>2];
   u32 fifo;        /* 0x80*/
   u32 padding2[(0xFE0-0x84)>>2];
   u32 periph_id0;        /* 0xFE0 mmc Peripheral Identifcation Register*/
   u32 periph_id1;        /* 0xFE4*/
   u32 periph_id2;        /* 0xFE8*/
   u32 periph_id3;        /* 0xFEC*/
   u32 pcell_id0;        /* 0xFF0*/
   u32 pcell_id1;        /* 0xFF4*/
   u32 pcell_id2;        /* 0xFF8*/
   u32 pcell_id3;        /* 0xFFC*/
};
 
struct pl180_mmc_host {
   struct sdi_registers *base;
   char name[32];
   unsigned int b_max;
   unsigned int voltages;
   unsigned int caps;
   unsigned int clock_in;
   unsigned int clock_min;
   unsigned int clock_max;
   unsigned int clkdiv_init;
   unsigned int pwr_init;
   int version2;
   struct mmc_config cfg;
};
 
int arm_pl180_mmci_init(struct pl180_mmc_host *);
 
#endif