dwc_mmc.c revision 1.6.2.5 1 1.6.2.5 skrll /* $NetBSD: dwc_mmc.c,v 1.6.2.5 2017/08/28 17:52:03 skrll Exp $ */
2 1.6.2.2 skrll
3 1.6.2.2 skrll /*-
4 1.6.2.5 skrll * Copyright (c) 2014-2017 Jared McNeill <jmcneill (at) invisible.ca>
5 1.6.2.2 skrll * All rights reserved.
6 1.6.2.2 skrll *
7 1.6.2.2 skrll * Redistribution and use in source and binary forms, with or without
8 1.6.2.2 skrll * modification, are permitted provided that the following conditions
9 1.6.2.2 skrll * are met:
10 1.6.2.2 skrll * 1. Redistributions of source code must retain the above copyright
11 1.6.2.2 skrll * notice, this list of conditions and the following disclaimer.
12 1.6.2.2 skrll * 2. Redistributions in binary form must reproduce the above copyright
13 1.6.2.2 skrll * notice, this list of conditions and the following disclaimer in the
14 1.6.2.2 skrll * documentation and/or other materials provided with the distribution.
15 1.6.2.2 skrll *
16 1.6.2.2 skrll * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
17 1.6.2.2 skrll * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
18 1.6.2.2 skrll * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
19 1.6.2.2 skrll * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
20 1.6.2.2 skrll * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
21 1.6.2.2 skrll * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
22 1.6.2.2 skrll * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
23 1.6.2.2 skrll * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
24 1.6.2.2 skrll * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
25 1.6.2.2 skrll * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
26 1.6.2.2 skrll * SUCH DAMAGE.
27 1.6.2.2 skrll */
28 1.6.2.2 skrll
29 1.6.2.2 skrll #include <sys/cdefs.h>
30 1.6.2.5 skrll __KERNEL_RCSID(0, "$NetBSD: dwc_mmc.c,v 1.6.2.5 2017/08/28 17:52:03 skrll Exp $");
31 1.6.2.2 skrll
32 1.6.2.2 skrll #include <sys/param.h>
33 1.6.2.2 skrll #include <sys/bus.h>
34 1.6.2.2 skrll #include <sys/device.h>
35 1.6.2.2 skrll #include <sys/intr.h>
36 1.6.2.2 skrll #include <sys/systm.h>
37 1.6.2.2 skrll #include <sys/kernel.h>
38 1.6.2.2 skrll
39 1.6.2.2 skrll #include <dev/sdmmc/sdmmcvar.h>
40 1.6.2.2 skrll #include <dev/sdmmc/sdmmcchip.h>
41 1.6.2.2 skrll #include <dev/sdmmc/sdmmc_ioreg.h>
42 1.6.2.2 skrll
43 1.6.2.2 skrll #include <dev/ic/dwc_mmc_reg.h>
44 1.6.2.2 skrll #include <dev/ic/dwc_mmc_var.h>
45 1.6.2.2 skrll
46 1.6.2.5 skrll #define DWC_MMC_NDESC 64
47 1.6.2.5 skrll
48 1.6.2.2 skrll static int dwc_mmc_host_reset(sdmmc_chipset_handle_t);
49 1.6.2.2 skrll static uint32_t dwc_mmc_host_ocr(sdmmc_chipset_handle_t);
50 1.6.2.2 skrll static int dwc_mmc_host_maxblklen(sdmmc_chipset_handle_t);
51 1.6.2.2 skrll static int dwc_mmc_card_detect(sdmmc_chipset_handle_t);
52 1.6.2.2 skrll static int dwc_mmc_write_protect(sdmmc_chipset_handle_t);
53 1.6.2.2 skrll static int dwc_mmc_bus_power(sdmmc_chipset_handle_t, uint32_t);
54 1.6.2.2 skrll static int dwc_mmc_bus_clock(sdmmc_chipset_handle_t, int);
55 1.6.2.2 skrll static int dwc_mmc_bus_width(sdmmc_chipset_handle_t, int);
56 1.6.2.2 skrll static int dwc_mmc_bus_rod(sdmmc_chipset_handle_t, int);
57 1.6.2.2 skrll static void dwc_mmc_exec_command(sdmmc_chipset_handle_t,
58 1.6.2.5 skrll struct sdmmc_command *);
59 1.6.2.2 skrll static void dwc_mmc_card_enable_intr(sdmmc_chipset_handle_t, int);
60 1.6.2.2 skrll static void dwc_mmc_card_intr_ack(sdmmc_chipset_handle_t);
61 1.6.2.2 skrll
62 1.6.2.2 skrll static struct sdmmc_chip_functions dwc_mmc_chip_functions = {
63 1.6.2.2 skrll .host_reset = dwc_mmc_host_reset,
64 1.6.2.2 skrll .host_ocr = dwc_mmc_host_ocr,
65 1.6.2.2 skrll .host_maxblklen = dwc_mmc_host_maxblklen,
66 1.6.2.2 skrll .card_detect = dwc_mmc_card_detect,
67 1.6.2.2 skrll .write_protect = dwc_mmc_write_protect,
68 1.6.2.2 skrll .bus_power = dwc_mmc_bus_power,
69 1.6.2.2 skrll .bus_clock = dwc_mmc_bus_clock,
70 1.6.2.2 skrll .bus_width = dwc_mmc_bus_width,
71 1.6.2.2 skrll .bus_rod = dwc_mmc_bus_rod,
72 1.6.2.2 skrll .exec_command = dwc_mmc_exec_command,
73 1.6.2.2 skrll .card_enable_intr = dwc_mmc_card_enable_intr,
74 1.6.2.2 skrll .card_intr_ack = dwc_mmc_card_intr_ack,
75 1.6.2.2 skrll };
76 1.6.2.2 skrll
77 1.6.2.5 skrll #define MMC_WRITE(sc, reg, val) \
78 1.6.2.2 skrll bus_space_write_4((sc)->sc_bst, (sc)->sc_bsh, (reg), (val))
79 1.6.2.2 skrll #define MMC_READ(sc, reg) \
80 1.6.2.2 skrll bus_space_read_4((sc)->sc_bst, (sc)->sc_bsh, (reg))
81 1.6.2.2 skrll
82 1.6.2.5 skrll static void
83 1.6.2.5 skrll dwc_mmc_dump_regs(struct dwc_mmc_softc *sc)
84 1.6.2.2 skrll {
85 1.6.2.5 skrll device_printf(sc->sc_dev, "device registers:\n");
86 1.6.2.5 skrll for (u_int off = 0x00; off < 0x100; off += 16) {
87 1.6.2.5 skrll device_printf(sc->sc_dev, "xxxxxx%02x: %08x %08x %08x %08x\n",
88 1.6.2.5 skrll off,
89 1.6.2.5 skrll MMC_READ(sc, off + 0), MMC_READ(sc, off + 4),
90 1.6.2.5 skrll MMC_READ(sc, off + 8), MMC_READ(sc, off + 12));
91 1.6.2.5 skrll }
92 1.6.2.5 skrll }
93 1.6.2.2 skrll
94 1.6.2.5 skrll static int
95 1.6.2.5 skrll dwc_mmc_idma_setup(struct dwc_mmc_softc *sc)
96 1.6.2.5 skrll {
97 1.6.2.5 skrll int error;
98 1.6.2.5 skrll
99 1.6.2.5 skrll sc->sc_idma_xferlen = 0x1000;
100 1.6.2.5 skrll
101 1.6.2.5 skrll sc->sc_idma_ndesc = DWC_MMC_NDESC;
102 1.6.2.5 skrll sc->sc_idma_size = sizeof(struct dwc_mmc_idma_desc) *
103 1.6.2.5 skrll sc->sc_idma_ndesc;
104 1.6.2.5 skrll error = bus_dmamem_alloc(sc->sc_dmat, sc->sc_idma_size, 8,
105 1.6.2.5 skrll sc->sc_idma_size, sc->sc_idma_segs, 1,
106 1.6.2.5 skrll &sc->sc_idma_nsegs, BUS_DMA_WAITOK);
107 1.6.2.5 skrll if (error)
108 1.6.2.5 skrll return error;
109 1.6.2.5 skrll error = bus_dmamem_map(sc->sc_dmat, sc->sc_idma_segs,
110 1.6.2.5 skrll sc->sc_idma_nsegs, sc->sc_idma_size,
111 1.6.2.5 skrll &sc->sc_idma_desc, BUS_DMA_WAITOK);
112 1.6.2.5 skrll if (error)
113 1.6.2.5 skrll goto free;
114 1.6.2.5 skrll error = bus_dmamap_create(sc->sc_dmat, sc->sc_idma_size, 1,
115 1.6.2.5 skrll sc->sc_idma_size, 0, BUS_DMA_WAITOK, &sc->sc_idma_map);
116 1.6.2.5 skrll if (error)
117 1.6.2.5 skrll goto unmap;
118 1.6.2.5 skrll error = bus_dmamap_load(sc->sc_dmat, sc->sc_idma_map,
119 1.6.2.5 skrll sc->sc_idma_desc, sc->sc_idma_size, NULL, BUS_DMA_WAITOK);
120 1.6.2.5 skrll if (error)
121 1.6.2.5 skrll goto destroy;
122 1.6.2.5 skrll return 0;
123 1.6.2.2 skrll
124 1.6.2.5 skrll destroy:
125 1.6.2.5 skrll bus_dmamap_destroy(sc->sc_dmat, sc->sc_idma_map);
126 1.6.2.5 skrll unmap:
127 1.6.2.5 skrll bus_dmamem_unmap(sc->sc_dmat, sc->sc_idma_desc, sc->sc_idma_size);
128 1.6.2.5 skrll free:
129 1.6.2.5 skrll bus_dmamem_free(sc->sc_dmat, sc->sc_idma_segs, sc->sc_idma_nsegs);
130 1.6.2.5 skrll return error;
131 1.6.2.5 skrll }
132 1.6.2.5 skrll
133 1.6.2.5 skrll static void
134 1.6.2.5 skrll dwc_mmc_attach_i(device_t self)
135 1.6.2.5 skrll {
136 1.6.2.5 skrll struct dwc_mmc_softc *sc = device_private(self);
137 1.6.2.5 skrll struct sdmmcbus_attach_args saa;
138 1.6.2.4 skrll
139 1.6.2.2 skrll dwc_mmc_host_reset(sc);
140 1.6.2.2 skrll dwc_mmc_bus_width(sc, 1);
141 1.6.2.2 skrll
142 1.6.2.2 skrll memset(&saa, 0, sizeof(saa));
143 1.6.2.2 skrll saa.saa_busname = "sdmmc";
144 1.6.2.2 skrll saa.saa_sct = &dwc_mmc_chip_functions;
145 1.6.2.2 skrll saa.saa_sch = sc;
146 1.6.2.2 skrll saa.saa_clkmin = 400;
147 1.6.2.5 skrll saa.saa_clkmax = sc->sc_clock_freq / 1000;
148 1.6.2.2 skrll saa.saa_caps = SMC_CAPS_4BIT_MODE|
149 1.6.2.2 skrll SMC_CAPS_8BIT_MODE|
150 1.6.2.2 skrll SMC_CAPS_SD_HIGHSPEED|
151 1.6.2.2 skrll SMC_CAPS_MMC_HIGHSPEED|
152 1.6.2.2 skrll SMC_CAPS_AUTO_STOP;
153 1.6.2.5 skrll if (ISSET(sc->sc_flags, DWC_MMC_F_DMA)) {
154 1.6.2.5 skrll saa.saa_dmat = sc->sc_dmat;
155 1.6.2.5 skrll saa.saa_caps |= SMC_CAPS_DMA |
156 1.6.2.5 skrll SMC_CAPS_MULTI_SEG_DMA;
157 1.6.2.2 skrll }
158 1.6.2.5 skrll if (sc->sc_card_detect)
159 1.6.2.5 skrll saa.saa_caps |= SMC_CAPS_POLL_CARD_DET;
160 1.6.2.2 skrll
161 1.6.2.5 skrll sc->sc_sdmmc_dev = config_found(self, &saa, NULL);
162 1.6.2.2 skrll }
163 1.6.2.2 skrll
164 1.6.2.2 skrll static int
165 1.6.2.2 skrll dwc_mmc_wait_rint(struct dwc_mmc_softc *sc, uint32_t mask, int timeout)
166 1.6.2.2 skrll {
167 1.6.2.5 skrll const bool use_dma = ISSET(sc->sc_flags, DWC_MMC_F_DMA);
168 1.6.2.2 skrll int retry, error;
169 1.6.2.2 skrll
170 1.6.2.2 skrll KASSERT(mutex_owned(&sc->sc_intr_lock));
171 1.6.2.2 skrll
172 1.6.2.2 skrll if (sc->sc_intr_rint & mask)
173 1.6.2.2 skrll return 0;
174 1.6.2.2 skrll
175 1.6.2.2 skrll retry = timeout / hz;
176 1.6.2.2 skrll
177 1.6.2.2 skrll while (retry > 0) {
178 1.6.2.5 skrll if (use_dma) {
179 1.6.2.5 skrll error = cv_timedwait(&sc->sc_intr_cv,
180 1.6.2.5 skrll &sc->sc_intr_lock, hz);
181 1.6.2.5 skrll if (error && error != EWOULDBLOCK)
182 1.6.2.5 skrll return error;
183 1.6.2.5 skrll if (sc->sc_intr_rint & mask)
184 1.6.2.5 skrll return 0;
185 1.6.2.5 skrll } else {
186 1.6.2.5 skrll sc->sc_intr_rint |= MMC_READ(sc, DWC_MMC_RINT);
187 1.6.2.5 skrll if (sc->sc_intr_rint & mask)
188 1.6.2.5 skrll return 0;
189 1.6.2.5 skrll delay(1000);
190 1.6.2.5 skrll }
191 1.6.2.2 skrll --retry;
192 1.6.2.2 skrll }
193 1.6.2.2 skrll
194 1.6.2.2 skrll return ETIMEDOUT;
195 1.6.2.2 skrll }
196 1.6.2.2 skrll
197 1.6.2.5 skrll static void
198 1.6.2.5 skrll dwc_mmc_led(struct dwc_mmc_softc *sc, int on)
199 1.6.2.2 skrll {
200 1.6.2.5 skrll if (sc->sc_set_led)
201 1.6.2.5 skrll sc->sc_set_led(sc, on);
202 1.6.2.2 skrll }
203 1.6.2.3 skrll
204 1.6.2.2 skrll static int
205 1.6.2.2 skrll dwc_mmc_host_reset(sdmmc_chipset_handle_t sch)
206 1.6.2.2 skrll {
207 1.6.2.2 skrll struct dwc_mmc_softc *sc = sch;
208 1.6.2.5 skrll uint32_t fifoth, ctrl;
209 1.6.2.2 skrll int retry = 1000;
210 1.6.2.2 skrll
211 1.6.2.5 skrll #ifdef DWC_MMC_DEBUG
212 1.6.2.5 skrll aprint_normal_dev(sc->sc_dev, "host reset\n");
213 1.6.2.5 skrll #endif
214 1.6.2.5 skrll
215 1.6.2.5 skrll MMC_WRITE(sc, DWC_MMC_PWREN, 1);
216 1.6.2.2 skrll
217 1.6.2.5 skrll MMC_WRITE(sc, DWC_MMC_GCTRL,
218 1.6.2.5 skrll MMC_READ(sc, DWC_MMC_GCTRL) | DWC_MMC_GCTRL_RESET);
219 1.6.2.2 skrll while (--retry > 0) {
220 1.6.2.5 skrll if (!(MMC_READ(sc, DWC_MMC_GCTRL) & DWC_MMC_GCTRL_RESET))
221 1.6.2.2 skrll break;
222 1.6.2.2 skrll delay(100);
223 1.6.2.2 skrll }
224 1.6.2.2 skrll
225 1.6.2.5 skrll MMC_WRITE(sc, DWC_MMC_CLKSRC, 0);
226 1.6.2.2 skrll
227 1.6.2.5 skrll MMC_WRITE(sc, DWC_MMC_TIMEOUT, 0xffffffff);
228 1.6.2.2 skrll
229 1.6.2.5 skrll MMC_WRITE(sc, DWC_MMC_IMASK,
230 1.6.2.5 skrll DWC_MMC_INT_CMD_DONE | DWC_MMC_INT_ERROR |
231 1.6.2.5 skrll DWC_MMC_INT_DATA_OVER | DWC_MMC_INT_AUTO_CMD_DONE);
232 1.6.2.2 skrll
233 1.6.2.5 skrll const uint32_t rx_wmark = (sc->sc_fifo_depth / 2) - 1;
234 1.6.2.5 skrll const uint32_t tx_wmark = sc->sc_fifo_depth / 2;
235 1.6.2.2 skrll fifoth = __SHIFTIN(DWC_MMC_FIFOTH_DMA_MULTIPLE_TXN_SIZE_16,
236 1.6.2.2 skrll DWC_MMC_FIFOTH_DMA_MULTIPLE_TXN_SIZE);
237 1.6.2.2 skrll fifoth |= __SHIFTIN(rx_wmark, DWC_MMC_FIFOTH_RX_WMARK);
238 1.6.2.2 skrll fifoth |= __SHIFTIN(tx_wmark, DWC_MMC_FIFOTH_TX_WMARK);
239 1.6.2.5 skrll MMC_WRITE(sc, DWC_MMC_FIFOTH, fifoth);
240 1.6.2.2 skrll
241 1.6.2.5 skrll MMC_WRITE(sc, DWC_MMC_UHS, 0);
242 1.6.2.5 skrll
243 1.6.2.5 skrll ctrl = MMC_READ(sc, DWC_MMC_GCTRL);
244 1.6.2.5 skrll ctrl |= DWC_MMC_GCTRL_INTEN;
245 1.6.2.5 skrll ctrl |= DWC_MMC_GCTRL_DMAEN;
246 1.6.2.5 skrll ctrl |= DWC_MMC_GCTRL_SEND_AUTO_STOP_CCSD;
247 1.6.2.5 skrll ctrl |= DWC_MMC_GCTRL_USE_INTERNAL_DMAC;
248 1.6.2.5 skrll MMC_WRITE(sc, DWC_MMC_GCTRL, ctrl);
249 1.6.2.2 skrll
250 1.6.2.2 skrll return 0;
251 1.6.2.2 skrll }
252 1.6.2.2 skrll
253 1.6.2.2 skrll static uint32_t
254 1.6.2.2 skrll dwc_mmc_host_ocr(sdmmc_chipset_handle_t sch)
255 1.6.2.2 skrll {
256 1.6.2.5 skrll return MMC_OCR_3_2V_3_3V | MMC_OCR_3_3V_3_4V | MMC_OCR_HCS;
257 1.6.2.2 skrll }
258 1.6.2.2 skrll
259 1.6.2.2 skrll static int
260 1.6.2.2 skrll dwc_mmc_host_maxblklen(sdmmc_chipset_handle_t sch)
261 1.6.2.2 skrll {
262 1.6.2.2 skrll return 32768;
263 1.6.2.2 skrll }
264 1.6.2.2 skrll
265 1.6.2.2 skrll static int
266 1.6.2.2 skrll dwc_mmc_card_detect(sdmmc_chipset_handle_t sch)
267 1.6.2.2 skrll {
268 1.6.2.2 skrll struct dwc_mmc_softc *sc = sch;
269 1.6.2.5 skrll int v = 0, i;
270 1.6.2.2 skrll
271 1.6.2.5 skrll if (!sc->sc_card_detect)
272 1.6.2.5 skrll return 1; /* no card detect pin, assume present */
273 1.6.2.5 skrll
274 1.6.2.5 skrll for (i = 0; i < 5; i++) {
275 1.6.2.5 skrll v += sc->sc_card_detect(sc);
276 1.6.2.5 skrll delay(1000);
277 1.6.2.5 skrll }
278 1.6.2.5 skrll if (v == 5)
279 1.6.2.5 skrll sc->sc_mmc_present = 0;
280 1.6.2.5 skrll else if (v == 0)
281 1.6.2.5 skrll sc->sc_mmc_present = 1;
282 1.6.2.5 skrll return sc->sc_mmc_present;
283 1.6.2.2 skrll }
284 1.6.2.2 skrll
285 1.6.2.2 skrll static int
286 1.6.2.2 skrll dwc_mmc_write_protect(sdmmc_chipset_handle_t sch)
287 1.6.2.2 skrll {
288 1.6.2.2 skrll struct dwc_mmc_softc *sc = sch;
289 1.6.2.2 skrll
290 1.6.2.5 skrll if (!sc->sc_write_protect)
291 1.6.2.5 skrll return 0; /* no write protect pin, assume rw */
292 1.6.2.5 skrll
293 1.6.2.5 skrll return sc->sc_write_protect(sc);
294 1.6.2.2 skrll }
295 1.6.2.2 skrll
296 1.6.2.2 skrll static int
297 1.6.2.2 skrll dwc_mmc_bus_power(sdmmc_chipset_handle_t sch, uint32_t ocr)
298 1.6.2.2 skrll {
299 1.6.2.2 skrll return 0;
300 1.6.2.2 skrll }
301 1.6.2.2 skrll
302 1.6.2.2 skrll static int
303 1.6.2.5 skrll dwc_mmc_update_clock(struct dwc_mmc_softc *sc)
304 1.6.2.2 skrll {
305 1.6.2.5 skrll uint32_t cmd;
306 1.6.2.5 skrll int retry;
307 1.6.2.2 skrll
308 1.6.2.2 skrll #ifdef DWC_MMC_DEBUG
309 1.6.2.5 skrll aprint_normal_dev(sc->sc_dev, "update clock\n");
310 1.6.2.2 skrll #endif
311 1.6.2.2 skrll
312 1.6.2.5 skrll cmd = DWC_MMC_CMD_START |
313 1.6.2.5 skrll DWC_MMC_CMD_UPCLK_ONLY |
314 1.6.2.5 skrll DWC_MMC_CMD_WAIT_PRE_OVER;
315 1.6.2.5 skrll if (ISSET(sc->sc_flags, DWC_MMC_F_USE_HOLD_REG))
316 1.6.2.5 skrll cmd |= DWC_MMC_CMD_USE_HOLD_REG;
317 1.6.2.5 skrll MMC_WRITE(sc, DWC_MMC_ARG, 0);
318 1.6.2.5 skrll MMC_WRITE(sc, DWC_MMC_CMD, cmd);
319 1.6.2.5 skrll retry = 0xfffff;
320 1.6.2.5 skrll while (--retry > 0) {
321 1.6.2.5 skrll if (!(MMC_READ(sc, DWC_MMC_CMD) & DWC_MMC_CMD_START))
322 1.6.2.5 skrll break;
323 1.6.2.5 skrll delay(10);
324 1.6.2.5 skrll }
325 1.6.2.5 skrll
326 1.6.2.5 skrll if (retry == 0) {
327 1.6.2.5 skrll aprint_error_dev(sc->sc_dev, "timeout updating clock\n");
328 1.6.2.5 skrll #ifdef DWC_MMC_DEBUG
329 1.6.2.5 skrll device_printf(sc->sc_dev, "GCTRL: 0x%08x\n",
330 1.6.2.5 skrll MMC_READ(sc, DWC_MMC_GCTRL));
331 1.6.2.5 skrll device_printf(sc->sc_dev, "CLKENA: 0x%08x\n",
332 1.6.2.5 skrll MMC_READ(sc, DWC_MMC_CLKENA));
333 1.6.2.5 skrll device_printf(sc->sc_dev, "CLKDIV: 0x%08x\n",
334 1.6.2.5 skrll MMC_READ(sc, DWC_MMC_CLKDIV));
335 1.6.2.5 skrll device_printf(sc->sc_dev, "TIMEOUT: 0x%08x\n",
336 1.6.2.5 skrll MMC_READ(sc, DWC_MMC_TIMEOUT));
337 1.6.2.5 skrll device_printf(sc->sc_dev, "WIDTH: 0x%08x\n",
338 1.6.2.5 skrll MMC_READ(sc, DWC_MMC_WIDTH));
339 1.6.2.5 skrll device_printf(sc->sc_dev, "CMD: 0x%08x\n",
340 1.6.2.5 skrll MMC_READ(sc, DWC_MMC_CMD));
341 1.6.2.5 skrll device_printf(sc->sc_dev, "MINT: 0x%08x\n",
342 1.6.2.5 skrll MMC_READ(sc, DWC_MMC_MINT));
343 1.6.2.5 skrll device_printf(sc->sc_dev, "RINT: 0x%08x\n",
344 1.6.2.5 skrll MMC_READ(sc, DWC_MMC_RINT));
345 1.6.2.5 skrll device_printf(sc->sc_dev, "STATUS: 0x%08x\n",
346 1.6.2.5 skrll MMC_READ(sc, DWC_MMC_STATUS));
347 1.6.2.5 skrll #endif
348 1.6.2.2 skrll return ETIMEDOUT;
349 1.6.2.5 skrll }
350 1.6.2.5 skrll
351 1.6.2.5 skrll return 0;
352 1.6.2.5 skrll }
353 1.6.2.5 skrll
354 1.6.2.5 skrll static int
355 1.6.2.5 skrll dwc_mmc_set_clock(struct dwc_mmc_softc *sc, u_int freq)
356 1.6.2.5 skrll {
357 1.6.2.5 skrll const u_int pll_freq = sc->sc_clock_freq / 1000;
358 1.6.2.5 skrll const u_int clk_div = howmany(pll_freq, freq * 2);
359 1.6.2.5 skrll
360 1.6.2.5 skrll MMC_WRITE(sc, DWC_MMC_CLKDIV, clk_div);
361 1.6.2.5 skrll
362 1.6.2.5 skrll return dwc_mmc_update_clock(sc);
363 1.6.2.5 skrll }
364 1.6.2.5 skrll
365 1.6.2.5 skrll static int
366 1.6.2.5 skrll dwc_mmc_bus_clock(sdmmc_chipset_handle_t sch, int freq)
367 1.6.2.5 skrll {
368 1.6.2.5 skrll struct dwc_mmc_softc *sc = sch;
369 1.6.2.5 skrll uint32_t clkena;
370 1.6.2.5 skrll
371 1.6.2.5 skrll MMC_WRITE(sc, DWC_MMC_CLKSRC, 0);
372 1.6.2.5 skrll MMC_WRITE(sc, DWC_MMC_CLKENA, 0);
373 1.6.2.5 skrll if (dwc_mmc_update_clock(sc) != 0)
374 1.6.2.5 skrll return 1;
375 1.6.2.2 skrll
376 1.6.2.2 skrll if (freq) {
377 1.6.2.2 skrll if (dwc_mmc_set_clock(sc, freq) != 0)
378 1.6.2.5 skrll return 1;
379 1.6.2.2 skrll
380 1.6.2.5 skrll clkena = DWC_MMC_CLKENA_CARDCLKON;
381 1.6.2.5 skrll MMC_WRITE(sc, DWC_MMC_CLKENA, clkena);
382 1.6.2.2 skrll if (dwc_mmc_update_clock(sc) != 0)
383 1.6.2.5 skrll return 1;
384 1.6.2.2 skrll }
385 1.6.2.2 skrll
386 1.6.2.2 skrll delay(1000);
387 1.6.2.2 skrll
388 1.6.2.2 skrll return 0;
389 1.6.2.2 skrll }
390 1.6.2.2 skrll
391 1.6.2.2 skrll static int
392 1.6.2.2 skrll dwc_mmc_bus_width(sdmmc_chipset_handle_t sch, int width)
393 1.6.2.2 skrll {
394 1.6.2.2 skrll struct dwc_mmc_softc *sc = sch;
395 1.6.2.5 skrll
396 1.6.2.5 skrll #ifdef DWC_MMC_DEBUG
397 1.6.2.5 skrll aprint_normal_dev(sc->sc_dev, "width = %d\n", width);
398 1.6.2.5 skrll #endif
399 1.6.2.2 skrll
400 1.6.2.2 skrll switch (width) {
401 1.6.2.2 skrll case 1:
402 1.6.2.5 skrll MMC_WRITE(sc, DWC_MMC_WIDTH, DWC_MMC_WIDTH_1);
403 1.6.2.2 skrll break;
404 1.6.2.2 skrll case 4:
405 1.6.2.5 skrll MMC_WRITE(sc, DWC_MMC_WIDTH, DWC_MMC_WIDTH_4);
406 1.6.2.2 skrll break;
407 1.6.2.2 skrll case 8:
408 1.6.2.5 skrll MMC_WRITE(sc, DWC_MMC_WIDTH, DWC_MMC_WIDTH_8);
409 1.6.2.2 skrll break;
410 1.6.2.2 skrll default:
411 1.6.2.5 skrll return 1;
412 1.6.2.2 skrll }
413 1.6.2.2 skrll
414 1.6.2.5 skrll sc->sc_mmc_width = width;
415 1.6.2.5 skrll
416 1.6.2.2 skrll return 0;
417 1.6.2.2 skrll }
418 1.6.2.2 skrll
419 1.6.2.2 skrll static int
420 1.6.2.2 skrll dwc_mmc_bus_rod(sdmmc_chipset_handle_t sch, int on)
421 1.6.2.2 skrll {
422 1.6.2.5 skrll return -1;
423 1.6.2.5 skrll }
424 1.6.2.5 skrll
425 1.6.2.5 skrll
426 1.6.2.5 skrll static int
427 1.6.2.5 skrll dwc_mmc_pio_wait(struct dwc_mmc_softc *sc, struct sdmmc_command *cmd)
428 1.6.2.5 skrll {
429 1.6.2.5 skrll int retry = 0xfffff;
430 1.6.2.5 skrll uint32_t bit = (cmd->c_flags & SCF_CMD_READ) ?
431 1.6.2.5 skrll DWC_MMC_STATUS_FIFO_EMPTY : DWC_MMC_STATUS_FIFO_FULL;
432 1.6.2.5 skrll
433 1.6.2.5 skrll while (--retry > 0) {
434 1.6.2.5 skrll uint32_t status = MMC_READ(sc, DWC_MMC_STATUS);
435 1.6.2.5 skrll if (!(status & bit))
436 1.6.2.5 skrll return 0;
437 1.6.2.5 skrll delay(10);
438 1.6.2.5 skrll }
439 1.6.2.5 skrll
440 1.6.2.5 skrll return ETIMEDOUT;
441 1.6.2.5 skrll }
442 1.6.2.5 skrll
443 1.6.2.5 skrll static int
444 1.6.2.5 skrll dwc_mmc_pio_transfer(struct dwc_mmc_softc *sc, struct sdmmc_command *cmd)
445 1.6.2.5 skrll {
446 1.6.2.5 skrll uint32_t *datap = (uint32_t *)cmd->c_data;
447 1.6.2.5 skrll int i;
448 1.6.2.5 skrll
449 1.6.2.5 skrll for (i = 0; i < (cmd->c_resid >> 2); i++) {
450 1.6.2.5 skrll if (dwc_mmc_pio_wait(sc, cmd))
451 1.6.2.5 skrll return ETIMEDOUT;
452 1.6.2.5 skrll if (cmd->c_flags & SCF_CMD_READ) {
453 1.6.2.5 skrll datap[i] = MMC_READ(sc, sc->sc_fifo_reg);
454 1.6.2.5 skrll } else {
455 1.6.2.5 skrll MMC_WRITE(sc, sc->sc_fifo_reg, datap[i]);
456 1.6.2.5 skrll }
457 1.6.2.5 skrll }
458 1.6.2.5 skrll
459 1.6.2.5 skrll return 0;
460 1.6.2.5 skrll }
461 1.6.2.5 skrll
462 1.6.2.5 skrll static int
463 1.6.2.5 skrll dwc_mmc_dma_prepare(struct dwc_mmc_softc *sc, struct sdmmc_command *cmd)
464 1.6.2.5 skrll {
465 1.6.2.5 skrll struct dwc_mmc_idma_desc *dma = sc->sc_idma_desc;
466 1.6.2.5 skrll bus_addr_t desc_paddr = sc->sc_idma_map->dm_segs[0].ds_addr;
467 1.6.2.5 skrll bus_size_t off;
468 1.6.2.5 skrll int desc, resid, seg;
469 1.6.2.5 skrll uint32_t val;
470 1.6.2.5 skrll
471 1.6.2.5 skrll desc = 0;
472 1.6.2.5 skrll for (seg = 0; seg < cmd->c_dmamap->dm_nsegs; seg++) {
473 1.6.2.5 skrll bus_addr_t paddr = cmd->c_dmamap->dm_segs[seg].ds_addr;
474 1.6.2.5 skrll bus_size_t len = cmd->c_dmamap->dm_segs[seg].ds_len;
475 1.6.2.5 skrll resid = min(len, cmd->c_resid);
476 1.6.2.5 skrll off = 0;
477 1.6.2.5 skrll while (resid > 0) {
478 1.6.2.5 skrll if (desc == sc->sc_idma_ndesc)
479 1.6.2.5 skrll break;
480 1.6.2.5 skrll len = min(sc->sc_idma_xferlen, resid);
481 1.6.2.5 skrll dma[desc].dma_buf_size = htole32(len);
482 1.6.2.5 skrll dma[desc].dma_buf_addr = htole32(paddr + off);
483 1.6.2.5 skrll dma[desc].dma_config = htole32(
484 1.6.2.5 skrll DWC_MMC_IDMA_CONFIG_OWN);
485 1.6.2.5 skrll cmd->c_resid -= len;
486 1.6.2.5 skrll resid -= len;
487 1.6.2.5 skrll off += len;
488 1.6.2.5 skrll dma[desc].dma_next = htole32(
489 1.6.2.5 skrll desc_paddr + ((desc+1) *
490 1.6.2.5 skrll sizeof(struct dwc_mmc_idma_desc)));
491 1.6.2.5 skrll if (desc == 0) {
492 1.6.2.5 skrll dma[desc].dma_config |= htole32(
493 1.6.2.5 skrll DWC_MMC_IDMA_CONFIG_FD);
494 1.6.2.5 skrll }
495 1.6.2.5 skrll if (cmd->c_resid == 0) {
496 1.6.2.5 skrll dma[desc].dma_config |= htole32(
497 1.6.2.5 skrll DWC_MMC_IDMA_CONFIG_LD);
498 1.6.2.5 skrll } else {
499 1.6.2.5 skrll dma[desc].dma_config |=
500 1.6.2.5 skrll htole32(DWC_MMC_IDMA_CONFIG_CH|
501 1.6.2.5 skrll DWC_MMC_IDMA_CONFIG_DIC);
502 1.6.2.5 skrll }
503 1.6.2.5 skrll ++desc;
504 1.6.2.5 skrll }
505 1.6.2.5 skrll }
506 1.6.2.5 skrll if (desc == sc->sc_idma_ndesc) {
507 1.6.2.5 skrll aprint_error_dev(sc->sc_dev,
508 1.6.2.5 skrll "not enough descriptors for %d byte transfer!\n",
509 1.6.2.5 skrll cmd->c_datalen);
510 1.6.2.5 skrll return EIO;
511 1.6.2.5 skrll }
512 1.6.2.5 skrll
513 1.6.2.5 skrll bus_dmamap_sync(sc->sc_dmat, sc->sc_idma_map, 0,
514 1.6.2.5 skrll sc->sc_idma_size, BUS_DMASYNC_PREWRITE);
515 1.6.2.5 skrll
516 1.6.2.5 skrll sc->sc_idma_idst = 0;
517 1.6.2.5 skrll
518 1.6.2.5 skrll val = MMC_READ(sc, DWC_MMC_GCTRL);
519 1.6.2.5 skrll val |= DWC_MMC_GCTRL_DMAEN;
520 1.6.2.5 skrll val |= DWC_MMC_GCTRL_INTEN;
521 1.6.2.5 skrll MMC_WRITE(sc, DWC_MMC_GCTRL, val);
522 1.6.2.5 skrll val |= DWC_MMC_GCTRL_DMARESET;
523 1.6.2.5 skrll MMC_WRITE(sc, DWC_MMC_GCTRL, val);
524 1.6.2.5 skrll MMC_WRITE(sc, DWC_MMC_DMAC, DWC_MMC_DMAC_SOFTRESET);
525 1.6.2.5 skrll MMC_WRITE(sc, DWC_MMC_DMAC,
526 1.6.2.5 skrll DWC_MMC_DMAC_IDMA_ON|DWC_MMC_DMAC_FIX_BURST);
527 1.6.2.5 skrll val = MMC_READ(sc, DWC_MMC_IDIE);
528 1.6.2.5 skrll val &= ~(DWC_MMC_IDST_RECEIVE_INT|DWC_MMC_IDST_TRANSMIT_INT);
529 1.6.2.5 skrll if (cmd->c_flags & SCF_CMD_READ)
530 1.6.2.5 skrll val |= DWC_MMC_IDST_RECEIVE_INT;
531 1.6.2.5 skrll else
532 1.6.2.5 skrll val |= DWC_MMC_IDST_TRANSMIT_INT;
533 1.6.2.5 skrll MMC_WRITE(sc, DWC_MMC_IDIE, val);
534 1.6.2.5 skrll MMC_WRITE(sc, DWC_MMC_DLBA, desc_paddr);
535 1.6.2.5 skrll
536 1.6.2.5 skrll return 0;
537 1.6.2.5 skrll }
538 1.6.2.5 skrll
539 1.6.2.5 skrll static void
540 1.6.2.5 skrll dwc_mmc_dma_complete(struct dwc_mmc_softc *sc)
541 1.6.2.5 skrll {
542 1.6.2.5 skrll bus_dmamap_sync(sc->sc_dmat, sc->sc_idma_map, 0,
543 1.6.2.5 skrll sc->sc_idma_size, BUS_DMASYNC_POSTWRITE);
544 1.6.2.2 skrll }
545 1.6.2.2 skrll
546 1.6.2.2 skrll static void
547 1.6.2.2 skrll dwc_mmc_exec_command(sdmmc_chipset_handle_t sch, struct sdmmc_command *cmd)
548 1.6.2.2 skrll {
549 1.6.2.2 skrll struct dwc_mmc_softc *sc = sch;
550 1.6.2.5 skrll uint32_t cmdval = DWC_MMC_CMD_START;
551 1.6.2.5 skrll int retry = 0xfffff;
552 1.6.2.2 skrll
553 1.6.2.2 skrll #ifdef DWC_MMC_DEBUG
554 1.6.2.5 skrll aprint_normal_dev(sc->sc_dev,
555 1.6.2.5 skrll "opcode %d flags 0x%x data %p datalen %d blklen %d\n",
556 1.6.2.5 skrll cmd->c_opcode, cmd->c_flags, cmd->c_data, cmd->c_datalen,
557 1.6.2.5 skrll cmd->c_blklen);
558 1.6.2.2 skrll #endif
559 1.6.2.2 skrll
560 1.6.2.5 skrll mutex_enter(&sc->sc_intr_lock);
561 1.6.2.2 skrll
562 1.6.2.5 skrll do {
563 1.6.2.5 skrll const uint32_t status = MMC_READ(sc, DWC_MMC_STATUS);
564 1.6.2.5 skrll if ((status & DWC_MMC_STATUS_CARD_DATA_BUSY) == 0)
565 1.6.2.5 skrll break;
566 1.6.2.5 skrll delay(10);
567 1.6.2.5 skrll } while (--retry > 0);
568 1.6.2.5 skrll if (retry == 0) {
569 1.6.2.5 skrll aprint_error_dev(sc->sc_dev, "timeout waiting for data busy\n");
570 1.6.2.5 skrll cmd->c_error = ETIMEDOUT;
571 1.6.2.5 skrll goto done;
572 1.6.2.5 skrll }
573 1.6.2.2 skrll
574 1.6.2.5 skrll MMC_WRITE(sc, DWC_MMC_IDST, 0xffffffff);
575 1.6.2.5 skrll MMC_WRITE(sc, DWC_MMC_RINT, 0xffffffff);
576 1.6.2.4 skrll
577 1.6.2.5 skrll if (ISSET(sc->sc_flags, DWC_MMC_F_USE_HOLD_REG))
578 1.6.2.5 skrll cmdval |= DWC_MMC_CMD_USE_HOLD_REG;
579 1.6.2.4 skrll
580 1.6.2.2 skrll if (cmd->c_opcode == 0)
581 1.6.2.5 skrll cmdval |= DWC_MMC_CMD_SEND_INIT_SEQ;
582 1.6.2.2 skrll if (cmd->c_flags & SCF_RSP_PRESENT)
583 1.6.2.5 skrll cmdval |= DWC_MMC_CMD_RSP_EXP;
584 1.6.2.2 skrll if (cmd->c_flags & SCF_RSP_136)
585 1.6.2.5 skrll cmdval |= DWC_MMC_CMD_LONG_RSP;
586 1.6.2.2 skrll if (cmd->c_flags & SCF_RSP_CRC)
587 1.6.2.5 skrll cmdval |= DWC_MMC_CMD_CHECK_RSP_CRC;
588 1.6.2.2 skrll
589 1.6.2.2 skrll if (cmd->c_datalen > 0) {
590 1.6.2.2 skrll unsigned int nblks;
591 1.6.2.2 skrll
592 1.6.2.5 skrll cmdval |= DWC_MMC_CMD_DATA_EXP | DWC_MMC_CMD_WAIT_PRE_OVER;
593 1.6.2.2 skrll if (!ISSET(cmd->c_flags, SCF_CMD_READ)) {
594 1.6.2.5 skrll cmdval |= DWC_MMC_CMD_WRITE;
595 1.6.2.2 skrll }
596 1.6.2.2 skrll
597 1.6.2.2 skrll nblks = cmd->c_datalen / cmd->c_blklen;
598 1.6.2.2 skrll if (nblks == 0 || (cmd->c_datalen % cmd->c_blklen) != 0)
599 1.6.2.2 skrll ++nblks;
600 1.6.2.2 skrll
601 1.6.2.2 skrll if (nblks > 1) {
602 1.6.2.2 skrll cmdval |= DWC_MMC_CMD_SEND_AUTO_STOP;
603 1.6.2.2 skrll }
604 1.6.2.2 skrll
605 1.6.2.5 skrll MMC_WRITE(sc, DWC_MMC_BLKSZ, cmd->c_blklen);
606 1.6.2.5 skrll MMC_WRITE(sc, DWC_MMC_BYTECNT, nblks * cmd->c_blklen);
607 1.6.2.2 skrll }
608 1.6.2.2 skrll
609 1.6.2.2 skrll sc->sc_intr_rint = 0;
610 1.6.2.2 skrll
611 1.6.2.5 skrll MMC_WRITE(sc, DWC_MMC_ARG, cmd->c_arg);
612 1.6.2.2 skrll
613 1.6.2.5 skrll #ifdef DWC_MMC_DEBUG
614 1.6.2.5 skrll aprint_normal_dev(sc->sc_dev, "cmdval = %08x\n", cmdval);
615 1.6.2.5 skrll #endif
616 1.6.2.2 skrll
617 1.6.2.5 skrll if (cmd->c_datalen > 0) {
618 1.6.2.5 skrll cmd->c_resid = cmd->c_datalen;
619 1.6.2.5 skrll dwc_mmc_led(sc, 0);
620 1.6.2.5 skrll if (ISSET(sc->sc_flags, DWC_MMC_F_DMA)) {
621 1.6.2.5 skrll cmd->c_error = dwc_mmc_dma_prepare(sc, cmd);
622 1.6.2.5 skrll MMC_WRITE(sc, DWC_MMC_CMD, cmdval | cmd->c_opcode);
623 1.6.2.5 skrll MMC_WRITE(sc, DWC_MMC_PLDMND, 1);
624 1.6.2.5 skrll if (cmd->c_error == 0) {
625 1.6.2.5 skrll const uint32_t idst_mask =
626 1.6.2.5 skrll DWC_MMC_IDST_ERROR | DWC_MMC_IDST_COMPLETE;
627 1.6.2.5 skrll retry = 10;
628 1.6.2.5 skrll while ((sc->sc_idma_idst & idst_mask) == 0) {
629 1.6.2.5 skrll if (retry == 0) {
630 1.6.2.5 skrll cmd->c_error = ETIMEDOUT;
631 1.6.2.5 skrll break;
632 1.6.2.5 skrll }
633 1.6.2.5 skrll cv_timedwait(&sc->sc_idst_cv,
634 1.6.2.5 skrll &sc->sc_intr_lock, hz);
635 1.6.2.5 skrll }
636 1.6.2.5 skrll }
637 1.6.2.5 skrll dwc_mmc_dma_complete(sc);
638 1.6.2.5 skrll if (sc->sc_idma_idst & DWC_MMC_IDST_ERROR) {
639 1.6.2.5 skrll cmd->c_error = EIO;
640 1.6.2.5 skrll } else if (!(sc->sc_idma_idst & DWC_MMC_IDST_COMPLETE)) {
641 1.6.2.5 skrll cmd->c_error = ETIMEDOUT;
642 1.6.2.5 skrll }
643 1.6.2.5 skrll } else {
644 1.6.2.5 skrll mutex_exit(&sc->sc_intr_lock);
645 1.6.2.5 skrll MMC_WRITE(sc, DWC_MMC_CMD, cmdval | cmd->c_opcode);
646 1.6.2.5 skrll cmd->c_error = dwc_mmc_pio_transfer(sc, cmd);
647 1.6.2.5 skrll mutex_enter(&sc->sc_intr_lock);
648 1.6.2.5 skrll }
649 1.6.2.5 skrll dwc_mmc_led(sc, 1);
650 1.6.2.5 skrll if (cmd->c_error) {
651 1.6.2.2 skrll #ifdef DWC_MMC_DEBUG
652 1.6.2.5 skrll aprint_error_dev(sc->sc_dev,
653 1.6.2.5 skrll "xfer failed, error %d\n", cmd->c_error);
654 1.6.2.2 skrll #endif
655 1.6.2.5 skrll goto done;
656 1.6.2.5 skrll }
657 1.6.2.5 skrll } else {
658 1.6.2.5 skrll MMC_WRITE(sc, DWC_MMC_CMD, cmdval | cmd->c_opcode);
659 1.6.2.5 skrll }
660 1.6.2.5 skrll
661 1.6.2.5 skrll cmd->c_error = dwc_mmc_wait_rint(sc,
662 1.6.2.5 skrll DWC_MMC_INT_ERROR|DWC_MMC_INT_CMD_DONE, hz * 10);
663 1.6.2.5 skrll if (cmd->c_error == 0 && (sc->sc_intr_rint & DWC_MMC_INT_ERROR)) {
664 1.6.2.5 skrll if (sc->sc_intr_rint & DWC_MMC_INT_RESP_TIMEOUT) {
665 1.6.2.2 skrll cmd->c_error = ETIMEDOUT;
666 1.6.2.2 skrll } else {
667 1.6.2.2 skrll cmd->c_error = EIO;
668 1.6.2.2 skrll }
669 1.6.2.2 skrll }
670 1.6.2.2 skrll if (cmd->c_error) {
671 1.6.2.5 skrll #ifdef DWC_MMC_DEBUG
672 1.6.2.5 skrll aprint_error_dev(sc->sc_dev,
673 1.6.2.5 skrll "cmd failed, error %d\n", cmd->c_error);
674 1.6.2.5 skrll #endif
675 1.6.2.2 skrll goto done;
676 1.6.2.2 skrll }
677 1.6.2.2 skrll
678 1.6.2.2 skrll if (cmd->c_datalen > 0) {
679 1.6.2.2 skrll cmd->c_error = dwc_mmc_wait_rint(sc,
680 1.6.2.5 skrll DWC_MMC_INT_ERROR|
681 1.6.2.5 skrll DWC_MMC_INT_AUTO_CMD_DONE|
682 1.6.2.5 skrll DWC_MMC_INT_DATA_OVER,
683 1.6.2.5 skrll hz*10);
684 1.6.2.2 skrll if (cmd->c_error == 0 &&
685 1.6.2.2 skrll (sc->sc_intr_rint & DWC_MMC_INT_ERROR)) {
686 1.6.2.2 skrll cmd->c_error = ETIMEDOUT;
687 1.6.2.2 skrll }
688 1.6.2.2 skrll if (cmd->c_error) {
689 1.6.2.5 skrll #ifdef DWC_MMC_DEBUG
690 1.6.2.5 skrll aprint_error_dev(sc->sc_dev,
691 1.6.2.5 skrll "data timeout, rint = %08x\n",
692 1.6.2.5 skrll sc->sc_intr_rint);
693 1.6.2.5 skrll #endif
694 1.6.2.5 skrll dwc_mmc_dump_regs(sc);
695 1.6.2.5 skrll cmd->c_error = ETIMEDOUT;
696 1.6.2.2 skrll goto done;
697 1.6.2.2 skrll }
698 1.6.2.2 skrll }
699 1.6.2.2 skrll
700 1.6.2.2 skrll if (cmd->c_flags & SCF_RSP_PRESENT) {
701 1.6.2.2 skrll if (cmd->c_flags & SCF_RSP_136) {
702 1.6.2.5 skrll cmd->c_resp[0] = MMC_READ(sc, DWC_MMC_RESP0);
703 1.6.2.5 skrll cmd->c_resp[1] = MMC_READ(sc, DWC_MMC_RESP1);
704 1.6.2.5 skrll cmd->c_resp[2] = MMC_READ(sc, DWC_MMC_RESP2);
705 1.6.2.5 skrll cmd->c_resp[3] = MMC_READ(sc, DWC_MMC_RESP3);
706 1.6.2.2 skrll if (cmd->c_flags & SCF_RSP_CRC) {
707 1.6.2.2 skrll cmd->c_resp[0] = (cmd->c_resp[0] >> 8) |
708 1.6.2.2 skrll (cmd->c_resp[1] << 24);
709 1.6.2.2 skrll cmd->c_resp[1] = (cmd->c_resp[1] >> 8) |
710 1.6.2.2 skrll (cmd->c_resp[2] << 24);
711 1.6.2.2 skrll cmd->c_resp[2] = (cmd->c_resp[2] >> 8) |
712 1.6.2.2 skrll (cmd->c_resp[3] << 24);
713 1.6.2.2 skrll cmd->c_resp[3] = (cmd->c_resp[3] >> 8);
714 1.6.2.2 skrll }
715 1.6.2.2 skrll } else {
716 1.6.2.5 skrll cmd->c_resp[0] = MMC_READ(sc, DWC_MMC_RESP0);
717 1.6.2.2 skrll }
718 1.6.2.2 skrll }
719 1.6.2.2 skrll
720 1.6.2.2 skrll done:
721 1.6.2.2 skrll cmd->c_flags |= SCF_ITSDONE;
722 1.6.2.2 skrll mutex_exit(&sc->sc_intr_lock);
723 1.6.2.2 skrll
724 1.6.2.5 skrll if (cmd->c_error) {
725 1.6.2.5 skrll #ifdef DWC_MMC_DEBUG
726 1.6.2.5 skrll aprint_error_dev(sc->sc_dev, "i/o error %d\n", cmd->c_error);
727 1.6.2.5 skrll #endif
728 1.6.2.5 skrll MMC_WRITE(sc, DWC_MMC_GCTRL,
729 1.6.2.5 skrll MMC_READ(sc, DWC_MMC_GCTRL) |
730 1.6.2.5 skrll DWC_MMC_GCTRL_DMARESET | DWC_MMC_GCTRL_FIFORESET);
731 1.6.2.5 skrll for (retry = 0; retry < 1000; retry++) {
732 1.6.2.5 skrll if (!(MMC_READ(sc, DWC_MMC_GCTRL) & DWC_MMC_GCTRL_RESET))
733 1.6.2.5 skrll break;
734 1.6.2.5 skrll delay(10);
735 1.6.2.5 skrll }
736 1.6.2.5 skrll dwc_mmc_update_clock(sc);
737 1.6.2.4 skrll }
738 1.6.2.4 skrll
739 1.6.2.5 skrll if (!ISSET(sc->sc_flags, DWC_MMC_F_DMA)) {
740 1.6.2.5 skrll MMC_WRITE(sc, DWC_MMC_GCTRL,
741 1.6.2.5 skrll MMC_READ(sc, DWC_MMC_GCTRL) | DWC_MMC_GCTRL_FIFORESET);
742 1.6.2.5 skrll }
743 1.6.2.2 skrll }
744 1.6.2.2 skrll
745 1.6.2.2 skrll static void
746 1.6.2.2 skrll dwc_mmc_card_enable_intr(sdmmc_chipset_handle_t sch, int enable)
747 1.6.2.2 skrll {
748 1.6.2.2 skrll }
749 1.6.2.2 skrll
750 1.6.2.2 skrll static void
751 1.6.2.2 skrll dwc_mmc_card_intr_ack(sdmmc_chipset_handle_t sch)
752 1.6.2.2 skrll {
753 1.6.2.2 skrll }
754 1.6.2.2 skrll
755 1.6.2.5 skrll int
756 1.6.2.5 skrll dwc_mmc_init(struct dwc_mmc_softc *sc)
757 1.6.2.2 skrll {
758 1.6.2.5 skrll mutex_init(&sc->sc_intr_lock, MUTEX_DEFAULT, IPL_BIO);
759 1.6.2.5 skrll cv_init(&sc->sc_intr_cv, "dwcmmcirq");
760 1.6.2.5 skrll cv_init(&sc->sc_idst_cv, "dwcmmcdma");
761 1.6.2.5 skrll
762 1.6.2.5 skrll const bool use_dma = ISSET(sc->sc_flags, DWC_MMC_F_DMA);
763 1.6.2.5 skrll
764 1.6.2.5 skrll aprint_debug_dev(sc->sc_dev, "using %s for transfers\n",
765 1.6.2.5 skrll use_dma ? "DMA" : "PIO");
766 1.6.2.5 skrll
767 1.6.2.5 skrll if (use_dma && dwc_mmc_idma_setup(sc) != 0) {
768 1.6.2.5 skrll aprint_error_dev(sc->sc_dev, "failed to setup DMA\n");
769 1.6.2.5 skrll return ENOMEM;
770 1.6.2.5 skrll }
771 1.6.2.5 skrll
772 1.6.2.5 skrll config_interrupts(sc->sc_dev, dwc_mmc_attach_i);
773 1.6.2.5 skrll
774 1.6.2.5 skrll return 0;
775 1.6.2.2 skrll }
776 1.6.2.5 skrll
777 1.6.2.5 skrll int
778 1.6.2.5 skrll dwc_mmc_intr(void *priv)
779 1.6.2.5 skrll {
780 1.6.2.5 skrll struct dwc_mmc_softc *sc = priv;
781 1.6.2.5 skrll uint32_t idst, rint, mint;
782 1.6.2.5 skrll
783 1.6.2.5 skrll mutex_enter(&sc->sc_intr_lock);
784 1.6.2.5 skrll idst = MMC_READ(sc, DWC_MMC_IDST);
785 1.6.2.5 skrll rint = MMC_READ(sc, DWC_MMC_RINT);
786 1.6.2.5 skrll mint = MMC_READ(sc, DWC_MMC_MINT);
787 1.6.2.5 skrll if (!idst && !rint && !mint) {
788 1.6.2.5 skrll mutex_exit(&sc->sc_intr_lock);
789 1.6.2.5 skrll return 0;
790 1.6.2.5 skrll }
791 1.6.2.5 skrll MMC_WRITE(sc, DWC_MMC_IDST, idst);
792 1.6.2.5 skrll MMC_WRITE(sc, DWC_MMC_RINT, rint);
793 1.6.2.5 skrll MMC_WRITE(sc, DWC_MMC_MINT, mint);
794 1.6.2.5 skrll
795 1.6.2.5 skrll #ifdef DWC_MMC_DEBUG
796 1.6.2.5 skrll device_printf(sc->sc_dev, "mmc intr idst=%08X rint=%08X mint=%08X\n",
797 1.6.2.5 skrll idst, rint, mint);
798 1.6.2.2 skrll #endif
799 1.6.2.2 skrll
800 1.6.2.5 skrll if (idst) {
801 1.6.2.5 skrll sc->sc_idma_idst |= idst;
802 1.6.2.5 skrll cv_broadcast(&sc->sc_idst_cv);
803 1.6.2.5 skrll }
804 1.6.2.2 skrll
805 1.6.2.5 skrll if (rint) {
806 1.6.2.5 skrll sc->sc_intr_rint |= rint;
807 1.6.2.5 skrll cv_broadcast(&sc->sc_intr_cv);
808 1.6.2.2 skrll }
809 1.6.2.5 skrll
810 1.6.2.5 skrll mutex_exit(&sc->sc_intr_lock);
811 1.6.2.5 skrll
812 1.6.2.5 skrll return 1;
813 1.6.2.2 skrll }
814