1 1.31 skrll /* $NetBSD: dwc_mmc.c,v 1.31 2024/02/09 17:16:42 skrll Exp $ */ 2 1.1 jmcneill 3 1.1 jmcneill /*- 4 1.11 jmcneill * Copyright (c) 2014-2017 Jared McNeill <jmcneill (at) invisible.ca> 5 1.1 jmcneill * All rights reserved. 6 1.1 jmcneill * 7 1.1 jmcneill * Redistribution and use in source and binary forms, with or without 8 1.1 jmcneill * modification, are permitted provided that the following conditions 9 1.1 jmcneill * are met: 10 1.1 jmcneill * 1. Redistributions of source code must retain the above copyright 11 1.1 jmcneill * notice, this list of conditions and the following disclaimer. 12 1.1 jmcneill * 2. Redistributions in binary form must reproduce the above copyright 13 1.1 jmcneill * notice, this list of conditions and the following disclaimer in the 14 1.1 jmcneill * documentation and/or other materials provided with the distribution. 15 1.1 jmcneill * 16 1.1 jmcneill * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 17 1.1 jmcneill * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 18 1.1 jmcneill * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 19 1.1 jmcneill * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 20 1.1 jmcneill * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, 21 1.1 jmcneill * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 22 1.1 jmcneill * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED 23 1.1 jmcneill * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, 24 1.1 jmcneill * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 25 1.1 jmcneill * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 26 1.1 jmcneill * SUCH DAMAGE. 27 1.1 jmcneill */ 28 1.1 jmcneill 29 1.1 jmcneill #include <sys/cdefs.h> 30 1.31 skrll __KERNEL_RCSID(0, "$NetBSD: dwc_mmc.c,v 1.31 2024/02/09 17:16:42 skrll Exp $"); 31 1.1 jmcneill 32 1.1 jmcneill #include <sys/param.h> 33 1.1 jmcneill #include <sys/bus.h> 34 1.1 jmcneill #include <sys/device.h> 35 1.1 jmcneill #include <sys/intr.h> 36 1.1 jmcneill #include <sys/systm.h> 37 1.1 jmcneill #include <sys/kernel.h> 38 1.21 jmcneill #include <sys/proc.h> 39 1.1 jmcneill 40 1.1 jmcneill #include <dev/sdmmc/sdmmcvar.h> 41 1.1 jmcneill #include <dev/sdmmc/sdmmcchip.h> 42 1.1 jmcneill #include <dev/sdmmc/sdmmc_ioreg.h> 43 1.1 jmcneill 44 1.1 jmcneill #include <dev/ic/dwc_mmc_reg.h> 45 1.1 jmcneill #include <dev/ic/dwc_mmc_var.h> 46 1.1 jmcneill 47 1.11 jmcneill #define DWC_MMC_NDESC 64 48 1.11 jmcneill 49 1.1 jmcneill static int dwc_mmc_host_reset(sdmmc_chipset_handle_t); 50 1.1 jmcneill static uint32_t dwc_mmc_host_ocr(sdmmc_chipset_handle_t); 51 1.1 jmcneill static int dwc_mmc_host_maxblklen(sdmmc_chipset_handle_t); 52 1.1 jmcneill static int dwc_mmc_card_detect(sdmmc_chipset_handle_t); 53 1.1 jmcneill static int dwc_mmc_write_protect(sdmmc_chipset_handle_t); 54 1.1 jmcneill static int dwc_mmc_bus_power(sdmmc_chipset_handle_t, uint32_t); 55 1.1 jmcneill static int dwc_mmc_bus_clock(sdmmc_chipset_handle_t, int); 56 1.1 jmcneill static int dwc_mmc_bus_width(sdmmc_chipset_handle_t, int); 57 1.1 jmcneill static int dwc_mmc_bus_rod(sdmmc_chipset_handle_t, int); 58 1.19 jmcneill static int dwc_mmc_signal_voltage(sdmmc_chipset_handle_t, int); 59 1.1 jmcneill static void dwc_mmc_exec_command(sdmmc_chipset_handle_t, 60 1.11 jmcneill struct sdmmc_command *); 61 1.1 jmcneill static void dwc_mmc_card_enable_intr(sdmmc_chipset_handle_t, int); 62 1.1 jmcneill static void dwc_mmc_card_intr_ack(sdmmc_chipset_handle_t); 63 1.1 jmcneill 64 1.1 jmcneill static struct sdmmc_chip_functions dwc_mmc_chip_functions = { 65 1.1 jmcneill .host_reset = dwc_mmc_host_reset, 66 1.1 jmcneill .host_ocr = dwc_mmc_host_ocr, 67 1.1 jmcneill .host_maxblklen = dwc_mmc_host_maxblklen, 68 1.1 jmcneill .card_detect = dwc_mmc_card_detect, 69 1.1 jmcneill .write_protect = dwc_mmc_write_protect, 70 1.1 jmcneill .bus_power = dwc_mmc_bus_power, 71 1.1 jmcneill .bus_clock = dwc_mmc_bus_clock, 72 1.1 jmcneill .bus_width = dwc_mmc_bus_width, 73 1.1 jmcneill .bus_rod = dwc_mmc_bus_rod, 74 1.19 jmcneill .signal_voltage = dwc_mmc_signal_voltage, 75 1.1 jmcneill .exec_command = dwc_mmc_exec_command, 76 1.1 jmcneill .card_enable_intr = dwc_mmc_card_enable_intr, 77 1.1 jmcneill .card_intr_ack = dwc_mmc_card_intr_ack, 78 1.1 jmcneill }; 79 1.1 jmcneill 80 1.11 jmcneill #define MMC_WRITE(sc, reg, val) \ 81 1.1 jmcneill bus_space_write_4((sc)->sc_bst, (sc)->sc_bsh, (reg), (val)) 82 1.1 jmcneill #define MMC_READ(sc, reg) \ 83 1.1 jmcneill bus_space_read_4((sc)->sc_bst, (sc)->sc_bsh, (reg)) 84 1.1 jmcneill 85 1.18 jmcneill static int 86 1.18 jmcneill dwc_mmc_dmabounce_setup(struct dwc_mmc_softc *sc) 87 1.1 jmcneill { 88 1.18 jmcneill bus_dma_segment_t ds[1]; 89 1.18 jmcneill int error, rseg; 90 1.18 jmcneill 91 1.18 jmcneill sc->sc_dmabounce_buflen = dwc_mmc_host_maxblklen(sc); 92 1.18 jmcneill error = bus_dmamem_alloc(sc->sc_dmat, sc->sc_dmabounce_buflen, 0, 93 1.18 jmcneill sc->sc_dmabounce_buflen, ds, 1, &rseg, BUS_DMA_WAITOK); 94 1.18 jmcneill if (error) 95 1.18 jmcneill return error; 96 1.18 jmcneill error = bus_dmamem_map(sc->sc_dmat, ds, 1, sc->sc_dmabounce_buflen, 97 1.18 jmcneill &sc->sc_dmabounce_buf, BUS_DMA_WAITOK); 98 1.18 jmcneill if (error) 99 1.18 jmcneill goto free; 100 1.18 jmcneill error = bus_dmamap_create(sc->sc_dmat, sc->sc_dmabounce_buflen, 1, 101 1.18 jmcneill sc->sc_dmabounce_buflen, 0, BUS_DMA_WAITOK, &sc->sc_dmabounce_map); 102 1.18 jmcneill if (error) 103 1.18 jmcneill goto unmap; 104 1.18 jmcneill error = bus_dmamap_load(sc->sc_dmat, sc->sc_dmabounce_map, 105 1.18 jmcneill sc->sc_dmabounce_buf, sc->sc_dmabounce_buflen, NULL, 106 1.18 jmcneill BUS_DMA_WAITOK); 107 1.18 jmcneill if (error) 108 1.18 jmcneill goto destroy; 109 1.18 jmcneill return 0; 110 1.18 jmcneill 111 1.18 jmcneill destroy: 112 1.18 jmcneill bus_dmamap_destroy(sc->sc_dmat, sc->sc_dmabounce_map); 113 1.18 jmcneill unmap: 114 1.18 jmcneill bus_dmamem_unmap(sc->sc_dmat, sc->sc_dmabounce_buf, 115 1.18 jmcneill sc->sc_dmabounce_buflen); 116 1.18 jmcneill free: 117 1.18 jmcneill bus_dmamem_free(sc->sc_dmat, ds, rseg); 118 1.18 jmcneill return error; 119 1.11 jmcneill } 120 1.11 jmcneill 121 1.11 jmcneill static int 122 1.11 jmcneill dwc_mmc_idma_setup(struct dwc_mmc_softc *sc) 123 1.11 jmcneill { 124 1.11 jmcneill int error; 125 1.11 jmcneill 126 1.11 jmcneill sc->sc_idma_xferlen = 0x1000; 127 1.11 jmcneill 128 1.11 jmcneill sc->sc_idma_ndesc = DWC_MMC_NDESC; 129 1.11 jmcneill sc->sc_idma_size = sizeof(struct dwc_mmc_idma_desc) * 130 1.11 jmcneill sc->sc_idma_ndesc; 131 1.11 jmcneill error = bus_dmamem_alloc(sc->sc_dmat, sc->sc_idma_size, 8, 132 1.11 jmcneill sc->sc_idma_size, sc->sc_idma_segs, 1, 133 1.11 jmcneill &sc->sc_idma_nsegs, BUS_DMA_WAITOK); 134 1.11 jmcneill if (error) 135 1.11 jmcneill return error; 136 1.11 jmcneill error = bus_dmamem_map(sc->sc_dmat, sc->sc_idma_segs, 137 1.11 jmcneill sc->sc_idma_nsegs, sc->sc_idma_size, 138 1.11 jmcneill &sc->sc_idma_desc, BUS_DMA_WAITOK); 139 1.11 jmcneill if (error) 140 1.11 jmcneill goto free; 141 1.11 jmcneill error = bus_dmamap_create(sc->sc_dmat, sc->sc_idma_size, 1, 142 1.11 jmcneill sc->sc_idma_size, 0, BUS_DMA_WAITOK, &sc->sc_idma_map); 143 1.11 jmcneill if (error) 144 1.11 jmcneill goto unmap; 145 1.11 jmcneill error = bus_dmamap_load(sc->sc_dmat, sc->sc_idma_map, 146 1.11 jmcneill sc->sc_idma_desc, sc->sc_idma_size, NULL, BUS_DMA_WAITOK); 147 1.11 jmcneill if (error) 148 1.11 jmcneill goto destroy; 149 1.11 jmcneill return 0; 150 1.1 jmcneill 151 1.11 jmcneill destroy: 152 1.11 jmcneill bus_dmamap_destroy(sc->sc_dmat, sc->sc_idma_map); 153 1.11 jmcneill unmap: 154 1.11 jmcneill bus_dmamem_unmap(sc->sc_dmat, sc->sc_idma_desc, sc->sc_idma_size); 155 1.11 jmcneill free: 156 1.11 jmcneill bus_dmamem_free(sc->sc_dmat, sc->sc_idma_segs, sc->sc_idma_nsegs); 157 1.11 jmcneill return error; 158 1.11 jmcneill } 159 1.1 jmcneill 160 1.11 jmcneill static void 161 1.11 jmcneill dwc_mmc_attach_i(device_t self) 162 1.11 jmcneill { 163 1.11 jmcneill struct dwc_mmc_softc *sc = device_private(self); 164 1.11 jmcneill struct sdmmcbus_attach_args saa; 165 1.29 jmcneill bool poll_detect; 166 1.29 jmcneill 167 1.29 jmcneill poll_detect = sc->sc_card_detect != NULL || 168 1.29 jmcneill (sc->sc_flags & (DWC_MMC_F_BROKEN_CD|DWC_MMC_F_NON_REMOVABLE)) == 0; 169 1.8 jmcneill 170 1.19 jmcneill if (sc->sc_pre_power_on) 171 1.19 jmcneill sc->sc_pre_power_on(sc); 172 1.19 jmcneill 173 1.19 jmcneill dwc_mmc_signal_voltage(sc, SDMMC_SIGNAL_VOLTAGE_330); 174 1.1 jmcneill dwc_mmc_host_reset(sc); 175 1.1 jmcneill dwc_mmc_bus_width(sc, 1); 176 1.1 jmcneill 177 1.19 jmcneill if (sc->sc_post_power_on) 178 1.19 jmcneill sc->sc_post_power_on(sc); 179 1.19 jmcneill 180 1.1 jmcneill memset(&saa, 0, sizeof(saa)); 181 1.1 jmcneill saa.saa_busname = "sdmmc"; 182 1.1 jmcneill saa.saa_sct = &dwc_mmc_chip_functions; 183 1.1 jmcneill saa.saa_sch = sc; 184 1.1 jmcneill saa.saa_clkmin = 400; 185 1.11 jmcneill saa.saa_clkmax = sc->sc_clock_freq / 1000; 186 1.18 jmcneill saa.saa_dmat = sc->sc_dmat; 187 1.19 jmcneill saa.saa_caps = SMC_CAPS_SD_HIGHSPEED | 188 1.19 jmcneill SMC_CAPS_MMC_HIGHSPEED | 189 1.18 jmcneill SMC_CAPS_AUTO_STOP | 190 1.18 jmcneill SMC_CAPS_DMA | 191 1.18 jmcneill SMC_CAPS_MULTI_SEG_DMA; 192 1.29 jmcneill if (sc->sc_bus_width == 8) { 193 1.19 jmcneill saa.saa_caps |= SMC_CAPS_8BIT_MODE; 194 1.29 jmcneill } else { 195 1.19 jmcneill saa.saa_caps |= SMC_CAPS_4BIT_MODE; 196 1.29 jmcneill } 197 1.29 jmcneill 198 1.29 jmcneill if (poll_detect) { 199 1.11 jmcneill saa.saa_caps |= SMC_CAPS_POLL_CARD_DET; 200 1.29 jmcneill } 201 1.1 jmcneill 202 1.28 thorpej sc->sc_sdmmc_dev = config_found(self, &saa, NULL, CFARGS_NONE); 203 1.1 jmcneill } 204 1.1 jmcneill 205 1.11 jmcneill static void 206 1.11 jmcneill dwc_mmc_led(struct dwc_mmc_softc *sc, int on) 207 1.1 jmcneill { 208 1.11 jmcneill if (sc->sc_set_led) 209 1.11 jmcneill sc->sc_set_led(sc, on); 210 1.1 jmcneill } 211 1.1 jmcneill 212 1.1 jmcneill static int 213 1.1 jmcneill dwc_mmc_host_reset(sdmmc_chipset_handle_t sch) 214 1.1 jmcneill { 215 1.1 jmcneill struct dwc_mmc_softc *sc = sch; 216 1.11 jmcneill uint32_t fifoth, ctrl; 217 1.1 jmcneill int retry = 1000; 218 1.1 jmcneill 219 1.11 jmcneill #ifdef DWC_MMC_DEBUG 220 1.11 jmcneill aprint_normal_dev(sc->sc_dev, "host reset\n"); 221 1.11 jmcneill #endif 222 1.11 jmcneill 223 1.19 jmcneill if (ISSET(sc->sc_flags, DWC_MMC_F_PWREN_INV)) 224 1.19 jmcneill MMC_WRITE(sc, DWC_MMC_PWREN, 0); 225 1.19 jmcneill else 226 1.19 jmcneill MMC_WRITE(sc, DWC_MMC_PWREN, 1); 227 1.19 jmcneill 228 1.19 jmcneill ctrl = MMC_READ(sc, DWC_MMC_GCTRL); 229 1.19 jmcneill ctrl &= ~DWC_MMC_GCTRL_USE_INTERNAL_DMAC; 230 1.19 jmcneill MMC_WRITE(sc, DWC_MMC_GCTRL, ctrl); 231 1.19 jmcneill 232 1.19 jmcneill MMC_WRITE(sc, DWC_MMC_DMAC, DWC_MMC_DMAC_SOFTRESET); 233 1.1 jmcneill 234 1.11 jmcneill MMC_WRITE(sc, DWC_MMC_GCTRL, 235 1.11 jmcneill MMC_READ(sc, DWC_MMC_GCTRL) | DWC_MMC_GCTRL_RESET); 236 1.1 jmcneill while (--retry > 0) { 237 1.11 jmcneill if (!(MMC_READ(sc, DWC_MMC_GCTRL) & DWC_MMC_GCTRL_RESET)) 238 1.1 jmcneill break; 239 1.1 jmcneill delay(100); 240 1.1 jmcneill } 241 1.1 jmcneill 242 1.11 jmcneill MMC_WRITE(sc, DWC_MMC_CLKSRC, 0); 243 1.2 jmcneill 244 1.11 jmcneill MMC_WRITE(sc, DWC_MMC_TIMEOUT, 0xffffffff); 245 1.1 jmcneill 246 1.18 jmcneill MMC_WRITE(sc, DWC_MMC_IMASK, 0); 247 1.18 jmcneill 248 1.18 jmcneill MMC_WRITE(sc, DWC_MMC_RINT, 0xffffffff); 249 1.1 jmcneill 250 1.11 jmcneill const uint32_t rx_wmark = (sc->sc_fifo_depth / 2) - 1; 251 1.11 jmcneill const uint32_t tx_wmark = sc->sc_fifo_depth / 2; 252 1.1 jmcneill fifoth = __SHIFTIN(DWC_MMC_FIFOTH_DMA_MULTIPLE_TXN_SIZE_16, 253 1.1 jmcneill DWC_MMC_FIFOTH_DMA_MULTIPLE_TXN_SIZE); 254 1.1 jmcneill fifoth |= __SHIFTIN(rx_wmark, DWC_MMC_FIFOTH_RX_WMARK); 255 1.1 jmcneill fifoth |= __SHIFTIN(tx_wmark, DWC_MMC_FIFOTH_TX_WMARK); 256 1.11 jmcneill MMC_WRITE(sc, DWC_MMC_FIFOTH, fifoth); 257 1.11 jmcneill 258 1.11 jmcneill MMC_WRITE(sc, DWC_MMC_UHS, 0); 259 1.1 jmcneill 260 1.11 jmcneill ctrl = MMC_READ(sc, DWC_MMC_GCTRL); 261 1.11 jmcneill ctrl |= DWC_MMC_GCTRL_INTEN; 262 1.11 jmcneill ctrl |= DWC_MMC_GCTRL_DMAEN; 263 1.11 jmcneill ctrl |= DWC_MMC_GCTRL_SEND_AUTO_STOP_CCSD; 264 1.11 jmcneill ctrl |= DWC_MMC_GCTRL_USE_INTERNAL_DMAC; 265 1.11 jmcneill MMC_WRITE(sc, DWC_MMC_GCTRL, ctrl); 266 1.1 jmcneill 267 1.1 jmcneill return 0; 268 1.1 jmcneill } 269 1.1 jmcneill 270 1.1 jmcneill static uint32_t 271 1.1 jmcneill dwc_mmc_host_ocr(sdmmc_chipset_handle_t sch) 272 1.1 jmcneill { 273 1.11 jmcneill return MMC_OCR_3_2V_3_3V | MMC_OCR_3_3V_3_4V | MMC_OCR_HCS; 274 1.1 jmcneill } 275 1.1 jmcneill 276 1.1 jmcneill static int 277 1.1 jmcneill dwc_mmc_host_maxblklen(sdmmc_chipset_handle_t sch) 278 1.1 jmcneill { 279 1.1 jmcneill return 32768; 280 1.1 jmcneill } 281 1.1 jmcneill 282 1.1 jmcneill static int 283 1.1 jmcneill dwc_mmc_card_detect(sdmmc_chipset_handle_t sch) 284 1.1 jmcneill { 285 1.1 jmcneill struct dwc_mmc_softc *sc = sch; 286 1.29 jmcneill int det_n; 287 1.29 jmcneill 288 1.29 jmcneill if (sc->sc_card_detect != NULL) { 289 1.29 jmcneill return sc->sc_card_detect(sc); 290 1.29 jmcneill } 291 1.29 jmcneill if ((sc->sc_flags & DWC_MMC_F_BROKEN_CD) != 0) { 292 1.29 jmcneill return 1; /* broken card detect, assume present */ 293 1.29 jmcneill } 294 1.29 jmcneill if ((sc->sc_flags & DWC_MMC_F_NON_REMOVABLE) != 0) { 295 1.29 jmcneill return 1; /* non-removable device is always present */ 296 1.29 jmcneill } 297 1.1 jmcneill 298 1.29 jmcneill det_n = MMC_READ(sc, DWC_MMC_CDETECT) & DWC_MMC_CDETECT_CARD_DETECT_N; 299 1.11 jmcneill 300 1.29 jmcneill return !det_n; 301 1.1 jmcneill } 302 1.1 jmcneill 303 1.1 jmcneill static int 304 1.1 jmcneill dwc_mmc_write_protect(sdmmc_chipset_handle_t sch) 305 1.1 jmcneill { 306 1.1 jmcneill struct dwc_mmc_softc *sc = sch; 307 1.1 jmcneill 308 1.11 jmcneill if (!sc->sc_write_protect) 309 1.11 jmcneill return 0; /* no write protect pin, assume rw */ 310 1.11 jmcneill 311 1.11 jmcneill return sc->sc_write_protect(sc); 312 1.1 jmcneill } 313 1.1 jmcneill 314 1.1 jmcneill static int 315 1.1 jmcneill dwc_mmc_bus_power(sdmmc_chipset_handle_t sch, uint32_t ocr) 316 1.1 jmcneill { 317 1.22 jmcneill struct dwc_mmc_softc *sc = sch; 318 1.22 jmcneill 319 1.22 jmcneill if (ocr == 0) 320 1.22 jmcneill sc->sc_card_inited = false; 321 1.22 jmcneill 322 1.1 jmcneill return 0; 323 1.1 jmcneill } 324 1.1 jmcneill 325 1.1 jmcneill static int 326 1.19 jmcneill dwc_mmc_signal_voltage(sdmmc_chipset_handle_t sch, int signal_voltage) 327 1.19 jmcneill { 328 1.19 jmcneill struct dwc_mmc_softc *sc = sch; 329 1.19 jmcneill 330 1.19 jmcneill if (sc->sc_signal_voltage == NULL) 331 1.19 jmcneill return 0; 332 1.19 jmcneill 333 1.19 jmcneill return sc->sc_signal_voltage(sc, signal_voltage); 334 1.19 jmcneill } 335 1.19 jmcneill 336 1.19 jmcneill static int 337 1.11 jmcneill dwc_mmc_update_clock(struct dwc_mmc_softc *sc) 338 1.11 jmcneill { 339 1.11 jmcneill uint32_t cmd; 340 1.11 jmcneill int retry; 341 1.11 jmcneill 342 1.11 jmcneill #ifdef DWC_MMC_DEBUG 343 1.11 jmcneill aprint_normal_dev(sc->sc_dev, "update clock\n"); 344 1.11 jmcneill #endif 345 1.11 jmcneill 346 1.11 jmcneill cmd = DWC_MMC_CMD_START | 347 1.11 jmcneill DWC_MMC_CMD_UPCLK_ONLY | 348 1.11 jmcneill DWC_MMC_CMD_WAIT_PRE_OVER; 349 1.11 jmcneill if (ISSET(sc->sc_flags, DWC_MMC_F_USE_HOLD_REG)) 350 1.11 jmcneill cmd |= DWC_MMC_CMD_USE_HOLD_REG; 351 1.11 jmcneill MMC_WRITE(sc, DWC_MMC_ARG, 0); 352 1.11 jmcneill MMC_WRITE(sc, DWC_MMC_CMD, cmd); 353 1.14 jmcneill retry = 200000; 354 1.11 jmcneill while (--retry > 0) { 355 1.11 jmcneill if (!(MMC_READ(sc, DWC_MMC_CMD) & DWC_MMC_CMD_START)) 356 1.11 jmcneill break; 357 1.11 jmcneill delay(10); 358 1.11 jmcneill } 359 1.11 jmcneill 360 1.11 jmcneill if (retry == 0) { 361 1.11 jmcneill aprint_error_dev(sc->sc_dev, "timeout updating clock\n"); 362 1.11 jmcneill #ifdef DWC_MMC_DEBUG 363 1.11 jmcneill device_printf(sc->sc_dev, "GCTRL: 0x%08x\n", 364 1.11 jmcneill MMC_READ(sc, DWC_MMC_GCTRL)); 365 1.11 jmcneill device_printf(sc->sc_dev, "CLKENA: 0x%08x\n", 366 1.11 jmcneill MMC_READ(sc, DWC_MMC_CLKENA)); 367 1.11 jmcneill device_printf(sc->sc_dev, "CLKDIV: 0x%08x\n", 368 1.11 jmcneill MMC_READ(sc, DWC_MMC_CLKDIV)); 369 1.11 jmcneill device_printf(sc->sc_dev, "TIMEOUT: 0x%08x\n", 370 1.11 jmcneill MMC_READ(sc, DWC_MMC_TIMEOUT)); 371 1.11 jmcneill device_printf(sc->sc_dev, "WIDTH: 0x%08x\n", 372 1.11 jmcneill MMC_READ(sc, DWC_MMC_WIDTH)); 373 1.11 jmcneill device_printf(sc->sc_dev, "CMD: 0x%08x\n", 374 1.11 jmcneill MMC_READ(sc, DWC_MMC_CMD)); 375 1.11 jmcneill device_printf(sc->sc_dev, "MINT: 0x%08x\n", 376 1.11 jmcneill MMC_READ(sc, DWC_MMC_MINT)); 377 1.11 jmcneill device_printf(sc->sc_dev, "RINT: 0x%08x\n", 378 1.11 jmcneill MMC_READ(sc, DWC_MMC_RINT)); 379 1.11 jmcneill device_printf(sc->sc_dev, "STATUS: 0x%08x\n", 380 1.11 jmcneill MMC_READ(sc, DWC_MMC_STATUS)); 381 1.11 jmcneill #endif 382 1.11 jmcneill return ETIMEDOUT; 383 1.11 jmcneill } 384 1.11 jmcneill 385 1.11 jmcneill return 0; 386 1.11 jmcneill } 387 1.11 jmcneill 388 1.11 jmcneill static int 389 1.11 jmcneill dwc_mmc_set_clock(struct dwc_mmc_softc *sc, u_int freq) 390 1.11 jmcneill { 391 1.11 jmcneill const u_int pll_freq = sc->sc_clock_freq / 1000; 392 1.20 jmcneill u_int clk_div, ciu_div; 393 1.20 jmcneill 394 1.20 jmcneill ciu_div = sc->sc_ciu_div > 0 ? sc->sc_ciu_div : 1; 395 1.13 jmcneill 396 1.13 jmcneill if (freq != pll_freq) 397 1.20 jmcneill clk_div = howmany(pll_freq, freq * ciu_div); 398 1.13 jmcneill else 399 1.13 jmcneill clk_div = 0; 400 1.11 jmcneill 401 1.11 jmcneill MMC_WRITE(sc, DWC_MMC_CLKDIV, clk_div); 402 1.11 jmcneill 403 1.11 jmcneill return dwc_mmc_update_clock(sc); 404 1.11 jmcneill } 405 1.11 jmcneill 406 1.11 jmcneill static int 407 1.1 jmcneill dwc_mmc_bus_clock(sdmmc_chipset_handle_t sch, int freq) 408 1.1 jmcneill { 409 1.1 jmcneill struct dwc_mmc_softc *sc = sch; 410 1.2 jmcneill uint32_t clkena; 411 1.1 jmcneill 412 1.11 jmcneill MMC_WRITE(sc, DWC_MMC_CLKSRC, 0); 413 1.11 jmcneill MMC_WRITE(sc, DWC_MMC_CLKENA, 0); 414 1.2 jmcneill if (dwc_mmc_update_clock(sc) != 0) 415 1.11 jmcneill return 1; 416 1.1 jmcneill 417 1.1 jmcneill if (freq) { 418 1.13 jmcneill if (sc->sc_bus_clock && sc->sc_bus_clock(sc, freq) != 0) 419 1.13 jmcneill return 1; 420 1.13 jmcneill 421 1.1 jmcneill if (dwc_mmc_set_clock(sc, freq) != 0) 422 1.11 jmcneill return 1; 423 1.1 jmcneill 424 1.11 jmcneill clkena = DWC_MMC_CLKENA_CARDCLKON; 425 1.11 jmcneill MMC_WRITE(sc, DWC_MMC_CLKENA, clkena); 426 1.1 jmcneill if (dwc_mmc_update_clock(sc) != 0) 427 1.11 jmcneill return 1; 428 1.1 jmcneill } 429 1.1 jmcneill 430 1.2 jmcneill delay(1000); 431 1.2 jmcneill 432 1.1 jmcneill return 0; 433 1.1 jmcneill } 434 1.1 jmcneill 435 1.1 jmcneill static int 436 1.1 jmcneill dwc_mmc_bus_width(sdmmc_chipset_handle_t sch, int width) 437 1.1 jmcneill { 438 1.1 jmcneill struct dwc_mmc_softc *sc = sch; 439 1.11 jmcneill 440 1.11 jmcneill #ifdef DWC_MMC_DEBUG 441 1.11 jmcneill aprint_normal_dev(sc->sc_dev, "width = %d\n", width); 442 1.11 jmcneill #endif 443 1.1 jmcneill 444 1.1 jmcneill switch (width) { 445 1.1 jmcneill case 1: 446 1.11 jmcneill MMC_WRITE(sc, DWC_MMC_WIDTH, DWC_MMC_WIDTH_1); 447 1.1 jmcneill break; 448 1.1 jmcneill case 4: 449 1.11 jmcneill MMC_WRITE(sc, DWC_MMC_WIDTH, DWC_MMC_WIDTH_4); 450 1.1 jmcneill break; 451 1.1 jmcneill case 8: 452 1.11 jmcneill MMC_WRITE(sc, DWC_MMC_WIDTH, DWC_MMC_WIDTH_8); 453 1.1 jmcneill break; 454 1.1 jmcneill default: 455 1.11 jmcneill return 1; 456 1.1 jmcneill } 457 1.1 jmcneill 458 1.11 jmcneill sc->sc_mmc_width = width; 459 1.24 skrll 460 1.11 jmcneill return 0; 461 1.11 jmcneill } 462 1.11 jmcneill 463 1.11 jmcneill static int 464 1.11 jmcneill dwc_mmc_bus_rod(sdmmc_chipset_handle_t sch, int on) 465 1.11 jmcneill { 466 1.11 jmcneill return -1; 467 1.11 jmcneill } 468 1.11 jmcneill 469 1.1 jmcneill static int 470 1.11 jmcneill dwc_mmc_dma_prepare(struct dwc_mmc_softc *sc, struct sdmmc_command *cmd) 471 1.11 jmcneill { 472 1.11 jmcneill struct dwc_mmc_idma_desc *dma = sc->sc_idma_desc; 473 1.11 jmcneill bus_addr_t desc_paddr = sc->sc_idma_map->dm_segs[0].ds_addr; 474 1.18 jmcneill bus_dmamap_t map; 475 1.11 jmcneill bus_size_t off; 476 1.11 jmcneill int desc, resid, seg; 477 1.11 jmcneill uint32_t val; 478 1.11 jmcneill 479 1.18 jmcneill /* 480 1.30 skrll * If the command includes a dma map use it, otherwise we need to 481 1.18 jmcneill * bounce. This can happen for SDIO IO_RW_EXTENDED (CMD53) commands. 482 1.18 jmcneill */ 483 1.18 jmcneill if (cmd->c_dmamap) { 484 1.18 jmcneill map = cmd->c_dmamap; 485 1.18 jmcneill } else { 486 1.18 jmcneill if (cmd->c_datalen > sc->sc_dmabounce_buflen) 487 1.18 jmcneill return E2BIG; 488 1.18 jmcneill map = sc->sc_dmabounce_map; 489 1.18 jmcneill 490 1.18 jmcneill if (ISSET(cmd->c_flags, SCF_CMD_READ)) { 491 1.18 jmcneill memset(sc->sc_dmabounce_buf, 0, cmd->c_datalen); 492 1.18 jmcneill bus_dmamap_sync(sc->sc_dmat, sc->sc_dmabounce_map, 493 1.18 jmcneill 0, cmd->c_datalen, BUS_DMASYNC_PREREAD); 494 1.18 jmcneill } else { 495 1.18 jmcneill memcpy(sc->sc_dmabounce_buf, cmd->c_data, 496 1.18 jmcneill cmd->c_datalen); 497 1.18 jmcneill bus_dmamap_sync(sc->sc_dmat, sc->sc_dmabounce_map, 498 1.18 jmcneill 0, cmd->c_datalen, BUS_DMASYNC_PREWRITE); 499 1.18 jmcneill } 500 1.18 jmcneill } 501 1.18 jmcneill 502 1.11 jmcneill desc = 0; 503 1.18 jmcneill for (seg = 0; seg < map->dm_nsegs; seg++) { 504 1.18 jmcneill bus_addr_t paddr = map->dm_segs[seg].ds_addr; 505 1.18 jmcneill bus_size_t len = map->dm_segs[seg].ds_len; 506 1.15 riastrad resid = uimin(len, cmd->c_resid); 507 1.11 jmcneill off = 0; 508 1.11 jmcneill while (resid > 0) { 509 1.11 jmcneill if (desc == sc->sc_idma_ndesc) 510 1.11 jmcneill break; 511 1.15 riastrad len = uimin(sc->sc_idma_xferlen, resid); 512 1.11 jmcneill dma[desc].dma_buf_size = htole32(len); 513 1.11 jmcneill dma[desc].dma_buf_addr = htole32(paddr + off); 514 1.11 jmcneill dma[desc].dma_config = htole32( 515 1.18 jmcneill DWC_MMC_IDMA_CONFIG_CH | 516 1.11 jmcneill DWC_MMC_IDMA_CONFIG_OWN); 517 1.11 jmcneill cmd->c_resid -= len; 518 1.11 jmcneill resid -= len; 519 1.11 jmcneill off += len; 520 1.11 jmcneill if (desc == 0) { 521 1.11 jmcneill dma[desc].dma_config |= htole32( 522 1.11 jmcneill DWC_MMC_IDMA_CONFIG_FD); 523 1.11 jmcneill } 524 1.11 jmcneill if (cmd->c_resid == 0) { 525 1.11 jmcneill dma[desc].dma_config |= htole32( 526 1.11 jmcneill DWC_MMC_IDMA_CONFIG_LD); 527 1.18 jmcneill dma[desc].dma_config |= htole32( 528 1.18 jmcneill DWC_MMC_IDMA_CONFIG_ER); 529 1.18 jmcneill dma[desc].dma_next = 0; 530 1.11 jmcneill } else { 531 1.11 jmcneill dma[desc].dma_config |= 532 1.18 jmcneill htole32(DWC_MMC_IDMA_CONFIG_DIC); 533 1.18 jmcneill dma[desc].dma_next = htole32( 534 1.18 jmcneill desc_paddr + ((desc+1) * 535 1.18 jmcneill sizeof(struct dwc_mmc_idma_desc))); 536 1.11 jmcneill } 537 1.11 jmcneill ++desc; 538 1.11 jmcneill } 539 1.11 jmcneill } 540 1.11 jmcneill if (desc == sc->sc_idma_ndesc) { 541 1.11 jmcneill aprint_error_dev(sc->sc_dev, 542 1.11 jmcneill "not enough descriptors for %d byte transfer!\n", 543 1.11 jmcneill cmd->c_datalen); 544 1.11 jmcneill return EIO; 545 1.11 jmcneill } 546 1.11 jmcneill 547 1.11 jmcneill bus_dmamap_sync(sc->sc_dmat, sc->sc_idma_map, 0, 548 1.11 jmcneill sc->sc_idma_size, BUS_DMASYNC_PREWRITE); 549 1.11 jmcneill 550 1.18 jmcneill MMC_WRITE(sc, DWC_MMC_DLBA, desc_paddr); 551 1.11 jmcneill 552 1.11 jmcneill val = MMC_READ(sc, DWC_MMC_GCTRL); 553 1.11 jmcneill val |= DWC_MMC_GCTRL_DMAEN; 554 1.11 jmcneill MMC_WRITE(sc, DWC_MMC_GCTRL, val); 555 1.11 jmcneill val |= DWC_MMC_GCTRL_DMARESET; 556 1.11 jmcneill MMC_WRITE(sc, DWC_MMC_GCTRL, val); 557 1.18 jmcneill 558 1.11 jmcneill if (cmd->c_flags & SCF_CMD_READ) 559 1.18 jmcneill val = DWC_MMC_IDST_RECEIVE_INT; 560 1.11 jmcneill else 561 1.18 jmcneill val = 0; 562 1.11 jmcneill MMC_WRITE(sc, DWC_MMC_IDIE, val); 563 1.18 jmcneill MMC_WRITE(sc, DWC_MMC_DMAC, 564 1.18 jmcneill DWC_MMC_DMAC_IDMA_ON|DWC_MMC_DMAC_FIX_BURST); 565 1.11 jmcneill 566 1.11 jmcneill return 0; 567 1.11 jmcneill } 568 1.11 jmcneill 569 1.11 jmcneill static void 570 1.18 jmcneill dwc_mmc_dma_complete(struct dwc_mmc_softc *sc, struct sdmmc_command *cmd) 571 1.1 jmcneill { 572 1.18 jmcneill MMC_WRITE(sc, DWC_MMC_DMAC, 0); 573 1.18 jmcneill MMC_WRITE(sc, DWC_MMC_IDIE, 0); 574 1.18 jmcneill 575 1.11 jmcneill bus_dmamap_sync(sc->sc_dmat, sc->sc_idma_map, 0, 576 1.11 jmcneill sc->sc_idma_size, BUS_DMASYNC_POSTWRITE); 577 1.18 jmcneill 578 1.18 jmcneill if (cmd->c_dmamap == NULL) { 579 1.18 jmcneill if (ISSET(cmd->c_flags, SCF_CMD_READ)) { 580 1.18 jmcneill bus_dmamap_sync(sc->sc_dmat, sc->sc_dmabounce_map, 581 1.18 jmcneill 0, cmd->c_datalen, BUS_DMASYNC_POSTREAD); 582 1.18 jmcneill memcpy(cmd->c_data, sc->sc_dmabounce_buf, 583 1.18 jmcneill cmd->c_datalen); 584 1.18 jmcneill } else { 585 1.18 jmcneill bus_dmamap_sync(sc->sc_dmat, sc->sc_dmabounce_map, 586 1.18 jmcneill 0, cmd->c_datalen, BUS_DMASYNC_POSTWRITE); 587 1.18 jmcneill } 588 1.18 jmcneill } 589 1.1 jmcneill } 590 1.1 jmcneill 591 1.1 jmcneill static void 592 1.1 jmcneill dwc_mmc_exec_command(sdmmc_chipset_handle_t sch, struct sdmmc_command *cmd) 593 1.1 jmcneill { 594 1.1 jmcneill struct dwc_mmc_softc *sc = sch; 595 1.11 jmcneill uint32_t cmdval = DWC_MMC_CMD_START; 596 1.18 jmcneill int retry, error; 597 1.18 jmcneill uint32_t imask; 598 1.22 jmcneill u_int reg; 599 1.1 jmcneill 600 1.2 jmcneill #ifdef DWC_MMC_DEBUG 601 1.11 jmcneill aprint_normal_dev(sc->sc_dev, 602 1.11 jmcneill "opcode %d flags 0x%x data %p datalen %d blklen %d\n", 603 1.11 jmcneill cmd->c_opcode, cmd->c_flags, cmd->c_data, cmd->c_datalen, 604 1.11 jmcneill cmd->c_blklen); 605 1.2 jmcneill #endif 606 1.2 jmcneill 607 1.22 jmcneill mutex_enter(&sc->sc_lock); 608 1.18 jmcneill if (sc->sc_curcmd != NULL) { 609 1.18 jmcneill device_printf(sc->sc_dev, 610 1.18 jmcneill "WARNING: driver submitted a command while the controller was busy\n"); 611 1.18 jmcneill cmd->c_error = EBUSY; 612 1.18 jmcneill SET(cmd->c_flags, SCF_ITSDONE); 613 1.22 jmcneill mutex_exit(&sc->sc_lock); 614 1.18 jmcneill return; 615 1.3 jmcneill } 616 1.18 jmcneill sc->sc_curcmd = cmd; 617 1.3 jmcneill 618 1.11 jmcneill MMC_WRITE(sc, DWC_MMC_IDST, 0xffffffff); 619 1.11 jmcneill 620 1.22 jmcneill if (!sc->sc_card_inited) { 621 1.22 jmcneill cmdval |= DWC_MMC_CMD_SEND_INIT_SEQ; 622 1.22 jmcneill sc->sc_card_inited = true; 623 1.22 jmcneill } 624 1.22 jmcneill 625 1.11 jmcneill if (ISSET(sc->sc_flags, DWC_MMC_F_USE_HOLD_REG)) 626 1.1 jmcneill cmdval |= DWC_MMC_CMD_USE_HOLD_REG; 627 1.1 jmcneill 628 1.22 jmcneill switch (cmd->c_opcode) { 629 1.22 jmcneill case SD_IO_RW_DIRECT: 630 1.22 jmcneill reg = (cmd->c_arg >> SD_ARG_CMD52_REG_SHIFT) & 631 1.22 jmcneill SD_ARG_CMD52_REG_MASK; 632 1.22 jmcneill if (reg != 0x6) /* func abort / card reset */ 633 1.22 jmcneill break; 634 1.22 jmcneill /* FALLTHROUGH */ 635 1.22 jmcneill case MMC_GO_IDLE_STATE: 636 1.22 jmcneill case MMC_STOP_TRANSMISSION: 637 1.22 jmcneill case MMC_INACTIVE_STATE: 638 1.22 jmcneill cmdval |= DWC_MMC_CMD_STOP_ABORT_CMD; 639 1.22 jmcneill break; 640 1.22 jmcneill } 641 1.22 jmcneill 642 1.1 jmcneill if (cmd->c_flags & SCF_RSP_PRESENT) 643 1.11 jmcneill cmdval |= DWC_MMC_CMD_RSP_EXP; 644 1.1 jmcneill if (cmd->c_flags & SCF_RSP_136) 645 1.11 jmcneill cmdval |= DWC_MMC_CMD_LONG_RSP; 646 1.1 jmcneill if (cmd->c_flags & SCF_RSP_CRC) 647 1.11 jmcneill cmdval |= DWC_MMC_CMD_CHECK_RSP_CRC; 648 1.1 jmcneill 649 1.18 jmcneill imask = DWC_MMC_INT_ERROR | DWC_MMC_INT_CMD_DONE; 650 1.18 jmcneill 651 1.1 jmcneill if (cmd->c_datalen > 0) { 652 1.1 jmcneill unsigned int nblks; 653 1.1 jmcneill 654 1.21 jmcneill MMC_WRITE(sc, DWC_MMC_GCTRL, 655 1.21 jmcneill MMC_READ(sc, DWC_MMC_GCTRL) | DWC_MMC_GCTRL_FIFORESET); 656 1.22 jmcneill for (retry = 0; retry < 100000; retry++) { 657 1.21 jmcneill if (!(MMC_READ(sc, DWC_MMC_DMAC) & DWC_MMC_DMAC_SOFTRESET)) 658 1.21 jmcneill break; 659 1.22 jmcneill delay(1); 660 1.21 jmcneill } 661 1.21 jmcneill 662 1.11 jmcneill cmdval |= DWC_MMC_CMD_DATA_EXP | DWC_MMC_CMD_WAIT_PRE_OVER; 663 1.1 jmcneill if (!ISSET(cmd->c_flags, SCF_CMD_READ)) { 664 1.11 jmcneill cmdval |= DWC_MMC_CMD_WRITE; 665 1.1 jmcneill } 666 1.1 jmcneill 667 1.1 jmcneill nblks = cmd->c_datalen / cmd->c_blklen; 668 1.1 jmcneill if (nblks == 0 || (cmd->c_datalen % cmd->c_blklen) != 0) 669 1.1 jmcneill ++nblks; 670 1.1 jmcneill 671 1.21 jmcneill if (nblks > 1 && cmd->c_opcode != SD_IO_RW_EXTENDED) { 672 1.1 jmcneill cmdval |= DWC_MMC_CMD_SEND_AUTO_STOP; 673 1.18 jmcneill imask |= DWC_MMC_INT_AUTO_CMD_DONE; 674 1.18 jmcneill } else { 675 1.18 jmcneill imask |= DWC_MMC_INT_DATA_OVER; 676 1.1 jmcneill } 677 1.1 jmcneill 678 1.21 jmcneill MMC_WRITE(sc, DWC_MMC_TIMEOUT, 0xffffffff); 679 1.11 jmcneill MMC_WRITE(sc, DWC_MMC_BLKSZ, cmd->c_blklen); 680 1.21 jmcneill MMC_WRITE(sc, DWC_MMC_BYTECNT, 681 1.21 jmcneill nblks > 1 ? nblks * cmd->c_blklen : cmd->c_datalen); 682 1.26 skrll 683 1.26 skrll #if 0 684 1.26 skrll /* 685 1.26 skrll * The following doesn't work on the 250a verid IP in Odroid-XU4. 686 1.26 skrll * 687 1.26 skrll * thrctl should only be used for UHS/HS200 and faster timings on 688 1.26 skrll * >=240a 689 1.26 skrll */ 690 1.26 skrll 691 1.21 jmcneill if (ISSET(cmd->c_flags, SCF_CMD_READ)) { 692 1.21 jmcneill MMC_WRITE(sc, DWC_MMC_CARDTHRCTL, 693 1.21 jmcneill __SHIFTIN(cmd->c_blklen, DWC_MMC_CARDTHRCTL_RDTHR) | 694 1.21 jmcneill DWC_MMC_CARDTHRCTL_RDTHREN); 695 1.21 jmcneill } 696 1.26 skrll #endif 697 1.1 jmcneill } 698 1.1 jmcneill 699 1.18 jmcneill MMC_WRITE(sc, DWC_MMC_IMASK, imask | sc->sc_intr_card); 700 1.18 jmcneill MMC_WRITE(sc, DWC_MMC_RINT, 0x7fff); 701 1.1 jmcneill 702 1.11 jmcneill MMC_WRITE(sc, DWC_MMC_ARG, cmd->c_arg); 703 1.1 jmcneill 704 1.11 jmcneill #ifdef DWC_MMC_DEBUG 705 1.11 jmcneill aprint_normal_dev(sc->sc_dev, "cmdval = %08x\n", cmdval); 706 1.11 jmcneill #endif 707 1.11 jmcneill 708 1.18 jmcneill cmd->c_resid = cmd->c_datalen; 709 1.11 jmcneill if (cmd->c_datalen > 0) { 710 1.11 jmcneill dwc_mmc_led(sc, 0); 711 1.18 jmcneill cmd->c_error = dwc_mmc_dma_prepare(sc, cmd); 712 1.18 jmcneill if (cmd->c_error != 0) { 713 1.18 jmcneill SET(cmd->c_flags, SCF_ITSDONE); 714 1.11 jmcneill goto done; 715 1.11 jmcneill } 716 1.18 jmcneill sc->sc_wait_dma = ISSET(cmd->c_flags, SCF_CMD_READ); 717 1.18 jmcneill sc->sc_wait_data = true; 718 1.11 jmcneill } else { 719 1.18 jmcneill sc->sc_wait_dma = false; 720 1.18 jmcneill sc->sc_wait_data = false; 721 1.11 jmcneill } 722 1.18 jmcneill sc->sc_wait_cmd = true; 723 1.1 jmcneill 724 1.22 jmcneill if ((cmdval & DWC_MMC_CMD_WAIT_PRE_OVER) != 0) { 725 1.22 jmcneill for (retry = 0; retry < 10000; retry++) { 726 1.22 jmcneill if (!(MMC_READ(sc, DWC_MMC_STATUS) & DWC_MMC_STATUS_CARD_DATA_BUSY)) 727 1.22 jmcneill break; 728 1.22 jmcneill delay(1); 729 1.22 jmcneill } 730 1.22 jmcneill } 731 1.22 jmcneill 732 1.22 jmcneill mutex_enter(&sc->sc_intr_lock); 733 1.22 jmcneill 734 1.18 jmcneill MMC_WRITE(sc, DWC_MMC_CMD, cmdval | cmd->c_opcode); 735 1.1 jmcneill 736 1.18 jmcneill if (sc->sc_wait_dma) 737 1.18 jmcneill MMC_WRITE(sc, DWC_MMC_PLDMND, 1); 738 1.18 jmcneill 739 1.18 jmcneill struct bintime timeout = { .sec = 15, .frac = 0 }; 740 1.18 jmcneill const struct bintime epsilon = { .sec = 1, .frac = 0 }; 741 1.18 jmcneill while (!ISSET(cmd->c_flags, SCF_ITSDONE)) { 742 1.18 jmcneill error = cv_timedwaitbt(&sc->sc_intr_cv, 743 1.18 jmcneill &sc->sc_intr_lock, &timeout, &epsilon); 744 1.18 jmcneill if (error != 0) { 745 1.18 jmcneill cmd->c_error = error; 746 1.18 jmcneill SET(cmd->c_flags, SCF_ITSDONE); 747 1.23 skrll mutex_exit(&sc->sc_intr_lock); 748 1.1 jmcneill goto done; 749 1.1 jmcneill } 750 1.1 jmcneill } 751 1.1 jmcneill 752 1.22 jmcneill mutex_exit(&sc->sc_intr_lock); 753 1.22 jmcneill 754 1.18 jmcneill if (cmd->c_error == 0 && cmd->c_datalen > 0) 755 1.18 jmcneill dwc_mmc_dma_complete(sc, cmd); 756 1.18 jmcneill 757 1.18 jmcneill if (cmd->c_datalen > 0) 758 1.18 jmcneill dwc_mmc_led(sc, 1); 759 1.18 jmcneill 760 1.1 jmcneill if (cmd->c_flags & SCF_RSP_PRESENT) { 761 1.1 jmcneill if (cmd->c_flags & SCF_RSP_136) { 762 1.11 jmcneill cmd->c_resp[0] = MMC_READ(sc, DWC_MMC_RESP0); 763 1.11 jmcneill cmd->c_resp[1] = MMC_READ(sc, DWC_MMC_RESP1); 764 1.11 jmcneill cmd->c_resp[2] = MMC_READ(sc, DWC_MMC_RESP2); 765 1.11 jmcneill cmd->c_resp[3] = MMC_READ(sc, DWC_MMC_RESP3); 766 1.1 jmcneill if (cmd->c_flags & SCF_RSP_CRC) { 767 1.1 jmcneill cmd->c_resp[0] = (cmd->c_resp[0] >> 8) | 768 1.1 jmcneill (cmd->c_resp[1] << 24); 769 1.1 jmcneill cmd->c_resp[1] = (cmd->c_resp[1] >> 8) | 770 1.1 jmcneill (cmd->c_resp[2] << 24); 771 1.1 jmcneill cmd->c_resp[2] = (cmd->c_resp[2] >> 8) | 772 1.1 jmcneill (cmd->c_resp[3] << 24); 773 1.1 jmcneill cmd->c_resp[3] = (cmd->c_resp[3] >> 8); 774 1.1 jmcneill } 775 1.1 jmcneill } else { 776 1.11 jmcneill cmd->c_resp[0] = MMC_READ(sc, DWC_MMC_RESP0); 777 1.1 jmcneill } 778 1.1 jmcneill } 779 1.1 jmcneill 780 1.1 jmcneill done: 781 1.18 jmcneill KASSERT(ISSET(cmd->c_flags, SCF_ITSDONE)); 782 1.18 jmcneill MMC_WRITE(sc, DWC_MMC_IMASK, sc->sc_intr_card); 783 1.18 jmcneill MMC_WRITE(sc, DWC_MMC_IDIE, 0); 784 1.18 jmcneill MMC_WRITE(sc, DWC_MMC_RINT, 0x7fff); 785 1.18 jmcneill MMC_WRITE(sc, DWC_MMC_IDST, 0xffffffff); 786 1.1 jmcneill 787 1.11 jmcneill if (cmd->c_error) { 788 1.11 jmcneill #ifdef DWC_MMC_DEBUG 789 1.11 jmcneill aprint_error_dev(sc->sc_dev, "i/o error %d\n", cmd->c_error); 790 1.11 jmcneill #endif 791 1.21 jmcneill MMC_WRITE(sc, DWC_MMC_DMAC, DWC_MMC_DMAC_SOFTRESET); 792 1.21 jmcneill for (retry = 0; retry < 100; retry++) { 793 1.21 jmcneill if (!(MMC_READ(sc, DWC_MMC_DMAC) & DWC_MMC_DMAC_SOFTRESET)) 794 1.11 jmcneill break; 795 1.22 jmcneill kpause("dwcmmcrst", false, uimax(mstohz(1), 1), &sc->sc_lock); 796 1.11 jmcneill } 797 1.8 jmcneill } 798 1.22 jmcneill 799 1.22 jmcneill sc->sc_curcmd = NULL; 800 1.22 jmcneill mutex_exit(&sc->sc_lock); 801 1.1 jmcneill } 802 1.1 jmcneill 803 1.1 jmcneill static void 804 1.1 jmcneill dwc_mmc_card_enable_intr(sdmmc_chipset_handle_t sch, int enable) 805 1.1 jmcneill { 806 1.18 jmcneill struct dwc_mmc_softc *sc = sch; 807 1.18 jmcneill uint32_t imask; 808 1.18 jmcneill 809 1.18 jmcneill mutex_enter(&sc->sc_intr_lock); 810 1.18 jmcneill imask = MMC_READ(sc, DWC_MMC_IMASK); 811 1.18 jmcneill if (enable) 812 1.21 jmcneill imask |= sc->sc_intr_cardmask; 813 1.18 jmcneill else 814 1.21 jmcneill imask &= ~sc->sc_intr_cardmask; 815 1.21 jmcneill sc->sc_intr_card = imask & sc->sc_intr_cardmask; 816 1.18 jmcneill MMC_WRITE(sc, DWC_MMC_IMASK, imask); 817 1.18 jmcneill mutex_exit(&sc->sc_intr_lock); 818 1.1 jmcneill } 819 1.1 jmcneill 820 1.1 jmcneill static void 821 1.1 jmcneill dwc_mmc_card_intr_ack(sdmmc_chipset_handle_t sch) 822 1.1 jmcneill { 823 1.18 jmcneill struct dwc_mmc_softc *sc = sch; 824 1.18 jmcneill uint32_t imask; 825 1.18 jmcneill 826 1.18 jmcneill mutex_enter(&sc->sc_intr_lock); 827 1.18 jmcneill imask = MMC_READ(sc, DWC_MMC_IMASK); 828 1.18 jmcneill MMC_WRITE(sc, DWC_MMC_IMASK, imask | sc->sc_intr_card); 829 1.18 jmcneill mutex_exit(&sc->sc_intr_lock); 830 1.1 jmcneill } 831 1.1 jmcneill 832 1.11 jmcneill int 833 1.11 jmcneill dwc_mmc_init(struct dwc_mmc_softc *sc) 834 1.5 jmcneill { 835 1.12 jmcneill uint32_t val; 836 1.12 jmcneill 837 1.25 skrll val = MMC_READ(sc, DWC_MMC_VERID); 838 1.25 skrll sc->sc_verid = __SHIFTOUT(val, DWC_MMC_VERID_ID); 839 1.25 skrll 840 1.31 skrll if (sizeof(bus_addr_t) > 4) { 841 1.31 skrll int error = bus_dmatag_subregion(sc->sc_dmat, 0, __MASK(32), 842 1.31 skrll &sc->sc_dmat, BUS_DMA_WAITOK); 843 1.31 skrll if (error != 0) { 844 1.31 skrll aprint_error_dev(sc->sc_dev, 845 1.31 skrll "failed to create DMA subregion\n"); 846 1.31 skrll return ENOMEM; 847 1.31 skrll } 848 1.31 skrll } 849 1.31 skrll 850 1.12 jmcneill if (sc->sc_fifo_reg == 0) { 851 1.25 skrll if (sc->sc_verid < DWC_MMC_VERID_240A) 852 1.12 jmcneill sc->sc_fifo_reg = 0x100; 853 1.12 jmcneill else 854 1.12 jmcneill sc->sc_fifo_reg = 0x200; 855 1.12 jmcneill } 856 1.12 jmcneill 857 1.12 jmcneill if (sc->sc_fifo_depth == 0) { 858 1.12 jmcneill val = MMC_READ(sc, DWC_MMC_FIFOTH); 859 1.12 jmcneill sc->sc_fifo_depth = __SHIFTOUT(val, DWC_MMC_FIFOTH_RX_WMARK) + 1; 860 1.12 jmcneill } 861 1.12 jmcneill 862 1.21 jmcneill if (sc->sc_intr_cardmask == 0) 863 1.21 jmcneill sc->sc_intr_cardmask = DWC_MMC_INT_SDIO_INT(0); 864 1.21 jmcneill 865 1.22 jmcneill mutex_init(&sc->sc_lock, MUTEX_DEFAULT, IPL_NONE); 866 1.11 jmcneill mutex_init(&sc->sc_intr_lock, MUTEX_DEFAULT, IPL_BIO); 867 1.11 jmcneill cv_init(&sc->sc_intr_cv, "dwcmmcirq"); 868 1.11 jmcneill 869 1.18 jmcneill if (dwc_mmc_dmabounce_setup(sc) != 0 || 870 1.18 jmcneill dwc_mmc_idma_setup(sc) != 0) { 871 1.11 jmcneill aprint_error_dev(sc->sc_dev, "failed to setup DMA\n"); 872 1.11 jmcneill return ENOMEM; 873 1.11 jmcneill } 874 1.11 jmcneill 875 1.11 jmcneill config_interrupts(sc->sc_dev, dwc_mmc_attach_i); 876 1.11 jmcneill 877 1.11 jmcneill return 0; 878 1.5 jmcneill } 879 1.11 jmcneill 880 1.11 jmcneill int 881 1.11 jmcneill dwc_mmc_intr(void *priv) 882 1.11 jmcneill { 883 1.11 jmcneill struct dwc_mmc_softc *sc = priv; 884 1.18 jmcneill struct sdmmc_command *cmd; 885 1.18 jmcneill uint32_t idst, mint, imask; 886 1.11 jmcneill 887 1.11 jmcneill mutex_enter(&sc->sc_intr_lock); 888 1.11 jmcneill idst = MMC_READ(sc, DWC_MMC_IDST); 889 1.11 jmcneill mint = MMC_READ(sc, DWC_MMC_MINT); 890 1.18 jmcneill if (!idst && !mint) { 891 1.11 jmcneill mutex_exit(&sc->sc_intr_lock); 892 1.11 jmcneill return 0; 893 1.11 jmcneill } 894 1.11 jmcneill MMC_WRITE(sc, DWC_MMC_IDST, idst); 895 1.18 jmcneill MMC_WRITE(sc, DWC_MMC_RINT, mint); 896 1.18 jmcneill 897 1.18 jmcneill cmd = sc->sc_curcmd; 898 1.11 jmcneill 899 1.11 jmcneill #ifdef DWC_MMC_DEBUG 900 1.18 jmcneill device_printf(sc->sc_dev, "mmc intr idst=%08X mint=%08X\n", 901 1.18 jmcneill idst, mint); 902 1.5 jmcneill #endif 903 1.5 jmcneill 904 1.18 jmcneill /* Handle SDIO card interrupt */ 905 1.21 jmcneill if ((mint & sc->sc_intr_cardmask) != 0) { 906 1.18 jmcneill imask = MMC_READ(sc, DWC_MMC_IMASK); 907 1.21 jmcneill MMC_WRITE(sc, DWC_MMC_IMASK, imask & ~sc->sc_intr_cardmask); 908 1.18 jmcneill sdmmc_card_intr(sc->sc_sdmmc_dev); 909 1.18 jmcneill } 910 1.18 jmcneill 911 1.18 jmcneill /* Error interrupts take priority over command and transfer interrupts */ 912 1.18 jmcneill if (cmd != NULL && (mint & DWC_MMC_INT_ERROR) != 0) { 913 1.18 jmcneill imask = MMC_READ(sc, DWC_MMC_IMASK); 914 1.18 jmcneill MMC_WRITE(sc, DWC_MMC_IMASK, imask & ~DWC_MMC_INT_ERROR); 915 1.18 jmcneill if ((mint & DWC_MMC_INT_RESP_TIMEOUT) != 0) { 916 1.18 jmcneill cmd->c_error = ETIMEDOUT; 917 1.18 jmcneill /* Wait for command to complete */ 918 1.18 jmcneill sc->sc_wait_data = sc->sc_wait_dma = false; 919 1.18 jmcneill if (cmd->c_opcode != SD_IO_SEND_OP_COND && 920 1.18 jmcneill cmd->c_opcode != SD_IO_RW_DIRECT && 921 1.18 jmcneill !ISSET(cmd->c_flags, SCF_TOUT_OK)) 922 1.18 jmcneill device_printf(sc->sc_dev, "host controller timeout, mint=0x%08x\n", mint); 923 1.18 jmcneill } else { 924 1.18 jmcneill device_printf(sc->sc_dev, "host controller error, mint=0x%08x\n", mint); 925 1.18 jmcneill cmd->c_error = EIO; 926 1.18 jmcneill SET(cmd->c_flags, SCF_ITSDONE); 927 1.18 jmcneill goto done; 928 1.18 jmcneill } 929 1.18 jmcneill } 930 1.18 jmcneill 931 1.18 jmcneill if (cmd != NULL && (idst & DWC_MMC_IDST_RECEIVE_INT) != 0) { 932 1.18 jmcneill MMC_WRITE(sc, DWC_MMC_IDIE, 0); 933 1.18 jmcneill if (sc->sc_wait_dma == false) 934 1.18 jmcneill device_printf(sc->sc_dev, "unexpected DMA receive interrupt\n"); 935 1.18 jmcneill sc->sc_wait_dma = false; 936 1.18 jmcneill } 937 1.18 jmcneill 938 1.18 jmcneill if (cmd != NULL && (mint & DWC_MMC_INT_CMD_DONE) != 0) { 939 1.18 jmcneill imask = MMC_READ(sc, DWC_MMC_IMASK); 940 1.18 jmcneill MMC_WRITE(sc, DWC_MMC_IMASK, imask & ~DWC_MMC_INT_CMD_DONE); 941 1.18 jmcneill if (sc->sc_wait_cmd == false) 942 1.18 jmcneill device_printf(sc->sc_dev, "unexpected command complete interrupt\n"); 943 1.18 jmcneill sc->sc_wait_cmd = false; 944 1.18 jmcneill } 945 1.18 jmcneill 946 1.18 jmcneill const uint32_t dmadone_mask = DWC_MMC_INT_AUTO_CMD_DONE|DWC_MMC_INT_DATA_OVER; 947 1.18 jmcneill if (cmd != NULL && (mint & dmadone_mask) != 0) { 948 1.18 jmcneill imask = MMC_READ(sc, DWC_MMC_IMASK); 949 1.18 jmcneill MMC_WRITE(sc, DWC_MMC_IMASK, imask & ~dmadone_mask); 950 1.18 jmcneill if (sc->sc_wait_data == false) 951 1.18 jmcneill device_printf(sc->sc_dev, "unexpected data complete interrupt\n"); 952 1.18 jmcneill sc->sc_wait_data = false; 953 1.18 jmcneill } 954 1.18 jmcneill 955 1.18 jmcneill if (cmd != NULL && 956 1.18 jmcneill sc->sc_wait_dma == false && 957 1.18 jmcneill sc->sc_wait_cmd == false && 958 1.18 jmcneill sc->sc_wait_data == false) { 959 1.18 jmcneill SET(cmd->c_flags, SCF_ITSDONE); 960 1.11 jmcneill } 961 1.1 jmcneill 962 1.18 jmcneill done: 963 1.18 jmcneill if (cmd != NULL && ISSET(cmd->c_flags, SCF_ITSDONE)) { 964 1.11 jmcneill cv_broadcast(&sc->sc_intr_cv); 965 1.1 jmcneill } 966 1.11 jmcneill 967 1.11 jmcneill mutex_exit(&sc->sc_intr_lock); 968 1.11 jmcneill 969 1.11 jmcneill return 1; 970 1.1 jmcneill } 971