1 1.48 thorpej /* $NetBSD: sunxi_mmc.c,v 1.48 2021/08/07 16:18:45 thorpej Exp $ */ 2 1.1 jmcneill 3 1.1 jmcneill /*- 4 1.1 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.13 jmcneill #include "opt_sunximmc.h" 30 1.13 jmcneill 31 1.1 jmcneill #include <sys/cdefs.h> 32 1.48 thorpej __KERNEL_RCSID(0, "$NetBSD: sunxi_mmc.c,v 1.48 2021/08/07 16:18:45 thorpej Exp $"); 33 1.1 jmcneill 34 1.1 jmcneill #include <sys/param.h> 35 1.1 jmcneill #include <sys/bus.h> 36 1.1 jmcneill #include <sys/device.h> 37 1.1 jmcneill #include <sys/intr.h> 38 1.1 jmcneill #include <sys/systm.h> 39 1.1 jmcneill #include <sys/kernel.h> 40 1.1 jmcneill #include <sys/gpio.h> 41 1.1 jmcneill 42 1.1 jmcneill #include <dev/sdmmc/sdmmcvar.h> 43 1.1 jmcneill #include <dev/sdmmc/sdmmcchip.h> 44 1.1 jmcneill #include <dev/sdmmc/sdmmc_ioreg.h> 45 1.1 jmcneill 46 1.1 jmcneill #include <dev/fdt/fdtvar.h> 47 1.1 jmcneill 48 1.1 jmcneill #include <arm/sunxi/sunxi_mmc.h> 49 1.1 jmcneill 50 1.13 jmcneill #ifdef SUNXI_MMC_DEBUG 51 1.13 jmcneill static int sunxi_mmc_debug = SUNXI_MMC_DEBUG; 52 1.13 jmcneill #define DPRINTF(dev, fmt, ...) \ 53 1.13 jmcneill do { \ 54 1.13 jmcneill if (sunxi_mmc_debug & __BIT(device_unit(dev))) \ 55 1.13 jmcneill device_printf((dev), fmt, ##__VA_ARGS__); \ 56 1.13 jmcneill } while (0) 57 1.13 jmcneill #else 58 1.13 jmcneill #define DPRINTF(dev, fmt, ...) ((void)0) 59 1.13 jmcneill #endif 60 1.13 jmcneill 61 1.3 jmcneill enum sunxi_mmc_timing { 62 1.3 jmcneill SUNXI_MMC_TIMING_400K, 63 1.3 jmcneill SUNXI_MMC_TIMING_25M, 64 1.3 jmcneill SUNXI_MMC_TIMING_50M, 65 1.3 jmcneill SUNXI_MMC_TIMING_50M_DDR, 66 1.3 jmcneill SUNXI_MMC_TIMING_50M_DDR_8BIT, 67 1.3 jmcneill }; 68 1.3 jmcneill 69 1.3 jmcneill struct sunxi_mmc_delay { 70 1.3 jmcneill u_int output_phase; 71 1.3 jmcneill u_int sample_phase; 72 1.3 jmcneill }; 73 1.3 jmcneill 74 1.10 jmcneill static const struct sunxi_mmc_delay sun7i_mmc_delays[] = { 75 1.3 jmcneill [SUNXI_MMC_TIMING_400K] = { 180, 180 }, 76 1.3 jmcneill [SUNXI_MMC_TIMING_25M] = { 180, 75 }, 77 1.3 jmcneill [SUNXI_MMC_TIMING_50M] = { 90, 120 }, 78 1.3 jmcneill [SUNXI_MMC_TIMING_50M_DDR] = { 60, 120 }, 79 1.3 jmcneill [SUNXI_MMC_TIMING_50M_DDR_8BIT] = { 90, 180 }, 80 1.3 jmcneill }; 81 1.3 jmcneill 82 1.10 jmcneill static const struct sunxi_mmc_delay sun9i_mmc_delays[] = { 83 1.10 jmcneill [SUNXI_MMC_TIMING_400K] = { 180, 180 }, 84 1.10 jmcneill [SUNXI_MMC_TIMING_25M] = { 180, 75 }, 85 1.10 jmcneill [SUNXI_MMC_TIMING_50M] = { 150, 120 }, 86 1.10 jmcneill [SUNXI_MMC_TIMING_50M_DDR] = { 54, 36 }, 87 1.10 jmcneill [SUNXI_MMC_TIMING_50M_DDR_8BIT] = { 72, 72 }, 88 1.10 jmcneill }; 89 1.10 jmcneill 90 1.21 ryo #define SUNXI_MMC_NDESC 64 91 1.1 jmcneill 92 1.1 jmcneill struct sunxi_mmc_softc; 93 1.1 jmcneill 94 1.1 jmcneill static int sunxi_mmc_match(device_t, cfdata_t, void *); 95 1.1 jmcneill static void sunxi_mmc_attach(device_t, device_t, void *); 96 1.1 jmcneill static void sunxi_mmc_attach_i(device_t); 97 1.1 jmcneill 98 1.1 jmcneill static int sunxi_mmc_intr(void *); 99 1.14 jmcneill static int sunxi_mmc_dmabounce_setup(struct sunxi_mmc_softc *); 100 1.1 jmcneill static int sunxi_mmc_idma_setup(struct sunxi_mmc_softc *); 101 1.38 jmcneill static void sunxi_mmc_dma_complete(struct sunxi_mmc_softc *, struct sdmmc_command *); 102 1.1 jmcneill 103 1.1 jmcneill static int sunxi_mmc_host_reset(sdmmc_chipset_handle_t); 104 1.1 jmcneill static uint32_t sunxi_mmc_host_ocr(sdmmc_chipset_handle_t); 105 1.1 jmcneill static int sunxi_mmc_host_maxblklen(sdmmc_chipset_handle_t); 106 1.1 jmcneill static int sunxi_mmc_card_detect(sdmmc_chipset_handle_t); 107 1.1 jmcneill static int sunxi_mmc_write_protect(sdmmc_chipset_handle_t); 108 1.1 jmcneill static int sunxi_mmc_bus_power(sdmmc_chipset_handle_t, uint32_t); 109 1.3 jmcneill static int sunxi_mmc_bus_clock(sdmmc_chipset_handle_t, int, bool); 110 1.1 jmcneill static int sunxi_mmc_bus_width(sdmmc_chipset_handle_t, int); 111 1.1 jmcneill static int sunxi_mmc_bus_rod(sdmmc_chipset_handle_t, int); 112 1.3 jmcneill static int sunxi_mmc_signal_voltage(sdmmc_chipset_handle_t, int); 113 1.23 jmcneill static int sunxi_mmc_execute_tuning(sdmmc_chipset_handle_t, int); 114 1.1 jmcneill static void sunxi_mmc_exec_command(sdmmc_chipset_handle_t, 115 1.1 jmcneill struct sdmmc_command *); 116 1.1 jmcneill static void sunxi_mmc_card_enable_intr(sdmmc_chipset_handle_t, int); 117 1.1 jmcneill static void sunxi_mmc_card_intr_ack(sdmmc_chipset_handle_t); 118 1.1 jmcneill 119 1.1 jmcneill static struct sdmmc_chip_functions sunxi_mmc_chip_functions = { 120 1.1 jmcneill .host_reset = sunxi_mmc_host_reset, 121 1.1 jmcneill .host_ocr = sunxi_mmc_host_ocr, 122 1.1 jmcneill .host_maxblklen = sunxi_mmc_host_maxblklen, 123 1.1 jmcneill .card_detect = sunxi_mmc_card_detect, 124 1.1 jmcneill .write_protect = sunxi_mmc_write_protect, 125 1.1 jmcneill .bus_power = sunxi_mmc_bus_power, 126 1.3 jmcneill .bus_clock_ddr = sunxi_mmc_bus_clock, 127 1.1 jmcneill .bus_width = sunxi_mmc_bus_width, 128 1.1 jmcneill .bus_rod = sunxi_mmc_bus_rod, 129 1.3 jmcneill .signal_voltage = sunxi_mmc_signal_voltage, 130 1.23 jmcneill .execute_tuning = sunxi_mmc_execute_tuning, 131 1.1 jmcneill .exec_command = sunxi_mmc_exec_command, 132 1.1 jmcneill .card_enable_intr = sunxi_mmc_card_enable_intr, 133 1.1 jmcneill .card_intr_ack = sunxi_mmc_card_intr_ack, 134 1.1 jmcneill }; 135 1.1 jmcneill 136 1.7 jmcneill struct sunxi_mmc_config { 137 1.7 jmcneill u_int idma_xferlen; 138 1.7 jmcneill u_int flags; 139 1.7 jmcneill #define SUNXI_MMC_FLAG_CALIB_REG 0x01 140 1.7 jmcneill #define SUNXI_MMC_FLAG_NEW_TIMINGS 0x02 141 1.7 jmcneill #define SUNXI_MMC_FLAG_MASK_DATA0 0x04 142 1.23 jmcneill #define SUNXI_MMC_FLAG_HS200 0x08 143 1.7 jmcneill const struct sunxi_mmc_delay *delays; 144 1.7 jmcneill uint32_t dma_ftrglevel; 145 1.7 jmcneill }; 146 1.7 jmcneill 147 1.1 jmcneill struct sunxi_mmc_softc { 148 1.1 jmcneill device_t sc_dev; 149 1.1 jmcneill bus_space_tag_t sc_bst; 150 1.1 jmcneill bus_space_handle_t sc_bsh; 151 1.1 jmcneill bus_dma_tag_t sc_dmat; 152 1.1 jmcneill int sc_phandle; 153 1.1 jmcneill 154 1.1 jmcneill void *sc_ih; 155 1.1 jmcneill kmutex_t sc_intr_lock; 156 1.1 jmcneill kcondvar_t sc_intr_cv; 157 1.1 jmcneill 158 1.1 jmcneill int sc_mmc_width; 159 1.1 jmcneill int sc_mmc_present; 160 1.1 jmcneill 161 1.23 jmcneill u_int sc_max_frequency; 162 1.23 jmcneill 163 1.1 jmcneill device_t sc_sdmmc_dev; 164 1.1 jmcneill 165 1.43 thorpej const struct sunxi_mmc_config *sc_config; 166 1.1 jmcneill 167 1.1 jmcneill bus_dma_segment_t sc_idma_segs[1]; 168 1.1 jmcneill int sc_idma_nsegs; 169 1.1 jmcneill bus_size_t sc_idma_size; 170 1.1 jmcneill bus_dmamap_t sc_idma_map; 171 1.1 jmcneill int sc_idma_ndesc; 172 1.1 jmcneill void *sc_idma_desc; 173 1.1 jmcneill 174 1.14 jmcneill bus_dmamap_t sc_dmabounce_map; 175 1.14 jmcneill void *sc_dmabounce_buf; 176 1.14 jmcneill size_t sc_dmabounce_buflen; 177 1.14 jmcneill 178 1.1 jmcneill struct clk *sc_clk_ahb; 179 1.1 jmcneill struct clk *sc_clk_mmc; 180 1.1 jmcneill struct clk *sc_clk_output; 181 1.1 jmcneill struct clk *sc_clk_sample; 182 1.1 jmcneill 183 1.1 jmcneill struct fdtbus_reset *sc_rst_ahb; 184 1.1 jmcneill 185 1.1 jmcneill struct fdtbus_gpio_pin *sc_gpio_cd; 186 1.1 jmcneill int sc_gpio_cd_inverted; 187 1.1 jmcneill struct fdtbus_gpio_pin *sc_gpio_wp; 188 1.1 jmcneill int sc_gpio_wp_inverted; 189 1.3 jmcneill 190 1.29 jmcneill struct fdtbus_regulator *sc_reg_vmmc; 191 1.3 jmcneill struct fdtbus_regulator *sc_reg_vqmmc; 192 1.12 jmcneill 193 1.12 jmcneill struct fdtbus_mmc_pwrseq *sc_pwrseq; 194 1.17 jmcneill 195 1.17 jmcneill bool sc_non_removable; 196 1.17 jmcneill bool sc_broken_cd; 197 1.38 jmcneill 198 1.38 jmcneill uint32_t sc_intr_card; 199 1.38 jmcneill struct sdmmc_command *sc_curcmd; 200 1.38 jmcneill bool sc_wait_dma; 201 1.38 jmcneill bool sc_wait_cmd; 202 1.38 jmcneill bool sc_wait_data; 203 1.1 jmcneill }; 204 1.1 jmcneill 205 1.1 jmcneill CFATTACH_DECL_NEW(sunxi_mmc, sizeof(struct sunxi_mmc_softc), 206 1.1 jmcneill sunxi_mmc_match, sunxi_mmc_attach, NULL, NULL); 207 1.1 jmcneill 208 1.1 jmcneill #define MMC_WRITE(sc, reg, val) \ 209 1.1 jmcneill bus_space_write_4((sc)->sc_bst, (sc)->sc_bsh, (reg), (val)) 210 1.1 jmcneill #define MMC_READ(sc, reg) \ 211 1.1 jmcneill bus_space_read_4((sc)->sc_bst, (sc)->sc_bsh, (reg)) 212 1.1 jmcneill 213 1.9 jmcneill static const struct sunxi_mmc_config sun4i_a10_mmc_config = { 214 1.9 jmcneill .idma_xferlen = 0x2000, 215 1.9 jmcneill .dma_ftrglevel = 0x20070008, 216 1.9 jmcneill .delays = NULL, 217 1.9 jmcneill .flags = 0, 218 1.9 jmcneill }; 219 1.9 jmcneill 220 1.7 jmcneill static const struct sunxi_mmc_config sun5i_a13_mmc_config = { 221 1.7 jmcneill .idma_xferlen = 0x10000, 222 1.7 jmcneill .dma_ftrglevel = 0x20070008, 223 1.7 jmcneill .delays = NULL, 224 1.7 jmcneill .flags = 0, 225 1.7 jmcneill }; 226 1.7 jmcneill 227 1.7 jmcneill static const struct sunxi_mmc_config sun7i_a20_mmc_config = { 228 1.8 jmcneill .idma_xferlen = 0x2000, 229 1.7 jmcneill .dma_ftrglevel = 0x20070008, 230 1.10 jmcneill .delays = sun7i_mmc_delays, 231 1.10 jmcneill .flags = 0, 232 1.10 jmcneill }; 233 1.10 jmcneill 234 1.16 jmcneill static const struct sunxi_mmc_config sun8i_a83t_emmc_config = { 235 1.16 jmcneill .idma_xferlen = 0x10000, 236 1.16 jmcneill .dma_ftrglevel = 0x20070008, 237 1.16 jmcneill .delays = NULL, 238 1.16 jmcneill .flags = SUNXI_MMC_FLAG_NEW_TIMINGS, 239 1.16 jmcneill }; 240 1.16 jmcneill 241 1.10 jmcneill static const struct sunxi_mmc_config sun9i_a80_mmc_config = { 242 1.10 jmcneill .idma_xferlen = 0x10000, 243 1.10 jmcneill .dma_ftrglevel = 0x200f0010, 244 1.10 jmcneill .delays = sun9i_mmc_delays, 245 1.7 jmcneill .flags = 0, 246 1.7 jmcneill }; 247 1.7 jmcneill 248 1.7 jmcneill static const struct sunxi_mmc_config sun50i_a64_mmc_config = { 249 1.7 jmcneill .idma_xferlen = 0x10000, 250 1.7 jmcneill .dma_ftrglevel = 0x20070008, 251 1.7 jmcneill .delays = NULL, 252 1.7 jmcneill .flags = SUNXI_MMC_FLAG_CALIB_REG | 253 1.7 jmcneill SUNXI_MMC_FLAG_NEW_TIMINGS | 254 1.7 jmcneill SUNXI_MMC_FLAG_MASK_DATA0, 255 1.7 jmcneill }; 256 1.7 jmcneill 257 1.18 jmcneill static const struct sunxi_mmc_config sun50i_a64_emmc_config = { 258 1.19 jakllsch .idma_xferlen = 0x2000, 259 1.18 jmcneill .dma_ftrglevel = 0x20070008, 260 1.18 jmcneill .delays = NULL, 261 1.28 jmcneill .flags = SUNXI_MMC_FLAG_CALIB_REG | 262 1.28 jmcneill SUNXI_MMC_FLAG_NEW_TIMINGS | 263 1.28 jmcneill SUNXI_MMC_FLAG_HS200, 264 1.18 jmcneill }; 265 1.18 jmcneill 266 1.20 jmcneill static const struct sunxi_mmc_config sun50i_h6_mmc_config = { 267 1.20 jmcneill .idma_xferlen = 0x10000, 268 1.20 jmcneill .dma_ftrglevel = 0x20070008, 269 1.20 jmcneill .delays = NULL, 270 1.20 jmcneill .flags = SUNXI_MMC_FLAG_CALIB_REG | 271 1.20 jmcneill SUNXI_MMC_FLAG_NEW_TIMINGS | 272 1.20 jmcneill SUNXI_MMC_FLAG_MASK_DATA0, 273 1.20 jmcneill }; 274 1.20 jmcneill 275 1.20 jmcneill static const struct sunxi_mmc_config sun50i_h6_emmc_config = { 276 1.20 jmcneill .idma_xferlen = 0x2000, 277 1.20 jmcneill .dma_ftrglevel = 0x20070008, 278 1.20 jmcneill .delays = NULL, 279 1.20 jmcneill .flags = SUNXI_MMC_FLAG_CALIB_REG, 280 1.20 jmcneill }; 281 1.20 jmcneill 282 1.43 thorpej static const struct device_compatible_entry compat_data[] = { 283 1.43 thorpej { .compat = "allwinner,sun4i-a10-mmc", 284 1.43 thorpej .data = &sun4i_a10_mmc_config }, 285 1.43 thorpej { .compat = "allwinner,sun5i-a13-mmc", 286 1.43 thorpej .data = &sun5i_a13_mmc_config }, 287 1.43 thorpej { .compat = "allwinner,sun7i-a20-mmc", 288 1.43 thorpej .data = &sun7i_a20_mmc_config }, 289 1.43 thorpej { .compat = "allwinner,sun8i-a83t-emmc", 290 1.43 thorpej .data = &sun8i_a83t_emmc_config }, 291 1.43 thorpej { .compat = "allwinner,sun9i-a80-mmc", 292 1.43 thorpej .data = &sun9i_a80_mmc_config }, 293 1.43 thorpej { .compat = "allwinner,sun50i-a64-mmc", 294 1.43 thorpej .data = &sun50i_a64_mmc_config }, 295 1.43 thorpej { .compat = "allwinner,sun50i-a64-emmc", 296 1.43 thorpej .data = &sun50i_a64_emmc_config }, 297 1.43 thorpej { .compat = "allwinner,sun50i-h6-mmc", 298 1.43 thorpej .data = &sun50i_h6_mmc_config }, 299 1.43 thorpej { .compat = "allwinner,sun50i-h6-emmc", 300 1.43 thorpej .data = &sun50i_h6_emmc_config }, 301 1.43 thorpej 302 1.45 thorpej DEVICE_COMPAT_EOL 303 1.1 jmcneill }; 304 1.1 jmcneill 305 1.1 jmcneill static int 306 1.1 jmcneill sunxi_mmc_match(device_t parent, cfdata_t cf, void *aux) 307 1.1 jmcneill { 308 1.1 jmcneill struct fdt_attach_args * const faa = aux; 309 1.1 jmcneill 310 1.46 thorpej return of_compatible_match(faa->faa_phandle, compat_data); 311 1.1 jmcneill } 312 1.1 jmcneill 313 1.1 jmcneill static void 314 1.1 jmcneill sunxi_mmc_attach(device_t parent, device_t self, void *aux) 315 1.1 jmcneill { 316 1.1 jmcneill struct sunxi_mmc_softc * const sc = device_private(self); 317 1.1 jmcneill struct fdt_attach_args * const faa = aux; 318 1.1 jmcneill const int phandle = faa->faa_phandle; 319 1.1 jmcneill char intrstr[128]; 320 1.1 jmcneill bus_addr_t addr; 321 1.1 jmcneill bus_size_t size; 322 1.1 jmcneill 323 1.1 jmcneill if (fdtbus_get_reg(phandle, 0, &addr, &size) != 0) { 324 1.1 jmcneill aprint_error(": couldn't get registers\n"); 325 1.1 jmcneill return; 326 1.1 jmcneill } 327 1.1 jmcneill 328 1.1 jmcneill sc->sc_clk_ahb = fdtbus_clock_get(phandle, "ahb"); 329 1.1 jmcneill sc->sc_clk_mmc = fdtbus_clock_get(phandle, "mmc"); 330 1.1 jmcneill sc->sc_clk_output = fdtbus_clock_get(phandle, "output"); 331 1.1 jmcneill sc->sc_clk_sample = fdtbus_clock_get(phandle, "sample"); 332 1.1 jmcneill 333 1.1 jmcneill #if notyet 334 1.1 jmcneill if (sc->sc_clk_ahb == NULL || sc->sc_clk_mmc == NULL || 335 1.1 jmcneill sc->sc_clk_output == NULL || sc->sc_clk_sample == NULL) { 336 1.1 jmcneill #else 337 1.1 jmcneill if (sc->sc_clk_ahb == NULL || sc->sc_clk_mmc == NULL) { 338 1.1 jmcneill #endif 339 1.1 jmcneill aprint_error(": couldn't get clocks\n"); 340 1.1 jmcneill return; 341 1.1 jmcneill } 342 1.1 jmcneill 343 1.1 jmcneill sc->sc_rst_ahb = fdtbus_reset_get(phandle, "ahb"); 344 1.1 jmcneill 345 1.12 jmcneill sc->sc_pwrseq = fdtbus_mmc_pwrseq_get(phandle); 346 1.12 jmcneill 347 1.1 jmcneill if (clk_enable(sc->sc_clk_ahb) != 0 || 348 1.1 jmcneill clk_enable(sc->sc_clk_mmc) != 0) { 349 1.1 jmcneill aprint_error(": couldn't enable clocks\n"); 350 1.1 jmcneill return; 351 1.1 jmcneill } 352 1.1 jmcneill 353 1.5 jmcneill if (sc->sc_rst_ahb != NULL) { 354 1.5 jmcneill if (fdtbus_reset_deassert(sc->sc_rst_ahb) != 0) { 355 1.5 jmcneill aprint_error(": couldn't de-assert resets\n"); 356 1.5 jmcneill return; 357 1.5 jmcneill } 358 1.1 jmcneill } 359 1.1 jmcneill 360 1.1 jmcneill sc->sc_dev = self; 361 1.1 jmcneill sc->sc_phandle = phandle; 362 1.46 thorpej sc->sc_config = of_compatible_lookup(phandle, compat_data)->data; 363 1.1 jmcneill sc->sc_bst = faa->faa_bst; 364 1.1 jmcneill sc->sc_dmat = faa->faa_dmat; 365 1.1 jmcneill mutex_init(&sc->sc_intr_lock, MUTEX_DEFAULT, IPL_BIO); 366 1.38 jmcneill cv_init(&sc->sc_intr_cv, "sunximmcirq"); 367 1.1 jmcneill 368 1.1 jmcneill if (bus_space_map(sc->sc_bst, addr, size, 0, &sc->sc_bsh) != 0) { 369 1.1 jmcneill aprint_error(": couldn't map registers\n"); 370 1.1 jmcneill return; 371 1.1 jmcneill } 372 1.1 jmcneill 373 1.33 jmcneill sc->sc_reg_vmmc = fdtbus_regulator_acquire(phandle, "vmmc-supply"); 374 1.33 jmcneill if (sc->sc_reg_vmmc != NULL && fdtbus_regulator_enable(sc->sc_reg_vmmc)) { 375 1.33 jmcneill aprint_error(": couldn't enable vmmc-supply\n"); 376 1.33 jmcneill return; 377 1.33 jmcneill } 378 1.33 jmcneill 379 1.1 jmcneill aprint_naive("\n"); 380 1.1 jmcneill aprint_normal(": SD/MMC controller\n"); 381 1.1 jmcneill 382 1.29 jmcneill sc->sc_reg_vqmmc = fdtbus_regulator_acquire(phandle, "vqmmc-supply"); 383 1.29 jmcneill 384 1.1 jmcneill sc->sc_gpio_cd = fdtbus_gpio_acquire(phandle, "cd-gpios", 385 1.1 jmcneill GPIO_PIN_INPUT); 386 1.1 jmcneill sc->sc_gpio_wp = fdtbus_gpio_acquire(phandle, "wp-gpios", 387 1.1 jmcneill GPIO_PIN_INPUT); 388 1.1 jmcneill 389 1.1 jmcneill sc->sc_gpio_cd_inverted = of_hasprop(phandle, "cd-inverted") ? 0 : 1; 390 1.1 jmcneill sc->sc_gpio_wp_inverted = of_hasprop(phandle, "wp-inverted") ? 0 : 1; 391 1.1 jmcneill 392 1.17 jmcneill sc->sc_non_removable = of_hasprop(phandle, "non-removable"); 393 1.17 jmcneill sc->sc_broken_cd = of_hasprop(phandle, "broken-cd"); 394 1.17 jmcneill 395 1.23 jmcneill if (of_getprop_uint32(phandle, "max-frequency", &sc->sc_max_frequency)) 396 1.23 jmcneill sc->sc_max_frequency = 52000000; 397 1.23 jmcneill 398 1.14 jmcneill if (sunxi_mmc_dmabounce_setup(sc) != 0 || 399 1.14 jmcneill sunxi_mmc_idma_setup(sc) != 0) { 400 1.1 jmcneill aprint_error_dev(self, "failed to setup DMA\n"); 401 1.1 jmcneill return; 402 1.1 jmcneill } 403 1.1 jmcneill 404 1.1 jmcneill if (!fdtbus_intr_str(phandle, 0, intrstr, sizeof(intrstr))) { 405 1.1 jmcneill aprint_error_dev(self, "failed to decode interrupt\n"); 406 1.1 jmcneill return; 407 1.1 jmcneill } 408 1.1 jmcneill 409 1.42 jmcneill sc->sc_ih = fdtbus_intr_establish_xname(phandle, 0, IPL_BIO, 410 1.42 jmcneill FDT_INTR_MPSAFE, sunxi_mmc_intr, sc, device_xname(self)); 411 1.1 jmcneill if (sc->sc_ih == NULL) { 412 1.1 jmcneill aprint_error_dev(self, "failed to establish interrupt on %s\n", 413 1.1 jmcneill intrstr); 414 1.1 jmcneill return; 415 1.1 jmcneill } 416 1.1 jmcneill aprint_normal_dev(self, "interrupting on %s\n", intrstr); 417 1.1 jmcneill 418 1.1 jmcneill config_interrupts(self, sunxi_mmc_attach_i); 419 1.1 jmcneill } 420 1.1 jmcneill 421 1.1 jmcneill static int 422 1.14 jmcneill sunxi_mmc_dmabounce_setup(struct sunxi_mmc_softc *sc) 423 1.14 jmcneill { 424 1.14 jmcneill bus_dma_segment_t ds[1]; 425 1.14 jmcneill int error, rseg; 426 1.14 jmcneill 427 1.14 jmcneill sc->sc_dmabounce_buflen = sunxi_mmc_host_maxblklen(sc); 428 1.14 jmcneill error = bus_dmamem_alloc(sc->sc_dmat, sc->sc_dmabounce_buflen, 0, 429 1.14 jmcneill sc->sc_dmabounce_buflen, ds, 1, &rseg, BUS_DMA_WAITOK); 430 1.14 jmcneill if (error) 431 1.14 jmcneill return error; 432 1.14 jmcneill error = bus_dmamem_map(sc->sc_dmat, ds, 1, sc->sc_dmabounce_buflen, 433 1.14 jmcneill &sc->sc_dmabounce_buf, BUS_DMA_WAITOK); 434 1.14 jmcneill if (error) 435 1.14 jmcneill goto free; 436 1.14 jmcneill error = bus_dmamap_create(sc->sc_dmat, sc->sc_dmabounce_buflen, 1, 437 1.14 jmcneill sc->sc_dmabounce_buflen, 0, BUS_DMA_WAITOK, &sc->sc_dmabounce_map); 438 1.14 jmcneill if (error) 439 1.14 jmcneill goto unmap; 440 1.14 jmcneill error = bus_dmamap_load(sc->sc_dmat, sc->sc_dmabounce_map, 441 1.14 jmcneill sc->sc_dmabounce_buf, sc->sc_dmabounce_buflen, NULL, 442 1.14 jmcneill BUS_DMA_WAITOK); 443 1.14 jmcneill if (error) 444 1.14 jmcneill goto destroy; 445 1.14 jmcneill return 0; 446 1.14 jmcneill 447 1.14 jmcneill destroy: 448 1.14 jmcneill bus_dmamap_destroy(sc->sc_dmat, sc->sc_dmabounce_map); 449 1.14 jmcneill unmap: 450 1.14 jmcneill bus_dmamem_unmap(sc->sc_dmat, sc->sc_dmabounce_buf, 451 1.14 jmcneill sc->sc_dmabounce_buflen); 452 1.14 jmcneill free: 453 1.14 jmcneill bus_dmamem_free(sc->sc_dmat, ds, rseg); 454 1.14 jmcneill return error; 455 1.14 jmcneill } 456 1.14 jmcneill 457 1.14 jmcneill static int 458 1.1 jmcneill sunxi_mmc_idma_setup(struct sunxi_mmc_softc *sc) 459 1.1 jmcneill { 460 1.1 jmcneill int error; 461 1.1 jmcneill 462 1.1 jmcneill sc->sc_idma_ndesc = SUNXI_MMC_NDESC; 463 1.1 jmcneill sc->sc_idma_size = sizeof(struct sunxi_mmc_idma_descriptor) * 464 1.1 jmcneill sc->sc_idma_ndesc; 465 1.1 jmcneill error = bus_dmamem_alloc(sc->sc_dmat, sc->sc_idma_size, 0, 466 1.1 jmcneill sc->sc_idma_size, sc->sc_idma_segs, 1, 467 1.1 jmcneill &sc->sc_idma_nsegs, BUS_DMA_WAITOK); 468 1.1 jmcneill if (error) 469 1.1 jmcneill return error; 470 1.1 jmcneill error = bus_dmamem_map(sc->sc_dmat, sc->sc_idma_segs, 471 1.1 jmcneill sc->sc_idma_nsegs, sc->sc_idma_size, 472 1.1 jmcneill &sc->sc_idma_desc, BUS_DMA_WAITOK); 473 1.1 jmcneill if (error) 474 1.1 jmcneill goto free; 475 1.1 jmcneill error = bus_dmamap_create(sc->sc_dmat, sc->sc_idma_size, 1, 476 1.1 jmcneill sc->sc_idma_size, 0, BUS_DMA_WAITOK, &sc->sc_idma_map); 477 1.1 jmcneill if (error) 478 1.1 jmcneill goto unmap; 479 1.1 jmcneill error = bus_dmamap_load(sc->sc_dmat, sc->sc_idma_map, 480 1.1 jmcneill sc->sc_idma_desc, sc->sc_idma_size, NULL, BUS_DMA_WAITOK); 481 1.1 jmcneill if (error) 482 1.1 jmcneill goto destroy; 483 1.1 jmcneill return 0; 484 1.1 jmcneill 485 1.1 jmcneill destroy: 486 1.1 jmcneill bus_dmamap_destroy(sc->sc_dmat, sc->sc_idma_map); 487 1.1 jmcneill unmap: 488 1.1 jmcneill bus_dmamem_unmap(sc->sc_dmat, sc->sc_idma_desc, sc->sc_idma_size); 489 1.1 jmcneill free: 490 1.1 jmcneill bus_dmamem_free(sc->sc_dmat, sc->sc_idma_segs, sc->sc_idma_nsegs); 491 1.1 jmcneill return error; 492 1.1 jmcneill } 493 1.1 jmcneill 494 1.1 jmcneill static int 495 1.37 bouyer sunxi_mmc_set_clock(struct sunxi_mmc_softc *sc, u_int freq, bool ddr, bool dbl) 496 1.1 jmcneill { 497 1.3 jmcneill const struct sunxi_mmc_delay *delays; 498 1.24 jmcneill int error, timing = SUNXI_MMC_TIMING_400K; 499 1.3 jmcneill 500 1.23 jmcneill if (sc->sc_config->delays) { 501 1.23 jmcneill if (freq <= 400) { 502 1.23 jmcneill timing = SUNXI_MMC_TIMING_400K; 503 1.23 jmcneill } else if (freq <= 25000) { 504 1.23 jmcneill timing = SUNXI_MMC_TIMING_25M; 505 1.23 jmcneill } else if (freq <= 52000) { 506 1.23 jmcneill if (ddr) { 507 1.23 jmcneill timing = sc->sc_mmc_width == 8 ? 508 1.23 jmcneill SUNXI_MMC_TIMING_50M_DDR_8BIT : 509 1.23 jmcneill SUNXI_MMC_TIMING_50M_DDR; 510 1.23 jmcneill } else { 511 1.23 jmcneill timing = SUNXI_MMC_TIMING_50M; 512 1.23 jmcneill } 513 1.23 jmcneill } else 514 1.23 jmcneill return EINVAL; 515 1.23 jmcneill } 516 1.23 jmcneill if (sc->sc_max_frequency) { 517 1.23 jmcneill if (freq * 1000 > sc->sc_max_frequency) 518 1.23 jmcneill return EINVAL; 519 1.23 jmcneill } 520 1.3 jmcneill 521 1.37 bouyer error = clk_set_rate(sc->sc_clk_mmc, (freq * 1000) << dbl); 522 1.3 jmcneill if (error != 0) 523 1.3 jmcneill return error; 524 1.3 jmcneill 525 1.7 jmcneill if (sc->sc_config->delays == NULL) 526 1.7 jmcneill return 0; 527 1.7 jmcneill 528 1.7 jmcneill delays = &sc->sc_config->delays[timing]; 529 1.7 jmcneill 530 1.3 jmcneill if (sc->sc_clk_sample) { 531 1.3 jmcneill error = clk_set_rate(sc->sc_clk_sample, delays->sample_phase); 532 1.3 jmcneill if (error != 0) 533 1.3 jmcneill return error; 534 1.3 jmcneill } 535 1.3 jmcneill if (sc->sc_clk_output) { 536 1.3 jmcneill error = clk_set_rate(sc->sc_clk_output, delays->output_phase); 537 1.3 jmcneill if (error != 0) 538 1.3 jmcneill return error; 539 1.3 jmcneill } 540 1.3 jmcneill 541 1.3 jmcneill return 0; 542 1.1 jmcneill } 543 1.1 jmcneill 544 1.1 jmcneill static void 545 1.32 jmcneill sunxi_mmc_hw_reset(struct sunxi_mmc_softc *sc) 546 1.32 jmcneill { 547 1.32 jmcneill MMC_WRITE(sc, SUNXI_MMC_HWRST, 0); 548 1.32 jmcneill delay(1000); 549 1.32 jmcneill MMC_WRITE(sc, SUNXI_MMC_HWRST, 1); 550 1.32 jmcneill delay(1000); 551 1.32 jmcneill } 552 1.32 jmcneill 553 1.32 jmcneill static void 554 1.1 jmcneill sunxi_mmc_attach_i(device_t self) 555 1.1 jmcneill { 556 1.1 jmcneill struct sunxi_mmc_softc *sc = device_private(self); 557 1.23 jmcneill const u_int flags = sc->sc_config->flags; 558 1.1 jmcneill struct sdmmcbus_attach_args saa; 559 1.1 jmcneill uint32_t width; 560 1.41 macallan const bool supports_hs200 = 561 1.41 macallan of_hasprop(sc->sc_phandle, "mmc-hs200-1_2v") | 562 1.41 macallan of_hasprop(sc->sc_phandle, "mmc-hs200-1_8v"); 563 1.41 macallan 564 1.41 macallan const bool supports_ddr = 565 1.41 macallan of_hasprop(sc->sc_phandle, "mmc-ddr-1_2v") | 566 1.41 macallan of_hasprop(sc->sc_phandle, "mmc-ddr-1_8v") | 567 1.41 macallan of_hasprop(sc->sc_phandle, "mmc-ddr-3_3v"); 568 1.1 jmcneill 569 1.12 jmcneill if (sc->sc_pwrseq) 570 1.12 jmcneill fdtbus_mmc_pwrseq_pre_power_on(sc->sc_pwrseq); 571 1.12 jmcneill 572 1.32 jmcneill if (of_hasprop(sc->sc_phandle, "cap-mmc-hw-reset")) 573 1.32 jmcneill sunxi_mmc_hw_reset(sc); 574 1.32 jmcneill 575 1.1 jmcneill sunxi_mmc_host_reset(sc); 576 1.1 jmcneill sunxi_mmc_bus_width(sc, 1); 577 1.37 bouyer sunxi_mmc_set_clock(sc, 400, false, false); 578 1.1 jmcneill 579 1.12 jmcneill if (sc->sc_pwrseq) 580 1.12 jmcneill fdtbus_mmc_pwrseq_post_power_on(sc->sc_pwrseq); 581 1.12 jmcneill 582 1.1 jmcneill if (of_getprop_uint32(sc->sc_phandle, "bus-width", &width) != 0) 583 1.1 jmcneill width = 4; 584 1.1 jmcneill 585 1.1 jmcneill memset(&saa, 0, sizeof(saa)); 586 1.1 jmcneill saa.saa_busname = "sdmmc"; 587 1.1 jmcneill saa.saa_sct = &sunxi_mmc_chip_functions; 588 1.1 jmcneill saa.saa_sch = sc; 589 1.1 jmcneill saa.saa_dmat = sc->sc_dmat; 590 1.1 jmcneill saa.saa_clkmin = 400; 591 1.23 jmcneill saa.saa_clkmax = sc->sc_max_frequency / 1000; 592 1.1 jmcneill saa.saa_caps = SMC_CAPS_DMA | 593 1.1 jmcneill SMC_CAPS_MULTI_SEG_DMA | 594 1.1 jmcneill SMC_CAPS_AUTO_STOP | 595 1.1 jmcneill SMC_CAPS_SD_HIGHSPEED | 596 1.40 jmcneill SMC_CAPS_MMC_HIGHSPEED; 597 1.25 jmcneill 598 1.41 macallan if ((sc->sc_config->delays || (flags & SUNXI_MMC_FLAG_NEW_TIMINGS)) && 599 1.41 macallan supports_ddr) 600 1.25 jmcneill saa.saa_caps |= SMC_CAPS_MMC_DDR52; 601 1.25 jmcneill 602 1.41 macallan if ((flags & SUNXI_MMC_FLAG_HS200) != 0 && supports_hs200) 603 1.23 jmcneill saa.saa_caps |= SMC_CAPS_MMC_HS200; 604 1.25 jmcneill 605 1.1 jmcneill if (width == 4) 606 1.1 jmcneill saa.saa_caps |= SMC_CAPS_4BIT_MODE; 607 1.1 jmcneill if (width == 8) 608 1.1 jmcneill saa.saa_caps |= SMC_CAPS_8BIT_MODE; 609 1.1 jmcneill 610 1.1 jmcneill if (sc->sc_gpio_cd) 611 1.1 jmcneill saa.saa_caps |= SMC_CAPS_POLL_CARD_DET; 612 1.1 jmcneill 613 1.48 thorpej sc->sc_sdmmc_dev = config_found(self, &saa, NULL, CFARGS_NONE); 614 1.1 jmcneill } 615 1.1 jmcneill 616 1.1 jmcneill static int 617 1.1 jmcneill sunxi_mmc_intr(void *priv) 618 1.1 jmcneill { 619 1.1 jmcneill struct sunxi_mmc_softc *sc = priv; 620 1.38 jmcneill struct sdmmc_command *cmd; 621 1.38 jmcneill uint32_t idst, mint, imask; 622 1.1 jmcneill 623 1.1 jmcneill mutex_enter(&sc->sc_intr_lock); 624 1.1 jmcneill idst = MMC_READ(sc, SUNXI_MMC_IDST); 625 1.38 jmcneill mint = MMC_READ(sc, SUNXI_MMC_MINT); 626 1.38 jmcneill if (!idst && !mint) { 627 1.1 jmcneill mutex_exit(&sc->sc_intr_lock); 628 1.1 jmcneill return 0; 629 1.1 jmcneill } 630 1.1 jmcneill MMC_WRITE(sc, SUNXI_MMC_IDST, idst); 631 1.38 jmcneill MMC_WRITE(sc, SUNXI_MMC_RINT, mint); 632 1.38 jmcneill 633 1.38 jmcneill cmd = sc->sc_curcmd; 634 1.1 jmcneill 635 1.38 jmcneill DPRINTF(sc->sc_dev, "mmc intr idst=%08X mint=%08X\n", 636 1.38 jmcneill idst, mint); 637 1.38 jmcneill 638 1.38 jmcneill /* Handle SDIO card interrupt */ 639 1.38 jmcneill if ((mint & SUNXI_MMC_INT_SDIO_INT) != 0) { 640 1.38 jmcneill imask = MMC_READ(sc, SUNXI_MMC_IMASK); 641 1.38 jmcneill MMC_WRITE(sc, SUNXI_MMC_IMASK, imask & ~SUNXI_MMC_INT_SDIO_INT); 642 1.38 jmcneill sdmmc_card_intr(sc->sc_sdmmc_dev); 643 1.38 jmcneill } 644 1.1 jmcneill 645 1.38 jmcneill /* Error interrupts take priority over command and transfer interrupts */ 646 1.38 jmcneill if (cmd != NULL && (mint & SUNXI_MMC_INT_ERROR) != 0) { 647 1.38 jmcneill imask = MMC_READ(sc, SUNXI_MMC_IMASK); 648 1.38 jmcneill MMC_WRITE(sc, SUNXI_MMC_IMASK, imask & ~SUNXI_MMC_INT_ERROR); 649 1.38 jmcneill if ((mint & SUNXI_MMC_INT_RESP_TIMEOUT) != 0) { 650 1.38 jmcneill cmd->c_error = ETIMEDOUT; 651 1.38 jmcneill /* Wait for command to complete */ 652 1.38 jmcneill sc->sc_wait_data = sc->sc_wait_dma = false; 653 1.38 jmcneill if (cmd->c_opcode != SD_IO_SEND_OP_COND && 654 1.39 jmcneill cmd->c_opcode != SD_IO_RW_DIRECT && 655 1.39 jmcneill !ISSET(cmd->c_flags, SCF_TOUT_OK)) 656 1.38 jmcneill device_printf(sc->sc_dev, "host controller timeout, mint=0x%08x\n", mint); 657 1.38 jmcneill } else { 658 1.38 jmcneill device_printf(sc->sc_dev, "host controller error, mint=0x%08x\n", mint); 659 1.38 jmcneill cmd->c_error = EIO; 660 1.38 jmcneill SET(cmd->c_flags, SCF_ITSDONE); 661 1.38 jmcneill goto done; 662 1.38 jmcneill } 663 1.38 jmcneill } 664 1.38 jmcneill 665 1.38 jmcneill if (cmd != NULL && (idst & SUNXI_MMC_IDST_RECEIVE_INT) != 0) { 666 1.22 jmcneill MMC_WRITE(sc, SUNXI_MMC_IDIE, 0); 667 1.38 jmcneill if (sc->sc_wait_dma == false) 668 1.38 jmcneill device_printf(sc->sc_dev, "unexpected DMA receive interrupt\n"); 669 1.38 jmcneill sc->sc_wait_dma = false; 670 1.1 jmcneill } 671 1.1 jmcneill 672 1.38 jmcneill if (cmd != NULL && (mint & SUNXI_MMC_INT_CMD_DONE) != 0) { 673 1.22 jmcneill imask = MMC_READ(sc, SUNXI_MMC_IMASK); 674 1.38 jmcneill MMC_WRITE(sc, SUNXI_MMC_IMASK, imask & ~SUNXI_MMC_INT_CMD_DONE); 675 1.38 jmcneill if (sc->sc_wait_cmd == false) 676 1.38 jmcneill device_printf(sc->sc_dev, "unexpected command complete interrupt\n"); 677 1.38 jmcneill sc->sc_wait_cmd = false; 678 1.1 jmcneill } 679 1.1 jmcneill 680 1.38 jmcneill const uint32_t dmadone_mask = SUNXI_MMC_INT_AUTO_CMD_DONE|SUNXI_MMC_INT_DATA_OVER; 681 1.38 jmcneill if (cmd != NULL && (mint & dmadone_mask) != 0) { 682 1.35 jmcneill imask = MMC_READ(sc, SUNXI_MMC_IMASK); 683 1.38 jmcneill MMC_WRITE(sc, SUNXI_MMC_IMASK, imask & ~dmadone_mask); 684 1.38 jmcneill if (sc->sc_wait_data == false) 685 1.38 jmcneill device_printf(sc->sc_dev, "unexpected data complete interrupt\n"); 686 1.38 jmcneill sc->sc_wait_data = false; 687 1.38 jmcneill } 688 1.38 jmcneill 689 1.38 jmcneill if (cmd != NULL && 690 1.38 jmcneill sc->sc_wait_dma == false && 691 1.38 jmcneill sc->sc_wait_cmd == false && 692 1.38 jmcneill sc->sc_wait_data == false) { 693 1.38 jmcneill SET(cmd->c_flags, SCF_ITSDONE); 694 1.38 jmcneill } 695 1.38 jmcneill 696 1.38 jmcneill done: 697 1.38 jmcneill if (cmd != NULL && ISSET(cmd->c_flags, SCF_ITSDONE)) { 698 1.38 jmcneill cv_broadcast(&sc->sc_intr_cv); 699 1.11 jmcneill } 700 1.11 jmcneill 701 1.1 jmcneill mutex_exit(&sc->sc_intr_lock); 702 1.1 jmcneill 703 1.1 jmcneill return 1; 704 1.1 jmcneill } 705 1.1 jmcneill 706 1.1 jmcneill static int 707 1.1 jmcneill sunxi_mmc_host_reset(sdmmc_chipset_handle_t sch) 708 1.1 jmcneill { 709 1.1 jmcneill struct sunxi_mmc_softc *sc = sch; 710 1.22 jmcneill uint32_t gctrl; 711 1.1 jmcneill int retry = 1000; 712 1.1 jmcneill 713 1.13 jmcneill DPRINTF(sc->sc_dev, "host reset\n"); 714 1.1 jmcneill 715 1.22 jmcneill gctrl = MMC_READ(sc, SUNXI_MMC_GCTRL); 716 1.22 jmcneill gctrl |= SUNXI_MMC_GCTRL_RESET; 717 1.22 jmcneill MMC_WRITE(sc, SUNXI_MMC_GCTRL, gctrl); 718 1.1 jmcneill while (--retry > 0) { 719 1.1 jmcneill if (!(MMC_READ(sc, SUNXI_MMC_GCTRL) & SUNXI_MMC_GCTRL_RESET)) 720 1.1 jmcneill break; 721 1.1 jmcneill delay(100); 722 1.1 jmcneill } 723 1.1 jmcneill 724 1.1 jmcneill MMC_WRITE(sc, SUNXI_MMC_TIMEOUT, 0xffffffff); 725 1.1 jmcneill 726 1.22 jmcneill MMC_WRITE(sc, SUNXI_MMC_IMASK, 0); 727 1.22 jmcneill 728 1.22 jmcneill MMC_WRITE(sc, SUNXI_MMC_RINT, 0xffffffff); 729 1.1 jmcneill 730 1.22 jmcneill gctrl = MMC_READ(sc, SUNXI_MMC_GCTRL); 731 1.22 jmcneill gctrl |= SUNXI_MMC_GCTRL_INTEN; 732 1.22 jmcneill gctrl &= ~SUNXI_MMC_GCTRL_WAIT_MEM_ACCESS_DONE; 733 1.22 jmcneill gctrl &= ~SUNXI_MMC_GCTRL_ACCESS_BY_AHB; 734 1.22 jmcneill MMC_WRITE(sc, SUNXI_MMC_GCTRL, gctrl); 735 1.1 jmcneill 736 1.1 jmcneill return 0; 737 1.1 jmcneill } 738 1.1 jmcneill 739 1.1 jmcneill static uint32_t 740 1.1 jmcneill sunxi_mmc_host_ocr(sdmmc_chipset_handle_t sch) 741 1.1 jmcneill { 742 1.1 jmcneill return MMC_OCR_3_2V_3_3V | MMC_OCR_3_3V_3_4V | MMC_OCR_HCS; 743 1.1 jmcneill } 744 1.1 jmcneill 745 1.1 jmcneill static int 746 1.1 jmcneill sunxi_mmc_host_maxblklen(sdmmc_chipset_handle_t sch) 747 1.1 jmcneill { 748 1.1 jmcneill return 8192; 749 1.1 jmcneill } 750 1.1 jmcneill 751 1.1 jmcneill static int 752 1.1 jmcneill sunxi_mmc_card_detect(sdmmc_chipset_handle_t sch) 753 1.1 jmcneill { 754 1.1 jmcneill struct sunxi_mmc_softc *sc = sch; 755 1.1 jmcneill 756 1.17 jmcneill if (sc->sc_non_removable || sc->sc_broken_cd) { 757 1.17 jmcneill /* 758 1.17 jmcneill * Non-removable or broken card detect flag set in 759 1.17 jmcneill * DT, assume always present 760 1.17 jmcneill */ 761 1.17 jmcneill return 1; 762 1.17 jmcneill } else if (sc->sc_gpio_cd != NULL) { 763 1.17 jmcneill /* Use card detect GPIO */ 764 1.1 jmcneill int v = 0, i; 765 1.1 jmcneill for (i = 0; i < 5; i++) { 766 1.1 jmcneill v += (fdtbus_gpio_read(sc->sc_gpio_cd) ^ 767 1.1 jmcneill sc->sc_gpio_cd_inverted); 768 1.1 jmcneill delay(1000); 769 1.1 jmcneill } 770 1.1 jmcneill if (v == 5) 771 1.1 jmcneill sc->sc_mmc_present = 0; 772 1.1 jmcneill else if (v == 0) 773 1.1 jmcneill sc->sc_mmc_present = 1; 774 1.1 jmcneill return sc->sc_mmc_present; 775 1.17 jmcneill } else { 776 1.17 jmcneill /* Use CARD_PRESENT field of SD_STATUS register */ 777 1.17 jmcneill const uint32_t present = MMC_READ(sc, SUNXI_MMC_STATUS) & 778 1.17 jmcneill SUNXI_MMC_STATUS_CARD_PRESENT; 779 1.17 jmcneill return present != 0; 780 1.1 jmcneill } 781 1.1 jmcneill } 782 1.1 jmcneill 783 1.1 jmcneill static int 784 1.1 jmcneill sunxi_mmc_write_protect(sdmmc_chipset_handle_t sch) 785 1.1 jmcneill { 786 1.1 jmcneill struct sunxi_mmc_softc *sc = sch; 787 1.1 jmcneill 788 1.1 jmcneill if (sc->sc_gpio_wp == NULL) { 789 1.1 jmcneill return 0; /* no write protect pin, assume rw */ 790 1.1 jmcneill } else { 791 1.1 jmcneill return fdtbus_gpio_read(sc->sc_gpio_wp) ^ 792 1.1 jmcneill sc->sc_gpio_wp_inverted; 793 1.1 jmcneill } 794 1.1 jmcneill } 795 1.1 jmcneill 796 1.1 jmcneill static int 797 1.1 jmcneill sunxi_mmc_bus_power(sdmmc_chipset_handle_t sch, uint32_t ocr) 798 1.1 jmcneill { 799 1.1 jmcneill return 0; 800 1.1 jmcneill } 801 1.1 jmcneill 802 1.1 jmcneill static int 803 1.1 jmcneill sunxi_mmc_update_clock(struct sunxi_mmc_softc *sc) 804 1.1 jmcneill { 805 1.1 jmcneill uint32_t cmd; 806 1.1 jmcneill int retry; 807 1.1 jmcneill 808 1.13 jmcneill DPRINTF(sc->sc_dev, "update clock\n"); 809 1.1 jmcneill 810 1.1 jmcneill cmd = SUNXI_MMC_CMD_START | 811 1.1 jmcneill SUNXI_MMC_CMD_UPCLK_ONLY | 812 1.1 jmcneill SUNXI_MMC_CMD_WAIT_PRE_OVER; 813 1.1 jmcneill MMC_WRITE(sc, SUNXI_MMC_CMD, cmd); 814 1.31 jmcneill retry = 100000; 815 1.1 jmcneill while (--retry > 0) { 816 1.1 jmcneill if (!(MMC_READ(sc, SUNXI_MMC_CMD) & SUNXI_MMC_CMD_START)) 817 1.1 jmcneill break; 818 1.1 jmcneill delay(10); 819 1.1 jmcneill } 820 1.1 jmcneill 821 1.1 jmcneill if (retry == 0) { 822 1.1 jmcneill aprint_error_dev(sc->sc_dev, "timeout updating clock\n"); 823 1.13 jmcneill DPRINTF(sc->sc_dev, "GCTRL: 0x%08x\n", 824 1.1 jmcneill MMC_READ(sc, SUNXI_MMC_GCTRL)); 825 1.13 jmcneill DPRINTF(sc->sc_dev, "CLKCR: 0x%08x\n", 826 1.1 jmcneill MMC_READ(sc, SUNXI_MMC_CLKCR)); 827 1.13 jmcneill DPRINTF(sc->sc_dev, "TIMEOUT: 0x%08x\n", 828 1.1 jmcneill MMC_READ(sc, SUNXI_MMC_TIMEOUT)); 829 1.13 jmcneill DPRINTF(sc->sc_dev, "WIDTH: 0x%08x\n", 830 1.1 jmcneill MMC_READ(sc, SUNXI_MMC_WIDTH)); 831 1.13 jmcneill DPRINTF(sc->sc_dev, "CMD: 0x%08x\n", 832 1.1 jmcneill MMC_READ(sc, SUNXI_MMC_CMD)); 833 1.13 jmcneill DPRINTF(sc->sc_dev, "MINT: 0x%08x\n", 834 1.1 jmcneill MMC_READ(sc, SUNXI_MMC_MINT)); 835 1.13 jmcneill DPRINTF(sc->sc_dev, "RINT: 0x%08x\n", 836 1.1 jmcneill MMC_READ(sc, SUNXI_MMC_RINT)); 837 1.13 jmcneill DPRINTF(sc->sc_dev, "STATUS: 0x%08x\n", 838 1.1 jmcneill MMC_READ(sc, SUNXI_MMC_STATUS)); 839 1.1 jmcneill return ETIMEDOUT; 840 1.1 jmcneill } 841 1.1 jmcneill 842 1.1 jmcneill return 0; 843 1.1 jmcneill } 844 1.1 jmcneill 845 1.1 jmcneill static int 846 1.3 jmcneill sunxi_mmc_bus_clock(sdmmc_chipset_handle_t sch, int freq, bool ddr) 847 1.1 jmcneill { 848 1.1 jmcneill struct sunxi_mmc_softc *sc = sch; 849 1.7 jmcneill uint32_t clkcr, gctrl, ntsr; 850 1.7 jmcneill const u_int flags = sc->sc_config->flags; 851 1.37 bouyer bool dbl = 0; 852 1.1 jmcneill 853 1.1 jmcneill clkcr = MMC_READ(sc, SUNXI_MMC_CLKCR); 854 1.1 jmcneill if (clkcr & SUNXI_MMC_CLKCR_CARDCLKON) { 855 1.1 jmcneill clkcr &= ~SUNXI_MMC_CLKCR_CARDCLKON; 856 1.7 jmcneill if (flags & SUNXI_MMC_CLKCR_MASK_DATA0) 857 1.7 jmcneill clkcr |= SUNXI_MMC_CLKCR_MASK_DATA0; 858 1.1 jmcneill MMC_WRITE(sc, SUNXI_MMC_CLKCR, clkcr); 859 1.1 jmcneill if (sunxi_mmc_update_clock(sc) != 0) 860 1.1 jmcneill return 1; 861 1.7 jmcneill if (flags & SUNXI_MMC_CLKCR_MASK_DATA0) { 862 1.7 jmcneill clkcr = MMC_READ(sc, SUNXI_MMC_CLKCR); 863 1.7 jmcneill clkcr &= ~SUNXI_MMC_CLKCR_MASK_DATA0; 864 1.7 jmcneill MMC_WRITE(sc, SUNXI_MMC_CLKCR, clkcr); 865 1.7 jmcneill } 866 1.1 jmcneill } 867 1.1 jmcneill 868 1.1 jmcneill if (freq) { 869 1.37 bouyer /* For 8bits ddr in old timing modes, and all ddr in new 870 1.37 bouyer * timing modes, the module clock has to be 2x the card clock. 871 1.37 bouyer */ 872 1.37 bouyer if (ddr && ((flags & SUNXI_MMC_FLAG_NEW_TIMINGS) || 873 1.37 bouyer sc->sc_mmc_width == 8)) 874 1.37 bouyer dbl = 1; 875 1.1 jmcneill 876 1.1 jmcneill clkcr &= ~SUNXI_MMC_CLKCR_DIV; 877 1.37 bouyer clkcr |= __SHIFTIN(dbl, SUNXI_MMC_CLKCR_DIV); 878 1.1 jmcneill MMC_WRITE(sc, SUNXI_MMC_CLKCR, clkcr); 879 1.7 jmcneill 880 1.7 jmcneill if (flags & SUNXI_MMC_FLAG_NEW_TIMINGS) { 881 1.7 jmcneill ntsr = MMC_READ(sc, SUNXI_MMC_NTSR); 882 1.7 jmcneill ntsr |= SUNXI_MMC_NTSR_MODE_SELECT; 883 1.7 jmcneill MMC_WRITE(sc, SUNXI_MMC_NTSR, ntsr); 884 1.7 jmcneill } 885 1.7 jmcneill 886 1.7 jmcneill if (flags & SUNXI_MMC_FLAG_CALIB_REG) 887 1.7 jmcneill MMC_WRITE(sc, SUNXI_MMC_SAMP_DL, SUNXI_MMC_SAMP_DL_SW_EN); 888 1.7 jmcneill 889 1.1 jmcneill if (sunxi_mmc_update_clock(sc) != 0) 890 1.1 jmcneill return 1; 891 1.1 jmcneill 892 1.3 jmcneill gctrl = MMC_READ(sc, SUNXI_MMC_GCTRL); 893 1.3 jmcneill if (ddr) 894 1.3 jmcneill gctrl |= SUNXI_MMC_GCTRL_DDR_MODE; 895 1.3 jmcneill else 896 1.3 jmcneill gctrl &= ~SUNXI_MMC_GCTRL_DDR_MODE; 897 1.3 jmcneill MMC_WRITE(sc, SUNXI_MMC_GCTRL, gctrl); 898 1.3 jmcneill 899 1.37 bouyer if (sunxi_mmc_set_clock(sc, freq, ddr, dbl) != 0) 900 1.1 jmcneill return 1; 901 1.1 jmcneill 902 1.1 jmcneill clkcr |= SUNXI_MMC_CLKCR_CARDCLKON; 903 1.7 jmcneill if (flags & SUNXI_MMC_CLKCR_MASK_DATA0) 904 1.7 jmcneill clkcr |= SUNXI_MMC_CLKCR_MASK_DATA0; 905 1.1 jmcneill MMC_WRITE(sc, SUNXI_MMC_CLKCR, clkcr); 906 1.1 jmcneill if (sunxi_mmc_update_clock(sc) != 0) 907 1.1 jmcneill return 1; 908 1.7 jmcneill if (flags & SUNXI_MMC_CLKCR_MASK_DATA0) { 909 1.7 jmcneill clkcr = MMC_READ(sc, SUNXI_MMC_CLKCR); 910 1.7 jmcneill clkcr &= ~SUNXI_MMC_CLKCR_MASK_DATA0; 911 1.7 jmcneill MMC_WRITE(sc, SUNXI_MMC_CLKCR, clkcr); 912 1.7 jmcneill } 913 1.1 jmcneill } 914 1.1 jmcneill 915 1.1 jmcneill return 0; 916 1.1 jmcneill } 917 1.1 jmcneill 918 1.1 jmcneill static int 919 1.1 jmcneill sunxi_mmc_bus_width(sdmmc_chipset_handle_t sch, int width) 920 1.1 jmcneill { 921 1.1 jmcneill struct sunxi_mmc_softc *sc = sch; 922 1.1 jmcneill 923 1.13 jmcneill DPRINTF(sc->sc_dev, "width = %d\n", width); 924 1.1 jmcneill 925 1.1 jmcneill switch (width) { 926 1.1 jmcneill case 1: 927 1.1 jmcneill MMC_WRITE(sc, SUNXI_MMC_WIDTH, SUNXI_MMC_WIDTH_1); 928 1.1 jmcneill break; 929 1.1 jmcneill case 4: 930 1.1 jmcneill MMC_WRITE(sc, SUNXI_MMC_WIDTH, SUNXI_MMC_WIDTH_4); 931 1.1 jmcneill break; 932 1.1 jmcneill case 8: 933 1.1 jmcneill MMC_WRITE(sc, SUNXI_MMC_WIDTH, SUNXI_MMC_WIDTH_8); 934 1.1 jmcneill break; 935 1.1 jmcneill default: 936 1.1 jmcneill return 1; 937 1.1 jmcneill } 938 1.1 jmcneill 939 1.1 jmcneill sc->sc_mmc_width = width; 940 1.1 jmcneill 941 1.1 jmcneill return 0; 942 1.1 jmcneill } 943 1.1 jmcneill 944 1.1 jmcneill static int 945 1.1 jmcneill sunxi_mmc_bus_rod(sdmmc_chipset_handle_t sch, int on) 946 1.1 jmcneill { 947 1.1 jmcneill return -1; 948 1.1 jmcneill } 949 1.1 jmcneill 950 1.1 jmcneill static int 951 1.3 jmcneill sunxi_mmc_signal_voltage(sdmmc_chipset_handle_t sch, int signal_voltage) 952 1.3 jmcneill { 953 1.3 jmcneill struct sunxi_mmc_softc *sc = sch; 954 1.3 jmcneill u_int uvol; 955 1.3 jmcneill int error; 956 1.3 jmcneill 957 1.3 jmcneill if (sc->sc_reg_vqmmc == NULL) 958 1.3 jmcneill return 0; 959 1.3 jmcneill 960 1.3 jmcneill switch (signal_voltage) { 961 1.3 jmcneill case SDMMC_SIGNAL_VOLTAGE_330: 962 1.3 jmcneill uvol = 3300000; 963 1.3 jmcneill break; 964 1.3 jmcneill case SDMMC_SIGNAL_VOLTAGE_180: 965 1.3 jmcneill uvol = 1800000; 966 1.3 jmcneill break; 967 1.3 jmcneill default: 968 1.3 jmcneill return EINVAL; 969 1.3 jmcneill } 970 1.3 jmcneill 971 1.30 jmcneill error = fdtbus_regulator_supports_voltage(sc->sc_reg_vqmmc, uvol, uvol); 972 1.30 jmcneill if (error != 0) 973 1.30 jmcneill return 0; 974 1.30 jmcneill 975 1.3 jmcneill error = fdtbus_regulator_set_voltage(sc->sc_reg_vqmmc, uvol, uvol); 976 1.3 jmcneill if (error != 0) 977 1.3 jmcneill return error; 978 1.3 jmcneill 979 1.3 jmcneill return fdtbus_regulator_enable(sc->sc_reg_vqmmc); 980 1.3 jmcneill } 981 1.3 jmcneill 982 1.3 jmcneill static int 983 1.23 jmcneill sunxi_mmc_execute_tuning(sdmmc_chipset_handle_t sch, int timing) 984 1.23 jmcneill { 985 1.23 jmcneill switch (timing) { 986 1.23 jmcneill case SDMMC_TIMING_MMC_HS200: 987 1.23 jmcneill break; 988 1.23 jmcneill default: 989 1.23 jmcneill return EINVAL; 990 1.23 jmcneill } 991 1.23 jmcneill 992 1.23 jmcneill return 0; 993 1.23 jmcneill } 994 1.23 jmcneill 995 1.23 jmcneill static int 996 1.1 jmcneill sunxi_mmc_dma_prepare(struct sunxi_mmc_softc *sc, struct sdmmc_command *cmd) 997 1.1 jmcneill { 998 1.1 jmcneill struct sunxi_mmc_idma_descriptor *dma = sc->sc_idma_desc; 999 1.1 jmcneill bus_addr_t desc_paddr = sc->sc_idma_map->dm_segs[0].ds_addr; 1000 1.14 jmcneill bus_dmamap_t map; 1001 1.1 jmcneill bus_size_t off; 1002 1.1 jmcneill int desc, resid, seg; 1003 1.1 jmcneill uint32_t val; 1004 1.1 jmcneill 1005 1.14 jmcneill /* 1006 1.14 jmcneill * If the command includes a dma map use it, otherwise we need to 1007 1.14 jmcneill * bounce. This can happen for SDIO IO_RW_EXTENDED (CMD53) commands. 1008 1.14 jmcneill */ 1009 1.14 jmcneill if (cmd->c_dmamap) { 1010 1.14 jmcneill map = cmd->c_dmamap; 1011 1.14 jmcneill } else { 1012 1.14 jmcneill if (cmd->c_datalen > sc->sc_dmabounce_buflen) 1013 1.14 jmcneill return E2BIG; 1014 1.14 jmcneill map = sc->sc_dmabounce_map; 1015 1.14 jmcneill 1016 1.15 jmcneill if (ISSET(cmd->c_flags, SCF_CMD_READ)) { 1017 1.15 jmcneill memset(sc->sc_dmabounce_buf, 0, cmd->c_datalen); 1018 1.15 jmcneill bus_dmamap_sync(sc->sc_dmat, sc->sc_dmabounce_map, 1019 1.15 jmcneill 0, cmd->c_datalen, BUS_DMASYNC_PREREAD); 1020 1.15 jmcneill } else { 1021 1.14 jmcneill memcpy(sc->sc_dmabounce_buf, cmd->c_data, 1022 1.14 jmcneill cmd->c_datalen); 1023 1.14 jmcneill bus_dmamap_sync(sc->sc_dmat, sc->sc_dmabounce_map, 1024 1.14 jmcneill 0, cmd->c_datalen, BUS_DMASYNC_PREWRITE); 1025 1.14 jmcneill } 1026 1.14 jmcneill } 1027 1.14 jmcneill 1028 1.1 jmcneill desc = 0; 1029 1.14 jmcneill for (seg = 0; seg < map->dm_nsegs; seg++) { 1030 1.14 jmcneill bus_addr_t paddr = map->dm_segs[seg].ds_addr; 1031 1.14 jmcneill bus_size_t len = map->dm_segs[seg].ds_len; 1032 1.27 riastrad resid = uimin(len, cmd->c_resid); 1033 1.1 jmcneill off = 0; 1034 1.1 jmcneill while (resid > 0) { 1035 1.1 jmcneill if (desc == sc->sc_idma_ndesc) 1036 1.1 jmcneill break; 1037 1.27 riastrad len = uimin(sc->sc_config->idma_xferlen, resid); 1038 1.26 jmcneill dma[desc].dma_buf_size = htole32(len); 1039 1.1 jmcneill dma[desc].dma_buf_addr = htole32(paddr + off); 1040 1.1 jmcneill dma[desc].dma_config = htole32(SUNXI_MMC_IDMA_CONFIG_CH | 1041 1.1 jmcneill SUNXI_MMC_IDMA_CONFIG_OWN); 1042 1.1 jmcneill cmd->c_resid -= len; 1043 1.1 jmcneill resid -= len; 1044 1.1 jmcneill off += len; 1045 1.1 jmcneill if (desc == 0) { 1046 1.1 jmcneill dma[desc].dma_config |= htole32(SUNXI_MMC_IDMA_CONFIG_FD); 1047 1.1 jmcneill } 1048 1.1 jmcneill if (cmd->c_resid == 0) { 1049 1.1 jmcneill dma[desc].dma_config |= htole32(SUNXI_MMC_IDMA_CONFIG_LD); 1050 1.1 jmcneill dma[desc].dma_config |= htole32(SUNXI_MMC_IDMA_CONFIG_ER); 1051 1.1 jmcneill dma[desc].dma_next = 0; 1052 1.1 jmcneill } else { 1053 1.1 jmcneill dma[desc].dma_config |= 1054 1.1 jmcneill htole32(SUNXI_MMC_IDMA_CONFIG_DIC); 1055 1.1 jmcneill dma[desc].dma_next = htole32( 1056 1.1 jmcneill desc_paddr + ((desc+1) * 1057 1.1 jmcneill sizeof(struct sunxi_mmc_idma_descriptor))); 1058 1.1 jmcneill } 1059 1.1 jmcneill ++desc; 1060 1.1 jmcneill } 1061 1.1 jmcneill } 1062 1.1 jmcneill if (desc == sc->sc_idma_ndesc) { 1063 1.1 jmcneill aprint_error_dev(sc->sc_dev, 1064 1.21 ryo "not enough descriptors for %d byte transfer! " 1065 1.21 ryo "there are %u segments with a max xfer length of %u\n", 1066 1.21 ryo cmd->c_datalen, map->dm_nsegs, sc->sc_config->idma_xferlen); 1067 1.1 jmcneill return EIO; 1068 1.1 jmcneill } 1069 1.1 jmcneill 1070 1.1 jmcneill bus_dmamap_sync(sc->sc_dmat, sc->sc_idma_map, 0, 1071 1.1 jmcneill sc->sc_idma_size, BUS_DMASYNC_PREWRITE); 1072 1.1 jmcneill 1073 1.22 jmcneill MMC_WRITE(sc, SUNXI_MMC_DLBA, desc_paddr); 1074 1.22 jmcneill MMC_WRITE(sc, SUNXI_MMC_FTRGLEVEL, sc->sc_config->dma_ftrglevel); 1075 1.22 jmcneill 1076 1.1 jmcneill val = MMC_READ(sc, SUNXI_MMC_GCTRL); 1077 1.1 jmcneill val |= SUNXI_MMC_GCTRL_DMAEN; 1078 1.1 jmcneill MMC_WRITE(sc, SUNXI_MMC_GCTRL, val); 1079 1.1 jmcneill val |= SUNXI_MMC_GCTRL_DMARESET; 1080 1.1 jmcneill MMC_WRITE(sc, SUNXI_MMC_GCTRL, val); 1081 1.22 jmcneill 1082 1.1 jmcneill MMC_WRITE(sc, SUNXI_MMC_DMAC, SUNXI_MMC_DMAC_SOFTRESET); 1083 1.14 jmcneill if (ISSET(cmd->c_flags, SCF_CMD_READ)) 1084 1.22 jmcneill val = SUNXI_MMC_IDST_RECEIVE_INT; 1085 1.1 jmcneill else 1086 1.22 jmcneill val = 0; 1087 1.1 jmcneill MMC_WRITE(sc, SUNXI_MMC_IDIE, val); 1088 1.22 jmcneill MMC_WRITE(sc, SUNXI_MMC_DMAC, 1089 1.22 jmcneill SUNXI_MMC_DMAC_IDMA_ON|SUNXI_MMC_DMAC_FIX_BURST); 1090 1.1 jmcneill 1091 1.1 jmcneill return 0; 1092 1.1 jmcneill } 1093 1.1 jmcneill 1094 1.1 jmcneill static void 1095 1.14 jmcneill sunxi_mmc_dma_complete(struct sunxi_mmc_softc *sc, struct sdmmc_command *cmd) 1096 1.1 jmcneill { 1097 1.22 jmcneill MMC_WRITE(sc, SUNXI_MMC_DMAC, 0); 1098 1.38 jmcneill MMC_WRITE(sc, SUNXI_MMC_IDIE, 0); 1099 1.22 jmcneill 1100 1.1 jmcneill bus_dmamap_sync(sc->sc_dmat, sc->sc_idma_map, 0, 1101 1.1 jmcneill sc->sc_idma_size, BUS_DMASYNC_POSTWRITE); 1102 1.14 jmcneill 1103 1.14 jmcneill if (cmd->c_dmamap == NULL) { 1104 1.14 jmcneill if (ISSET(cmd->c_flags, SCF_CMD_READ)) { 1105 1.14 jmcneill bus_dmamap_sync(sc->sc_dmat, sc->sc_dmabounce_map, 1106 1.15 jmcneill 0, cmd->c_datalen, BUS_DMASYNC_POSTREAD); 1107 1.14 jmcneill memcpy(cmd->c_data, sc->sc_dmabounce_buf, 1108 1.14 jmcneill cmd->c_datalen); 1109 1.14 jmcneill } else { 1110 1.14 jmcneill bus_dmamap_sync(sc->sc_dmat, sc->sc_dmabounce_map, 1111 1.15 jmcneill 0, cmd->c_datalen, BUS_DMASYNC_POSTWRITE); 1112 1.14 jmcneill } 1113 1.14 jmcneill } 1114 1.1 jmcneill } 1115 1.1 jmcneill 1116 1.1 jmcneill static void 1117 1.1 jmcneill sunxi_mmc_exec_command(sdmmc_chipset_handle_t sch, struct sdmmc_command *cmd) 1118 1.1 jmcneill { 1119 1.1 jmcneill struct sunxi_mmc_softc *sc = sch; 1120 1.1 jmcneill uint32_t cmdval = SUNXI_MMC_CMD_START; 1121 1.38 jmcneill uint32_t imask; 1122 1.38 jmcneill int retry, error; 1123 1.1 jmcneill 1124 1.13 jmcneill DPRINTF(sc->sc_dev, 1125 1.38 jmcneill "opcode %d flags 0x%x data %p datalen %d blklen %d\n", 1126 1.1 jmcneill cmd->c_opcode, cmd->c_flags, cmd->c_data, cmd->c_datalen, 1127 1.38 jmcneill cmd->c_blklen); 1128 1.1 jmcneill 1129 1.1 jmcneill mutex_enter(&sc->sc_intr_lock); 1130 1.38 jmcneill if (sc->sc_curcmd != NULL) { 1131 1.38 jmcneill device_printf(sc->sc_dev, 1132 1.38 jmcneill "WARNING: driver submitted a command while the controller was busy\n"); 1133 1.38 jmcneill cmd->c_error = EBUSY; 1134 1.38 jmcneill SET(cmd->c_flags, SCF_ITSDONE); 1135 1.38 jmcneill mutex_exit(&sc->sc_intr_lock); 1136 1.38 jmcneill return; 1137 1.38 jmcneill } 1138 1.38 jmcneill sc->sc_curcmd = cmd; 1139 1.1 jmcneill 1140 1.1 jmcneill if (cmd->c_opcode == 0) 1141 1.1 jmcneill cmdval |= SUNXI_MMC_CMD_SEND_INIT_SEQ; 1142 1.1 jmcneill if (cmd->c_flags & SCF_RSP_PRESENT) 1143 1.1 jmcneill cmdval |= SUNXI_MMC_CMD_RSP_EXP; 1144 1.1 jmcneill if (cmd->c_flags & SCF_RSP_136) 1145 1.1 jmcneill cmdval |= SUNXI_MMC_CMD_LONG_RSP; 1146 1.1 jmcneill if (cmd->c_flags & SCF_RSP_CRC) 1147 1.1 jmcneill cmdval |= SUNXI_MMC_CMD_CHECK_RSP_CRC; 1148 1.1 jmcneill 1149 1.38 jmcneill imask = SUNXI_MMC_INT_ERROR | SUNXI_MMC_INT_CMD_DONE; 1150 1.22 jmcneill 1151 1.1 jmcneill if (cmd->c_datalen > 0) { 1152 1.1 jmcneill unsigned int nblks; 1153 1.1 jmcneill 1154 1.1 jmcneill cmdval |= SUNXI_MMC_CMD_DATA_EXP | SUNXI_MMC_CMD_WAIT_PRE_OVER; 1155 1.1 jmcneill if (!ISSET(cmd->c_flags, SCF_CMD_READ)) { 1156 1.1 jmcneill cmdval |= SUNXI_MMC_CMD_WRITE; 1157 1.1 jmcneill } 1158 1.1 jmcneill 1159 1.1 jmcneill nblks = cmd->c_datalen / cmd->c_blklen; 1160 1.1 jmcneill if (nblks == 0 || (cmd->c_datalen % cmd->c_blklen) != 0) 1161 1.1 jmcneill ++nblks; 1162 1.1 jmcneill 1163 1.1 jmcneill if (nblks > 1) { 1164 1.1 jmcneill cmdval |= SUNXI_MMC_CMD_SEND_AUTO_STOP; 1165 1.22 jmcneill imask |= SUNXI_MMC_INT_AUTO_CMD_DONE; 1166 1.22 jmcneill } else { 1167 1.22 jmcneill imask |= SUNXI_MMC_INT_DATA_OVER; 1168 1.1 jmcneill } 1169 1.1 jmcneill 1170 1.1 jmcneill MMC_WRITE(sc, SUNXI_MMC_BLKSZ, cmd->c_blklen); 1171 1.1 jmcneill MMC_WRITE(sc, SUNXI_MMC_BYTECNT, nblks * cmd->c_blklen); 1172 1.1 jmcneill } 1173 1.1 jmcneill 1174 1.38 jmcneill MMC_WRITE(sc, SUNXI_MMC_IMASK, imask | sc->sc_intr_card); 1175 1.38 jmcneill MMC_WRITE(sc, SUNXI_MMC_RINT, 0x7fff); 1176 1.1 jmcneill 1177 1.1 jmcneill MMC_WRITE(sc, SUNXI_MMC_A12A, 1178 1.1 jmcneill (cmdval & SUNXI_MMC_CMD_SEND_AUTO_STOP) ? 0 : 0xffff); 1179 1.1 jmcneill 1180 1.1 jmcneill MMC_WRITE(sc, SUNXI_MMC_ARG, cmd->c_arg); 1181 1.1 jmcneill 1182 1.38 jmcneill cmd->c_resid = cmd->c_datalen; 1183 1.38 jmcneill if (cmd->c_resid > 0) { 1184 1.1 jmcneill cmd->c_error = sunxi_mmc_dma_prepare(sc, cmd); 1185 1.38 jmcneill if (cmd->c_error != 0) { 1186 1.38 jmcneill SET(cmd->c_flags, SCF_ITSDONE); 1187 1.38 jmcneill goto done; 1188 1.1 jmcneill } 1189 1.38 jmcneill sc->sc_wait_dma = ISSET(cmd->c_flags, SCF_CMD_READ); 1190 1.38 jmcneill sc->sc_wait_data = true; 1191 1.38 jmcneill } else { 1192 1.38 jmcneill sc->sc_wait_dma = false; 1193 1.38 jmcneill sc->sc_wait_data = false; 1194 1.1 jmcneill } 1195 1.38 jmcneill sc->sc_wait_cmd = true; 1196 1.1 jmcneill 1197 1.38 jmcneill DPRINTF(sc->sc_dev, "cmdval = %08x\n", cmdval); 1198 1.38 jmcneill 1199 1.38 jmcneill MMC_WRITE(sc, SUNXI_MMC_CMD, cmdval | cmd->c_opcode); 1200 1.22 jmcneill 1201 1.38 jmcneill struct bintime timeout = { .sec = 15, .frac = 0 }; 1202 1.38 jmcneill const struct bintime epsilon = { .sec = 1, .frac = 0 }; 1203 1.38 jmcneill while (!ISSET(cmd->c_flags, SCF_ITSDONE)) { 1204 1.38 jmcneill error = cv_timedwaitbt(&sc->sc_intr_cv, 1205 1.38 jmcneill &sc->sc_intr_lock, &timeout, &epsilon); 1206 1.38 jmcneill if (error != 0) { 1207 1.38 jmcneill cmd->c_error = error; 1208 1.38 jmcneill SET(cmd->c_flags, SCF_ITSDONE); 1209 1.1 jmcneill goto done; 1210 1.1 jmcneill } 1211 1.1 jmcneill } 1212 1.1 jmcneill 1213 1.38 jmcneill if (cmd->c_error == 0 && cmd->c_datalen > 0) 1214 1.38 jmcneill sunxi_mmc_dma_complete(sc, cmd); 1215 1.38 jmcneill 1216 1.1 jmcneill if (cmd->c_flags & SCF_RSP_PRESENT) { 1217 1.1 jmcneill if (cmd->c_flags & SCF_RSP_136) { 1218 1.1 jmcneill cmd->c_resp[0] = MMC_READ(sc, SUNXI_MMC_RESP0); 1219 1.1 jmcneill cmd->c_resp[1] = MMC_READ(sc, SUNXI_MMC_RESP1); 1220 1.1 jmcneill cmd->c_resp[2] = MMC_READ(sc, SUNXI_MMC_RESP2); 1221 1.1 jmcneill cmd->c_resp[3] = MMC_READ(sc, SUNXI_MMC_RESP3); 1222 1.1 jmcneill if (cmd->c_flags & SCF_RSP_CRC) { 1223 1.1 jmcneill cmd->c_resp[0] = (cmd->c_resp[0] >> 8) | 1224 1.1 jmcneill (cmd->c_resp[1] << 24); 1225 1.1 jmcneill cmd->c_resp[1] = (cmd->c_resp[1] >> 8) | 1226 1.1 jmcneill (cmd->c_resp[2] << 24); 1227 1.1 jmcneill cmd->c_resp[2] = (cmd->c_resp[2] >> 8) | 1228 1.1 jmcneill (cmd->c_resp[3] << 24); 1229 1.1 jmcneill cmd->c_resp[3] = (cmd->c_resp[3] >> 8); 1230 1.1 jmcneill } 1231 1.1 jmcneill } else { 1232 1.1 jmcneill cmd->c_resp[0] = MMC_READ(sc, SUNXI_MMC_RESP0); 1233 1.1 jmcneill } 1234 1.1 jmcneill } 1235 1.1 jmcneill 1236 1.1 jmcneill done: 1237 1.38 jmcneill KASSERT(ISSET(cmd->c_flags, SCF_ITSDONE)); 1238 1.38 jmcneill MMC_WRITE(sc, SUNXI_MMC_IMASK, sc->sc_intr_card); 1239 1.38 jmcneill MMC_WRITE(sc, SUNXI_MMC_RINT, 0x7fff); 1240 1.22 jmcneill MMC_WRITE(sc, SUNXI_MMC_IDST, 0x337); 1241 1.38 jmcneill sc->sc_curcmd = NULL; 1242 1.1 jmcneill mutex_exit(&sc->sc_intr_lock); 1243 1.1 jmcneill 1244 1.1 jmcneill if (cmd->c_error) { 1245 1.13 jmcneill DPRINTF(sc->sc_dev, "i/o error %d\n", cmd->c_error); 1246 1.1 jmcneill MMC_WRITE(sc, SUNXI_MMC_GCTRL, 1247 1.1 jmcneill MMC_READ(sc, SUNXI_MMC_GCTRL) | 1248 1.1 jmcneill SUNXI_MMC_GCTRL_DMARESET | SUNXI_MMC_GCTRL_FIFORESET); 1249 1.1 jmcneill for (retry = 0; retry < 1000; retry++) { 1250 1.1 jmcneill if (!(MMC_READ(sc, SUNXI_MMC_GCTRL) & SUNXI_MMC_GCTRL_RESET)) 1251 1.1 jmcneill break; 1252 1.1 jmcneill delay(10); 1253 1.1 jmcneill } 1254 1.1 jmcneill sunxi_mmc_update_clock(sc); 1255 1.1 jmcneill } 1256 1.1 jmcneill 1257 1.1 jmcneill MMC_WRITE(sc, SUNXI_MMC_GCTRL, 1258 1.1 jmcneill MMC_READ(sc, SUNXI_MMC_GCTRL) | SUNXI_MMC_GCTRL_FIFORESET); 1259 1.1 jmcneill } 1260 1.1 jmcneill 1261 1.1 jmcneill static void 1262 1.1 jmcneill sunxi_mmc_card_enable_intr(sdmmc_chipset_handle_t sch, int enable) 1263 1.1 jmcneill { 1264 1.11 jmcneill struct sunxi_mmc_softc *sc = sch; 1265 1.11 jmcneill uint32_t imask; 1266 1.11 jmcneill 1267 1.35 jmcneill mutex_enter(&sc->sc_intr_lock); 1268 1.11 jmcneill imask = MMC_READ(sc, SUNXI_MMC_IMASK); 1269 1.11 jmcneill if (enable) 1270 1.11 jmcneill imask |= SUNXI_MMC_INT_SDIO_INT; 1271 1.11 jmcneill else 1272 1.11 jmcneill imask &= ~SUNXI_MMC_INT_SDIO_INT; 1273 1.35 jmcneill sc->sc_intr_card = imask & SUNXI_MMC_INT_SDIO_INT; 1274 1.11 jmcneill MMC_WRITE(sc, SUNXI_MMC_IMASK, imask); 1275 1.35 jmcneill mutex_exit(&sc->sc_intr_lock); 1276 1.1 jmcneill } 1277 1.1 jmcneill 1278 1.1 jmcneill static void 1279 1.1 jmcneill sunxi_mmc_card_intr_ack(sdmmc_chipset_handle_t sch) 1280 1.1 jmcneill { 1281 1.11 jmcneill struct sunxi_mmc_softc *sc = sch; 1282 1.35 jmcneill uint32_t imask; 1283 1.11 jmcneill 1284 1.35 jmcneill mutex_enter(&sc->sc_intr_lock); 1285 1.35 jmcneill imask = MMC_READ(sc, SUNXI_MMC_IMASK); 1286 1.35 jmcneill MMC_WRITE(sc, SUNXI_MMC_IMASK, imask | sc->sc_intr_card); 1287 1.35 jmcneill mutex_exit(&sc->sc_intr_lock); 1288 1.1 jmcneill } 1289