]>
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" | |
29 | #include "sysbus.h" | |
30 | #include "sd.h" | |
31 | ||
32 | /* R/W SDMA System Address register 0x0 */ | |
33 | #define SDHC_SYSAD 0x00 | |
34 | ||
35 | /* R/W Host DMA Buffer Boundary and Transfer Block Size Register 0x0 */ | |
36 | #define SDHC_BLKSIZE 0x04 | |
37 | ||
38 | /* R/W Blocks count for current transfer 0x0 */ | |
39 | #define SDHC_BLKCNT 0x06 | |
40 | ||
41 | /* R/W Command Argument Register 0x0 */ | |
42 | #define SDHC_ARGUMENT 0x08 | |
43 | ||
44 | /* R/W Transfer Mode Setting Register 0x0 */ | |
45 | #define SDHC_TRNMOD 0x0C | |
46 | #define SDHC_TRNS_DMA 0x0001 | |
47 | #define SDHC_TRNS_BLK_CNT_EN 0x0002 | |
48 | #define SDHC_TRNS_ACMD12 0x0004 | |
49 | #define SDHC_TRNS_READ 0x0010 | |
50 | #define SDHC_TRNS_MULTI 0x0020 | |
51 | ||
52 | /* R/W Command Register 0x0 */ | |
53 | #define SDHC_CMDREG 0x0E | |
54 | #define SDHC_CMD_RSP_WITH_BUSY (3 << 0) | |
55 | #define SDHC_CMD_DATA_PRESENT (1 << 5) | |
56 | #define SDHC_CMD_SUSPEND (1 << 6) | |
57 | #define SDHC_CMD_RESUME (1 << 7) | |
58 | #define SDHC_CMD_ABORT ((1 << 6)|(1 << 7)) | |
59 | #define SDHC_CMD_TYPE_MASK ((1 << 6)|(1 << 7)) | |
60 | #define SDHC_COMMAND_TYPE(x) ((x) & SDHC_CMD_TYPE_MASK) | |
61 | ||
62 | /* ROC Response Register 0 0x0 */ | |
63 | #define SDHC_RSPREG0 0x10 | |
64 | /* ROC Response Register 1 0x0 */ | |
65 | #define SDHC_RSPREG1 0x14 | |
66 | /* ROC Response Register 2 0x0 */ | |
67 | #define SDHC_RSPREG2 0x18 | |
68 | /* ROC Response Register 3 0x0 */ | |
69 | #define SDHC_RSPREG3 0x1C | |
70 | ||
71 | /* R/W Buffer Data Register 0x0 */ | |
72 | #define SDHC_BDATA 0x20 | |
73 | ||
74 | /* R/ROC Present State Register 0x000A0000 */ | |
75 | #define SDHC_PRNSTS 0x24 | |
76 | #define SDHC_CMD_INHIBIT 0x00000001 | |
77 | #define SDHC_DATA_INHIBIT 0x00000002 | |
78 | #define SDHC_DAT_LINE_ACTIVE 0x00000004 | |
79 | #define SDHC_DOING_WRITE 0x00000100 | |
80 | #define SDHC_DOING_READ 0x00000200 | |
81 | #define SDHC_SPACE_AVAILABLE 0x00000400 | |
82 | #define SDHC_DATA_AVAILABLE 0x00000800 | |
83 | #define SDHC_CARD_PRESENT 0x00010000 | |
84 | #define SDHC_CARD_DETECT 0x00040000 | |
85 | #define SDHC_WRITE_PROTECT 0x00080000 | |
86 | #define TRANSFERRING_DATA(x) \ | |
87 | ((x) & (SDHC_DOING_READ | SDHC_DOING_WRITE)) | |
88 | ||
89 | /* R/W Host control Register 0x0 */ | |
90 | #define SDHC_HOSTCTL 0x28 | |
91 | #define SDHC_CTRL_DMA_CHECK_MASK 0x18 | |
92 | #define SDHC_CTRL_SDMA 0x00 | |
93 | #define SDHC_CTRL_ADMA1_32 0x08 | |
94 | #define SDHC_CTRL_ADMA2_32 0x10 | |
95 | #define SDHC_CTRL_ADMA2_64 0x18 | |
96 | #define SDHC_DMA_TYPE(x) ((x) & SDHC_CTRL_DMA_CHECK_MASK) | |
97 | ||
98 | /* R/W Power Control Register 0x0 */ | |
99 | #define SDHC_PWRCON 0x29 | |
100 | #define SDHC_POWER_ON (1 << 0) | |
101 | ||
102 | /* R/W Block Gap Control Register 0x0 */ | |
103 | #define SDHC_BLKGAP 0x2A | |
104 | #define SDHC_STOP_AT_GAP_REQ 0x01 | |
105 | #define SDHC_CONTINUE_REQ 0x02 | |
106 | ||
107 | /* R/W WakeUp Control Register 0x0 */ | |
108 | #define SDHC_WAKCON 0x2B | |
109 | #define SDHC_WKUP_ON_INS (1 << 1) | |
110 | #define SDHC_WKUP_ON_RMV (1 << 2) | |
111 | ||
112 | /* CLKCON */ | |
113 | #define SDHC_CLKCON 0x2C | |
114 | #define SDHC_CLOCK_INT_STABLE 0x0002 | |
115 | #define SDHC_CLOCK_INT_EN 0x0001 | |
116 | #define SDHC_CLOCK_SDCLK_EN (1 << 2) | |
117 | #define SDHC_CLOCK_CHK_MASK 0x0007 | |
118 | #define SDHC_CLOCK_IS_ON(x) \ | |
119 | (((x) & SDHC_CLOCK_CHK_MASK) == SDHC_CLOCK_CHK_MASK) | |
120 | ||
121 | /* R/W Timeout Control Register 0x0 */ | |
122 | #define SDHC_TIMEOUTCON 0x2E | |
123 | ||
124 | /* R/W Software Reset Register 0x0 */ | |
125 | #define SDHC_SWRST 0x2F | |
126 | #define SDHC_RESET_ALL 0x01 | |
127 | #define SDHC_RESET_CMD 0x02 | |
128 | #define SDHC_RESET_DATA 0x04 | |
129 | ||
130 | /* ROC/RW1C Normal Interrupt Status Register 0x0 */ | |
131 | #define SDHC_NORINTSTS 0x30 | |
132 | #define SDHC_NIS_ERR 0x8000 | |
133 | #define SDHC_NIS_CMDCMP 0x0001 | |
134 | #define SDHC_NIS_TRSCMP 0x0002 | |
135 | #define SDHC_NIS_BLKGAP 0x0004 | |
136 | #define SDHC_NIS_DMA 0x0008 | |
137 | #define SDHC_NIS_WBUFRDY 0x0010 | |
138 | #define SDHC_NIS_RBUFRDY 0x0020 | |
139 | #define SDHC_NIS_INSERT 0x0040 | |
140 | #define SDHC_NIS_REMOVE 0x0080 | |
141 | #define SDHC_NIS_CARDINT 0x0100 | |
142 | ||
143 | /* ROC/RW1C Error Interrupt Status Register 0x0 */ | |
144 | #define SDHC_ERRINTSTS 0x32 | |
145 | #define SDHC_EIS_CMDTIMEOUT 0x0001 | |
146 | #define SDHC_EIS_BLKGAP 0x0004 | |
147 | #define SDHC_EIS_CMDIDX 0x0008 | |
148 | #define SDHC_EIS_CMD12ERR 0x0100 | |
149 | #define SDHC_EIS_ADMAERR 0x0200 | |
150 | ||
151 | /* R/W Normal Interrupt Status Enable Register 0x0 */ | |
152 | #define SDHC_NORINTSTSEN 0x34 | |
153 | #define SDHC_NISEN_CMDCMP 0x0001 | |
154 | #define SDHC_NISEN_TRSCMP 0x0002 | |
155 | #define SDHC_NISEN_DMA 0x0008 | |
156 | #define SDHC_NISEN_WBUFRDY 0x0010 | |
157 | #define SDHC_NISEN_RBUFRDY 0x0020 | |
158 | #define SDHC_NISEN_INSERT 0x0040 | |
159 | #define SDHC_NISEN_REMOVE 0x0080 | |
160 | #define SDHC_NISEN_CARDINT 0x0100 | |
161 | ||
162 | /* R/W Error Interrupt Status Enable Register 0x0 */ | |
163 | #define SDHC_ERRINTSTSEN 0x36 | |
164 | #define SDHC_EISEN_CMDTIMEOUT 0x0001 | |
165 | #define SDHC_EISEN_BLKGAP 0x0004 | |
166 | #define SDHC_EISEN_CMDIDX 0x0008 | |
167 | #define SDHC_EISEN_ADMAERR 0x0200 | |
168 | ||
169 | /* R/W Normal Interrupt Signal Enable Register 0x0 */ | |
170 | #define SDHC_NORINTSIGEN 0x38 | |
171 | #define SDHC_NORINTSIG_INSERT (1 << 6) | |
172 | #define SDHC_NORINTSIG_REMOVE (1 << 7) | |
173 | ||
174 | /* R/W Error Interrupt Signal Enable Register 0x0 */ | |
175 | #define SDHC_ERRINTSIGEN 0x3A | |
176 | ||
177 | /* ROC Auto CMD12 error status register 0x0 */ | |
178 | #define SDHC_ACMD12ERRSTS 0x3C | |
179 | ||
180 | /* HWInit Capabilities Register 0x05E80080 */ | |
181 | #define SDHC_CAPAREG 0x40 | |
182 | #define SDHC_CAN_DO_DMA 0x00400000 | |
183 | #define SDHC_CAN_DO_ADMA2 0x00080000 | |
184 | #define SDHC_CAN_DO_ADMA1 0x00100000 | |
185 | #define SDHC_64_BIT_BUS_SUPPORT (1 << 28) | |
186 | #define SDHC_CAPAB_BLOCKSIZE(x) (((x) >> 16) & 0x3) | |
187 | ||
188 | /* HWInit Maximum Current Capabilities Register 0x0 */ | |
189 | #define SDHC_MAXCURR 0x48 | |
190 | ||
191 | /* W Force Event Auto CMD12 Error Interrupt Register 0x0000 */ | |
192 | #define SDHC_FEAER 0x50 | |
193 | /* W Force Event Error Interrupt Register Error Interrupt 0x0000 */ | |
194 | #define SDHC_FEERR 0x52 | |
195 | ||
196 | /* R/W ADMA Error Status Register 0x00 */ | |
197 | #define SDHC_ADMAERR 0x54 | |
198 | #define SDHC_ADMAERR_LENGTH_MISMATCH (1 << 2) | |
199 | #define SDHC_ADMAERR_STATE_ST_STOP (0 << 0) | |
200 | #define SDHC_ADMAERR_STATE_ST_FDS (1 << 0) | |
201 | #define SDHC_ADMAERR_STATE_ST_TFR (3 << 0) | |
202 | #define SDHC_ADMAERR_STATE_MASK (3 << 0) | |
203 | ||
204 | /* R/W ADMA System Address Register 0x00 */ | |
205 | #define SDHC_ADMASYSADDR 0x58 | |
206 | #define SDHC_ADMA_ATTR_SET_LEN (1 << 4) | |
207 | #define SDHC_ADMA_ATTR_ACT_TRAN (1 << 5) | |
208 | #define SDHC_ADMA_ATTR_ACT_LINK (3 << 4) | |
209 | #define SDHC_ADMA_ATTR_INT (1 << 2) | |
210 | #define SDHC_ADMA_ATTR_END (1 << 1) | |
211 | #define SDHC_ADMA_ATTR_VALID (1 << 0) | |
212 | #define SDHC_ADMA_ATTR_ACT_MASK ((1 << 4)|(1 << 5)) | |
213 | ||
214 | /* Slot interrupt status */ | |
215 | #define SDHC_SLOT_INT_STATUS 0xFC | |
216 | ||
217 | /* HWInit Host Controller Version Register 0x0401 */ | |
218 | #define SDHC_HCVER 0xFE | |
219 | #define SD_HOST_SPECv2_VERS 0x2401 | |
220 | ||
221 | #define SDHC_REGISTERS_MAP_SIZE 0x100 | |
222 | #define SDHC_INSERTION_DELAY (get_ticks_per_sec()) | |
223 | #define SDHC_TRANSFER_DELAY 100 | |
224 | #define SDHC_ADMA_DESCS_PER_DELAY 5 | |
225 | #define SDHC_CMD_RESPONSE (3 << 0) | |
226 | ||
227 | enum { | |
228 | sdhc_not_stopped = 0, /* normal SDHC state */ | |
229 | sdhc_gap_read = 1, /* SDHC stopped at block gap during read operation */ | |
230 | sdhc_gap_write = 2 /* SDHC stopped at block gap during write operation */ | |
231 | }; | |
232 | ||
233 | /* SD/MMC host controller state */ | |
234 | typedef struct SDHCIState { | |
235 | SysBusDevice busdev; | |
236 | SDState *card; | |
237 | MemoryRegion iomem; | |
238 | ||
239 | QEMUTimer *insert_timer; /* timer for 'changing' sd card. */ | |
240 | QEMUTimer *transfer_timer; | |
241 | qemu_irq eject_cb; | |
242 | qemu_irq ro_cb; | |
243 | qemu_irq irq; | |
244 | ||
245 | uint32_t sdmasysad; /* SDMA System Address register */ | |
246 | uint16_t blksize; /* Host DMA Buff Boundary and Transfer BlkSize Reg */ | |
247 | uint16_t blkcnt; /* Blocks count for current transfer */ | |
248 | uint32_t argument; /* Command Argument Register */ | |
249 | uint16_t trnmod; /* Transfer Mode Setting Register */ | |
250 | uint16_t cmdreg; /* Command Register */ | |
251 | uint32_t rspreg[4]; /* Response Registers 0-3 */ | |
252 | uint32_t prnsts; /* Present State Register */ | |
253 | uint8_t hostctl; /* Host Control Register */ | |
254 | uint8_t pwrcon; /* Power control Register */ | |
255 | uint8_t blkgap; /* Block Gap Control Register */ | |
256 | uint8_t wakcon; /* WakeUp Control Register */ | |
257 | uint16_t clkcon; /* Clock control Register */ | |
258 | uint8_t timeoutcon; /* Timeout Control Register */ | |
259 | uint8_t admaerr; /* ADMA Error Status Register */ | |
260 | uint16_t norintsts; /* Normal Interrupt Status Register */ | |
261 | uint16_t errintsts; /* Error Interrupt Status Register */ | |
262 | uint16_t norintstsen; /* Normal Interrupt Status Enable Register */ | |
263 | uint16_t errintstsen; /* Error Interrupt Status Enable Register */ | |
264 | uint16_t norintsigen; /* Normal Interrupt Signal Enable Register */ | |
265 | uint16_t errintsigen; /* Error Interrupt Signal Enable Register */ | |
266 | uint16_t acmd12errsts; /* Auto CMD12 error status register */ | |
267 | uint64_t admasysaddr; /* ADMA System Address Register */ | |
268 | ||
269 | uint32_t capareg; /* Capabilities Register */ | |
270 | uint32_t maxcurr; /* Maximum Current Capabilities Register */ | |
271 | uint8_t *fifo_buffer; /* SD host i/o FIFO buffer */ | |
272 | uint32_t buf_maxsz; | |
273 | uint16_t data_count; /* current element in FIFO buffer */ | |
274 | uint8_t stopped_state;/* Current SDHC state */ | |
275 | /* Buffer Data Port Register - virtual access point to R and W buffers */ | |
276 | /* Software Reset Register - always reads as 0 */ | |
277 | /* Force Event Auto CMD12 Error Interrupt Reg - write only */ | |
278 | /* Force Event Error Interrupt Register- write only */ | |
279 | /* RO Host Controller Version Register always reads as 0x2401 */ | |
280 | } SDHCIState; | |
281 | ||
282 | typedef struct SDHCIClass { | |
283 | SysBusDeviceClass busdev_class; | |
284 | ||
285 | void (*reset)(SDHCIState *s); | |
286 | uint32_t (*mem_read)(SDHCIState *s, unsigned int offset, unsigned size); | |
287 | void (*mem_write)(SDHCIState *s, unsigned int offset, uint32_t value, | |
288 | unsigned size); | |
289 | void (*send_command)(SDHCIState *s); | |
290 | bool (*can_issue_command)(SDHCIState *s); | |
291 | void (*data_transfer)(SDHCIState *s); | |
292 | void (*end_data_transfer)(SDHCIState *s); | |
293 | void (*do_sdma_single)(SDHCIState *s); | |
294 | void (*do_sdma_multi)(SDHCIState *s); | |
295 | void (*do_adma)(SDHCIState *s); | |
296 | void (*read_block_from_card)(SDHCIState *s); | |
297 | void (*write_block_to_card)(SDHCIState *s); | |
298 | uint32_t (*bdata_read)(SDHCIState *s, unsigned size); | |
299 | void (*bdata_write)(SDHCIState *s, uint32_t value, unsigned size); | |
300 | } SDHCIClass; | |
301 | ||
302 | extern const VMStateDescription sdhci_vmstate; | |
303 | ||
304 | #define TYPE_SDHCI "generic-sdhci" | |
305 | #define SDHCI(obj) \ | |
306 | OBJECT_CHECK(SDHCIState, (obj), TYPE_SDHCI) | |
307 | #define SDHCI_CLASS(klass) \ | |
308 | OBJECT_CLASS_CHECK(SDHCIClass, (klass), TYPE_SDHCI) | |
309 | #define SDHCI_GET_CLASS(obj) \ | |
310 | OBJECT_GET_CLASS(SDHCIClass, (obj), TYPE_SDHCI) | |
311 | ||
312 | #endif /* SDHCI_H */ |