]>
Commit | Line | Data |
---|---|---|
d7dfca08 IM |
1 | /* |
2 | * SD Association Host Standard Specification v2.0 controller emulation | |
3 | * | |
4 | * Copyright (c) 2011 Samsung Electronics Co., Ltd. | |
5 | * Mitsyanko Igor <[email protected]> | |
6 | * Peter A.G. Crosthwaite <[email protected]> | |
7 | * | |
8 | * Based on MMC controller for Samsung S5PC1xx-based board emulation | |
9 | * by Alexey Merkulov and Vladimir Monakhov. | |
10 | * | |
11 | * This program is free software; you can redistribute it and/or modify it | |
12 | * under the terms of the GNU General Public License as published by the | |
13 | * Free Software Foundation; either version 2 of the License, or (at your | |
14 | * option) any later version. | |
15 | * | |
16 | * This program is distributed in the hope that it will be useful, | |
17 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | |
18 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. | |
19 | * See the GNU General Public License for more details. | |
20 | * | |
21 | * You should have received a copy of the GNU General Public License along | |
22 | * with this program; if not, see <http://www.gnu.org/licenses/>. | |
23 | */ | |
24 | ||
25 | #ifndef SDHCI_H | |
26 | #define SDHCI_H | |
27 | ||
28 | #include "qemu-common.h" | |
224d10ff | 29 | #include "hw/pci/pci.h" |
83c9f4ca PB |
30 | #include "hw/sysbus.h" |
31 | #include "hw/sd.h" | |
d7dfca08 IM |
32 | |
33 | /* R/W SDMA System Address register 0x0 */ | |
34 | #define SDHC_SYSAD 0x00 | |
35 | ||
36 | /* R/W Host DMA Buffer Boundary and Transfer Block Size Register 0x0 */ | |
37 | #define SDHC_BLKSIZE 0x04 | |
38 | ||
39 | /* R/W Blocks count for current transfer 0x0 */ | |
40 | #define SDHC_BLKCNT 0x06 | |
41 | ||
42 | /* R/W Command Argument Register 0x0 */ | |
43 | #define SDHC_ARGUMENT 0x08 | |
44 | ||
45 | /* R/W Transfer Mode Setting Register 0x0 */ | |
46 | #define SDHC_TRNMOD 0x0C | |
47 | #define SDHC_TRNS_DMA 0x0001 | |
48 | #define SDHC_TRNS_BLK_CNT_EN 0x0002 | |
49 | #define SDHC_TRNS_ACMD12 0x0004 | |
50 | #define SDHC_TRNS_READ 0x0010 | |
51 | #define SDHC_TRNS_MULTI 0x0020 | |
52 | ||
53 | /* R/W Command Register 0x0 */ | |
54 | #define SDHC_CMDREG 0x0E | |
55 | #define SDHC_CMD_RSP_WITH_BUSY (3 << 0) | |
56 | #define SDHC_CMD_DATA_PRESENT (1 << 5) | |
57 | #define SDHC_CMD_SUSPEND (1 << 6) | |
58 | #define SDHC_CMD_RESUME (1 << 7) | |
59 | #define SDHC_CMD_ABORT ((1 << 6)|(1 << 7)) | |
60 | #define SDHC_CMD_TYPE_MASK ((1 << 6)|(1 << 7)) | |
61 | #define SDHC_COMMAND_TYPE(x) ((x) & SDHC_CMD_TYPE_MASK) | |
62 | ||
63 | /* ROC Response Register 0 0x0 */ | |
64 | #define SDHC_RSPREG0 0x10 | |
65 | /* ROC Response Register 1 0x0 */ | |
66 | #define SDHC_RSPREG1 0x14 | |
67 | /* ROC Response Register 2 0x0 */ | |
68 | #define SDHC_RSPREG2 0x18 | |
69 | /* ROC Response Register 3 0x0 */ | |
70 | #define SDHC_RSPREG3 0x1C | |
71 | ||
72 | /* R/W Buffer Data Register 0x0 */ | |
73 | #define SDHC_BDATA 0x20 | |
74 | ||
75 | /* R/ROC Present State Register 0x000A0000 */ | |
76 | #define SDHC_PRNSTS 0x24 | |
77 | #define SDHC_CMD_INHIBIT 0x00000001 | |
78 | #define SDHC_DATA_INHIBIT 0x00000002 | |
79 | #define SDHC_DAT_LINE_ACTIVE 0x00000004 | |
80 | #define SDHC_DOING_WRITE 0x00000100 | |
81 | #define SDHC_DOING_READ 0x00000200 | |
82 | #define SDHC_SPACE_AVAILABLE 0x00000400 | |
83 | #define SDHC_DATA_AVAILABLE 0x00000800 | |
84 | #define SDHC_CARD_PRESENT 0x00010000 | |
85 | #define SDHC_CARD_DETECT 0x00040000 | |
86 | #define SDHC_WRITE_PROTECT 0x00080000 | |
87 | #define TRANSFERRING_DATA(x) \ | |
88 | ((x) & (SDHC_DOING_READ | SDHC_DOING_WRITE)) | |
89 | ||
90 | /* R/W Host control Register 0x0 */ | |
91 | #define SDHC_HOSTCTL 0x28 | |
92 | #define SDHC_CTRL_DMA_CHECK_MASK 0x18 | |
93 | #define SDHC_CTRL_SDMA 0x00 | |
94 | #define SDHC_CTRL_ADMA1_32 0x08 | |
95 | #define SDHC_CTRL_ADMA2_32 0x10 | |
96 | #define SDHC_CTRL_ADMA2_64 0x18 | |
97 | #define SDHC_DMA_TYPE(x) ((x) & SDHC_CTRL_DMA_CHECK_MASK) | |
98 | ||
99 | /* R/W Power Control Register 0x0 */ | |
100 | #define SDHC_PWRCON 0x29 | |
101 | #define SDHC_POWER_ON (1 << 0) | |
102 | ||
103 | /* R/W Block Gap Control Register 0x0 */ | |
104 | #define SDHC_BLKGAP 0x2A | |
105 | #define SDHC_STOP_AT_GAP_REQ 0x01 | |
106 | #define SDHC_CONTINUE_REQ 0x02 | |
107 | ||
108 | /* R/W WakeUp Control Register 0x0 */ | |
109 | #define SDHC_WAKCON 0x2B | |
110 | #define SDHC_WKUP_ON_INS (1 << 1) | |
111 | #define SDHC_WKUP_ON_RMV (1 << 2) | |
112 | ||
113 | /* CLKCON */ | |
114 | #define SDHC_CLKCON 0x2C | |
115 | #define SDHC_CLOCK_INT_STABLE 0x0002 | |
116 | #define SDHC_CLOCK_INT_EN 0x0001 | |
117 | #define SDHC_CLOCK_SDCLK_EN (1 << 2) | |
118 | #define SDHC_CLOCK_CHK_MASK 0x0007 | |
119 | #define SDHC_CLOCK_IS_ON(x) \ | |
120 | (((x) & SDHC_CLOCK_CHK_MASK) == SDHC_CLOCK_CHK_MASK) | |
121 | ||
122 | /* R/W Timeout Control Register 0x0 */ | |
123 | #define SDHC_TIMEOUTCON 0x2E | |
124 | ||
125 | /* R/W Software Reset Register 0x0 */ | |
126 | #define SDHC_SWRST 0x2F | |
127 | #define SDHC_RESET_ALL 0x01 | |
128 | #define SDHC_RESET_CMD 0x02 | |
129 | #define SDHC_RESET_DATA 0x04 | |
130 | ||
131 | /* ROC/RW1C Normal Interrupt Status Register 0x0 */ | |
132 | #define SDHC_NORINTSTS 0x30 | |
133 | #define SDHC_NIS_ERR 0x8000 | |
134 | #define SDHC_NIS_CMDCMP 0x0001 | |
135 | #define SDHC_NIS_TRSCMP 0x0002 | |
136 | #define SDHC_NIS_BLKGAP 0x0004 | |
137 | #define SDHC_NIS_DMA 0x0008 | |
138 | #define SDHC_NIS_WBUFRDY 0x0010 | |
139 | #define SDHC_NIS_RBUFRDY 0x0020 | |
140 | #define SDHC_NIS_INSERT 0x0040 | |
141 | #define SDHC_NIS_REMOVE 0x0080 | |
142 | #define SDHC_NIS_CARDINT 0x0100 | |
143 | ||
144 | /* ROC/RW1C Error Interrupt Status Register 0x0 */ | |
145 | #define SDHC_ERRINTSTS 0x32 | |
146 | #define SDHC_EIS_CMDTIMEOUT 0x0001 | |
147 | #define SDHC_EIS_BLKGAP 0x0004 | |
148 | #define SDHC_EIS_CMDIDX 0x0008 | |
149 | #define SDHC_EIS_CMD12ERR 0x0100 | |
150 | #define SDHC_EIS_ADMAERR 0x0200 | |
151 | ||
152 | /* R/W Normal Interrupt Status Enable Register 0x0 */ | |
153 | #define SDHC_NORINTSTSEN 0x34 | |
154 | #define SDHC_NISEN_CMDCMP 0x0001 | |
155 | #define SDHC_NISEN_TRSCMP 0x0002 | |
156 | #define SDHC_NISEN_DMA 0x0008 | |
157 | #define SDHC_NISEN_WBUFRDY 0x0010 | |
158 | #define SDHC_NISEN_RBUFRDY 0x0020 | |
159 | #define SDHC_NISEN_INSERT 0x0040 | |
160 | #define SDHC_NISEN_REMOVE 0x0080 | |
161 | #define SDHC_NISEN_CARDINT 0x0100 | |
162 | ||
163 | /* R/W Error Interrupt Status Enable Register 0x0 */ | |
164 | #define SDHC_ERRINTSTSEN 0x36 | |
165 | #define SDHC_EISEN_CMDTIMEOUT 0x0001 | |
166 | #define SDHC_EISEN_BLKGAP 0x0004 | |
167 | #define SDHC_EISEN_CMDIDX 0x0008 | |
168 | #define SDHC_EISEN_ADMAERR 0x0200 | |
169 | ||
170 | /* R/W Normal Interrupt Signal Enable Register 0x0 */ | |
171 | #define SDHC_NORINTSIGEN 0x38 | |
172 | #define SDHC_NORINTSIG_INSERT (1 << 6) | |
173 | #define SDHC_NORINTSIG_REMOVE (1 << 7) | |
174 | ||
175 | /* R/W Error Interrupt Signal Enable Register 0x0 */ | |
176 | #define SDHC_ERRINTSIGEN 0x3A | |
177 | ||
178 | /* ROC Auto CMD12 error status register 0x0 */ | |
179 | #define SDHC_ACMD12ERRSTS 0x3C | |
180 | ||
181 | /* HWInit Capabilities Register 0x05E80080 */ | |
182 | #define SDHC_CAPAREG 0x40 | |
183 | #define SDHC_CAN_DO_DMA 0x00400000 | |
184 | #define SDHC_CAN_DO_ADMA2 0x00080000 | |
185 | #define SDHC_CAN_DO_ADMA1 0x00100000 | |
186 | #define SDHC_64_BIT_BUS_SUPPORT (1 << 28) | |
187 | #define SDHC_CAPAB_BLOCKSIZE(x) (((x) >> 16) & 0x3) | |
188 | ||
189 | /* HWInit Maximum Current Capabilities Register 0x0 */ | |
190 | #define SDHC_MAXCURR 0x48 | |
191 | ||
192 | /* W Force Event Auto CMD12 Error Interrupt Register 0x0000 */ | |
193 | #define SDHC_FEAER 0x50 | |
194 | /* W Force Event Error Interrupt Register Error Interrupt 0x0000 */ | |
195 | #define SDHC_FEERR 0x52 | |
196 | ||
197 | /* R/W ADMA Error Status Register 0x00 */ | |
198 | #define SDHC_ADMAERR 0x54 | |
199 | #define SDHC_ADMAERR_LENGTH_MISMATCH (1 << 2) | |
200 | #define SDHC_ADMAERR_STATE_ST_STOP (0 << 0) | |
201 | #define SDHC_ADMAERR_STATE_ST_FDS (1 << 0) | |
202 | #define SDHC_ADMAERR_STATE_ST_TFR (3 << 0) | |
203 | #define SDHC_ADMAERR_STATE_MASK (3 << 0) | |
204 | ||
205 | /* R/W ADMA System Address Register 0x00 */ | |
206 | #define SDHC_ADMASYSADDR 0x58 | |
207 | #define SDHC_ADMA_ATTR_SET_LEN (1 << 4) | |
208 | #define SDHC_ADMA_ATTR_ACT_TRAN (1 << 5) | |
209 | #define SDHC_ADMA_ATTR_ACT_LINK (3 << 4) | |
210 | #define SDHC_ADMA_ATTR_INT (1 << 2) | |
211 | #define SDHC_ADMA_ATTR_END (1 << 1) | |
212 | #define SDHC_ADMA_ATTR_VALID (1 << 0) | |
213 | #define SDHC_ADMA_ATTR_ACT_MASK ((1 << 4)|(1 << 5)) | |
214 | ||
215 | /* Slot interrupt status */ | |
216 | #define SDHC_SLOT_INT_STATUS 0xFC | |
217 | ||
218 | /* HWInit Host Controller Version Register 0x0401 */ | |
219 | #define SDHC_HCVER 0xFE | |
220 | #define SD_HOST_SPECv2_VERS 0x2401 | |
221 | ||
222 | #define SDHC_REGISTERS_MAP_SIZE 0x100 | |
223 | #define SDHC_INSERTION_DELAY (get_ticks_per_sec()) | |
224 | #define SDHC_TRANSFER_DELAY 100 | |
225 | #define SDHC_ADMA_DESCS_PER_DELAY 5 | |
226 | #define SDHC_CMD_RESPONSE (3 << 0) | |
227 | ||
228 | enum { | |
229 | sdhc_not_stopped = 0, /* normal SDHC state */ | |
230 | sdhc_gap_read = 1, /* SDHC stopped at block gap during read operation */ | |
231 | sdhc_gap_write = 2 /* SDHC stopped at block gap during write operation */ | |
232 | }; | |
233 | ||
234 | /* SD/MMC host controller state */ | |
235 | typedef struct SDHCIState { | |
224d10ff KC |
236 | union { |
237 | PCIDevice pcidev; | |
238 | SysBusDevice busdev; | |
239 | }; | |
d7dfca08 IM |
240 | SDState *card; |
241 | MemoryRegion iomem; | |
242 | ||
243 | QEMUTimer *insert_timer; /* timer for 'changing' sd card. */ | |
244 | QEMUTimer *transfer_timer; | |
245 | qemu_irq eject_cb; | |
246 | qemu_irq ro_cb; | |
247 | qemu_irq irq; | |
248 | ||
249 | uint32_t sdmasysad; /* SDMA System Address register */ | |
250 | uint16_t blksize; /* Host DMA Buff Boundary and Transfer BlkSize Reg */ | |
251 | uint16_t blkcnt; /* Blocks count for current transfer */ | |
252 | uint32_t argument; /* Command Argument Register */ | |
253 | uint16_t trnmod; /* Transfer Mode Setting Register */ | |
254 | uint16_t cmdreg; /* Command Register */ | |
255 | uint32_t rspreg[4]; /* Response Registers 0-3 */ | |
256 | uint32_t prnsts; /* Present State Register */ | |
257 | uint8_t hostctl; /* Host Control Register */ | |
258 | uint8_t pwrcon; /* Power control Register */ | |
259 | uint8_t blkgap; /* Block Gap Control Register */ | |
260 | uint8_t wakcon; /* WakeUp Control Register */ | |
261 | uint16_t clkcon; /* Clock control Register */ | |
262 | uint8_t timeoutcon; /* Timeout Control Register */ | |
263 | uint8_t admaerr; /* ADMA Error Status Register */ | |
264 | uint16_t norintsts; /* Normal Interrupt Status Register */ | |
265 | uint16_t errintsts; /* Error Interrupt Status Register */ | |
266 | uint16_t norintstsen; /* Normal Interrupt Status Enable Register */ | |
267 | uint16_t errintstsen; /* Error Interrupt Status Enable Register */ | |
268 | uint16_t norintsigen; /* Normal Interrupt Signal Enable Register */ | |
269 | uint16_t errintsigen; /* Error Interrupt Signal Enable Register */ | |
270 | uint16_t acmd12errsts; /* Auto CMD12 error status register */ | |
271 | uint64_t admasysaddr; /* ADMA System Address Register */ | |
272 | ||
273 | uint32_t capareg; /* Capabilities Register */ | |
274 | uint32_t maxcurr; /* Maximum Current Capabilities Register */ | |
275 | uint8_t *fifo_buffer; /* SD host i/o FIFO buffer */ | |
276 | uint32_t buf_maxsz; | |
277 | uint16_t data_count; /* current element in FIFO buffer */ | |
278 | uint8_t stopped_state;/* Current SDHC state */ | |
279 | /* Buffer Data Port Register - virtual access point to R and W buffers */ | |
280 | /* Software Reset Register - always reads as 0 */ | |
281 | /* Force Event Auto CMD12 Error Interrupt Reg - write only */ | |
282 | /* Force Event Error Interrupt Register- write only */ | |
283 | /* RO Host Controller Version Register always reads as 0x2401 */ | |
284 | } SDHCIState; | |
285 | ||
d7dfca08 IM |
286 | extern const VMStateDescription sdhci_vmstate; |
287 | ||
224d10ff KC |
288 | #define TYPE_PCI_SDHCI "sdhci-pci" |
289 | #define PCI_SDHCI(obj) OBJECT_CHECK(SDHCIState, (obj), TYPE_PCI_SDHCI) | |
290 | ||
7302dcd6 KC |
291 | #define TYPE_SYSBUS_SDHCI "generic-sdhci" |
292 | #define SYSBUS_SDHCI(obj) \ | |
293 | OBJECT_CHECK(SDHCIState, (obj), TYPE_SYSBUS_SDHCI) | |
d7dfca08 IM |
294 | |
295 | #endif /* SDHCI_H */ |